File Coverage

blib/lib/Class/Superclasses.pm
Criterion Covered Total %
statement 107 107 100.0
branch 40 40 100.0
condition 5 5 100.0
subroutine 16 16 100.0
pod 3 3 100.0
total 171 171 100.0


line stmt bran cond sub pod time code
1             package Class::Superclasses;
2              
3 16     16   1061160 use strict;
  16         158  
  16         500  
4 16     16   106 use warnings;
  16         33  
  16         532  
5              
6 16     16   90 use List::Util qw(first);
  16         48  
  16         1750  
7 16     16   8490 use PPI;
  16         2023691  
  16         20144  
8              
9             our $VERSION = '0.08';
10              
11             sub new{
12 16     16 1 3125 my ($class,$doc) = @_,
13             my $self = {};
14              
15 16         50 bless $self,$class;
16            
17 16         121 $self->document($doc);
18            
19 16         44 return $self;
20             }
21              
22             sub superclasses{
23 14     14 1 94 my ($self) = @_;
24 14 100       58 return wantarray ? @{$self->{super}} : $self->{super};
  13         53  
25             }
26              
27             sub document{
28 28     28 1 6308 my ($self,$doc) = @_;
29              
30 28 100       108 if(defined $doc){
31 13         64 $self->{document} = $doc;
32 13         49 $self->{super} = $self->_find_super($doc);
33             }
34              
35 28         2172 return $self;
36             }
37              
38             sub _find_super{
39 18     18   3046 my ($self,$doc) = @_;
40              
41 18 100       151 my $ppi = PPI::Document->new($doc) or die $!;
42 17         58173 my $varref = $ppi->find('PPI::Statement::Variable');
43 17         12283 my @vars = ();
44              
45 17 100       68 if($varref){
46 4         21 @vars = $self->_get_isa_values($varref);
47             }
48            
49 17   100     57 my $baseref = $ppi->find('PPI::Statement::Include') || [];
50 17         10622 my @includes = qw(base parent);
51 17         72 my @base = $self->_get_include_values([grep{my $i = $_->module; grep{ $_ eq $i }@includes }@$baseref]);
  13         63  
  13         774  
  26         107  
52              
53 17         34 my @moose;
54 17         61 my @moose_like_modules = qw(Moose Moo Mouse Mo);
55 17         30 my $is_moose;
56              
57 17         33 for my $base_class ( @{$baseref} ) {
  17         42  
58 13 100   35   96 if ( first{ $base_class->module eq $_ }@moose_like_modules ) {
  35         522  
59              
60 7         177 for my $stmt ( @{ $ppi->find('PPI::Statement') } ) {
  7         17  
61 24         4908 push @moose, $self->_get_moose_values( $stmt );
62             }
63             }
64             }
65              
66 17         406 return [@vars, @base, @moose];
67             }
68              
69             sub _get_moose_values{
70 34     34   28259 my ($self,$elem) = @_;
71              
72 34         59 my @parents;
73              
74 34 100       86 return if $elem->schild(0)->content ne 'extends';
75              
76 12 100       219 if ( $elem->find_any('PPI::Statement::Expression') ) {
    100          
    100          
77 5         1544 push @parents, $self->_parse_expression( $elem );
78             }
79             elsif ( $elem->find_any('PPI::Token::QuoteLike::Words') ) {
80 2         901 push @parents, $self->_parse_quotelike( $elem );
81             }
82             elsif( $elem->find( \&_any_quotes ) ){
83 4         293 push @parents, $self->_parse_quotes( $elem );
84             }
85              
86 12         137 return @parents;
87             }
88              
89             sub _get_include_values{
90 24     24   24622 my ($self, $baseref) = @_;
91 24         117 my @parents;
92              
93             BASE:
94 24         48 for my $base( @{$baseref} ){
  24         103  
95 13         23 my @tmp_array;
96              
97 13 100       65 if( $base->find_any('PPI::Statement::Expression') ){
    100          
    100          
98 8         2931 push @tmp_array, $self->_parse_expression( $base );
99             }
100             elsif( $base->find_any('PPI::Token::QuoteLike::Words') ){
101 1         598 push @tmp_array, $self->_parse_quotelike( $base );
102             }
103             elsif( $base->find( \&_any_quotes ) ){
104 3         277 push @tmp_array, $self->_parse_quotes( $base );
105             }
106              
107 13 100       191 if ( $base->module eq 'parent' ) {
108 6         180 @tmp_array = grep{ $_ ne '-norequire' }@tmp_array;
  13         40  
109             }
110              
111 13         235 push @parents, @tmp_array;
112             }
113              
114 24         76 return @parents;
115             }
116              
117             sub _any_quotes{
118 79     79   13936 my ($parent,$elem) = @_;
119              
120 79 100 100     289 $parent eq $elem->parent and (
121             $elem->isa( 'PPI::Token::Quote::Double' ) or
122             $elem->isa( 'PPI::Token::Quote::Single' )
123             );
124             }
125              
126             sub _get_isa_values{
127 10     10   15914 my ($self,$varref) = @_;
128 10         22 my @parents;
129              
130 10 100       18 for my $variable ( @{ $varref || [] } ) {
  10         50  
131 8         45 my @children = $variable->children();
132            
133 8 100       59 if( grep{$_->content eq '@ISA'}@children ) {
  56         313  
134 7 100       138 if( $variable->find_any('PPI::Token::QuoteLike::Words') ) {
    100          
135 2         683 push @parents, $self->_parse_quotelike($variable);
136             }
137             elsif( $variable->find_any('PPI::Statement::Expression') ) {
138 4         3898 push @parents, $self->_parse_expression($variable);
139             }
140             }
141             }
142              
143 10         564 return @parents;
144             }
145              
146             sub _parse_expression {
147 20     20   8886 my ($self, $variable) = @_;
148              
149 20         149 my $ref = $variable->find( 'PPI::Statement::Expression' );
150 20         9757 my @parents;
151              
152 20         50 for my $expression ( @{$ref} ) {
  20         57  
153 21         130 for my $element( $expression->children ){
154 74 100       669 if( $element->class =~ /^PPI::Token::Quote::/ ) {
155 37         338 push @parents, $element->string;
156             }
157             }
158             }
159              
160 20         184 return @parents;
161             }
162              
163             sub _parse_quotes{
164 7     7   23 my ($self,$variable,$type) = @_;
165            
166 7         15 my @parents;
167            
168 7         40 for my $element( $variable->children ){
169 52         194 my ($type) = $element->class =~ /PPI::Token::Quote::([^:]+)$/;
170              
171 52 100       318 next unless $type;
172              
173 12         45 my $value = $element->string;
174 12         103 push @parents, $value;
175             }
176              
177 7         30 return @parents;
178             }
179              
180             sub _parse_quotelike{
181 11     11   8690 my ($self,$variable) = @_;
182              
183 11         49 my $words = ($variable->find('PPI::Token::QuoteLike::Words'))[0]->[0];
184 11         2809 my $operator = $words->{operator};
185 11         32 my $section_type = $words->{sections}->[0]->{type};
186 11         66 my ($left,$right) = split //, $section_type;
187 11         39 (my $value = $words->content) =~ s~$operator\Q$left\E(.*)\Q$right\E~$1~;
188 11         313 my @parents = split /\s+/, $value;
189              
190 11         52 return @parents;
191             }
192              
193              
194             1;
195              
196             __END__