File Coverage

blib/lib/SourceCode/LineCounter/Perl.pm
Criterion Covered Total %
statement 91 91 100.0
branch 36 38 94.7
condition 2 3 66.6
subroutine 32 32 100.0
pod 13 13 100.0
total 174 177 98.3


line stmt bran cond sub pod time code
1             package SourceCode::LineCounter::Perl;
2 7     7   5094 use strict;
  7         18  
  7         206  
3              
4 7     7   40 use warnings;
  7         17  
  7         225  
5 7     7   38 no warnings;
  7         13  
  7         280  
6              
7 7     7   3614 use subs qw();
  7         161  
  7         171  
8 7     7   35 use vars qw($VERSION);
  7         14  
  7         349  
9              
10 7     7   40 use Carp qw(carp);
  7         15  
  7         8707  
11              
12             $VERSION = '1.021';
13              
14             =encoding utf8
15              
16             =head1 NAME
17              
18             SourceCode::LineCounter::Perl - Count lines in Perl source code
19              
20             =head1 SYNOPSIS
21              
22             use SourceCode::LineCounter::Perl;
23              
24             my $counter = SourceCode::LineCounter::Perl->new;
25              
26             $counter->count( $file );
27              
28             my $total_lines = $counter->total;
29              
30             my $pod_lines = $counter->documentation;
31              
32             my $code_lines = $counter->code;
33              
34             my $comment_lines = $counter->comment;
35              
36             my $comment_lines = $counter->blank;
37              
38              
39             =head1 DESCRIPTION
40              
41             This module counts the lines in Perl source code and tries to classify
42             them as code lines, documentation lines, and blank lines.
43              
44             Read a line
45              
46             If it's a blank line, record it and move on to the next line
47              
48             If it is the start of pod, mark that we are in pod, and count
49             it as a pod line and move on
50              
51             If we are in pod and the line is blank, record it as a blank line
52             and a pod line, and move on.
53              
54             If we are ending pod (with C<=cut>, record it as a pod line and
55             move on.
56              
57             If we are in pod and it is not blank, record it as a pod line and
58             move on.
59              
60             If we are not in pod, guess if the line has a comment. If the
61             line has a comment, record it.
62              
63             Removing comments, see if there is anything left. If there is,
64             record it as a code line.
65              
66             Move on to the next line.
67              
68             =cut
69              
70             =over 4
71              
72             =item new
73              
74             =cut
75              
76             sub new {
77 6     6 1 7735 my( $class, %hash ) = @_;
78              
79 6         17 my $self = bless {}, $class;
80 6         21 $self->_init;
81              
82 6         16 $self;
83             }
84              
85             =item reset
86              
87             Reset everything the object counted so you can use the same object
88             with another file.
89              
90             =cut
91              
92             sub reset {
93 1     1 1 1068 $_[0]->_init;
94             }
95              
96             =item accumulate( [ BOOLEAN ] )
97              
98             With no argument, returns the current setting as true or false.
99              
100             With one argument, sets the value for accumulation. If that's true,
101             the counter will add to the count from previous calls to C.
102             If false, C starts fresh each time.
103              
104             =cut
105              
106             sub accumulate {
107 1     1 1 4 my( $self ) = @_;
108              
109 1 50       5 $self->{accumulate} = !! $_[1] if @_ > 1;
110              
111 1         7 return $self->{accumulate};
112             }
113              
114             =item count( FILE )
115              
116             Counts the lines in FILE. The optional second argument, if true,
117             adds those counts to the counts from the last run. By default,
118             previous results are cleared.
119              
120             =cut
121              
122             sub count {
123 2     2 1 4104 my( $self, $file ) = @_;
124              
125 2         20 my $fh;
126 2 100       73 unless( open $fh, "<", $file ) {
127 1         226 carp "Could not open file [$file]: $!";
128 1         125 return;
129             }
130              
131 1 50       7 $self->_clear_line_info unless $self->accumulate;
132              
133 1         36 LINE: while( <$fh> ) {
134 15         30 chomp;
135 15         43 $self->_set_current_line( \$_ );
136              
137 15         40 $self->_total( \$_ );
138 15 100       33 $self->add_to_blank if $self->_is_blank( \$_ );
139              
140 15         32 foreach my $type ( qw( _start_pod _end_pod _pod_line ) ) {
141 42 100 66     100 $self->$type( \$_ ) && $self->add_to_documentation && next LINE;
142             }
143              
144 5 100       12 $self->add_to_comment if $self->_is_comment( \$_ );
145 5 100       13 $self->add_to_code if $self->_is_code( \$_ );
146             }
147              
148 1         21 $self;
149             }
150              
151             sub _clear_line_info {
152 8     8   23 $_[0]->{line_info} = {};
153             }
154              
155             sub _set_current_line {
156 15     15   30 $_[0]->{line_info}{current_line} = \ $_[1];
157             }
158              
159             sub _init {
160 7     7   22 my @attrs = qw(total blank documentation code comment accumulate);
161 7 100       19 foreach ( @attrs ) { $_[0]->{$_} = 0 unless defined $_[0]->{$_} }
  42         126  
162 7         21 $_[0]->_clear_line_info;
163             };
164              
165             =item total
166              
167             Returns the total number of lines in the file
168              
169             =cut
170              
171 4     4 1 826 sub total { $_[0]->{total} }
172              
173 22     22   1388 sub _total { ++ $_[0]->{total} }
174              
175             =item documentation
176              
177             Returns the total number of Pod lines in the file, including
178             and blank lines in Pod.
179              
180             =cut
181              
182 10     10 1 5986 sub documentation { $_[0]->{documentation} }
183              
184             =item add_to_documentation
185              
186             Add to the documentation line counter if the line is documentation.
187              
188             =cut
189              
190             sub add_to_documentation {
191 11     11 1 22 $_[0]->{line_info}{documentation}++;
192 11         17 $_[0]->{documentation}++;
193              
194 11         60 1;
195             }
196              
197             sub _start_pod {
198 20 100   20   44 return if $_[0]->_in_pod;
199 10 100       18 return unless ${$_[1]} =~ /^=\w+/;
  10         39  
200              
201 2         6 $_[0]->_mark_in_pod;
202              
203 2         8 1;
204             }
205              
206             sub _end_pod {
207 17 100   17   38 return unless $_[0]->_in_pod;
208 11 100       21 return unless ${$_[1]} =~ /^=cut$/;
  11         38  
209              
210 2         10 $_[0]->_clear_in_pod;
211              
212 2         6 1;
213             }
214              
215             sub _pod_line {
216 26 100   26   5088 return unless $_[0]->_in_pod;
217             }
218              
219 10     10   15305 sub _mark_in_pod { $_[0]->{line_info}{in_pod}++ }
220 117     117   1941 sub _in_pod { $_[0]->{line_info}{in_pod} }
221 9     9   7438 sub _clear_in_pod { $_[0]->{line_info}{in_pod} = 0 }
222              
223              
224             =item code
225              
226             Returns the number of non-blank lines, whether documentation
227             or code.
228              
229             =cut
230              
231 4     4 1 3815 sub code { $_[0]->{code} }
232              
233             =item add_to_code( LINE )
234              
235             Add to the code line counter if the line is a code line.
236              
237             =cut
238              
239             sub add_to_code {
240 2     2 1 8 $_[0]->{line_info}{code}++;
241 2         8 ++$_[0]->{code};
242             }
243              
244             sub _is_code {
245 12     12   2720 my( $self, $line_ref ) = @_;
246 12 100       24 return if grep { $self->$_() } qw(_is_blank _in_pod);
  24         63  
247              
248             # this will be false for things in strings!
249 10         59 ( my $copy = $$line_ref ) =~ s/\s*#.*//;
250              
251 10 100       44 return unless length $copy;
252              
253 5         18 1;
254             }
255              
256             =item comment
257              
258             The number of lines with comments. These are the things
259             that start with #. That might be lines that are all comments
260             or code lines that have comments.
261              
262             =cut
263              
264 5     5 1 3502 sub comment { $_[0]->{comment} }
265              
266             =item add_to_comment
267              
268             Add to the comment line counter if the line has a comment. A line
269             might be counted as both code and comments.
270              
271             =cut
272              
273             sub add_to_comment {
274 3     3 1 8 $_[0]->{line_info}{comment}++;
275 3         9 ++$_[0]->{comment};
276             }
277              
278             sub _is_comment {
279 20 100   20   12310 return if $_[0]->_in_pod;
280 16 100       22 return unless ${$_[1]} =~ m/#/;
  16         61  
281 9         39 1;
282             }
283              
284             =item blank
285              
286             The number of blank lines. By default, these are lines that
287             match the regex qr/^\s*$/. You can change this in C
288             by specifying the C parameter.
289              
290             =cut
291              
292 4     4 1 2923 sub blank { $_[0]->{blank} }
293              
294             =item add_to_blank
295              
296             Add to the blank line counter if the line is blank.
297              
298             =cut
299              
300             sub add_to_blank {
301 7     7 1 15 $_[0]->{line_info}{blank}++;
302 7         13 ++$_[0]->{blank};
303             }
304              
305             sub _is_blank {
306 36 100   36   5478 return unless defined $_[1];
307 24 100       36 return unless ${$_[1]} =~ m/^\s*$/;
  24         122  
308 11         39 1;
309             }
310              
311             =back
312              
313             =head1 TO DO
314              
315             =over 4
316              
317             =item * Generalized LineCounter that can dispatch to language
318             delegates.
319              
320             =back
321              
322             =head1 SEE ALSO
323              
324              
325             =head1 SOURCE AVAILABILITY
326              
327             This source is in Github
328              
329             https://github.com/briandfoy/sourcecode-linecounter-perl
330              
331             =head1 AUTHOR
332              
333             brian d foy, C<< >>
334              
335             =head1 COPYRIGHT AND LICENSE
336              
337             Copyright © 2008-2018, brian d foy . All rights reserved.
338              
339             You may redistribute this under the terms of the Artistic License 2.0.
340              
341             =cut
342              
343             1;