Login
More self compliance
[gknop/Perl-Critic.git] / lib / Perl / Critic / Policy / CodeLayout / ProhibitParensWithBuiltins.pm
CommitLineData
6036a254 1##############################################################################
dff08b70
JRT
2# $URL$
3# $Date$
4# $Author$
5# $Revision$
6036a254 6##############################################################################
dff08b70 7
59b05e08
JRT
8package Perl::Critic::Policy::CodeLayout::ProhibitParensWithBuiltins;
9
df6dee2b 10use 5.006001;
59b05e08
JRT
11use strict;
12use warnings;
c680a9c9
ES
13use Readonly;
14
bbf4108c 15use Perl::Critic::Utils qw{
248401aa 16 :booleans :severities :data_conversion :classification :language
bbf4108c 17};
59b05e08
JRT
18use base 'Perl::Critic::Policy';
19
173667ce 20our $VERSION = '1.093_01';
59b05e08 21
6036a254 22#-----------------------------------------------------------------------------
dff08b70 23
c680a9c9
ES
24Readonly::Array my @ALLOW => qw( my our local return );
25Readonly::Hash my %ALLOW => hashify( @ALLOW );
8aee85bd 26
c296c678 27Readonly::Scalar my $DESC => q{Builtin function called with parentheses};
c680a9c9 28Readonly::Scalar my $EXPL => [ 13 ];
59b05e08 29
8df8213a
CD
30Readonly::Scalar my $PRECENDENCE_OF_LIST => precedence_of(q{>>}) + 1;
31Readonly::Scalar my $PRECEDENCE_OF_COMMA => precedence_of(q{,});
32
6036a254 33#-----------------------------------------------------------------------------
a7753069 34# These are all the functions that are considered named unary
c296c678 35# operators. These frequently require parentheses because they have lower
a7753069
JRT
36# precedence than ordinary function calls.
37
c680a9c9 38Readonly::Array my @NAMED_UNARY_OPS => qw(
a91b8a46
AL
39 alarm glob rand
40 caller gmtime readlink
41 chdir hex ref
42 chroot int require
43 cos lc return
44 defined lcfirst rmdir
45 delete length scalar
46 do localtime sin
47 eval lock sleep
48 exists log sqrt
49 exit lstat srand
50 getgrp my stat
51 gethostbyname oct uc
52 getnetbyname ord ucfirst
53 getprotobyname quotemeta umask
54 undef
a7753069 55);
c680a9c9 56Readonly::Hash my %NAMED_UNARY_OPS => hashify( @NAMED_UNARY_OPS );
a7753069 57
6036a254 58#-----------------------------------------------------------------------------
59b05e08 59
e178fe38 60sub supported_parameters { return () }
c680a9c9
ES
61sub default_severity { return $SEVERITY_LOWEST }
62sub default_themes { return qw( core pbp cosmetic ) }
63sub applies_to { return 'PPI::Token::Word' }
dff08b70 64
6036a254 65#-----------------------------------------------------------------------------
bf159007 66
59b05e08 67sub violates {
e5f6c18d
AL
68 my ( $self, $elem, undef ) = @_;
69
c680a9c9 70 return if exists $ALLOW{$elem};
8aee85bd
JRT
71 return if not is_perl_builtin($elem);
72 return if not is_function_call($elem);
a7753069 73
248401aa
ES
74 my $sibling = $elem->snext_sibling();
75 return if not $sibling;
76 if ( $sibling->isa('PPI::Structure::List') ) {
77 my $elem_after_parens = $sibling->snext_sibling();
a7753069 78
248401aa
ES
79 return if _is_named_unary_exemption($elem, $elem_after_parens);
80 return if _is_precedence_exemption($elem_after_parens);
81 return if _is_equals_exemption($sibling);
82 return if _is_sort_exemption($elem, $sibling);
a7753069 83
248401aa
ES
84 # If we get here, it must be a violation
85 return $self->violation( $DESC, $EXPL, $elem );
86 }
87 return; #ok!
88}
a7753069 89
248401aa 90#-----------------------------------------------------------------------------
a7753069 91
248401aa
ES
92# EXCEPTION 1: If the function is a named unary and there is an
93# operator with higher precedence right after the parentheses.
94# Example: int( 1.5 ) + 0.5;
a7753069 95
248401aa
ES
96sub _is_named_unary_exemption {
97 my ($elem, $elem_after_parens) = @_;
a7753069 98
248401aa
ES
99 if ( _is_named_unary( $elem ) && $elem_after_parens ){
100 # Smaller numbers mean higher precedence
101 my $precedence = precedence_of( $elem_after_parens );
102 return $TRUE if defined $precedence && $precedence < $PRECENDENCE_OF_LIST;
103 }
a7753069 104
248401aa
ES
105 return $FALSE;
106}
a7753069 107
248401aa
ES
108sub _is_named_unary {
109 my ($elem) = @_;
0f0af79d 110
248401aa 111 return exists $NAMED_UNARY_OPS{$elem->content};
59b05e08
JRT
112}
113
a7753069
JRT
114#-----------------------------------------------------------------------------
115
248401aa
ES
116# EXCEPTION 2, If there is an operator immediately after the
117# parentheses, and that operator has precedence greater than
118# or equal to a comma.
119# Example: join($delim, @list) . "\n";
120
121sub _is_precedence_exemption {
122 my ($elem_after_parens) = @_;
123
124 if ( $elem_after_parens ){
125 # Smaller numbers mean higher precedence
126 my $precedence = precedence_of( $elem_after_parens );
127 return $TRUE if defined $precedence && $precedence <= $PRECEDENCE_OF_COMMA;
128 }
129
130 return $FALSE;
131}
132
133# EXCEPTION 3: If the first operator within the parentheses is '='
134# Example: chomp( my $foo = <STDIN> );
135
136sub _is_equals_exemption {
137 my ($sibling) = @_;
138
139 if ( my $first_op = $sibling->find_first('PPI::Token::Operator') ){
140 return $TRUE if $first_op eq q{=};
141 }
142
143 return $FALSE;
144}
145
146# EXCEPTION 4: sort with default comparator but a function for the list data
147# Example: sort(foo(@x))
148
149sub _is_sort_exemption {
150 my ($elem, $sibling) = @_;
151
152 if ( $elem eq 'sort' ) {
153 my $first_arg = $sibling->schild(0);
154 if ( $first_arg && $first_arg->isa('PPI::Statement::Expression') ) {
155 $first_arg = $first_arg->schild(0);
156 }
157 if ( $first_arg && $first_arg->isa('PPI::Token::Word') ) {
158 my $next_arg = $first_arg->snext_sibling;
159 return $TRUE if $next_arg && $next_arg->isa('PPI::Structure::List');
160 }
161 }
162
163 return $FALSE;
a7753069
JRT
164}
165
59b05e08
JRT
1661;
167
168__END__
169
a7753069
JRT
170#-----------------------------------------------------------------------------
171
dff08b70
JRT
172=pod
173
0fc740da 174=for stopwords disambiguates builtins
4c0ca345 175
59b05e08
JRT
176=head1 NAME
177
9c338374 178Perl::Critic::Policy::CodeLayout::ProhibitParensWithBuiltins - Write C<open $handle, $path> instead of C<open($handle, $path)>.
59b05e08 179
11f53956 180
af93c316
ES
181=head1 AFFILIATION
182
11f53956
ES
183This Policy is part of the core L<Perl::Critic|Perl::Critic>
184distribution.
af93c316
ES
185
186
59b05e08
JRT
187=head1 DESCRIPTION
188
40b4a6ae
AL
189Conway suggests that all built-in functions be called without
190parentheses around the argument list. This reduces visual clutter and
59b05e08 191disambiguates built-in functions from user functions. Exceptions are
40b4a6ae 192made for C<my>, C<local>, and C<our> which require parentheses when
a7753069 193called with multiple arguments.
59b05e08 194
11f53956
ES
195 open($handle, '>', $filename); #not ok
196 open $handle, '>', $filename; #ok
59b05e08 197
11f53956
ES
198 split(/$pattern/, @list); #not ok
199 split /$pattern/, @list; #ok
59b05e08 200
0cb729f0
ES
201
202=head1 CONFIGURATION
203
49860482 204This Policy is not configurable except for the standard options.
0cb729f0
ES
205
206
a7753069
JRT
207=head1 NOTES
208
c296c678 209Coding with parentheses can sometimes lead to verbose and awkward
a7753069 210constructs, so I think the intent of Conway's guideline is to remove
c296c678
ES
211only the F<unnecessary> parentheses. This policy makes exceptions for
212some common situations where parentheses are usually required.
213However, you may find other situations where the parentheses are
214necessary to enforce precedence, but they cause still violations. In
215those cases, consider using the '## no critic' comments to silence
216Perl::Critic.
a7753069 217
11f53956 218
5931cd9b
ES
219=head1 BUGS
220
221Some builtin functions (particularly those that take a variable number
222of scalar arguments) should probably get parentheses. This policy
223should be enhanced to allow the user to specify a list of builtins
224that are exempt from the policy.
225
226
59b05e08
JRT
227=head1 AUTHOR
228
229Jeffrey Ryan Thalhammer <thaljef@cpan.org>
230
11f53956 231
dff08b70
JRT
232=head1 COPYRIGHT
233
20dfddeb 234Copyright (c) 2005-2008 Jeffrey Ryan Thalhammer. All rights reserved.
59b05e08
JRT
235
236This program is free software; you can redistribute it and/or modify
237it under the same terms as Perl itself. The full text of this license
238can be found in the LICENSE file included with this module.
dff08b70
JRT
239
240=cut
737d3b65
CD
241
242# Local Variables:
243# mode: cperl
244# cperl-indent-level: 4
245# fill-column: 78
246# indent-tabs-mode: nil
247# c-indentation-style: bsd
248# End:
96fed375 249# ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :