| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Perl::Critic::Policy::References::ProhibitRefChecks; |
|
2
|
|
|
|
|
|
|
|
|
3
|
5
|
|
|
5
|
|
3903
|
use 5.010001; |
|
|
5
|
|
|
|
|
20
|
|
|
4
|
5
|
|
|
5
|
|
28
|
use strict; |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
114
|
|
|
5
|
5
|
|
|
5
|
|
19
|
use warnings; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
201
|
|
|
6
|
5
|
|
|
5
|
|
30
|
use Readonly; |
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
290
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
5
|
|
|
5
|
|
37
|
use Perl::Critic::Utils qw/:severities :classification precedence_of/; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
322
|
|
|
9
|
5
|
|
|
5
|
|
2065
|
use base 'Perl::Critic::Policy'; |
|
|
5
|
|
|
|
|
42
|
|
|
|
5
|
|
|
|
|
5331
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.0.7'; |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
Readonly::Scalar my $DESC => q{Do not perform manual ref checks}; |
|
14
|
|
|
|
|
|
|
Readonly::Scalar my $EXPL => undef; # [ ]; |
|
15
|
|
|
|
|
|
|
Readonly::Scalar my $UPREC => precedence_of('-e'); # named unary function precedence |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
####----------------------------------------------------------------------------- |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub supported_parameters { |
|
20
|
|
|
|
|
|
|
return ( |
|
21
|
|
|
|
|
|
|
{ |
|
22
|
11
|
|
|
11
|
0
|
495415
|
name => 'eq', |
|
23
|
|
|
|
|
|
|
description => 'Reference types that may be checked via string equality.', |
|
24
|
|
|
|
|
|
|
default_string => '', |
|
25
|
|
|
|
|
|
|
behavior => 'string list', |
|
26
|
|
|
|
|
|
|
}, |
|
27
|
|
|
|
|
|
|
{ |
|
28
|
|
|
|
|
|
|
name => 'ne', |
|
29
|
|
|
|
|
|
|
description => 'Reference types that may be checked via string inequality.', |
|
30
|
|
|
|
|
|
|
default_string => '', |
|
31
|
|
|
|
|
|
|
behavior => 'string list', |
|
32
|
|
|
|
|
|
|
}, |
|
33
|
|
|
|
|
|
|
{ |
|
34
|
|
|
|
|
|
|
name => 'regexp', |
|
35
|
|
|
|
|
|
|
description => 'Permit regular expression comparisons.', |
|
36
|
|
|
|
|
|
|
default_string => '0', |
|
37
|
|
|
|
|
|
|
behavior => 'boolean', |
|
38
|
|
|
|
|
|
|
}, |
|
39
|
|
|
|
|
|
|
{ |
|
40
|
|
|
|
|
|
|
name => 'bareref', |
|
41
|
|
|
|
|
|
|
description => 'Permit a bare if(ref) style check.', |
|
42
|
|
|
|
|
|
|
default_string => '0', |
|
43
|
|
|
|
|
|
|
behavior => 'boolean', |
|
44
|
|
|
|
|
|
|
}, |
|
45
|
|
|
|
|
|
|
); |
|
46
|
|
|
|
|
|
|
} |
|
47
|
|
|
|
|
|
|
|
|
48
|
7818
|
|
|
7818
|
1
|
58989257
|
sub applies_to { return 'PPI::Token::Word' } |
|
49
|
5768
|
|
|
5768
|
1
|
78497
|
sub default_severity { return $SEVERITY_MEDIUM } |
|
50
|
1
|
|
|
1
|
1
|
3056
|
sub default_themes { return qw/cosmetic maintenance performance/ } |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub invalid { |
|
55
|
5768
|
|
|
5768
|
0
|
17945
|
my ($self,$elem,$note)=@_; |
|
56
|
5768
|
|
100
|
|
|
18275
|
$note//=''; |
|
57
|
5768
|
100
|
|
|
|
17640
|
if($note) { $note=" ($note)" } |
|
|
5767
|
|
|
|
|
13487
|
|
|
58
|
5768
|
|
|
|
|
33739
|
return $self->violation(sprintf("%s%s",$DESC,$note),$EXPL,$elem); |
|
59
|
|
|
|
|
|
|
} |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub eqne { |
|
62
|
9225
|
|
|
9225
|
0
|
238168
|
my ($node)=@_; |
|
63
|
9225
|
100
|
|
|
|
33225
|
if(!$node) { return } |
|
|
6916
|
|
|
|
|
25807
|
|
|
64
|
2309
|
100
|
|
|
|
14246
|
if(!$node->isa('PPI::Token::Operator')) { return } |
|
|
1
|
|
|
|
|
5
|
|
|
65
|
2308
|
|
|
|
|
7172
|
my $op=$node->content(); |
|
66
|
2308
|
100
|
100
|
|
|
22829
|
if(($op eq 'eq')||($op eq 'ne')) { return 1 } |
|
|
257
|
|
|
|
|
870
|
|
|
67
|
2051
|
|
|
|
|
7707
|
return; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub decompose { |
|
71
|
9000
|
|
|
9000
|
0
|
1896460
|
my ($elem)=@_; |
|
72
|
9000
|
|
|
|
|
23787
|
my %operator=map {$_=>undef} (qw/eq ne !~ =~ cmp/); |
|
|
45000
|
|
|
|
|
131088
|
|
|
73
|
9000
|
|
|
|
|
29411
|
my ($node,$operator,$rhs)=($elem,undef,undef); |
|
74
|
9000
|
|
|
|
|
45406
|
while($node) { |
|
75
|
31620
|
100
|
100
|
|
|
714065
|
if($node->isa('PPI::Token::Operator') && exists($operator{$node->content()})) { |
|
|
|
100
|
100
|
|
|
|
|
|
76
|
7964
|
|
|
|
|
52234
|
$operator=$node->content(); |
|
77
|
7964
|
|
|
|
|
38531
|
$rhs=$node->snext_sibling(); |
|
78
|
7964
|
|
|
|
|
295249
|
$node=0; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
516
|
|
|
|
|
18639
|
elsif($node->isa('PPI::Token::Operator') && (precedence_of($node)>$UPREC)) { $node=0 } |
|
81
|
23140
|
|
|
|
|
139526
|
else { $node=$node->snext_sibling() } |
|
82
|
|
|
|
|
|
|
} |
|
83
|
9000
|
100
|
|
|
|
46325
|
if(!$rhs) { return ($operator) } |
|
|
1036
|
|
|
|
|
4579
|
|
|
84
|
7964
|
100
|
|
|
|
34590
|
if($rhs->isa('PPI::Token::Quote')) { return ($operator,lc($rhs->string())) } |
|
|
6927
|
|
|
|
|
31441
|
|
|
85
|
1037
|
100
|
66
|
|
|
4947
|
if($rhs->isa('PPI::Token::Word') && ($rhs->content() eq 'ref')) { return ($operator,'ref') } |
|
|
260
|
|
|
|
|
2372
|
|
|
86
|
777
|
|
|
|
|
2130
|
return ($operator,$rhs->content()); |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub violates { |
|
90
|
13576
|
|
|
13576
|
1
|
1240413
|
my ($self,$elem,undef)=@_; |
|
91
|
13576
|
100
|
|
|
|
72290
|
if(!$elem->isa('PPI::Token::Word')) { return } |
|
|
1
|
|
|
|
|
10
|
|
|
92
|
13575
|
100
|
|
|
|
59787
|
if(!is_perl_builtin($elem)) { return } |
|
|
4345
|
|
|
|
|
134870
|
|
|
93
|
9230
|
100
|
|
|
|
327492
|
if(!is_function_call($elem)) { return } |
|
|
2
|
|
|
|
|
307
|
|
|
94
|
9228
|
100
|
|
|
|
2693933
|
if($elem->content() ne 'ref') { return } |
|
|
3
|
|
|
|
|
48
|
|
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# Already handled. |
|
97
|
|
|
|
|
|
|
# No support for ('quoted' eq ref($x)) at this time. |
|
98
|
9225
|
100
|
|
|
|
66033
|
if(eqne($elem->sprevious_sibling())){ return } |
|
|
257
|
|
|
|
|
864
|
|
|
99
|
|
|
|
|
|
|
|
|
100
|
8968
|
|
50
|
|
|
33157
|
$$self{_eq} //={}; |
|
101
|
8968
|
|
50
|
|
|
28708
|
$$self{_ne} //={}; |
|
102
|
8968
|
|
50
|
|
|
27984
|
$$self{_regexp} //=0; |
|
103
|
8968
|
|
50
|
|
|
31605
|
$$self{_bareref}//=0; |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# Without options, 'ref' should never be called. |
|
106
|
8968
|
100
|
100
|
|
|
16312
|
if(!%{$$self{_eq}} && !%{$$self{_ne}} && !$$self{_regexp} && !$$self{_bareref}) { return $self->invalid($elem) } |
|
|
8968
|
|
100
|
|
|
36114
|
|
|
|
4353
|
|
100
|
|
|
23514
|
|
|
|
1
|
|
|
|
|
5
|
|
|
107
|
|
|
|
|
|
|
|
|
108
|
8967
|
|
|
|
|
26855
|
my ($operator,$rhs)=decompose($elem); |
|
109
|
|
|
|
|
|
|
|
|
110
|
8967
|
100
|
100
|
|
|
145149
|
if(!$operator) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
111
|
1028
|
100
|
|
|
|
3826
|
if(!$$self{_bareref}) { return $self->invalid($elem,'bare ref check') } |
|
|
260
|
|
|
|
|
804
|
|
|
112
|
768
|
|
|
|
|
3364
|
return; |
|
113
|
|
|
|
|
|
|
} |
|
114
|
|
|
|
|
|
|
elsif($operator eq 'eq') { |
|
115
|
3586
|
|
50
|
|
|
15411
|
$$self{_eqfold}//={map {lc($_)=>undef} keys(%{$$self{_eq}//{}})}; |
|
|
4
|
|
100
|
|
|
27
|
|
|
|
6
|
|
|
|
|
36
|
|
|
116
|
3586
|
100
|
|
|
|
13868
|
if(!exists($$self{_eqfold}{$rhs})) { return $self->invalid($elem,$rhs) } |
|
|
2562
|
|
|
|
|
8663
|
|
|
117
|
1024
|
|
|
|
|
4637
|
return; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
elsif($operator eq 'ne') { |
|
120
|
3584
|
|
50
|
|
|
14606
|
$$self{_nefold}//={map {lc($_)=>undef} keys(%{$$self{_ne}//{}})}; |
|
|
2
|
|
100
|
|
|
12
|
|
|
|
5
|
|
|
|
|
30
|
|
|
121
|
3584
|
100
|
|
|
|
16609
|
if(!exists($$self{_nefold}{$rhs})) { return $self->invalid($elem,$rhs) } |
|
|
2560
|
|
|
|
|
9455
|
|
|
122
|
1024
|
|
|
|
|
3945
|
return; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
elsif(($operator eq '=~')||($operator eq '!~')) { |
|
125
|
768
|
100
|
|
|
|
2801
|
if(!$$self{_regexp}) { return $self->invalid($elem,$rhs) } |
|
|
384
|
|
|
|
|
1239
|
|
|
126
|
384
|
|
|
|
|
1246
|
return; |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
else { |
|
129
|
1
|
|
|
|
|
10
|
return $self->invalid($elem,$rhs); |
|
130
|
|
|
|
|
|
|
} |
|
131
|
0
|
|
|
|
|
|
return; |
|
132
|
|
|
|
|
|
|
} |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
1; |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
__END__ |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=pod |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head1 NAME |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
Perl::Critic::Policy::References::ProhibitRefChecks - Write C<is_arrayref($var)> instead of C<ref($var) eq 'ARRAY'>. |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Checking references manually is less efficient that using L<Ref::Util> and prone to typos. |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
if(ref($var) eq 'ARRYA') # oops! |
|
151
|
|
|
|
|
|
|
if(is_arrayref($var)) # ok |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
if(ref($var) ne 'HASH') # no |
|
154
|
|
|
|
|
|
|
if(!is_hashref($var)) # ok |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
if(ref($var)) # no |
|
157
|
|
|
|
|
|
|
if(is_ref($var)) # ok |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=head1 CONFIGURATION |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
Explicit strings may be permitted for checks of the form C<ref(...) eq 'string'>, or C<ref(...) ne 'string'>. Entries are case insensitive and can be the core types or custom modules. |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
[References::ProhibitRefChecks] |
|
164
|
|
|
|
|
|
|
eq = code |
|
165
|
|
|
|
|
|
|
ne = code my::module |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
As a special scenario, checks of the form C<ref(...) eq ref(...)> can be permitted with C<eq = ref>. The same works for C<ne = ref>. |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
Regular expression matches are violations by default. To permit checks of the form C<ref(...) =~ /pattern/> or C<!~>: |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
[References::ProhibitRefChecks] |
|
172
|
|
|
|
|
|
|
regexp = 1 |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Since L<Ref::Util> provides C<is_ref>, in the default configuration the bare C<ref> call is rarely needed. To specifically permit using direct C<ref(...)> calls: |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
[References::ProhibitRefChecks] |
|
177
|
|
|
|
|
|
|
bareref = 1 |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 NOTES |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Comparisons to stored values or constants are not supported: C<ref(...) eq $thing> and C<ref(...) eq HASH()> are violations. |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Lexicographic comparison via C<ref(...) cmp "string"> is a violation. |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
In/equality checks are not bidirectional: C<'HASH' eq ref(...)> will not be considered a violation. |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=head1 BUGS |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
Named unary functions are not separately considered. A call of C<lc(ref $x) eq "array"> is considered a "bare ref check", whereas C<lc ref($x) eq "array"> is considered an "eq ref check". |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=cut |