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