File Coverage

blib/lib/Perl/Critic/Policy/TestingAndDebugging/RequireUseWarnings.pm
Criterion Covered Total %
statement 65 65 100.0
branch 25 34 73.5
condition 4 9 44.4
subroutine 18 18 100.0
pod 5 6 83.3
total 117 132 88.6


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings;
2              
3 40     40   25547 use 5.010001;
  40         145  
4 40     40   172 use strict;
  40         73  
  40         982  
5 40     40   130 use warnings;
  40         61  
  40         1555  
6 40     40   160 use Readonly;
  40         92  
  40         1868  
7              
8 40     40   235 use version ();
  40         74  
  40         986  
9              
10 40     40   176 use Perl::Critic::Utils qw{ :severities $EMPTY };
  40         77  
  40         1992  
11 40     40   4790 use Perl::Critic::Utils::Constants qw{ :equivalent_modules };
  40         75  
  40         3595  
12 40     40   203 use parent 'Perl::Critic::Policy';
  40         92  
  40         249  
13              
14             our $VERSION = '1.156';
15              
16             #-----------------------------------------------------------------------------
17              
18             Readonly::Scalar my $DESC => q{Code before warnings are enabled};
19             Readonly::Scalar my $EXPL => [431];
20              
21             Readonly::Scalar my $MINIMUM_VERSION => version->new(5.006);
22             Readonly::Scalar my $PERL_VERSION_WHICH_IMPLIES_WARNINGS => version->new(5.036);
23              
24             #-----------------------------------------------------------------------------
25              
26             sub supported_parameters {
27             return (
28             {
29 91     91 0 1045 name => 'equivalent_modules',
30             description =>
31             q<The additional modules to treat as equivalent to "warnings".>,
32             default_string => $EMPTY,
33             behavior => 'string list',
34             list_always_present_values => ['warnings', @WARNINGS_EQUIVALENT_MODULES],
35             },
36             );
37             }
38              
39 83     83 1 266 sub default_severity { return $SEVERITY_HIGH }
40 92     92 1 289 sub default_themes { return qw( core pbp bugs certrule ) }
41 33     33 1 70 sub applies_to { return 'PPI::Document' }
42              
43 37     37 1 79 sub default_maximum_violations_per_document { return 1; }
44              
45             #-----------------------------------------------------------------------------
46              
47             sub violates {
48 33     33 1 82 my ( $self, undef, $document ) = @_;
49              
50 33         133 my $version = $document->highest_explicit_perl_version();
51 33 0 0     87 return if $version and ($version < $MINIMUM_VERSION or $version >= $PERL_VERSION_WHICH_IMPLIES_WARNINGS);
      33        
52              
53             # Find the first 'use warnings' statement
54 33         124 my $warn_stmnt = $document->find_first( $self->_generate_is_use_warnings() );
55 33 100       524 my $warn_line = $warn_stmnt ? $warn_stmnt->location()->[0] : undef;
56              
57             # Find all statements that aren't 'use', 'require', or 'package'
58 33         466 my $stmnts_ref = _find_isnt_include_or_package($document);
59 33 100       114 return if !$stmnts_ref;
60              
61             # If the 'use warnings' statement is not defined, or the other
62             # statement appears before the 'use warnings', then it violates.
63              
64 31         49 my @viols;
65 31         47 for my $stmnt ( @{ $stmnts_ref } ) {
  31         63  
66 205 50       523 last if $stmnt->isa('PPI::Statement::End');
67 205 50       435 last if $stmnt->isa('PPI::Statement::Data');
68              
69 205         361 my $stmnt_line = $stmnt->location()->[0];
70 205 100 100     2545 if ( (! defined $warn_line) || ($stmnt_line < $warn_line) ) {
71 8         153 push @viols, $self->violation( $DESC, $EXPL, $stmnt );
72             }
73             }
74 31         117 return @viols;
75             }
76              
77             #-----------------------------------------------------------------------------
78              
79             sub _generate_is_use_warnings {
80 33     33   67 my ($self) = @_;
81              
82             return sub {
83 479     479   3539 my (undef, $elem) = @_;
84              
85 479 100       1241 return 0 if !$elem->isa('PPI::Statement::Include');
86 59 50       166 return 0 if $elem->type() ne 'use';
87              
88             # We only want file-scoped pragmas
89 59         1046 my $parent = $elem->parent();
90 59 50       278 return 0 if !$parent->isa('PPI::Document');
91              
92 59 100       110 if ( my $pragma = $elem->pragma() ) {
    50          
93 58 100       1485 return 1 if $self->{_equivalent_modules}{$pragma};
94             }
95             elsif ( my $module = $elem->module() ) {
96 1 50       43 return 1 if $self->{_equivalent_modules}{$module};
97             }
98              
99 30         84 return 0;
100 33         199 };
101             }
102              
103             #-----------------------------------------------------------------------------
104             # Here, we're using the fact that Perl::Critic::Document::find() is optimized
105             # to search for elements based on their type. This is faster than using the
106             # native PPI::Node::find() method with a custom callback function.
107              
108             sub _find_isnt_include_or_package {
109 33     33   65 my ($doc) = @_;
110 33 100       96 my $all_statements = $doc->find('PPI::Statement') or return;
111 31         60 my @wanted_statements = grep { _statement_isnt_include_or_package($_) } @{$all_statements};
  296         427  
  31         65  
112 31 50       91 return @wanted_statements ? \@wanted_statements : ();
113             }
114              
115             #-----------------------------------------------------------------------------
116              
117             sub _statement_isnt_include_or_package {
118 296     296   384 my ($elem) = @_;
119 296 100       690 return 0 if $elem->isa('PPI::Statement::Package');
120 266 100       567 return 0 if $elem->isa('PPI::Statement::Include');
121 205         320 return 1;
122             }
123              
124             1;
125              
126             __END__
127              
128             #-----------------------------------------------------------------------------
129              
130             =pod
131              
132             =head1 NAME
133              
134             Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings - Always C<use warnings>.
135              
136              
137             =head1 AFFILIATION
138              
139             This Policy is part of the core L<Perl::Critic|Perl::Critic>
140             distribution.
141              
142              
143             =head1 DESCRIPTION
144              
145             Using warnings, and paying attention to what they say, is probably the
146             single most effective way to improve the quality of your code. This
147             policy requires that the C<'use warnings'> statement must come before
148             any other statements except C<package>, C<require>, and other C<use>
149             statements. Thus, all the code in the entire package will be
150             affected.
151              
152             There are special exemptions for L<Moose|Moose>,
153             L<Moose::Role|Moose::Role>, and
154             L<Moose::Util::TypeConstraints|Moose::Util::TypeConstraints> because
155             they enforces warnings; e.g. C<'use Moose'> is treated as
156             equivalent to C<'use warnings'>.
157              
158             This policy will not complain if the file explicitly states that it is
159             compatible with a version of perl prior to 5.6 via an include
160             statement, e.g. by having C<require 5.005> in it.
161              
162             The maximum number of violations per document for this policy defaults
163             to 1.
164              
165              
166             =head1 CONFIGURATION
167              
168             If you make use of things like
169             L<Moose::Exporter|Moose::Exporter>, you can create your own modules
170             that import the L<warnings|warnings> pragma into the code that is
171             C<use>ing them. There is an option to add to the default set of
172             pragmata and modules in your F<.perlcriticrc>: C<equivalent_modules>.
173              
174             [TestingAndDebugging::RequireUseWarnings]
175             equivalent_modules = MooseX::My::Sugar
176              
177              
178             =head1 BUGS
179              
180             Needs to check for -w on the shebang line.
181              
182              
183             =head1 SEE ALSO
184              
185             L<Perl::Critic::Policy::TestingAndDebugging::ProhibitNoWarnings|Perl::Critic::Policy::TestingAndDebugging::ProhibitNoWarnings>
186              
187              
188             =head1 AUTHOR
189              
190             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
191              
192              
193             =head1 COPYRIGHT
194              
195             Copyright (c) 2005-2011 Imaginative Software Systems. All rights reserved.
196              
197             This program is free software; you can redistribute it and/or modify
198             it under the same terms as Perl itself. The full text of this license
199             can be found in the LICENSE file included with this module
200              
201             =cut
202              
203             ##############################################################################
204             # Local Variables:
205             # mode: cperl
206             # cperl-indent-level: 4
207             # fill-column: 78
208             # indent-tabs-mode: nil
209             # c-indentation-style: bsd
210             # End:
211             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :