File Coverage

blib/lib/App/PerlPackage2PlantUMLClassDiagram/Package.pm
Criterion Covered Total %
statement 81 82 98.7
branch 25 36 69.4
condition 8 10 80.0
subroutine 18 18 100.0
pod 0 10 0.0
total 132 156 84.6


line stmt bran cond sub pod time code
1             package App::PerlPackage2PlantUMLClassDiagram::Package;
2 3     3   21413 use 5.014;
  3         10  
3 3     3   15 use strict;
  3         5  
  3         66  
4 3     3   14 use warnings;
  3         6  
  3         83  
5              
6 3     3   2533 use PPI::Document;
  3         457424  
  3         123  
7 3     3   2330 use Text::MicroTemplate::DataSection 'render_mt';
  3         58504  
  3         3067  
8              
9             sub new {
10 13     13 0 24124 my ($class, $source) = @_;
11              
12 13 100       355 unless (-f $source) {
13 1         10 die "file not exist: $source";
14             }
15              
16             bless {
17 12         62 source => $source,
18             }, $class;
19             }
20              
21             sub source {
22 13     13 0 520 my ($self) = @_;
23              
24 13         84 $self->{source};
25             }
26              
27             sub document {
28 44     44 0 61 my ($self) = @_;
29              
30 44   66     280 $self->{document} ||= PPI::Document->new($self->source);
31             }
32              
33             sub package_name {
34 13     13 0 11834 my ($self) = @_;
35              
36 13         39 my $package = $self->document->find_first('PPI::Statement::Package');
37 13 100       31489 return unless $package;
38 12         72 $package->namespace;
39             }
40              
41             sub parent_packages {
42 7     7 0 14 my ($self) = @_;
43              
44 7   100     18 my $includes = $self->document->find('PPI::Statement::Include') || [];
45 7 50       20528 return [] unless $includes;
46              
47 7         14 my $parent_packages = [];
48              
49             # see also: App::PRT::Command::RenameClass
50 7         20 for my $statement (@$includes) {
51 2 50       15 next unless defined $statement->pragma;
52 2 50       97 next unless $statement->pragma =~ /^parent|base$/; # only 'use parent' and 'use base' are supported
53              
54             # schild(2) is 'Foo' of use parent Foo
55 2         71 my $parent = $statement->schild(2);
56              
57 2 50       59 if ($parent->isa('PPI::Token::Quote')) {
    50          
58             # The 'literal' method is not implemented by ::Quote::Double or ::Quote::Interpolate.
59 0 0       0 push @$parent_packages, $parent->can('literal') ? $parent->literal : $parent->string;
60             } elsif ($parent->isa('PPI::Token::QuoteLike::Words')) {
61             # use parent qw(A B C) pattern
62             # literal is array when QuoteLike::Words
63 2         14 push @$parent_packages, $parent->literal;
64             }
65             }
66              
67 7         41 $parent_packages;
68             }
69              
70             sub _methods {
71 23     23   38 my ($self) = @_;
72              
73 23 100       48 $self->document->find('PPI::Statement::Sub') || [];
74             }
75              
76             sub _arguments ($) {
77 64     64   99 my ($sub) = @_;
78              
79 64         228 my $variable = $sub->find_first('PPI::Statement::Variable');
80 64 100       26090 return () unless $variable;
81              
82 62         177 my $list = $variable->find_first('PPI::Structure::List');
83 62 50       15116 return () unless $list;
84              
85 62   50     180 my $symbols = $list->find('PPI::Token::Symbol') || [];
86 62 50       14845 return () unless @$symbols;
87 62 100 100     188 my $receiver = shift @$symbols if $symbols->[0]->content eq '$self' || $symbols->[0]->content eq '$class';
88 62         602 ($receiver, @$symbols);
89             }
90              
91             sub _method_signature ($) {
92 18     18   34 my ($sub) = @_;
93              
94 18         34 my (undef, @arguments) = _arguments($sub);
95              
96 18         32 "@{[ $sub->name ]}(@{[ join ', ', @arguments ]})";
  18         60  
  18         530  
97             }
98              
99             sub static_methods {
100 6     6 0 606 my ($self) = @_;
101 5         108 [ map { _method_signature $_ } grep {
102 14         15369 my ($receiver) = _arguments $_;
103 14 50       83 $receiver && $receiver eq '$class';
104 6         12 } @{$self->_methods} ];
  6         20  
105             }
106              
107             sub public_methods {
108 10     10 0 741 my ($self) = @_;
109              
110 10         258 [ map { _method_signature $_ } grep { index($_->name, '_') != 0 } grep {
  13         249  
111 18         35500 my ($receiver) = _arguments $_;
112 18 100       100 !$receiver || $receiver eq '$self';
113 10         19 } @{$self->_methods} ];
  10         27  
114             }
115              
116             sub private_methods {
117 6     6 0 39 my ($self) = @_;
118              
119 3         77 [ map { _method_signature $_ } grep { index($_->name, '_') == 0 } grep {
  9         190  
120 14         14919 my ($receiver) = _arguments $_;
121 14 50       74 !$receiver || $receiver eq '$self';
122 6         14 } @{$self->_methods} ];
  6         16  
123             }
124              
125             sub to_class_syntax {
126 6     6 0 16 my ($self) = @_;
127              
128 6         21 my $package_name = $self->package_name;
129              
130 6 100       146 return '' unless $package_name;
131              
132 5         19 render_mt('class_syntax', {
133             package_name => $self->package_name,
134             static_methods => $self->static_methods,
135             public_methods => $self->public_methods,
136             private_methods => $self->private_methods,
137             });
138             }
139              
140             sub to_inherit_syntax {
141 6     6 0 13 my ($self) = @_;
142              
143 6         24 my $parent_packages = $self->parent_packages;
144              
145 6 100       38 return '' unless @$parent_packages;
146              
147 1         5 render_mt('inherit_syntax', {
148             package_name => $self->package_name,
149             parent_packages => $parent_packages,
150             });
151             }
152              
153             1;
154             __DATA__