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__ |