line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Perl::Critic::Policy::CognitiveComplexity::ProhibitExcessCognitiveComplexity; |
2
|
8
|
|
|
8
|
|
1129244
|
use strict; |
|
8
|
|
|
|
|
10
|
|
|
8
|
|
|
|
|
186
|
|
3
|
8
|
|
|
8
|
|
37
|
use warnings; |
|
8
|
|
|
|
|
11
|
|
|
8
|
|
|
|
|
165
|
|
4
|
|
|
|
|
|
|
|
5
|
8
|
|
|
8
|
|
550
|
use Readonly; |
|
8
|
|
|
|
|
2965
|
|
|
8
|
|
|
|
|
349
|
|
6
|
8
|
|
|
8
|
|
34
|
use Readonly qw (Scalar); |
|
8
|
|
|
|
|
17
|
|
|
8
|
|
|
|
|
339
|
|
7
|
8
|
|
|
8
|
|
691
|
use Perl::Critic::Utils qw{ :severities :classification :ppi }; |
|
8
|
|
|
|
|
125059
|
|
|
8
|
|
|
|
|
492
|
|
8
|
8
|
|
|
8
|
|
6660
|
use Perl::Critic::Violation; |
|
8
|
|
|
|
|
108165
|
|
|
8
|
|
|
|
|
268
|
|
9
|
8
|
|
|
8
|
|
69
|
use base 'Perl::Critic::Policy'; |
|
8
|
|
|
|
|
11
|
|
|
8
|
|
|
|
|
4429
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
Scalar my $EXPL => q{Avoid code that is nested, and thus difficult to grasp.}; |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub supported_parameters { |
16
|
|
|
|
|
|
|
return ( { |
17
|
7
|
|
|
7
|
0
|
50508
|
name => 'warn_level', |
18
|
|
|
|
|
|
|
description => 'The complexity score allowed before warning starts.', |
19
|
|
|
|
|
|
|
default_string => '10', |
20
|
|
|
|
|
|
|
behavior => 'integer', |
21
|
|
|
|
|
|
|
integer_minimum => 1, |
22
|
|
|
|
|
|
|
}, |
23
|
|
|
|
|
|
|
{ |
24
|
|
|
|
|
|
|
name => 'info_level', |
25
|
|
|
|
|
|
|
description => 'The complexity score allowed before informational reporting starts.', |
26
|
|
|
|
|
|
|
default_string => '1', |
27
|
|
|
|
|
|
|
behavior => 'integer', |
28
|
|
|
|
|
|
|
integer_minimum => 1, |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
); |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub default_severity { |
34
|
1
|
|
|
1
|
1
|
12
|
return $SEVERITY_MEDIUM; |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub default_themes { |
38
|
0
|
|
|
0
|
1
|
0
|
return qw( complexity maintenance ); |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub applies_to { |
42
|
7
|
|
|
7
|
1
|
64261
|
return 'PPI::Statement::Sub'; |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub violates { |
46
|
7
|
|
|
7
|
1
|
127
|
my ( $self, $elem, undef ) = @_; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# only report complexity for named subs. |
49
|
7
|
50
|
|
|
|
33
|
my $name = $elem->name() or return; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# start with complexity of 0 |
52
|
7
|
|
|
|
|
184
|
my $block = $elem->find_first('PPI::Structure::Block'); |
53
|
7
|
|
|
|
|
1883
|
my $score = $self->nested_complexity($block , 0); |
54
|
|
|
|
|
|
|
|
55
|
7
|
100
|
|
|
|
35
|
return if($score < $self->{'_info_level'}); |
56
|
5
|
|
|
|
|
14
|
return ($self->new_violation($elem, $score)); |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub new_violation { |
60
|
5
|
|
|
5
|
0
|
8
|
my $self = shift; |
61
|
5
|
|
|
|
|
9
|
my ($elem, $score) = @_; |
62
|
5
|
|
|
|
|
17
|
my $name = $elem->name(); |
63
|
5
|
|
|
|
|
95
|
my $desc = qq<Subroutine '$name' with complexity score of '$score'>; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
return Perl::Critic::Violation->new( $desc, $EXPL, $elem, |
66
|
5
|
100
|
|
|
|
72
|
($score >= $self->{'_warn_level'} ? $self->get_severity() : $SEVERITY_LOWEST )); |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub nested_complexity { |
70
|
194
|
|
|
194
|
0
|
161
|
my $self = shift; |
71
|
194
|
|
|
|
|
157
|
my ( $elem, $nesting ) = @_; |
72
|
|
|
|
|
|
|
|
73
|
194
|
100
|
|
|
|
735
|
return 0 unless ( $elem->can('schildren') ); |
74
|
|
|
|
|
|
|
|
75
|
78
|
|
|
|
|
79
|
my $complexity = 0; |
76
|
|
|
|
|
|
|
|
77
|
78
|
|
|
|
|
112
|
for my $child ( $elem->schildren() ) { |
78
|
|
|
|
|
|
|
#my $inc = 0; |
79
|
187
|
100
|
100
|
|
|
2156
|
if ( $child->isa('PPI::Structure::Given') |
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
80
|
|
|
|
|
|
|
|| $child->isa('PPI::Structure::Condition') |
81
|
|
|
|
|
|
|
|| $child->isa('PPI::Structure::For') |
82
|
|
|
|
|
|
|
) |
83
|
|
|
|
|
|
|
{ |
84
|
11
|
100
|
|
|
|
92
|
if($self->nesting_increase($child->parent)) { |
85
|
7
|
|
|
|
|
11
|
$complexity += $nesting; |
86
|
|
|
|
|
|
|
} else { |
87
|
|
|
|
|
|
|
# missing compound statement / increment on postfix operators |
88
|
4
|
|
|
|
|
4
|
$complexity += $nesting + 1; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
# 'return' is a break-statement, but does not count in terms of cognitive complexity. |
92
|
|
|
|
|
|
|
elsif ( $child->isa('PPI::Statement::Break') && ! $self->is_return_statement($child)) { |
93
|
1
|
|
|
|
|
11
|
$complexity++; |
94
|
|
|
|
|
|
|
} |
95
|
187
|
|
|
|
|
336
|
$complexity += $self->nested_complexity( $child, $nesting + $self->nesting_increase($child) ); |
96
|
|
|
|
|
|
|
} |
97
|
78
|
|
|
|
|
112
|
return $complexity; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub is_return_statement { |
101
|
6
|
|
|
6
|
0
|
9
|
my $self = shift; |
102
|
6
|
|
|
|
|
8
|
my ($child) = @_; |
103
|
6
|
|
|
22
|
|
27
|
scalar $child->find( sub { $_[1]->content eq 'return' }); |
|
22
|
|
|
|
|
179
|
|
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub nesting_increase { |
107
|
198
|
|
|
198
|
0
|
200
|
my $self = shift; |
108
|
198
|
|
|
|
|
159
|
my ($child) = @_; |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# if/when/for... |
111
|
198
|
100
|
|
|
|
493
|
return 1 if ($child->isa('PPI::Statement::Compound')); |
112
|
186
|
100
|
|
|
|
401
|
return 1 if ($child->isa('PPI::Statement::Given')); |
113
|
|
|
|
|
|
|
# anonymous sub |
114
|
184
|
100
|
100
|
366
|
|
546
|
return 1 if ($child->isa('PPI::Statement') && $child->find( sub { $_[1]->content eq 'sub' })); |
|
366
|
|
|
|
|
3422
|
|
115
|
|
|
|
|
|
|
|
116
|
183
|
|
|
|
|
711
|
return 0; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
1; |