add new warning categories from 5.21 series
[p5sagit/strictures.git] / lib / strictures.pm
CommitLineData
394c3a46 1package strictures;
2
3use strict;
4use warnings FATAL => 'all';
5
500f28df 6BEGIN {
7 *_PERL_LT_5_8_4 = ($] < 5.008004) ? sub(){1} : sub(){0};
8}
084caaf3 9
23c0b85d 10our $VERSION = '2.000000';
20b853bb 11$VERSION = eval $VERSION;
394c3a46 12
23c0b85d 13our @WARNING_CATEGORIES = grep { exists $warnings::Offsets{$_} } qw(
14 closure
15 deprecated
16 exiting
17 experimental
c5b35ddf 18 experimental::autoderef
1e139b49 19 experimental::const_attr
23c0b85d 20 experimental::lexical_subs
21 experimental::lexical_topic
c5b35ddf 22 experimental::postderef
1e139b49 23 experimental::re_strict
24 experimental::refaliasing
23c0b85d 25 experimental::regex_sets
c5b35ddf 26 experimental::signatures
23c0b85d 27 experimental::smartmatch
1e139b49 28 experimental::win32_perlio
23c0b85d 29 glob
30 imprecision
31 io
32 closed
33 exec
34 layer
35 newline
36 pipe
c5b35ddf 37 syscalls
23c0b85d 38 unopened
1e139b49 39 locale
23c0b85d 40 misc
1e139b49 41 missing
23c0b85d 42 numeric
43 once
44 overflow
45 pack
46 portable
47 recursion
48 redefine
1e139b49 49 redundant
23c0b85d 50 regexp
51 severe
52 debugging
53 inplace
54 internal
55 malloc
56 signal
57 substr
58 syntax
59 ambiguous
60 bareword
61 digit
62 illegalproto
63 parenthesis
64 precedence
65 printf
66 prototype
67 qw
68 reserved
69 semicolon
70 taint
71 threads
72 uninitialized
73 unpack
74 untie
75 utf8
76 non_unicode
77 nonchar
78 surrogate
79 void
1e139b49 80 void_unusual
23c0b85d 81 y2k
82);
83
394c3a46 84sub VERSION {
92cde693 85 no warnings;
86 local $@;
87 if (defined $_[1] && eval { $_[0]->UNIVERSAL::VERSION($_[1]); 1}) {
88 $^H |= 0x20000
89 unless _PERL_LT_5_8_4;
90 $^H{strictures_enable} = int $_[1];
394c3a46 91 }
92cde693 92 goto &UNIVERSAL::VERSION;
394c3a46 93}
94
8f0df510 95our %extra_load_states;
ffedb166 96
2da53f4a 97our $Smells_Like_VCS;
12b8f19b 98
394c3a46 99sub import {
92cde693 100 my $class = shift;
101 my %opts = ref $_[0] ? %{$_[0]} : @_;
102 if (!exists $opts{version}) {
103 $opts{version}
104 = exists $^H{strictures_enable} ? delete $^H{strictures_enable}
105 : int $VERSION;
106 }
c5a67be6 107 $opts{file} = (caller)[1];
92cde693 108 $class->_enable(\%opts);
109}
110
111sub _enable {
112 my ($class, $opts) = @_;
113 my $version = $opts->{version};
114 $version = 'undef'
115 if !defined $version;
116 my $method = "_enable_$version";
117 if (!$class->can($method)) {
a97f64c7 118 require Carp;
119 Carp::croak("Major version specified as $version - not supported!");
92cde693 120 }
121 $class->$method($opts);
122}
123
124sub _enable_1 {
c5a67be6 125 my ($class, $opts) = @_;
394c3a46 126 strict->import;
127 warnings->import(FATAL => 'all');
084caaf3 128
c5a67be6 129 if (_want_extra($opts->{file})) {
130 _load_extras(qw(indirect multidimensional bareword::filehandles));
131 indirect->unimport(':fatal')
132 if $extra_load_states{indirect};
133 multidimensional->unimport
134 if $extra_load_states{multidimensional};
135 bareword::filehandles->unimport
136 if $extra_load_states{'bareword::filehandles'};
137 }
8f0df510 138}
139
1931c77d 140our @V2_NONFATAL = grep { exists $warnings::Offsets{$_} } (
141 'exec', # not safe to catch
142 'recursion', # will be caught by other mechanisms
143 'internal', # not safe to catch
144 'malloc', # not safe to catch
145 'newline', # stat on nonexistent file with a newline in it
146 'experimental', # no reason for these to be fatal
147 'deprecated', # unfortunately can't make these fatal
148 'portable', # everything worked fine here, just may not elsewhere
23c0b85d 149);
1931c77d 150our @V2_DISABLE = grep { exists $warnings::Offsets{$_} } (
151 'once' # triggers inconsistently, can't be fatalized
23c0b85d 152);
153
154sub _enable_2 {
155 my ($class, $opts) = @_;
156 strict->import;
157 warnings->import;
158 warnings->import(FATAL => @WARNING_CATEGORIES);
d50343b9 159 warnings->unimport(FATAL => @V2_NONFATAL);
160 warnings->import(@V2_NONFATAL);
23c0b85d 161 warnings->unimport(@V2_DISABLE);
162
163 if (_want_extra($opts->{file})) {
164 _load_extras(qw(indirect multidimensional bareword::filehandles));
165 indirect->unimport(':fatal')
166 if $extra_load_states{indirect};
167 multidimensional->unimport
168 if $extra_load_states{multidimensional};
169 bareword::filehandles->unimport
170 if $extra_load_states{'bareword::filehandles'};
171 }
172}
173
9d763997 174sub _want_extra_env {
c5a67be6 175 if (exists $ENV{PERL_STRICTURES_EXTRA}) {
176 if (_PERL_LT_5_8_4 and $ENV{PERL_STRICTURES_EXTRA}) {
177 die 'PERL_STRICTURES_EXTRA checks are not available on perls older'
178 . "than 5.8.4: please unset \$ENV{PERL_STRICTURES_EXTRA}\n";
394c3a46 179 }
9d763997 180 return $ENV{PERL_STRICTURES_EXTRA} ? 1 : 0;
c5a67be6 181 }
9d763997 182 return undef;
183}
184
185sub _want_extra {
186 my $file = shift;
187 my $want_env = _want_extra_env();
188 return $want_env
189 if defined $want_env;
c5a67be6 190 return (
191 !_PERL_LT_5_8_4
192 and $file =~ /^(?:t|xt|lib|blib)[\\\/]/
193 and defined $Smells_Like_VCS ? $Smells_Like_VCS
194 : ( $Smells_Like_VCS = !!(
195 -e '.git' || -e '.svn' || -e '.hg'
196 || (-e '../../dist.ini'
197 && (-e '../../.git' || -e '../../.svn' || -e '../../.hg' ))
198 ))
199 );
200}
4f219885 201
c5a67be6 202sub _load_extras {
203 my @extras = @_;
8f0df510 204 my @failed;
205 foreach my $mod (@extras) {
206 next
207 if exists $extra_load_states{$mod};
4f219885 208
8f0df510 209 $extra_load_states{$mod} = eval "require $mod; 1;" or do {
210 push @failed, $mod;
488f2966 211
8f0df510 212 #work around 5.8 require bug
213 (my $file = $mod) =~ s|::|/|g;
214 delete $INC{"${file}.pm"};
215 };
216 }
4f219885 217
8f0df510 218 if (@failed) {
219 my $failed = join ' ', @failed;
220 my $extras = join ' ', @extras;
221 print STDERR <<EOE;
ffedb166 222strictures.pm extra testing active but couldn't load all modules. Missing were:
223
224 $failed
225
0925b84b 226Extra testing is auto-enabled in checkouts only, so if you're the author
624cf8bb 227of a strictures-using module you need to run:
653f4377 228
8f0df510 229 cpan $extras
653f4377 230
231but these modules are not required by your users.
084caaf3 232EOE
394c3a46 233 }
234}
235
2361;
237
238__END__
239=head1 NAME
240
241strictures - turn on strict and make all warnings fatal
242
243=head1 SYNOPSIS
244
1c35787c 245 use strictures 2;
394c3a46 246
247is equivalent to
248
249 use strict;
250 use warnings FATAL => 'all';
1c35787c 251 use warnings NONFATAL => qw(
252 exec
253 recursion
254 internal
255 malloc
256 newline
257 experimental
258 deprecated
259 portable
260 );
261 no warnings 'once';
394c3a46 262
5ab06a4d 263except when called from a file which matches:
394c3a46 264
5b2a026b 265 (caller)[1] =~ /^(?:t|xt|lib|blib)[\\\/]/
394c3a46 266
3e14202f 267and when either C<.git>, C<.svn>, or C<.hg> is present in the current directory
268(with the intention of only forcing extra tests on the author side) -- or when
269C<.git>, C<.svn>, or C<.hg> is present two directories up along with
270C<dist.ini> (which would indicate we are in a C<dzil test> operation, via
271L<Dist::Zilla>) -- or when the C<PERL_STRICTURES_EXTRA> environment variable is
40836ccc 272set, in which case it also does the equivalent of
394c3a46 273
394c3a46 274 no indirect 'fatal';
653f4377 275 no multidimensional;
276 no bareword::filehandles;
394c3a46 277
3e14202f 278Note that C<PERL_STRICTURES_EXTRA> may at some point add even more tests, with
279only a minor version increase, but any changes to the effect of C<use
280strictures> in normal mode will involve a major version bump.
394c3a46 281
0eb0d037 282If any of the extra testing modules are not present, L<strictures> will
25877bf2 283complain loudly, once, via C<warn()>, and then shut up. But you really
ffedb166 284should consider installing them, they're all great anti-footgun tools.
17b03f2e 285
394c3a46 286=head1 DESCRIPTION
287
288I've been writing the equivalent of this module at the top of my code for
289about a year now. I figured it was time to make it shorter.
290
25877bf2 291Things like the importer in C<use Moose> don't help me because they turn
d8c1c6b2 292warnings on but don't make them fatal -- which from my point of view is
2288278f 293useless because I want an exception to tell me my code isn't warnings-clean.
394c3a46 294
295Any time I see a warning from my code, that indicates a mistake.
296
d8c1c6b2 297Any time my code encounters a mistake, I want a crash -- not spew to STDERR
394c3a46 298and then unknown (and probably undesired) subsequent behaviour.
299
300I also want to ensure that obvious coding mistakes, like indirect object
301syntax (and not so obvious mistakes that cause things to accidentally compile
302as such) get caught, but not at the cost of an XS dependency and not at the
303cost of blowing things up on another machine.
304
0eb0d037 305Therefore, L<strictures> turns on additional checking, but only when it thinks
2288278f 306it's running in a test file in a VCS checkout -- although if this causes
93ae637e 307undesired behaviour this can be overridden by setting the
25877bf2 308C<PERL_STRICTURES_EXTRA> environment variable.
394c3a46 309
310If additional useful author side checks come to mind, I'll add them to the
3e14202f 311C<PERL_STRICTURES_EXTRA> code path only -- this will result in a minor version
312increase (e.g. 1.000000 to 1.001000 (1.1.0) or similar). Any fixes only to the
313mechanism of this code will result in a sub-version increase (e.g. 1.000000 to
3141.000001 (1.0.1)).
394c3a46 315
1c35787c 316=head1 VERSIONS
317
318Depending on the version of strictures requested, different warnings will be
319enabled. If no specific version is requested, the current version's behavior
320will be used. Versions can be requested using perl's standard mechanism:
321
322 use strictures 2;
323
324Or, by passing in a C<version> option:
325
326 use strictures version => 2;
394c3a46 327
1c35787c 328=head2 VERSION 2
394c3a46 329
1c35787c 330Equivalent to:
331
332 use strict;
333 use warnings FATAL => 'all';
334 use warnings NONFATAL => 'deprecated', 'experimental';
335 # and if in dev mode:
336 no indirect 'fatal';
337 no multidimensional;
338 no bareword::filehandles;
339
340=head2 VERSION 1
341
342Equivalent to:
343
344 use strict;
345 use warnings FATAL => 'all';
346 # and if in dev mode:
347 no indirect 'fatal';
348 no multidimensional;
349 no bareword::filehandles;
eae006ee 350
351=head1 METHODS
352
353=head2 import
354
1c35787c 355This method does the setup work described above in L</DESCRIPTION>. Optionally
356accepts a C<version> option to request a specific version's behavior.
eae006ee 357
358=head2 VERSION
359
25877bf2 360This method traps the C<< strictures->VERSION(1) >> call produced by a use line
eae006ee 361with a version number on it and does the version check.
362
f9df7e2e 363=head1 EXTRA TESTING RATIONALE
364
25877bf2 365Every so often, somebody complains that they're deploying via C<git pull>
d8c1c6b2 366and that they don't want L<strictures> to enable itself in this case -- and that
f9df7e2e 367setting C<PERL_STRICTURES_EXTRA> to 0 isn't acceptable (additional ways to
368disable extra testing would be welcome but the discussion never seems to get
369that far).
370
371In order to allow us to skip a couple of stages and get straight to a
372productive conversation, here's my current rationale for turning the
373extra testing on via a heuristic:
374
375The extra testing is all stuff that only ever blows up at compile time;
2288278f 376this is intentional. So the oft-raised concern that it's different code being
d8c1c6b2 377tested is only sort of the case -- none of the modules involved affect the
f9df7e2e 378final optree to my knowledge, so the author gets some additional compile
379time crashes which he/she then fixes, and the rest of the testing is
380completely valid for all environments.
381
d8c1c6b2 382The point of the extra testing -- especially C<no indirect> -- is to catch
f9df7e2e 383mistakes that newbie users won't even realise are mistakes without
384help. For example,
385
386 foo { ... };
387
d8c1c6b2 388where foo is an & prototyped sub that you forgot to import -- this is
9a363fed 389pernicious to track down since all I<seems> fine until it gets called
f9df7e2e 390and you get a crash. Worse still, you can fail to have imported it due
391to a circular require, at which point you have a load order dependent
9a363fed 392bug which I've seen before now I<only> show up in production due to tiny
f9df7e2e 393differences between the production and the development environment. I wrote
394L<http://shadow.cat/blog/matt-s-trout/indirect-but-still-fatal/> to explain
395this particular problem before L<strictures> itself existed.
396
2288278f 397As such, in my experience so far L<strictures>' extra testing has
9a363fed 398I<avoided> production versus development differences, not caused them.
f9df7e2e 399
0eb0d037 400Additionally, L<strictures>' policy is very much "try and provide as much
d8c1c6b2 401protection as possible for newbies -- who won't think about whether there's
402an option to turn on or not" -- so having only the environment variable
f9df7e2e 403is not sufficient to achieve that (I get to explain that you need to add
d8c1c6b2 404C<use strict> at least once a week on freenode #perl -- newbies sometimes
f9df7e2e 405completely skip steps because they don't understand that that step
406is important).
407
d8c1c6b2 408I make no claims that the heuristic is perfect -- it's already been evolved
f9df7e2e 409significantly over time, especially for 1.004 where we changed things to
0eb0d037 410ensure it only fires on files in your checkout (rather than L<strictures>-using
f9df7e2e 411modules you happened to have installed, which was just silly). However, I
412hope the above clarifies why a heuristic approach is not only necessary but
3e14202f 413desirable from a point of view of providing new users with as much safety as
414possible, and will allow any future discussion on the subject to focus on "how
415do we minimise annoyance to people deploying from checkouts intentionally".
f9df7e2e 416
96c8649b 417=head1 SEE ALSO
418
419=over 4
420
421=item *
422
423L<indirect>
424
425=item *
426
427L<multidimensional>
428
429=item *
430
431L<bareword::filehandles>
432
433=back
434
eae006ee 435=head1 COMMUNITY AND SUPPORT
436
437=head2 IRC channel
438
439irc.perl.org #toolchain
440
441(or bug 'mst' in query on there or freenode)
442
443=head2 Git repository
444
445Gitweb is on http://git.shadowcat.co.uk/ and the clone URL is:
446
447 git clone git://git.shadowcat.co.uk/p5sagit/strictures.git
448
91be28bc 449The web interface to the repository is at:
450
451 http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit/strictures.git
452
eae006ee 453=head1 AUTHOR
454
d81f898d 455mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk>
eae006ee 456
457=head1 CONTRIBUTORS
458
8190ff5b 459Karen Etheridge (cpan:ETHER) <ether@cpan.org>
eae006ee 460
04b4a35d 461Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@gmail.com>
462
a79d1096 463haarg - Graham Knop (cpan:HAARG) <haarg@haarg.org>
464
eae006ee 465=head1 COPYRIGHT
466
467Copyright (c) 2010 the strictures L</AUTHOR> and L</CONTRIBUTORS>
468as listed above.
469
470=head1 LICENSE
471
472This library is free software and may be distributed under the same terms
473as perl itself.
474
475=cut