File Coverage

blib/lib/Perl/Metric/Basic.pm
Criterion Covered Total %
statement 64 67 95.5
branch 17 18 94.4
condition 3 3 100.0
subroutine 7 7 100.0
pod 1 1 100.0
total 92 96 95.8


line stmt bran cond sub pod time code
1             package Perl::Metric::Basic;
2 1     1   979 use strict;
  1         2  
  1         42  
3 1     1   4 use base qw(Class::Accessor);
  1         2  
  1         1055  
4 1     1   2990 use Scalar::Util qw(blessed);
  1         3  
  1         775  
5             __PACKAGE__->mk_accessors(qw());
6             our $VERSION = '0.31';
7              
8             sub measure {
9 3     3 1 17201 my $self = shift;
10 3         5 my $document = shift;
11              
12 3 100 100     59 die "No PPI::Document passed"
13             unless blessed($document) && $document->isa('PPI::Document');
14              
15 1         3 my $metrics;
16              
17             # go though all the nodes
18             my @packages;
19 0         0 my $package;
20 0         0 my @contents;
21 1         10 foreach my $node ($document->children) {
22 14 100       104 if ($node->isa('PPI::Statement::Package')) {
23 1 50       9 if (@contents) {
24 0         0 push @packages,
25             {
26             package => $package,
27             contents => [@contents],
28             };
29             }
30 1         2 $package = $node;
31 1         3 @contents = ();
32             } else {
33 13         27 push @contents, $node;
34             }
35             }
36 1         9 push @packages,
37             {
38             package => $package,
39             contents => [@contents],
40             };
41              
42 1         2 foreach my $data (@packages) {
43 1         3 my $package = $data->{package};
44 1         2 my $contents = $data->{contents};
45              
46 1         5 my $package_name = $self->_package_name($package);
47              
48 1         8 foreach my $node (@$contents) {
49 13 100       78 next unless $node->isa('PPI::Statement::Sub');
50 2         14 my $sub_name = $node->name;
51 2         190 my $content = $node->content;
52 2         567 my $lines = $content =~ tr/\n//;
53              
54 31         2956 my $whitespace = join ',',
55 2         6 map { $_->content } @{ $node->find('PPI::Token::Whitespace') };
  2         14  
56 2         29 my $lines_of_code = $whitespace =~ tr/\n//;
57              
58 2         9 my $all_comments = $node->find('PPI::Token::Comment');
59 2         3031 my $comments = 0;
60 2 100       9 $comments = scalar(@$all_comments) if $all_comments;
61              
62 2         3 my $blank_lines = 0;
63 2     76   15 my $all_nodes = $node->find(sub { 1 });
  76         693  
64 2         23 my $last_node_was_newline = 0;
65 2         6 foreach my $node (@$all_nodes) {
66 76 100       292 if ($node->isa('PPI::Token::Whitespace')) {
67 31         81 my $has_newline = $node->content =~ /\n/;
68 31 100       149 if ($has_newline) {
69 9 100       20 $blank_lines++ if $last_node_was_newline;
70 9         15 $last_node_was_newline = 1;
71             } else {
72 22         35 $last_node_was_newline = 0;
73             }
74             }
75             }
76              
77 2         7 my ($symbols, $symbols_unique) =
78             $self->_unique($node->find('PPI::Token::Symbol'));
79              
80 2         10 my ($numbers, $numbers_unique) =
81             $self->_unique($node->find('PPI::Token::Number'));
82              
83 2         8 my ($words, $words_unique) =
84             $self->_unique($node->find('PPI::Token::Word'));
85              
86 2         8 my ($operators, $operators_unique) =
87             $self->_unique($node->find('PPI::Token::Operator'));
88              
89 2         26 my $metric = {
90             blank_lines => $blank_lines,
91             comments => $comments,
92             lines => $lines,
93             lines_of_code => $lines_of_code,
94             numbers => $numbers,
95             numbers_unique => $numbers_unique,
96             operators => $operators,
97             operators_unique => $operators_unique,
98             symbols => $symbols,
99             symbols_unique => $symbols_unique,
100             words => $words,
101             words_unique => $words_unique,
102             };
103              
104 2         15 $metrics->{$package_name}->{$sub_name} = $metric;
105             }
106             }
107 1         18 return $metrics;
108             }
109              
110             # this should be rolled into PPI
111             sub _package_name {
112 1     1   2 my ($self, $package) = @_;
113 1         12 my $words = $package->find('PPI::Token::Word');
114 1         475 return $words->[1]->content;
115             }
116              
117             # return the total number of nodes and the number of nodes with unique
118             # content
119             sub _unique {
120 8     8   9816 my ($self, $nodes) = @_;
121 8 100       19 return (0, 0) unless $nodes;
122 7         9 my $count = scalar @$nodes;
123 7         10 my %count;
124 7         27 $count{ $_->content }++ foreach @$nodes;
125 7         136 my $count_unique = (keys %count);
126 7         24 return ($count, $count_unique);
127             }
128              
129             __END__