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