File Coverage

blib/lib/Devel/PerlySense/CallTree.pm
Criterion Covered Total %
statement 60 60 100.0
branch 4 4 100.0
condition 2 2 100.0
subroutine 16 16 100.0
pod 0 4 0.0
total 82 86 95.3


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Devel::PerlySense::CallTree - A tree of method calls
4              
5             =head1 DESCRIPTION
6              
7              
8             =cut
9              
10             package Devel::PerlySense::CallTree;
11             $Devel::PerlySense::CallTree::VERSION = '0.0218';
12 69     69   243 use strict;
  69         83  
  69         1730  
13 69     69   220 use warnings;
  69         87  
  69         1381  
14 69     69   202 use utf8;
  69         85  
  69         282  
15              
16 69     69   30807 use Moo;
  69         511462  
  69         303  
17 69     69   68558 use Path::Tiny;
  69         105  
  69         3165  
18 69     69   32431 use List::AllUtils qw/ min /;
  69         790674  
  69         5323  
19 69     69   30350 use Tree::Parser;
  69         380408  
  69         1840  
20              
21 69     69   20219 use Devel::PerlySense::CallTree::Caller;
  69         162  
  69         29276  
22              
23              
24              
25             =head1 PROPERTIES
26              
27             =head2 source
28              
29             The call-tree source with callers indented above their targets.
30              
31             =cut
32             has source => ( is => "ro", required => 1 );
33              
34             =head2 callers
35              
36             Arrayref with Caller objects from the ->source
37              
38             =cut
39             has callers => ( is => "lazy" );
40             sub _build_callers {
41 2     2   293 my $self = shift;
42             return [
43 58         737 grep { defined $_->id }
44 2         20 map { Devel::PerlySense::CallTree::Caller->new({ line => $_ }) }
  58         2392  
45             reverse split("\n", $self->source)
46             ];
47             }
48              
49             =head2 unique_callers
50              
51              
52              
53             =cut
54             has package_callers => ( is => "lazy" );
55             sub _build_package_callers {
56 1     1   279 my $self = shift;
57 1         2 my $package_callers = {};
58 1         1 my %seen;
59 1         2 for my $caller (@{$self->callers}) {
  1         14  
60 28 100       368 $seen{ $caller->id }++ and next;
61 19   100     293 my $callers = $package_callers->{ $caller->package } ||= [];
62 19         27 push(@$callers, $caller);
63             }
64 1         9 return $package_callers;
65             }
66              
67             has method_called_by_caller => ( is => "lazy" );
68 2     2   338 sub _build_method_called_by_caller { +{ } }
69              
70             sub BUILD {
71 2     2 0 9414 my $self = shift;
72 2         4 $self->assign_called_by();
73             }
74              
75             sub assign_called_by {
76 2     2 0 3 my $self = shift;
77              
78 2         17 my $tree_parser = Tree::Parser->new( $self->callers );
79             $tree_parser->setParseFilter(
80             sub {
81 56     56   4683 my ($line_iterator) = @_;
82 56         85 my $caller = $line_iterator->next();
83             return (
84 56         1690 int( $caller->indentation / 4 ),
85             $caller,
86             );
87 2         158 });
88 2         13 my $tree = $tree_parser->parse();
89              
90 2         154 $self->walk_tree(undef, $tree);
91              
92 2         31 return $self->method_called_by_caller;
93             }
94              
95             sub walk_tree {
96 58     58 0 39 my $self = shift;
97 58         38 my ($parent_caller, $tree) = @_;
98 58         42 for my $tree_node ( @{$tree->getAllChildren} ) {
  58         66  
99 56         201 my $caller = $tree_node->getNodeValue;
100 56         113 $self->method_called_by($parent_caller, $caller);
101 56         1048 $self->walk_tree($caller, $tree_node);
102             }
103             }
104              
105             sub method_called_by {
106 56     56 0 49 my $self = shift;
107 56         52 my ($target, $called) = @_;
108 56 100       70 $target or return;
109 54         649 $self->method_called_by_caller->{ $target->caller }->{ $called->caller }++;
110             }
111              
112             1;
113              
114              
115              
116              
117             __END__
118              
119              
120              
121             =encoding utf8
122              
123             =head1 AUTHOR
124              
125             Johan Lindstrom, C<< <johanl@cpan.org> >>
126              
127             =head1 BUGS
128              
129             Please report any bugs or feature requests to
130             C<bug-devel-perlysense@rt.cpan.org>, or through the web interface at
131             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Devel-PerlySense>.
132             I will be notified, and then you'll automatically be notified of progress on
133             your bug as I make changes.
134              
135             =head1 ACKNOWLEDGEMENTS
136              
137             =head1 COPYRIGHT & LICENSE
138              
139             Copyright 2005 Johan Lindstrom, All Rights Reserved.
140              
141             This program is free software; you can redistribute it and/or modify it
142             under the same terms as Perl itself.
143              
144             =cut