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