File Coverage

blib/lib/PPI/Statement/Compound.pm
Criterion Covered Total %
statement 23 33 69.7
branch 21 38 55.2
condition n/a
subroutine 3 4 75.0
pod 1 1 100.0
total 48 76 63.1


line stmt bran cond sub pod time code
1             package PPI::Statement::Compound;
2              
3             =pod
4              
5             =head1 NAME
6              
7             PPI::Statement::Compound - Describes all compound statements
8              
9             =head1 SYNOPSIS
10              
11             # A compound if statement
12             if ( foo ) {
13             bar();
14             } else {
15             baz();
16             }
17              
18             # A compound loop statement
19             foreach ( @list ) {
20             bar($_);
21             }
22              
23             =head1 INHERITANCE
24              
25             PPI::Statement::Compound
26             isa PPI::Statement
27             isa PPI::Node
28             isa PPI::Element
29              
30             =head1 DESCRIPTION
31              
32             C<PPI::Statement::Compound> objects are used to describe all current forms
33             of compound statements, as described in L<perlsyn>.
34              
35             This covers blocks using C<if>, C<unless>, C<for>, C<foreach>, C<while>,
36             and C<continue>. Please note this does B<not> cover "simple" statements
37             with trailing conditions. Please note also that "do" is also not part of
38             a compound statement.
39              
40             # This is NOT a compound statement
41             my $foo = 1 if $condition;
42              
43             # This is also not a compound statement
44             do { ... } until $condition;
45              
46             =head1 METHODS
47              
48             C<PPI::Statement::Compound> has a number of methods in addition to the
49             standard L<PPI::Statement>, L<PPI::Node> and L<PPI::Element> methods.
50              
51             =cut
52              
53 66     66   362 use strict;
  66         103  
  66         1758  
54 66     66   233 use PPI::Statement ();
  66         88  
  66         29150  
55              
56             our $VERSION = '1.284';
57              
58             our @ISA = "PPI::Statement";
59              
60             # Keyword type map
61             my %TYPES = (
62             'if' => 'if',
63             'unless' => 'if',
64             'while' => 'while',
65             'until' => 'while',
66             'for' => 'for',
67             'foreach' => 'foreach',
68             );
69              
70             # Lexer clues
71             sub __LEXER__normal() { '' }
72              
73              
74              
75              
76              
77             #####################################################################
78             # PPI::Statement::Compound analysis methods
79              
80             =pod
81              
82             =head2 type
83              
84             The C<type> method returns the syntactic type of the compound statement.
85              
86             There are four basic compound statement types.
87              
88             The C<'if'> type includes all variations of the if and unless statements,
89             including any C<'elsif'> or C<'else'> parts of the compound statement.
90              
91             The C<'while'> type describes the standard while and until statements, but
92             again does B<not> describes simple statements with a trailing while.
93              
94             The C<'for'> type covers the C-style for loops, regardless of whether they
95             were declared using C<'for'> or C<'foreach'>.
96              
97             The C<'foreach'> type covers loops that iterate over collections,
98             regardless of whether they were declared using C<'for'> or C<'foreach'>.
99              
100             All of the compounds are a variation on one of these four.
101              
102             Returns the simple string C<'if'>, C<'for'>, C<'foreach'> or C<'while'>,
103             or C<undef> if the type cannot be determined.
104              
105             =cut
106              
107             sub type {
108 6428     6428 1 42858 my $self = shift;
109 6428         8186 my $p = 0; # Child position
110 6428 50       15505 my $Element = $self->schild($p) or return undef;
111              
112             # A labelled statement
113 6428 100       26103 if ( $Element->isa('PPI::Token::Label') ) {
114 732 100       1817 $Element = $self->schild(++$p) or return 'label';
115             }
116              
117             # Most simple cases
118 6060         11440 my $content = $Element->content;
119 6060 100       19615 if ( $content =~ /^for(?:each)?\z/ ) {
120 1406 100       2699 $Element = $self->schild(++$p) or return $content;
121 1104 100       3083 if ( $Element->isa('PPI::Token') ) {
122 967 100       1612 return 'foreach' if $Element->content =~ /^(?:my|our|state)\z/;
123 141 100       584 return 'foreach' if $Element->isa('PPI::Token::Symbol');
124 26 50       118 return 'foreach' if $Element->isa('PPI::Token::QuoteLike::Words');
125             }
126 137 100       322 if ( $Element->isa('PPI::Structure::List') ) {
127 86         265 return 'foreach';
128             }
129 51         153 return 'for';
130             }
131             return {
132             %TYPES,
133             ( try => 'try' ) x !!$self->presumed_features->{try},
134 4654 100       28687 }->{$content}
135             if $Element->isa('PPI::Token::Word');
136 184 50       1320 return 'continue' if $Element->isa('PPI::Structure::Block');
137              
138             # Unknown (shouldn't exist?)
139 0           undef;
140             }
141              
142              
143              
144              
145              
146             #####################################################################
147             # PPI::Node Methods
148              
149             sub scope() { 1 }
150              
151              
152              
153              
154              
155             #####################################################################
156             # PPI::Element Methods
157              
158             sub _complete {
159 0     0     my $self = shift;
160 0 0         my $type = $self->type or die "Illegal compound statement type";
161              
162             # Check the different types of compound statements
163 0 0         if ( $type eq 'if' ) {
    0          
164             # Unless the last significant child is a complete
165             # block, it must be incomplete.
166 0 0         my $child = $self->schild(-1) or return '';
167 0 0         $child->isa('PPI::Structure') or return '';
168 0 0         $child->braces eq '{}' or return '';
169 0 0         $child->_complete or return '';
170              
171             # It can STILL be
172             } elsif ( $type eq 'while' ) {
173 0           die "CODE INCOMPLETE";
174             } else {
175 0           die "CODE INCOMPLETE";
176             }
177             }
178              
179             1;
180              
181             =pod
182              
183             =head1 TO DO
184              
185             - Write unit tests for this package
186              
187             =head1 SUPPORT
188              
189             See the L<support section|PPI/SUPPORT> in the main module.
190              
191             =head1 AUTHOR
192              
193             Adam Kennedy E<lt>adamk@cpan.orgE<gt>
194              
195             =head1 COPYRIGHT
196              
197             Copyright 2001 - 2011 Adam Kennedy.
198              
199             This program is free software; you can redistribute
200             it and/or modify it under the same terms as Perl itself.
201              
202             The full text of the license can be found in the
203             LICENSE file included with this module.
204              
205             =cut