File Coverage

blib/lib/warnings/everywhere.pm
Criterion Covered Total %
statement 63 72 87.5
branch 12 18 66.6
condition n/a
subroutine 17 18 94.4
pod 4 4 100.0
total 96 112 85.7


line stmt bran cond sub pod time code
1             package warnings::everywhere;
2              
3 7     7   11208 use 5.008;
  7         27  
4 7     7   33 use strict;
  7         11  
  7         199  
5 7     7   34 use warnings;
  7         13  
  7         235  
6 7     7   31 no warnings qw(uninitialized);
  7         14  
  7         1032  
7              
8             our $VERSION = '0.031';
9             $VERSION = eval $VERSION;
10              
11             sub import {
12 7     7   37 my $package = shift;
13 7         192 for my $category (@_) {
14 0         0 enable_warning_category($category);
15             }
16             }
17              
18             sub unimport {
19 3     3   22 my $package = shift;
20 3         7 for my $category (@_) {
21 6         15 disable_warning_category($category);
22             }
23             }
24              
25 7     7   47 use Carp;
  7         13  
  7         5482  
26              
27             =head1 NAME
28              
29             warnings::everywhere - a way of ensuring consistent global warning settings
30              
31             =head1 VERSION
32              
33             This is version 0.030.
34              
35             =head1 SYNOPSIS
36              
37             use strict;
38             use warnings;
39             no warnings::anywhere qw(uninitialized);
40            
41             use Module::That::Spits::Out::Warnings;
42             use Other::Unnecessarily::Chatty::Module;
43              
44             use warnings::everywhere qw(uninitialized);
45             # Write your own bondage-and-discipline code that really, really
46             # cares about the difference between undef and the empty string
47              
48             =head1 DESCRIPTION
49              
50             Warnings are great - in your own code. Tools like prove, and libraries
51             like Moose and Modern::Perl, turn them on for you so you can spot things
52             like ambiguous syntax, variables you only used once, deprecated syntax
53             and other useful things.
54              
55             By default C turns on all warnings, including some that
56             you might not care about, like uninitialised variables. You could explicitly
57             say
58              
59             use warnings;
60             no warnings qw(uninitialized);
61              
62             or you could use a module like C which disables some warnings
63             and makes others fatal, or you could roll your own system. Either way,
64             for your own code, there are plenty of ways around unwanted warnings.
65              
66             Not so for other code, though.
67              
68             The test suite at $WORK produces a large number of 'use of uninitialized
69             variable' warnings from (at the last count) four separate modules. Some of
70             them are because warnings got switched on for that module,
71             even though the module itself didn't say anything about warnings
72             (probably because the test suite was run with prove).
73             Others are there because the module explicitly said C, and
74             then proceeded to blithely throw around variables without checking whether
75             they were defined first.
76              
77             Either way, this isn't my code, and it's not something I'm going to fix.
78             These warnings are just spam.
79              
80             This is where warnings::everywhere comes in.
81              
82             =head2 Usage
83              
84             At its simplest, say
85              
86             use warnings::everywhere qw(all);
87              
88             and all modules imported from there onwards will have all warnings switched
89             on. Modules imported previously will be unaffected. You can turn specific
90             warnings off by saying e.g.
91              
92             no warnings::everywhere qw(uninitialized);
93              
94             or, depending on how frustrated and/or grammatically-sensitive you happen
95             to be feeling,
96              
97             no warnings::anywhere qw(uninitialized);
98              
99             or
100              
101             no goddamn::warnings::anywhere qw(uninitialized);
102              
103             Parameters are the same as C: a list of categories
104             as per L, where C means all warnings.
105              
106             =head2 Limitations
107              
108             warnings::everywhere works by fiddling with the contents of the global hashes
109             %warnings::Bits and %warnings::DeadBits. As such, there are limitations on
110             what it can and cannot do:
111              
112             =over
113              
114             =item It cannot affect modules that are already loaded.
115              
116             If you say
117              
118             use Chatty::Module;
119             no warnings::anywhere qw(uninitialized);
120              
121             that's no good - Chatty::Module has already called C and
122             uninitialized variables was in the list of enabled warnings at that point,
123             so it will still spam you.
124              
125             Similarly, this is no help:
126              
127             use Module::That::Uses::Chatty::Module;
128             no warnings::anywhere qw(uninitialized);
129             use Chatty::Module;
130              
131             Chatty::Module was pulled in by that other module already by the time
132             perl gets to your use statement, so it's ignored.
133              
134             =item It's vulnerable to anything that sets $^W
135              
136             Any code that sets the global variable $^W, rather than saying C
137             or Cimport>, will turn on all warnings everywhere, bypassing the
138             changes warnings::everywhere makes. This also includes any code that sets -w
139             via the shebang.
140              
141             Any change to warnings by any of the warnings::anywhere code will turn off $^W
142             again, whether it's a use statement or an explicit call to
143             L or similar.
144              
145             Any module that claims to enable warnings for you is potentially suspect
146             - Moose is fine, but Dancer sets $^W to 1 as soon as it loads, even if your
147             configuration subsequently disables import_warnings.
148              
149             =item It cannot make all modules use warnings
150              
151             All it does is fiddle with the exact behaviour of C,
152             so a module that doesn't say C, or import a module that
153             injects warnings like Moose, will be unaffected.
154              
155             =item It's not lexical
156              
157             While it I like a pragma, it's not - it fiddles with global settings,
158             after all. So you can't say
159              
160             {
161             no warnings::anywhere qw(uninitialized);
162             Chatty::Module->do_things;
163             }
164             Unchatty::Module->do_stuff(undef);
165              
166             and expect to get a warning from the last line. That warning's been
167             turned off for good.
168              
169             =item It won't work for compile-time warnings
170              
171             It works by fiddling with the (global) %warnings::Bits variable, and that's
172             fine for run-time warnings. But if you say e.g.
173              
174             use warnings;
175             use experimental 'signatures';
176             no warnings::anywhere 'experimental::signatures';
177             use Moose; # or Moo, or Dancer2, or... or...
178              
179             that won't work, as when Moose (or Moo, or Dancer2 etc.) injects all warnings
180             into your package, it turns everything back on, and warnings::everywhere
181             can't thwart that.
182              
183             (Previous versions of warnings::everywhere I to thwart this by
184             basically a source filter, but that proved untenable.)
185              
186             The solution is to remember that Moose, Moo, Dancer2 etc. only turn on
187             these compile-time warnings I, so just say e.g.
188              
189             use warnings;
190             use Moose; # or Moo etc.
191             use experimental 'signatures';
192              
193             =back
194              
195             =head1 SUBROUTINES
196              
197             warnings::anywhere provides the following functions, mostly for diagnostic
198             use. They are not exported or exportable.
199              
200             =over
201              
202             =item categories_enabled
203              
204             Out: @categories
205              
206             Returns a sorted list of warning categories enabled globally. Before you've
207             fiddled with anything, this will be the list of warning categories from
208             L, minus C which isn't a category itself.
209              
210             Fatal warnings are ignored for the purpose of this function.
211              
212             =cut
213              
214             sub categories_enabled {
215 27     27 1 600 my @categories;
216 27         65 for my $category (_warning_categories()) {
217             push @categories, $category
218             if _is_bit_set($warnings::Bits{$category},
219 1884 100       2753 $warnings::Offsets{$category});
220             }
221 27         261 return @categories;
222             }
223              
224             =item categories_disabled
225              
226             Out: @categories
227              
228             Returns a sorted list of warning categories disabled globally. Before
229             you've fiddled with anything, this will be the empty list.
230              
231             Fatal warnings are ignored for the purpose of this function.
232              
233             =cut
234              
235             sub categories_disabled {
236 13     13 1 514 my @categories;
237 13         28 for my $category (_warning_categories()) {
238             push @categories, $category
239             if !_is_bit_set($warnings::Bits{$category},
240 910 100       1221 $warnings::Offsets{$category});
241             }
242 13         78 return @categories;
243             }
244              
245             sub _warning_categories {
246 41     41   2058 my @categories = sort grep { $_ ne 'all' } keys %warnings::Offsets;
  2905         4665  
247 41         373 return @categories;
248             }
249              
250             =item enable_warning_category
251              
252             In: $category
253              
254             Supplied with a valid warning category, enables it for all future
255             uses of C.
256              
257             =cut
258              
259             sub enable_warning_category {
260 9     9 1 4886 my ($category) = @_;
261              
262 9 50       37 _check_warning_category($category) or return;
263 9         38 _set_category_mask($category, 1);
264 9         62 return 1;
265             }
266              
267             sub _set_category_mask {
268 23     23   48 my ($category, $bit_value) = @_;
269              
270             # Set or unset the specific category bit value (e.g. if
271             # someone says use warnings qw(uninitialized) or
272             # no warnings qw(uninitialized)).
273             _set_bit_mask(\($warnings::Bits{$category}),
274 23         89 $warnings::Offsets{$category}, $bit_value);
275              
276             # Compute what the bitmask for all should be.
277 23         53 $warnings::Bits{all} = _bitmask_categories_enabled();
278              
279             # If we've enabled all categories, we should probably set
280             # the all bit as well, just for tidiness.
281 23 100       73 if ($bit_value) {
282 9 100       30 if (!categories_disabled()) {
283 7         23 _set_bit_mask(\$warnings::Bits{all}, $warnings::Offsets{all}, 1);
284             }
285             }
286             ### TODO: fatal warnings
287              
288             # Finally, if someone specified the -w flag (which turns on all
289             # warnings, globally), turn it off.
290 23         63 $^W = 0;
291             }
292              
293             =item disable_warning_category
294              
295             In: $category
296              
297             Supplied with a valid warning category, disables it for future
298             uses of C - even calls to explicitly enable it.
299              
300             =cut
301              
302             sub disable_warning_category {
303 14     14 1 3310 my ($category) = @_;
304              
305 14 50       41 _check_warning_category($category) or return;
306 14         96 _set_category_mask($category, 0);
307 14         185 return 1;
308             }
309              
310             sub _bitmask_categories_enabled {
311 23     23   40 my $mask;
312 23         59 for my $category_enabled (categories_enabled()) {
313 1585         2285 _set_bit_mask(\$mask, $warnings::Offsets{$category_enabled}, 1)
314             }
315 23         124 return $mask;
316             }
317              
318             sub _set_bit_mask {
319 1615     1615   2068 my ($mask_ref, $bit_num, $bit_value) = @_;
320              
321             # First get the correct byte from the mask, then set that byte's
322             # bit accordingly.
323             # We have to do it this way as warning masks are hundreds of bits wide,
324             # which neither a 32- nor a 64-bit Perl can deal with natively.
325             # The mask might not be long enough, so pad it with null bytes if
326             # we need to first.
327 1615         2069 my $byte_num = int($bit_num / 8);
328 1615         2434 while (length($$mask_ref) < $byte_num) {
329 391         690 $$mask_ref .= "\x0";
330             }
331 1615         2143 my $byte_value = substr($$mask_ref, $byte_num, 1);
332 1615         2563 vec($byte_value, $bit_num % 8, 1) = $bit_value;
333 1615         2295 substr($$mask_ref, $byte_num, 1) = $byte_value;
334 1615         2222 return $$mask_ref;
335             }
336              
337             sub _is_bit_set {
338 2797     2797   3619 my ($mask, $bit_num) = @_;
339              
340 2797         6203 return vec($mask, int($bit_num / 8), 8) & (1 << ($bit_num % 8));
341             }
342              
343             sub _dump_mask {
344 0     0   0 my ($mask) = @_;
345              
346 0         0 my $output;
347 0         0 for my $byte_num (reverse 0..15) {
348 0         0 $output .= sprintf('%08b', vec($mask, $byte_num, 8));
349 0 0       0 $output .= ($byte_num % 4 == 0 ? "\n" : '|');
350             }
351 0         0 return $output;
352             }
353              
354             sub _check_warning_category {
355 23     23   49 my ($category) = @_;
356              
357 23 50       130 return if $category eq 'all';
358 23 50       71 if (!exists $warnings::Offsets{$category}) {
359 0         0 carp "Unrecognised warning category $category";
360 0         0 return;
361             }
362 23         71 return 1;
363             }
364              
365             =back
366              
367             =head1 TO DO
368              
369             Support for fatal warnings, possibly.
370             It's possible it doesn't behave correctly when passed 'all'.
371              
372             =head1 DIAGNOSTICS
373              
374             =over
375              
376             =item Unrecognised warning category $category
377              
378             Your version of Perl doesn't recognise the warning category $category.
379             Either you're using a different version of Perl than you thought, or a
380             third-party module that defined that warning isn't loaded yet.
381              
382             =back
383              
384             =head1 SEE ALSO
385              
386             L
387              
388             =head1 AUTHOR
389              
390             Sam Kington
391              
392             The source code for this module is hosted on GitHub
393             L - this is probably the
394             best place to look for suggestions and feedback.
395              
396             =head1 COPYRIGHT
397              
398             Copyright (c) 2013 Sam Kington.
399              
400             =head1 LICENSE
401              
402             This library is free software and may be distributed under the same terms as
403             perl itself.
404              
405             =cut
406              
407             1;