| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Module::Checkstyle::Check::Label; |
|
2
|
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
13106
|
use strict; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
661
|
|
|
4
|
2
|
|
|
2
|
|
14
|
use warnings; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
83
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
12
|
use Carp qw(croak); |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
321
|
|
|
7
|
2
|
|
|
2
|
|
972
|
use Readonly; |
|
|
2
|
|
|
|
|
2827
|
|
|
|
2
|
|
|
|
|
122
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
2
|
|
|
2
|
|
523
|
use Module::Checkstyle::Util qw(:args :problem); |
|
|
2
|
|
|
|
|
7
|
|
|
|
2
|
|
|
|
|
1202
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
2
|
|
|
2
|
|
13
|
use base qw(Module::Checkstyle::Check); |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
4508
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# The directives we provide |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Readonly my $MATCHES_NAME => 'matches-name'; |
|
16
|
|
|
|
|
|
|
Readonly my $POSITION => 'position'; |
|
17
|
|
|
|
|
|
|
Readonly my $REQUIRE_FOR_BREAK => 'require-for-break'; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub register { |
|
20
|
|
|
|
|
|
|
return ( |
|
21
|
0
|
|
|
0
|
1
|
0
|
'PPI::Token::Label' => \&handle_label, |
|
22
|
|
|
|
|
|
|
'PPI::Statement::Break' => \&handle_break, |
|
23
|
|
|
|
|
|
|
); |
|
24
|
|
|
|
|
|
|
} |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub new { |
|
27
|
3
|
|
|
3
|
1
|
7
|
my ($class, $config) = @_; |
|
28
|
|
|
|
|
|
|
|
|
29
|
3
|
|
|
|
|
22
|
my $self = $class->SUPER::new($config); |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Keep configuration local |
|
32
|
3
|
|
|
|
|
13
|
$self->{$MATCHES_NAME} = as_regexp($config->get_directive($MATCHES_NAME)); |
|
33
|
|
|
|
|
|
|
|
|
34
|
3
|
|
|
|
|
24
|
my $position = $config->get_directive($POSITION); |
|
35
|
3
|
100
|
|
|
|
9
|
if ($position) { |
|
36
|
1
|
50
|
|
|
|
6
|
croak qq/Invalid setting '$position' for directive '$POSITION' in [Label]/ if !is_valid_position($position); |
|
37
|
1
|
|
|
|
|
5
|
$self->{$POSITION} = lc($position); |
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
|
|
40
|
3
|
|
|
|
|
18
|
$self->{$REQUIRE_FOR_BREAK} = as_true($config->get_directive($REQUIRE_FOR_BREAK)); |
|
41
|
|
|
|
|
|
|
|
|
42
|
3
|
|
|
|
|
24
|
return $self; |
|
43
|
|
|
|
|
|
|
} |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub handle_label { |
|
46
|
7
|
|
|
7
|
1
|
27122
|
my ($self, $label, $file) = @_; |
|
47
|
|
|
|
|
|
|
|
|
48
|
7
|
|
|
|
|
13
|
my @problems; |
|
49
|
|
|
|
|
|
|
|
|
50
|
7
|
100
|
|
|
|
32
|
if ($self->{$MATCHES_NAME}) { |
|
51
|
3
|
|
|
|
|
30
|
my ($name) = $label->content() =~ /(.*):$/; |
|
52
|
3
|
100
|
66
|
|
|
37
|
if ($name && $name !~ $self->{$MATCHES_NAME}) { |
|
53
|
1
|
|
|
|
|
27
|
push @problems, new_problem($self->config, $MATCHES_NAME, |
|
54
|
|
|
|
|
|
|
qq(Label '$label' does not match '$self->{$MATCHES_NAME}'), |
|
55
|
|
|
|
|
|
|
$label, $file); |
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
7
|
100
|
|
|
|
71
|
if ($self->{$POSITION}) { |
|
60
|
4
|
|
|
|
|
47
|
my $next = $label->snext_sibling; |
|
61
|
|
|
|
|
|
|
|
|
62
|
4
|
50
|
|
|
|
124
|
if ($self->{$POSITION} eq 'alone') { |
|
63
|
|
|
|
|
|
|
# Find first previous non-whitespace token |
|
64
|
4
|
|
|
|
|
26
|
my $prev = do { |
|
65
|
4
|
|
|
|
|
18
|
my $p = $label->previous_token; |
|
66
|
4
|
|
100
|
|
|
267
|
while ($p && $p->isa('PPI::Token::Whitespace')) { |
|
67
|
4
|
|
|
|
|
87
|
$p = $p->previous_token; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
4
|
|
|
|
|
191
|
$p; |
|
70
|
|
|
|
|
|
|
}; |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# On single line |
|
73
|
4
|
100
|
100
|
|
|
43
|
if (($prev && $prev->location->[0] == $label->location->[0]) or |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
74
|
|
|
|
|
|
|
($next && $next->location->[0] == $label->location->[0])) { |
|
75
|
3
|
|
|
|
|
120
|
push @problems, new_problem($self->config, $POSITION, |
|
76
|
|
|
|
|
|
|
qq(Label '$label' is not on a line by its own), |
|
77
|
|
|
|
|
|
|
$label, $file); |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
else { |
|
81
|
|
|
|
|
|
|
# On same line |
|
82
|
0
|
0
|
0
|
|
|
0
|
if ($next && $next->location->[0] != $label->location->[0]) { |
|
83
|
0
|
|
|
|
|
0
|
push @problems, new_problem($self->config, $POSITION, |
|
84
|
|
|
|
|
|
|
qq(Label '$label' is not on the same line as '$next'), |
|
85
|
|
|
|
|
|
|
$label, $file); |
|
86
|
|
|
|
|
|
|
} |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
7
|
|
|
|
|
80
|
return @problems; |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub handle_break { |
|
94
|
6
|
|
|
6
|
1
|
14717
|
my ($self, $break, $file) = @_; |
|
95
|
|
|
|
|
|
|
|
|
96
|
6
|
|
|
|
|
11
|
my @problems; |
|
97
|
|
|
|
|
|
|
|
|
98
|
6
|
100
|
66
|
|
|
28
|
if ($self->{$REQUIRE_FOR_BREAK} && $break->first_token->content =~ /^last|next|redo$/) { |
|
99
|
|
|
|
|
|
|
# next significan should be word |
|
100
|
5
|
|
|
|
|
187
|
my $next = do { |
|
101
|
5
|
|
|
|
|
22
|
my $n = $break->schild(0)->next_token; |
|
102
|
5
|
|
66
|
|
|
241
|
while ($n && $n->isa('PPI::Token::Whitespace')) { |
|
103
|
2
|
|
|
|
|
14
|
$n = $n->next_token; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
5
|
|
|
|
|
69
|
$n; |
|
106
|
|
|
|
|
|
|
}; |
|
107
|
|
|
|
|
|
|
|
|
108
|
5
|
100
|
66
|
|
|
72
|
if (($next && !$next->isa('PPI::Token::Word')) or |
|
|
|
|
33
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
109
|
|
|
|
|
|
|
($next && $next->isa('PPI::Token::Word') && $next->content =~ /^if|unless$/)) { |
|
110
|
4
|
|
|
|
|
24
|
my $break_type = $break->first_token->content; |
|
111
|
4
|
|
|
|
|
76
|
push @problems, new_problem($self->config, $REQUIRE_FOR_BREAK, |
|
112
|
|
|
|
|
|
|
qq(Break '$break_type' used without a label), |
|
113
|
|
|
|
|
|
|
$break, $file); |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
6
|
|
|
|
|
68
|
return @problems; |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
1; |
|
122
|
|
|
|
|
|
|
__END__ |