File Coverage

blib/lib/File/PackageIndexer/PPI/Inheritance.pm
Criterion Covered Total %
statement 75 79 94.9
branch 31 46 67.3
condition 18 33 54.5
subroutine 7 7 100.0
pod 0 2 0.0
total 131 167 78.4


line stmt bran cond sub pod time code
1             package File::PackageIndexer::PPI::Inheritance;
2              
3 9     9   145 use 5.008001;
  9         28  
  9         394  
4 9     9   68 use strict;
  9         17  
  9         267  
5 9     9   48 use warnings;
  9         17  
  9         7540  
6              
7             our $VERSION = '0.01';
8              
9              
10             # The base case
11             sub handle_base {
12 44     44 0 54 my $indexer = shift;
13 44         53 my $statement = shift;
14 44         55 my $curpkg = shift;
15 44         54 my $pkgs = shift;
16 44 50       95 if (not defined $curpkg) {
17 0         0 $curpkg = $indexer->lazy_create_pkg($indexer->default_package, $pkgs);
18             }
19              
20 44         121 my $list_start = $statement->schild(0)->snext_sibling;
21 44         1386 my $classes = File::PackageIndexer::PPI::Util::list_structure_to_array($list_start);
22              
23             return
24 44 50 33     245 if not defined $classes or ref($classes) ne 'ARRAY';
25              
26             # remove options if 'parent'
27 44 100       118 if ($list_start->content() eq 'parent') {
28 18         152 @$classes = grep $_ !~ /^-/, @$classes;
29             }
30              
31 44 50 33     346 push @{$curpkg->{begin_isa}}, @$classes
  44         111  
32             if defined $classes and ref($classes) eq 'ARRAY';
33              
34 44         242 return 1;
35             }
36              
37             # assumes that the statement contains @ISA somehow!
38             sub handle_isa {
39 85     85 0 113 my $indexer = shift;
40 85         129 my $statement = shift;
41 85         90 my $curpkg = shift;
42 85         89 my $pkgs = shift;
43 85         107 my $in_scheduled_block = shift;
44              
45             # skip if @ISA is modified in END block.
46             return
47 85 100 66     407 if defined $in_scheduled_block and $in_scheduled_block eq 'END';
48              
49             return
50 82 50       292 unless $statement->isa("PPI::Statement");
51              
52 82         211 my $child = $statement->schild(0);
53 82 50       974 return if not $child;
54              
55             # push/unshift @ISA...
56 82 100 100     526 if ($child->isa("PPI::Token::Word") and $child->content =~ /^(?:unshift|push)$/) {
    100          
    50          
57 45         429 _handle_extend($indexer, $statement, $curpkg, $pkgs, $in_scheduled_block);
58             }
59             # our @ISA ...
60             elsif ( $statement->isa("PPI::Statement::Variable") ) {
61 21 50 33     260 if ( $statement->type eq 'our'
      33        
62             and $statement->variables
63             and ($statement->variables)[0] eq '@ISA' )
64             {
65             # declare and assign can probably be handled by the same code
66 21         2744 _handle_assign($indexer, $statement, $curpkg, $pkgs, $in_scheduled_block);
67             }
68             # else: do nothing. my/local shouldn't be used for @ISA!
69             }
70             # @ISA = ...
71             # could this be done more elegantly?
72             elsif (
73             $statement->content =~ /\@ISA\s*\)?\s*=/
74             ) {
75 16         981 _handle_assign($indexer, $statement, $curpkg, $pkgs, $in_scheduled_block);
76             }
77            
78             }
79              
80              
81             sub _handle_extend {
82 45     45   90 my $indexer = shift;
83 45         56 my $statement = shift;
84 45         59 my $curpkg = shift;
85 45         48 my $pkgs = shift;
86 45         66 my $in_scheduled_block = shift;
87              
88 45 50       106 if (not defined $curpkg) {
89 0         0 $curpkg = $indexer->lazy_create_pkg($indexer->default_package, $pkgs);
90             }
91              
92 45         123 my $child = $statement->schild(0);
93 45         527 my $type = $child->content;
94              
95             # $child = $child->snext_sibling;
96             # return unless defined $child;
97 45         260 my $arguments = File::PackageIndexer::PPI::Util::list_structure_to_array($child);
98             return
99 45 50 33     369 unless defined $arguments
      33        
100             and @$arguments
101             and $arguments->[0] eq '@ISA';
102 45         65 shift @$arguments;
103              
104 45 100       182 if ($type eq 'push') {
    50          
105 26 100       36 push @{ $in_scheduled_block eq 'BEGIN' ? $curpkg->{begin_isa} : $curpkg->{isa_push} }, @$arguments;
  26         119  
106             }
107             elsif ($type eq 'unshift') {
108 19 50       25 unshift @{ $in_scheduled_block eq 'BEGIN' ? $curpkg->{begin_isa} : $curpkg->{isa_unshift} }, @$arguments;
  19         85  
109             }
110             else {
111 0         0 die "Unknown operation on \@ISA: '$type'";
112             }
113              
114 45         308 return();
115             }
116              
117              
118             # either "our @ISA" or "@ISA ="
119             sub _handle_assign {
120 37     37   64 my $indexer = shift;
121 37         51 my $statement = shift;
122 37         49 my $curpkg = shift;
123 37         51 my $pkgs = shift;
124 37         51 my $in_scheduled_block = shift;
125              
126 37 50       83 if (not defined $curpkg) {
127 0         0 $curpkg = $indexer->lazy_create_pkg($indexer->default_package, $pkgs);
128             }
129              
130 37         113 my $child = $statement->schild(0);
131 37 50       442 return unless $child;
132            
133             # skip until =
134 37   100     433 $child = $child->snext_sibling()
      66        
135             while $child
136             and not $child->isa("PPI::Token::Operator")
137             and not $child->content eq '=';
138 37 100       2746 return unless $child;
139              
140 19         79 my $arguments = File::PackageIndexer::PPI::Util::list_structure_to_array($child);
141              
142             return
143 19 50       48 unless defined $arguments;
144              
145 19 100 66     98 if ($in_scheduled_block and $in_scheduled_block ne 'END') {
    50          
146 8         51 @{ $curpkg->{begin_isa} } = @$arguments;
  8         26  
147 8         23 $curpkg->{isa_cleared_at_compiletime} = 1;
148             }
149             elsif(!$in_scheduled_block) {
150 11         17 @{ $curpkg->{isa_push} } = @$arguments;
  11         36  
151 11         15 @{ $curpkg->{isa_unshift} } = ();
  11         25  
152 11         45 $curpkg->{isa_cleared_at_runtime} = 1;
153             }
154             else {
155             # END, skip
156             }
157              
158 19         164 return();
159             }
160              
161             1;
162              
163             __END__