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