File Coverage

blib/lib/Perl/Metrics/Simple/Analysis.pm
Criterion Covered Total %
statement 130 130 100.0
branch 10 10 100.0
condition n/a
subroutine 29 29 100.0
pod 13 13 100.0
total 182 182 100.0


line stmt bran cond sub pod time code
1             package Perl::Metrics::Simple::Analysis;
2 7     7   61 use strict;
  7         25  
  7         246  
3 7     7   51 use warnings;
  7         38  
  7         270  
4              
5 7     7   62 use Carp qw(confess);
  7         17  
  7         421  
6 7     7   55 use English qw(-no_match_vars);
  7         18  
  7         67  
7 7     7   5469 use Readonly 1.03;
  7         20628  
  7         394  
8 7     7   3227 use Statistics::Basic::StdDev;
  7         250999  
  7         234  
9 7     7   62 use Statistics::Basic::Mean;
  7         19  
  7         131  
10 7     7   35 use Statistics::Basic::Median;
  7         15  
  7         9682  
11              
12             our $VERSION = 'v1.0.3';
13              
14             my %_ANALYSIS_DATA = ();
15             my %_FILES = ();
16             my %_FILE_STATS = ();
17             my %_LINES = ();
18             my %_MAIN = ();
19             my %_PACKAGES = ();
20             my %_SUBS = ();
21             my %_SUMMARY_STATS = ();
22              
23             sub new {
24 13     13 1 256 my ( $class, $analysis_data ) = @_;
25 13 100       51 if ( !is_ref( $analysis_data, 'ARRAY' ) ) {
26 1         332 confess 'Did not supply an arryref of analysis data.';
27             }
28 12         37 my $self = {};
29 12         33 bless $self, $class;
30 12         53 $self->_init($analysis_data); # Load object properties
31 12         44 return $self;
32             }
33              
34             sub files {
35 2     2 1 6 my ($self) = @_;
36 2         13 return $_FILES{$self};
37             }
38              
39             sub data {
40 17     17 1 643 my $self = shift;
41 17         90 return $_ANALYSIS_DATA{$self};
42             }
43              
44             sub file_count {
45 1     1 1 3 my $self = shift;
46 1         3 return scalar @{ $self->files };
  1         3  
47             }
48              
49             sub lines {
50 1     1 1 25 my $self = shift;
51 1         9 return $_LINES{$self};
52             }
53              
54             sub packages {
55 2     2 1 5 my ($self) = @_;
56 2         12 return $_PACKAGES{$self};
57             }
58              
59             sub package_count {
60 1     1 1 3 my $self = shift;
61 1         3 return scalar @{ $self->packages };
  1         4  
62             }
63              
64             sub file_stats {
65 13     13 1 85 my $self = shift;
66 13         53 return $_FILE_STATS{$self};
67             }
68              
69             sub main_stats {
70 3     3 1 67 my $self = shift;
71 3         19 return $_MAIN{$self};
72             }
73              
74             sub summary_stats {
75 3     3 1 5065 my $self = shift;
76 3         14 return $_SUMMARY_STATS{$self};
77             }
78              
79             sub subs {
80 26     26 1 53 my ($self) = @_;
81 26         94 return $_SUBS{$self};
82             }
83              
84             sub sub_count {
85 1     1 1 2 my $self = shift;
86 1         3 return scalar @{ $self->subs };
  1         2  
87             }
88              
89             sub _get_min_max_values {
90 37     37   114 my $nodes = shift;
91 37         70 my $hash_key = shift;
92 37 100       88 if ( !is_ref( $nodes, 'ARRAY' ) ) {
93 1         657 confess("Didn't get an ARRAY ref, got '$nodes' instead");
94             }
95 36         77 my @sorted_values = sort _numerically map { $_->{$hash_key} } @{$nodes};
  94         288  
  36         76  
96 36         95 my $min = $sorted_values[0];
97 36         63 my $max = $sorted_values[-1];
98 36         159 return ( $min, $max, \@sorted_values );
99             }
100              
101             sub _numerically {
102 116     116   207 return $a <=> $b;
103             }
104              
105             sub _init {
106 12     12   38 my ( $self, $file_objects ) = @_;
107 12         52 $_ANALYSIS_DATA{$self} = $file_objects;
108              
109 12         33 my @all_files = ();
110 12         25 my @packages = ();
111 12         28 my $lines = 0;
112 12         31 my @subs = ();
113 12         24 my @file_stats = ();
114 12         58 my %main_stats = ( lines => 0, mccabe_complexity => 0 );
115              
116 12         26 foreach my $file ( @{ $self->data() } ) {
  12         50  
117 28         111 $lines += $file->lines();
118 28         86 $main_stats{lines} += $file->main_stats()->{lines};
119             $main_stats{mccabe_complexity} +=
120 28         70 $file->main_stats()->{mccabe_complexity};
121 28         76 push @all_files, $file->path();
122 28         75 push @file_stats,
123             { path => $file->path, main_stats => $file->main_stats };
124 28         51 push @packages, @{ $file->packages };
  28         73  
125 28         43 push @subs, @{ $file->subs };
  28         97  
126             }
127              
128 12         47 $_FILE_STATS{$self} = \@file_stats;
129 12         35 $_FILES{$self} = \@all_files;
130 12         36 $_MAIN{$self} = \%main_stats;
131 12         35 $_PACKAGES{$self} = \@packages;
132 12         26 $_LINES{$self} = $lines;
133 12         39 $_SUBS{$self} = \@subs;
134 12         37 $_SUMMARY_STATS{$self} = $self->_make_summary_stats();
135 12         36 return 1;
136             }
137              
138             sub _make_summary_stats {
139 12     12   26 my $self = shift;
140 12         58 my $summary_stats = {
141             sub_length => $self->_summary_stats_sub_length,
142             sub_complexity => $self->_summary_stats_sub_complexity,
143             main_complexity => $self->_summary_stats_main_complexity,
144             };
145 12         39 return $summary_stats;
146             }
147              
148             sub _summary_stats_sub_length {
149 12     12   24 my $self = shift;
150              
151 12         25 my %sub_length = ();
152              
153 12         44 @sub_length{ 'min', 'max', 'sorted_values' } =
154             _get_min_max_values( $self->subs, 'lines' );
155              
156             @sub_length{ 'mean', 'median', 'standard_deviation' } =
157 12         48 _get_mean_median_std_dev( $sub_length{sorted_values} );
158              
159 12         60 return \%sub_length;
160             }
161              
162             sub _summary_stats_sub_complexity {
163 12     12   32 my $self = shift;
164              
165 12         26 my %sub_complexity = ();
166              
167 12         30 @sub_complexity{ 'min', 'max', 'sorted_values' } =
168             _get_min_max_values( $self->subs, 'mccabe_complexity' );
169              
170             @sub_complexity{ 'mean', 'median', 'standard_deviation' } =
171 12         35 _get_mean_median_std_dev( $sub_complexity{sorted_values} );
172              
173 12         78 return \%sub_complexity;
174             }
175              
176             sub _summary_stats_main_complexity {
177 12     12   25 my $self = shift;
178              
179 12         25 my %main_complexity = ();
180              
181 12         21 my @main_stats = map { $_->{main_stats} } @{ $self->file_stats };
  28         68  
  12         41  
182 12         36 @main_complexity{ 'min', 'max', 'sorted_values' } =
183             _get_min_max_values( \@main_stats, 'mccabe_complexity' );
184              
185             @main_complexity{ 'mean', 'median', 'standard_deviation' } =
186 12         37 _get_mean_median_std_dev( $main_complexity{sorted_values} );
187              
188 12         58 return \%main_complexity;
189             }
190              
191             sub is_ref {
192 136     136 1 247 my $thing = shift;
193 136         254 my $type = shift;
194 136         270 my $ref = ref $thing;
195 136 100       477 return if !$ref;
196 89 100       228 return if ( $ref ne $type );
197 88         315 return $ref;
198             }
199              
200             sub _get_mean_median_std_dev {
201 37     37   64 my $values = shift;
202 37         56 my $count = scalar @{$values};
  37         86  
203 37 100       92 if ( $count < 1 ) {
204 3         11 return;
205             }
206 34         168 my $mean = sprintf '%.2f', Statistics::Basic::Mean->new($values)->query;
207              
208 34         5097 my $median = sprintf '%.2f', Statistics::Basic::Median->new($values)->query;
209              
210 34         4409 my $standard_deviation = sprintf '%.2f',
211             Statistics::Basic::StdDev->new( $values, $count )->query;
212              
213 34         9459 return ( $mean, $median, $standard_deviation );
214             }
215              
216             1;
217             __END__