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