File Coverage

blib/lib/warnings/pedantic.pm
Criterion Covered Total %
statement 32 36 88.8
branch 8 12 66.6
condition n/a
subroutine 7 8 87.5
pod 0 2 0.0
total 47 58 81.0


line stmt bran cond sub pod time code
1             package warnings::pedantic;
2              
3 3     3   155374 use 5.010;
  3         10  
  3         116  
4 3     3   23 use strict;
  3         5  
  3         103  
5 3     3   15 use warnings FATAL => 'all';
  3         10  
  3         2578  
6              
7             =encoding UTF-8
8             =head1 NAME
9              
10             warnings::pedantic - Dubious warnings for dubious constructs.
11              
12             =head1 VERSION
13              
14             Version 0.02
15              
16             =cut
17              
18             sub mkMask {
19 42     42 0 42 my ($bit) = @_;
20 42         44 my $mask = "";
21              
22 42         89 vec($mask, $bit, 1) = 1;
23 42         176 return $mask;
24             };
25              
26             sub register_categories {
27 21     21 0 31 for my $package ( @_ ) {
28 21         25 my ($submask, $deadmask);
29 21 100       47 if (ref $package) {
30 3         9 ($package, $submask, $deadmask) = @$package;
31             }
32 21 50       55 if (! defined $warnings::Bits{$package}) {
33 21         35 $warnings::Bits{$package} = mkMask($warnings::LAST_BIT);
34 21 100       50 $warnings::Bits{$package} |= $submask if $submask;
35 21         53 vec($warnings::Bits{'all'}, $warnings::LAST_BIT, 1) = 1;
36 21         55 $warnings::Offsets{$package} = $warnings::LAST_BIT ++;
37 21         223 foreach my $k (keys %warnings::Bits) {
38 1414         2552 vec($warnings::Bits{$k}, $warnings::LAST_BIT, 1) = 0;
39             }
40 21         105 $warnings::DeadBits{$package} = mkMask($warnings::LAST_BIT);
41 21 100       48 $warnings::DeadBits{$package} |= $deadmask if $deadmask;
42 21         94 vec($warnings::DeadBits{'all'}, $warnings::LAST_BIT++, 1) = 1;
43             }
44             }
45             }
46              
47             our $VERSION = '0.02';
48             require XSLoader;
49             XSLoader::load(__PACKAGE__);
50              
51             my @categories;
52             for my $name (qw(grep close print)) {
53             push @categories, "void_$name";
54             }
55              
56             push @categories, "sort_prototype";
57             push @categories, "ref_assignment";
58             push @categories, "maybe_const";
59              
60             register_categories($_) for @categories;
61              
62             my @offsets = map {
63             $warnings::Offsets{$_} / 2
64             } @categories;
65              
66             # This code creates the 'pedantic' category, and adds all of the new
67             # categories as subcategories.
68             # In short, this allows 'use warnings "pedantic"' to turn all of them by
69             # default, while also allowing this to work:
70             # use warnings "pedantic"; no warnings "void_print"
71             {
72             my ($submask, $deadmask);
73             $submask |= $_ for map { $warnings::Bits{$_} } @categories;
74             $deadmask |= $_ for map { $warnings::DeadBits{$_} } @categories;
75             register_categories(['pedantic', $submask, $deadmask]);
76             }
77              
78             start(shift, @offsets);
79              
80             my %categories = map { $_ => $_ } @categories;
81             sub import {
82 3     3   22 shift;
83 3 50       16 my @import = @_ ? @_ : @categories;
84 3         7 warnings->import(map { $categories{$_} } @import);
  18         2148  
85             }
86              
87             sub unimport {
88 0     0     shift;
89 0 0         my @unimport = @_ ? @_ : @categories;
90 0           warnings->unimport(map { $categories{$_} } @unimport);
  0            
91             }
92              
93 3     3   11573 END { done(__PACKAGE__); }
94              
95              
96             =head1 SYNOPSIS
97              
98             This module provides a C warning category, which, when enabled,
99             warns of certain extra dubious constructs.
100              
101             use warnings::pedantic;
102              
103             grep { ... } 1..10; # grep in void context
104             close($fh); # close() in void context
105             print 1; # print() in void context
106              
107             =head1 DESCRIPTION
108              
109             Besides the C category, which enables all of the following,
110             the module also provides separate categories for individual groups
111             of warnings:
112              
113             =over
114              
115             =item * void_grep
116              
117             Warns on void-context C:
118              
119             grep /42/, @INC;
120             grep { /42/ } @INC;
121              
122             This code is not particularly wrong; it's merely using grep as
123             an alternative to a foreach loop.
124              
125             =item * void_close
126              
127             Warns on void-context C and C:
128              
129             close($fh);
130             closedir($dirh);
131              
132             This is considered dubious behaviour because errors on IO operations,
133             such as ENOSPC, are not usually caught on the operation itself, but
134             on the close() of the related filehandle.
135              
136             =item * void_print
137              
138             Warns on void-context print(), printf(), and say():
139              
140             print();
141             say();
142             printf();
143              
144             =item * sort_prototype
145              
146             Warns when C's first argument is a subroutine with a prototype,
147             and that prototype isn't C<$$>.
148              
149             sub takes_a_block (&@) { ... }
150             takes_a_block { stuff_here } @args;
151             sort takes_a_block sub {...}, @args;
152              
153             This probably doesn't do what the author intended for it to do.
154              
155             =item * ref_assignment
156              
157             Warns when you attempt to assign an arrayref to an array, without using
158             parenthesis to disambiguate:
159              
160             my @a = [1,2,3]; # Warns; did you mean (...) instead of [...]?
161             my @a2 = ([1,2,3]); # Doesn't warn
162              
163             This is a common mistake for people who've recently picked up Perl.
164              
165             =item * maybe_const
166              
167             Identifiers used as either hash keys or on the left hand side of the fat
168             comma are always interpreted as barewords, even if they have a constant
169             attached to that name:
170              
171             use constant CONSTANT => 1;
172             my %x = CONSTANT => 5; # Used as "CONSTANT"
173             $x{CONSTANT} = 5; # Ditto
174              
175             This is intended behaviour on Perl's part, but is an occasional source of
176             bugs.
177              
178             =back
179              
180             Or in tree form:
181              
182             all -+
183             |
184             +- pedantic --+
185             |
186             +- void_grep
187             |
188             +- void_close
189             |
190             +- void_print
191             |
192             +- sort_prototype
193             |
194             +- ref_assignment
195             |
196             +- maybe_const
197            
198            
199              
200             All of the warnings can be turned off with
201              
202             no warnings 'pedantic';
203              
204             as well as
205              
206             no warnings;
207              
208             or even
209              
210             no warnings::pedantic;
211              
212             Additionally, you can turn off specific warnings with
213              
214             no warnings 'void_grep';
215             no warnings 'void_close';
216             no warnings 'void_print'; # printf, print, and say
217             #etc
218              
219             =head1 AUTHOR
220              
221             Brian Fraser, C<< >>
222              
223             =head1 BUGS
224              
225             Please report any bugs or feature requests to C, or through
226             the web interface at L. I will be notified, and then you'll
227             automatically be notified of progress on your bug as I make changes.
228              
229             =head1 ACKNOWLEDGEMENTS
230              
231             The warning for void-context grep was at one point part of the Perl core,
232             but was deemed too controversial and was removed.
233             Ævar Arnfjörð Bjarmason recently attempted to get it back to the core as
234             part of an RFC to extend warnings.pm, which in turn inspired this module.
235              
236             =head1 LICENSE AND COPYRIGHT
237              
238             Copyright 2014 Brian Fraser.
239              
240             This program is free software; you can redistribute it and/or modify it
241             under the same terms as Perl itself.
242              
243             =cut
244              
245             1; # End of warnings::pedantic