#!/usr/bin/perl # $Header: /usr/local/CVS/Perl-Metrics-Simple/bin/countperl,v 1.8 2008/07/19 17:36:29 matisse Exp $ # $Revision: 1.8 $ # $Author: matisse $ # $Source: /usr/local/CVS/Perl-Metrics-Simple/bin/countperl,v $ # $Date: 2008/07/19 17:36:29 $ ############################################################################### package main; use strict; use warnings; use Carp qw(); use Perl::Metrics::Simple qw(0.03); use Pod::Usage; our $VERSION = 0.035; if ( !@ARGV ) { pod2usage( -verbose => 1 ); } my $analzyer = Perl::Metrics::Simple->new; my $analysis = $analzyer->analyze_files(@ARGV); my $file_count = $analysis->file_count; my $package_count = $analysis->package_count; my $sub_count = $analysis->sub_count; my $lines = $analysis->lines; my $main_stats = $analysis->main_stats; my $file_stats = $analysis->file_stats; my $summary_stats = $analysis->summary_stats; print <<"EOS" or Carp::croak('Could not print!'); Perl files found: $file_count Counts ------ total code lines: $lines lines of non-sub code: $main_stats->{lines} packages found: $package_count subs/methods: $sub_count Subroutine/Method Size ---------------------- min: $summary_stats->{sub_length}->{min} lines max: $summary_stats->{sub_length}->{max} lines mean: $summary_stats->{sub_length}->{mean} lines std. deviation: $summary_stats->{sub_length}->{standard_deviation} median: $summary_stats->{sub_length}->{median} McCabe Complexity ----------------- Code not in any subroutine:: min: $summary_stats->{main_complexity}->{min} max $summary_stats->{main_complexity}->{max} mean: $summary_stats->{main_complexity}->{mean} std. deviation: $summary_stats->{main_complexity}->{standard_deviation} median: $summary_stats->{main_complexity}->{median} Subroutines/Methods: min: $summary_stats->{sub_complexity}->{min} max: $summary_stats->{sub_complexity}->{max} mean: $summary_stats->{sub_complexity}->{mean} std. deviation: $summary_stats->{sub_complexity}->{standard_deviation} median: $summary_stats->{sub_complexity}->{median} Tab-delimited list of subroutines, with most complex at top ----------------------------------------------------------- EOS my @main_from_each_file = map { $_->{main_stats} } @{ $analysis->file_stats }; my @sorted_subs = sort _by_complexity(), @{ $analysis->subs }, @main_from_each_file; my $header = join( "\t", 'complexity', 'sub', 'path', 'size' ), "\n"; print "$header" || Carp::croak('Could not print to currently selectd filehandle.'); foreach my $sub (@sorted_subs) { my %sub_hash = %{$sub}; my $line = join( "\t", @sub_hash{ 'mccabe_complexity', 'name', 'path', 'lines' } ), "\n"; print "$line" || Carp::croak('Could not print to currently selected file handle.'); } exit; sub _by_complexity { return $b->{mccabe_complexity} <=> $a->{mccabe_complexity}; } __END__ =head1 NAME countperl - count lines, packages, subs and complexity of Perl files. =head1 SYNOPSIS B F [F ....] =head1 REQUIRED ARGUMENTS At least one file or directory path must be supplied. =head1 EXIT STATUS Exits zero on success, non-zero on failure. =head1 DESCRIPTION F uses B to examines the named files and recursivesly searches named directories for Perl files. Perl files are identified by Bis_perl_file>. Basically if the file ends in C<.pl>, C<.pm>, or C<.t> or has what appears to be a perl I line. F produces a report on F of counts of total lines, packages, subroutines/methods, the minimum, maximum, mean, standard deviation, and median size and mccabe_complexity (cyclomatic complexity) of subroutines and the 'main' portion of each file (everything not in a subroutine.) =head2 Output Format Line counts do not include comments nor pod. The current output format is human-readable text: Perl files found: 3 Counts ------ total code lines: 856 lines of non-sub code: 450 packages found: 3 subs/methods: 42 Subroutine/Method Size ---------------------- min: 3 lines max: 32 lines mean: 9.67 lines std. deviation: 7.03 median: 7.50 McCabe Complexity ----------------- Code not in any subroutine:: min: 1 max 1 mean: 1.00 std. deviation: 0.00 median: 1.00 Subroutines/Methods: min: 1 max: 5 avg: 1.00 std. deviation: 1.36 median: 1.00 Tab-delimited list of subroutines, with most complex at top ----------------------------------------------------------- complexity sub path size 5 is_perl_file lib/Perl/Metrics/Simple.pm 11 5 _has_perl_shebang lib/Perl/Metrics/Simple.pm 13 5 _init lib/Perl/Metrics/Simple/Analysis/File.pm 30 4 find_files lib/Perl/Metrics/Simple.pm 11 4 new lib/Perl/Metrics/Simple/Analysis.pm 10 4 is_ref lib/Perl/Metrics/Simple/Analysis.pm 8 =head1 VERSION This is version 0.031 of F. =head1 BUGS AND LIMITATIONS =head2 Bugs No bugs reported yet :-) See: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Perl-Metrics-Simple =head2 Limitations =over 4 =item Does not accept input from STDIN. =item No machine-readable report format available (e.g. XML, tab-delimited) =back =head1 SUPPORT Via CPAN: =head2 Disussion Forum http://www.cpanforum.com/dist/Perl-Metrics-Simple =head2 Bug Reports http://rt.cpan.org/NoAuth/Bugs.html?Dist=Perl-Metrics-Simple =head1 DEPENDENCIES =over 4 =item L 0.03 (which depends upon L.) =item L =back =head1 SEE ALSO =over 4 =item L =item L =item L =item http://en.wikipedia.org/wiki/Cyclomatic_complexity =back =head1 AUTHOR Matisse Enzer CPAN ID: MATISSE Eigenstate Consulting, LLC matisse@eigenstate.net http://www.eigenstate.net/ =head1 LICENSE AND COPYRIGHT This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of the license can be found in the LICENSE file included with this module. =cut