File Coverage

blib/lib/Perl/Critic/Policy/InputOutput/RequireBracedFileHandleWithPrint.pm
Criterion Covered Total %
statement 38 44 86.3
branch 13 30 43.3
condition 2 6 33.3
subroutine 11 11 100.0
pod 4 5 80.0
total 68 96 70.8


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::InputOutput::RequireBracedFileHandleWithPrint;
2              
3 40     40   26642 use 5.010001;
  40         164  
4 40     40   265 use strict;
  40         96  
  40         882  
5 40     40   251 use warnings;
  40         93  
  40         1128  
6 40     40   249 use Readonly;
  40         123  
  40         2290  
7              
8 40     40   373 use Perl::Critic::Utils qw{ :severities :classification :data_conversion };
  40         146  
  40         2054  
9 40     40   15646 use parent 'Perl::Critic::Policy';
  40         107  
  40         262  
10              
11             our $VERSION = '1.150';
12              
13             #-----------------------------------------------------------------------------
14              
15             Readonly::Array my @POSTFIX_WORDS => qw( if unless for );
16             Readonly::Hash my %POSTFIX_WORDS => hashify( @POSTFIX_WORDS );
17             Readonly::Scalar my $PRINT_RX => qr/ \A (?: print f? | say ) \z /xms;
18              
19             Readonly::Scalar my $DESC => q{File handle for "print" or "printf" is not braced};
20             Readonly::Scalar my $EXPL => [ 217 ];
21              
22             #-----------------------------------------------------------------------------
23              
24 89     89 0 1633 sub supported_parameters { return () }
25 74     74 1 337 sub default_severity { return $SEVERITY_LOWEST }
26 84     84 1 368 sub default_themes { return qw( core pbp cosmetic ) }
27 30     30 1 96 sub applies_to { return 'PPI::Token::Word' }
28              
29             #-----------------------------------------------------------------------------
30              
31             sub violates {
32 329     329 1 556 my ( $self, $elem, undef ) = @_;
33              
34 329 100       879 return if $elem !~ $PRINT_RX;
35 2 50       20 return if ! is_function_call($elem);
36              
37 2         16 my @sib;
38              
39 2         12 $sib[0] = $elem->snext_sibling();
40 2 50       56 return if !$sib[0];
41              
42             # Deal with situations where 'print' is called with parentheses
43 2 50       14 if ( $sib[0]->isa('PPI::Structure::List') ) {
44 0         0 my $expr = $sib[0]->schild(0);
45 0 0       0 return if !$expr;
46 0         0 $sib[0] = $expr->schild(0);
47 0 0       0 return if !$sib[0];
48             }
49              
50 2         15 $sib[1] = $sib[0]->next_sibling();
51 2 50       57 return if !$sib[1];
52 2         10 $sib[2] = $sib[1]->next_sibling();
53 2 50       51 return if !$sib[2];
54              
55             # First token must be a scalar symbol or bareword;
56 2 50 33     15 return if !( ($sib[0]->isa('PPI::Token::Symbol') && $sib[0] =~ m/\A \$/xms)
      33        
57             || $sib[0]->isa('PPI::Token::Word') );
58              
59             # First token must not be a builtin function or control
60 2 50       27 return if is_perl_builtin($sib[0]);
61 2 50       42 return if exists $POSTFIX_WORDS{ $sib[0] };
62              
63             # Second token must be white space
64 2 50       50 return if !$sib[1]->isa('PPI::Token::Whitespace');
65              
66             # Third token must not be an operator
67 2 50       10 return if $sib[2]->isa('PPI::Token::Operator');
68              
69             # Special case for postfix controls
70 2 50       24 return if exists $POSTFIX_WORDS{ $sib[2] };
71              
72 0 0         return if $sib[0]->isa('PPI::Structure::Block');
73              
74 0           return $self->violation( $DESC, $EXPL, $elem );
75             }
76              
77             1;
78              
79             __END__
80              
81             #-----------------------------------------------------------------------------
82              
83             =pod
84              
85             =head1 NAME
86              
87             Perl::Critic::Policy::InputOutput::RequireBracedFileHandleWithPrint - Write C<print {$FH} $foo, $bar;> instead of C<print $FH $foo, $bar;>.
88              
89             =head1 AFFILIATION
90              
91             This Policy is part of the core L<Perl::Critic|Perl::Critic>
92             distribution.
93              
94              
95             =head1 DESCRIPTION
96              
97             The C<print> and C<printf> functions have a unique syntax that
98             supports an optional file handle argument. Conway suggests wrapping
99             this argument in braces to make it visually stand out from the other
100             arguments. When you put braces around any of the special
101             package-level file handles like C<STDOUT>, C<STDERR>, and C<DATA>, you
102             must add the C<'*'> sigil or else it won't compile under C<use strict
103             'subs'>.
104              
105             print $FH "Mary had a little lamb\n"; #not ok
106             print {$FH} "Mary had a little lamb\n"; #ok
107              
108             print STDERR $foo, $bar, $baz; #not ok
109             print {STDERR} $foo, $bar, $baz; #won't compile under 'strict'
110             print {*STDERR} $foo, $bar, $baz; #perfect!
111              
112              
113             =head1 CONFIGURATION
114              
115             This Policy is not configurable except for the standard options.
116              
117              
118             =head1 AUTHOR
119              
120             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
121              
122             =head1 COPYRIGHT
123              
124             Copyright (c) 2005-2011 Imaginative Software Systems. All rights reserved.
125              
126             This program is free software; you can redistribute it and/or modify
127             it under the same terms as Perl itself. The full text of this license
128             can be found in the LICENSE file included with this module.
129              
130             =cut
131              
132             # Local Variables:
133             # mode: cperl
134             # cperl-indent-level: 4
135             # fill-column: 78
136             # indent-tabs-mode: nil
137             # c-indentation-style: bsd
138             # End:
139             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :