File Coverage

blib/lib/Perl/Critic/Policy/InputOutput/RequireCheckedSyscalls.pm
Criterion Covered Total %
statement 39 44 88.6
branch 6 14 42.8
condition n/a
subroutine 12 12 100.0
pod 5 6 83.3
total 62 76 81.5


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::InputOutput::RequireCheckedSyscalls;
2              
3 40     40   27234 use 5.010001;
  40         180  
4 40     40   270 use strict;
  40         106  
  40         1161  
5 40     40   258 use warnings;
  40         129  
  40         1092  
6 40     40   247 use Readonly;
  40         113  
  40         2409  
7              
8 40         2307 use Perl::Critic::Utils qw{ :booleans :characters :severities :classification
9 40     40   322 hashify is_perl_bareword };
  40         146  
10              
11 40     40   23785 use parent 'Perl::Critic::Policy';
  40         137  
  40         260  
12              
13             our $VERSION = '1.150';
14              
15             #-----------------------------------------------------------------------------
16              
17             Readonly::Scalar my $DESC => q{Return value of flagged function ignored};
18             Readonly::Scalar my $EXPL => [208, 278];
19              
20             Readonly::Array my @DEFAULT_FUNCTIONS => qw(
21             open close print say
22             );
23             # I created this list by searching for "return" in perlfunc
24             Readonly::Array my @BUILTIN_FUNCTIONS => qw(
25             accept bind binmode chdir chmod chown close closedir connect
26             dbmclose dbmopen exec fcntl flock fork ioctl kill link listen
27             mkdir msgctl msgget msgrcv msgsnd open opendir pipe print read
28             readdir readline readlink readpipe recv rename rmdir say seek seekdir
29             semctl semget semop send setpgrp setpriority setsockopt shmctl
30             shmget shmread shutdown sleep socket socketpair symlink syscall
31             sysopen sysread sysseek system syswrite tell telldir truncate
32             umask unlink utime wait waitpid
33             );
34              
35             #-----------------------------------------------------------------------------
36              
37             sub supported_parameters {
38             return (
39             {
40 92     92 0 2026 name => 'functions',
41             description =>
42             'The set of functions to require checking the return value of.',
43             default_string => join( $SPACE, @DEFAULT_FUNCTIONS ),
44             behavior => 'string list',
45             },
46             {
47             name => 'exclude_functions',
48             description =>
49             'The set of functions to not require checking the return value of.',
50             default_string => $EMPTY,
51             behavior => 'string list',
52             },
53             {
54             name => 'autodie_modules',
55             description => 'Modules which export autodie.',
56             default_string => 'autodie',
57             behavior => 'string list',
58             },
59             );
60             }
61              
62 76     76 1 320 sub default_severity { return $SEVERITY_LOWEST }
63 74     74 1 303 sub default_themes { return qw( core maintenance certrule ) }
64 30     30 1 140 sub applies_to { return 'PPI::Token::Word' }
65              
66             #-----------------------------------------------------------------------------
67              
68             sub initialize_if_enabled {
69 49     49 1 223 my ($self, $config) = @_;
70              
71 49         106 my @specified_functions = keys %{ $self->{_functions} };
  49         330  
72 49         161 my @resulting_functions;
73              
74 49         169 foreach my $function (@specified_functions) {
75 196 50       512 if ( $function eq ':defaults' ) {
    50          
76 0         0 push @resulting_functions, @DEFAULT_FUNCTIONS;
77             }
78             elsif ( $function eq ':builtins' ) {
79 0         0 push @resulting_functions, @BUILTIN_FUNCTIONS;
80             }
81             else {
82 196         449 push @resulting_functions, $function;
83             }
84             }
85              
86 49         275 my %functions = hashify(@resulting_functions);
87              
88 49         171 foreach my $function ( keys %{ $self->{_exclude_functions} } ) {
  49         257  
89 0         0 delete $functions{$function};
90             }
91              
92 49         165 $self->{_functions} = \%functions;
93              
94 49         309 return $TRUE;
95             }
96              
97             #-----------------------------------------------------------------------------
98              
99             sub violates {
100 329     329 1 550 my ( $self, $elem, undef ) = @_;
101              
102 329 50       768 if ( $self->{_functions}->{':all'} ) {
    100          
103 0 0       0 return if is_perl_bareword($elem);
104 0 0       0 return if $self->{_exclude_functions}->{ $elem->content() };
105             }
106             elsif ( not $self->{_functions}->{ $elem->content() } ) {
107 327         1336 return;
108             }
109              
110 2 50       12 return if ! is_unchecked_call( $elem, [ keys %{ $self->{_autodie_modules} } ] );
  2         17  
111              
112 2         15 return $self->violation( "$DESC - " . $elem->content(), $EXPL, $elem );
113             }
114              
115              
116             1;
117              
118             __END__
119              
120             #-----------------------------------------------------------------------------
121              
122             =pod
123              
124             =for stopwords nyah autodie builtins
125              
126             =head1 NAME
127              
128             Perl::Critic::Policy::InputOutput::RequireCheckedSyscalls - Return value of flagged function ignored.
129              
130             =head1 AFFILIATION
131              
132             This Policy is part of the core L<Perl::Critic|Perl::Critic>
133             distribution.
134              
135              
136             =head1 DESCRIPTION
137              
138             This performs identically to InputOutput::RequireCheckedOpen/Close
139             except that this is configurable to apply to any function, whether
140             core or user-defined.
141              
142             If your module uses L<Fatal|Fatal>,
143             L<Fatal::Exception|Fatal::Exception>, or L<autodie|autodie> then any functions
144             wrapped by those modules will not trigger this policy. For example:
145              
146             use Fatal qw(open);
147             open my $fh, $filename; # no violation
148             close $fh; # yes violation
149              
150             use autodie;
151             open $filehandle, $mode, $filename; # no violation
152              
153             Currently, L<autodie|autodie> is not properly treated as a pragma; its
154             lexical effects aren't taken into account.
155              
156              
157             =head1 CONFIGURATION
158              
159             This policy watches for a configurable list of function names. By
160             default, it applies to C<open>, C<print>, C<say> and C<close>. You can
161             override this to set it to a different list of functions with the
162             C<functions> and C<exclude_functions> settings. To do this, put
163             entries in a F<.perlcriticrc> file like this:
164              
165             [InputOutput::RequireCheckedSyscalls]
166             functions = open opendir read readline readdir close closedir
167              
168             We have defined a few shortcuts for creating this list
169              
170             [InputOutput::RequireCheckedSyscalls]
171             functions = :defaults opendir readdir closedir
172              
173             [InputOutput::RequireCheckedSyscalls]
174             functions = :builtins
175              
176             [InputOutput::RequireCheckedSyscalls]
177             functions = :all
178              
179             The C<:builtins> shortcut above represents all of the builtin
180             functions that have error conditions (about 65 of them, many of them
181             rather obscure).
182              
183             You can require checking all builtins except C<print> by combining
184             the C<functions> and C<exclude_functions>:
185              
186             [InputOutput::RequireCheckedSyscalls]
187             functions = :builtins
188             exclude_functions = print
189              
190             This is a lot easier to read than the alternative.
191              
192             The C<:all> is the insane case: you must check the return value of
193             EVERY function call, even C<return> and C<exit>. Yes, this "feature"
194             is overkill and is wasting CPU cycles on your computer by just
195             existing. Nyah nyah. I shouldn't code after midnight.
196              
197             If you create a module that exports C<autodie> you can tell this policy about
198             it with the C<autodie_modules> setting:
199              
200             [InputOutput::RequireCheckedSyscalls]
201             autodie_modules = My::Thing
202              
203             =head1 CREDITS
204              
205             Initial development of this policy was supported by a grant from the
206             Perl Foundation.
207              
208             This policy module is based heavily on policies written by Andrew
209             Moore <amoore@mooresystems.com>.
210              
211              
212             =head1 AUTHOR
213              
214             Chris Dolan <cdolan@cpan.org>
215              
216              
217             =head1 COPYRIGHT
218              
219             Copyright (c) 2007-2011 Chris Dolan. Many rights reserved.
220              
221             This program is free software; you can redistribute it and/or modify
222             it under the same terms as Perl itself. The full text of this license
223             can be found in the LICENSE file included with this module.
224              
225             =cut
226              
227             ##############################################################################
228             # Local Variables:
229             # mode: cperl
230             # cperl-indent-level: 4
231             # fill-column: 78
232             # indent-tabs-mode: nil
233             # c-indentation-style: bsd
234             # End:
235             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :