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   27971 use 5.010001;
  40         186  
4 40     40   235 use strict;
  40         110  
  40         817  
5 40     40   258 use warnings;
  40         114  
  40         918  
6 40     40   236 use Readonly;
  40         122  
  40         1850  
7              
8 40     40   272 use version ();
  40         135  
  40         847  
9              
10 40     40   248 use Perl::Critic::Utils qw{ :severities $EMPTY };
  40         120  
  40         1960  
11 40     40   5376 use Perl::Critic::Utils::Constants qw{ :equivalent_modules };
  40         122  
  40         4092  
12 40     40   345 use parent 'Perl::Critic::Policy';
  40         124  
  40         272  
13              
14             our $VERSION = '1.150';
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 90     90 0 2106 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 80     80 1 303 sub default_severity { return $SEVERITY_HIGH }
40 92     92 1 390 sub default_themes { return qw( core pbp bugs certrule ) }
41 32     32 1 116 sub applies_to { return 'PPI::Document' }
42              
43 36     36 1 96 sub default_maximum_violations_per_document { return 1; }
44              
45             #-----------------------------------------------------------------------------
46              
47             sub violates {
48 32     32 1 98 my ( $self, undef, $document ) = @_;
49              
50 32         106 my $version = $document->highest_explicit_perl_version();
51 32 0 0     93 return if $version and ($version < $MINIMUM_VERSION or $version >= $PERL_VERSION_WHICH_IMPLIES_WARNINGS);
      33        
52              
53             # Find the first 'use warnings' statement
54 32         120 my $warn_stmnt = $document->find_first( $self->_generate_is_use_warnings() );
55 32 100       583 my $warn_line = $warn_stmnt ? $warn_stmnt->location()->[0] : undef;
56              
57             # Find all statements that aren't 'use', 'require', or 'package'
58 32         540 my $stmnts_ref = $self->_find_isnt_include_or_package($document);
59 32 100       109 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 30         84 my @viols;
65 30         59 for my $stmnt ( @{ $stmnts_ref } ) {
  30         75  
66 203 50       556 last if $stmnt->isa('PPI::Statement::End');
67 203 50       517 last if $stmnt->isa('PPI::Statement::Data');
68              
69 203         405 my $stmnt_line = $stmnt->location()->[0];
70 203 100 100     3064 if ( (! defined $warn_line) || ($stmnt_line < $warn_line) ) {
71 6         30 push @viols, $self->violation( $DESC, $EXPL, $stmnt );
72             }
73             }
74 30         158 return @viols;
75             }
76              
77             #-----------------------------------------------------------------------------
78              
79             sub _generate_is_use_warnings {
80 32     32   107 my ($self) = @_;
81              
82             return sub {
83 462     462   4062 my (undef, $elem) = @_;
84              
85 462 100       1368 return 0 if !$elem->isa('PPI::Statement::Include');
86 59 50       140 return 0 if $elem->type() ne 'use';
87              
88             # We only want file-scoped pragmas
89 59         1567 my $parent = $elem->parent();
90 59 50       332 return 0 if !$parent->isa('PPI::Document');
91              
92 59 100       156 if ( my $pragma = $elem->pragma() ) {
    50          
93 58 100       1653 return 1 if $self->{_equivalent_modules}{$pragma};
94             }
95             elsif ( my $module = $elem->module() ) {
96 1 50       68 return 1 if $self->{_equivalent_modules}{$module};
97             }
98              
99 30         90 return 0;
100 32         244 };
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 32     32   103 my ($self, $doc) = @_;
110 32 100       125 my $all_statements = $doc->find('PPI::Statement') or return;
111 30         69 my @wanted_statements = grep { _statement_isnt_include_or_package($_) } @{$all_statements};
  294         460  
  30         84  
112 30 50       150 return @wanted_statements ? \@wanted_statements : ();
113             }
114              
115             #-----------------------------------------------------------------------------
116              
117             sub _statement_isnt_include_or_package {
118 294     294   437 my ($elem) = @_;
119 294 100       825 return 0 if $elem->isa('PPI::Statement::Package');
120 264 100       632 return 0 if $elem->isa('PPI::Statement::Include');
121 203         371 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 :