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 objects are used to describe all current forms
33             of compound statements, as described in L.
34              
35             This covers blocks using C, C, C, C, C,
36             and C. Please note this does B 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 has a number of methods in addition to the
49             standard L, L and L methods.
50              
51             =cut
52              
53 64     64   379 use strict;
  64         117  
  64         1514  
54 64     64   267 use PPI::Statement ();
  64         128  
  64         24547  
55              
56             our $VERSION = '1.276';
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 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 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 if the type cannot be determined.
104              
105             =cut
106              
107             sub type {
108 6201     6201 1 30650 my $self = shift;
109 6201         7278 my $p = 0; # Child position
110 6201 50       11459 my $Element = $self->schild($p) or return undef;
111              
112             # A labelled statement
113 6201 100       19504 if ( $Element->isa('PPI::Token::Label') ) {
114 660 100       1364 $Element = $self->schild(++$p) or return 'label';
115             }
116              
117             # Most simple cases
118 5874         10737 my $content = $Element->content;
119 5874 100       13613 if ( $content =~ /^for(?:each)?\z/ ) {
120 1410 100       3006 $Element = $self->schild(++$p) or return $content;
121 1107 100       2975 if ( $Element->isa('PPI::Token') ) {
122 970 100       1859 return 'foreach' if $Element->content =~ /^my|our|state\z/;
123 141 100       578 return 'foreach' if $Element->isa('PPI::Token::Symbol');
124 26 50       101 return 'foreach' if $Element->isa('PPI::Token::QuoteLike::Words');
125             }
126 137 100       351 if ( $Element->isa('PPI::Structure::List') ) {
127 86         244 return 'foreach';
128             }
129 51         160 return 'for';
130             }
131 4464 100       15049 return $TYPES{$content} if $Element->isa('PPI::Token::Word');
132 153 50       893 return 'continue' if $Element->isa('PPI::Structure::Block');
133              
134             # Unknown (shouldn't exist?)
135 0           undef;
136             }
137              
138              
139              
140              
141              
142             #####################################################################
143             # PPI::Node Methods
144              
145             sub scope() { 1 }
146              
147              
148              
149              
150              
151             #####################################################################
152             # PPI::Element Methods
153              
154             sub _complete {
155 0     0     my $self = shift;
156 0 0         my $type = $self->type or die "Illegal compound statement type";
157              
158             # Check the different types of compound statements
159 0 0         if ( $type eq 'if' ) {
    0          
160             # Unless the last significant child is a complete
161             # block, it must be incomplete.
162 0 0         my $child = $self->schild(-1) or return '';
163 0 0         $child->isa('PPI::Structure') or return '';
164 0 0         $child->braces eq '{}' or return '';
165 0 0         $child->_complete or return '';
166              
167             # It can STILL be
168             } elsif ( $type eq 'while' ) {
169 0           die "CODE INCOMPLETE";
170             } else {
171 0           die "CODE INCOMPLETE";
172             }
173             }
174              
175             1;
176              
177             =pod
178              
179             =head1 TO DO
180              
181             - Write unit tests for this package
182              
183             =head1 SUPPORT
184              
185             See the L in the main module.
186              
187             =head1 AUTHOR
188              
189             Adam Kennedy Eadamk@cpan.orgE
190              
191             =head1 COPYRIGHT
192              
193             Copyright 2001 - 2011 Adam Kennedy.
194              
195             This program is free software; you can redistribute
196             it and/or modify it under the same terms as Perl itself.
197              
198             The full text of the license can be found in the
199             LICENSE file included with this module.
200              
201             =cut