Perl::Metrics::Simple - Count packages, subs, lines, etc. of many files.


Perl-Metrics-Simple documentation Contained in the Perl-Metrics-Simple distribution.

Index


Code Index:

NAME

Top

Perl::Metrics::Simple - Count packages, subs, lines, etc. of many files.

SYNOPSIS

Top

  use Perl::Metrics::Simple;
  my $analyzer = Perl::Metrics::Simple->new;
  my $analysis = $analyzer->analyze_files(@paths, @refs_to_file_contents);
  $file_count    = $analysis->file_count;
  $package_count = $analysis->package_count;
  $sub_count     = $analysis->sub_count;
  $lines         = $analysis->lines;
  $main_stats    = $analysis->main_stats;
  $file_stats    = $analysis->file_stats;

VERSION

Top

This is VERSION 0.12

DESCRIPTION

Top

Perl::Metrics::Simple provides just enough methods to run static analysis of one or many Perl files and obtain a few metrics: packages, subroutines, lines of code, and an approximation of cyclomatic (mccabe) complexity for the subroutines and the "main" portion of the code.

Perl::Metrics::Simple is far simpler than Perl::Metrics.

Installs a script called countperl.

USAGE

Top

See the countperl script (included with this distribution) for a simple example of usage.

CLASS METHODS

Top

new

Takes no arguments and returns a new Perl::Metrics::Simple object.

is_perl_file

Takes a path and returns true if the target is a Perl file.

OBJECT METHODS

Top

analyze_files( @paths, @refs_to_file_contents )

Takes an array of files and or directory paths, and/or SCALAR refs to file contents and returns an Perl::Metrics::Simple::Analysis object.

find_files( @directories_and_files )

Uses list_perl_files to find all the readable Perl files and returns a reference to a (possibly empty) list of paths.

list_perl_files

Takes a list of one or more paths and returns an alphabetically sorted list of only the perl files. Uses is_perl_file so may throw an exception if a file is unreadable.

is_perl_file($path)

Takes a path to a file and returns true if the file appears to be a Perl file, otherwise returns false.

If the file name does not match any of @Perl::Metrics::Simple::PERL_FILE_SUFFIXES then the file is opened for reading and the first line examined for a a Perl 'shebang' line. An exception is thrown if the file cannot be opened in this case.

should_be_skipped($path)

Returns true if the path should be skipped when looking for Perl files. Currently skips .svn, CVS, and _darcs directories.

BUGS AND LIMITATIONS

Top

See: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Perl-Metrics-Simple

SUPPORT

Top

Via CPAN:

Disussion Forum

http://www.cpanforum.com/dist/Perl-Metrics-Simple

Bug Reports

http://rt.cpan.org/NoAuth/Bugs.html?Dist=Perl-Metrics-Simple

AUTHOR

Top

    Matisse Enzer
    CPAN ID: MATISSE
    Eigenstate Consulting, LLC
    matisse@eigenstate.net
    http://www.eigenstate.net/

LICENSE AND COPYRIGHT

Top

SEE ALSO

Top

The countperl script included with this distribution.
PPI
Perl::Critic
Perl::Metrics
http://en.wikipedia.org/wiki/Cyclomatic_complexity

Perl-Metrics-Simple documentation Contained in the Perl-Metrics-Simple distribution.

# $Header: /Library/VersionControl/CVS/Perl-Metrics-Simple/lib/Perl/Metrics/Simple.pm,v 1.23 2010/05/09 18:02:28 matisse Exp $
# $Revision: 1.23 $
# $Author: matisse $
# $Source: /Library/VersionControl/CVS/Perl-Metrics-Simple/lib/Perl/Metrics/Simple.pm,v $
# $Date: 2010/05/09 18:02:28 $
###############################################################################

package Perl::Metrics::Simple;
use 5.006;
use strict;
use warnings;

use Carp qw(cluck confess);
use Data::Dumper;
use English qw(-no_match_vars);
use File::Basename qw(fileparse);
use File::Find qw(find);
use IO::File;
use PPI;
use Perl::Metrics::Simple::Analysis;
use Perl::Metrics::Simple::Analysis::File;
use Readonly;

our $VERSION = '0.15';

Readonly::Scalar our $PERL_FILE_SUFFIXES => qr{ \. (:? pl | pm | t ) }sxmi;
Readonly::Scalar our $SKIP_LIST_REGEX    => qr{ \.svn | \. git | _darcs | CVS }sxmi;
Readonly::Scalar my $PERL_SHEBANG_REGEX  => qr/ \A [#] ! .* perl /sxm;
Readonly::Scalar my $DOT_FILE_REGEX      => qr/ \A [.] /sxm;

sub new {
    my ($class) = @_;
    my $self = {};
    bless $self, $class;
    return $self;
}

sub analyze_files {
    my ( $self, @dirs_and_files ) = @_;
    my @results = ();
    my @objects = grep { ref $_ } @dirs_and_files;
    @dirs_and_files = grep { not ref $_ } @dirs_and_files;
    foreach my $file ( (scalar(@dirs_and_files)?@{ $self->find_files(@dirs_and_files) }:()),@objects ) {
        my $file_analysis =
          Perl::Metrics::Simple::Analysis::File->new( path => $file );
        push @results, $file_analysis;
    }
    my $analysis = Perl::Metrics::Simple::Analysis->new( \@results );
    return $analysis;
}

sub find_files {
    my ($self, @directories_and_files) = @_;
    foreach my $path (@directories_and_files) {
        if ( !-r $path ) {
            confess "Path '$path' is not readable!";
        }
    }
    my @found = $self->list_perl_files(@directories_and_files);
    return \@found;
}

sub list_perl_files {
    my ( $self, @paths ) = @_;
    my @files;

    my $wanted = sub {
        return if $self->should_be_skipped($File::Find::name);
        if ( $self->is_perl_file($File::Find::name) )
        {
            push @files, $File::Find::name;  ## no critic (ProhibitPackageVars)
        }
    };

    File::Find::find( { wanted => $wanted, no_chdir => 1 }, @paths );

    my @sorted_list = sort @files;
    return @sorted_list;
}

sub should_be_skipped {
    my ( $self, $fullpath ) = @_;
    my ( $name, $path, $suffix ) = File::Basename::fileparse($fullpath);
    return $path =~ $SKIP_LIST_REGEX;
}

sub is_perl_file {
    my ( $self, $path ) = @_;
    return if ( !-f $path );
    my ( $name, $path_part, $suffix ) =
      File::Basename::fileparse( $path, $PERL_FILE_SUFFIXES );
    return if $name =~ $DOT_FILE_REGEX;
    if ( length $suffix ) {
        return 1;
    }
    return _has_perl_shebang($path);
}

sub _has_perl_shebang {
    my $path = shift;

    my $fh = IO::File->new( $path, '<' );
    if ( !-r $fh ) {
        cluck "Could not open '$path' for reading: $OS_ERROR";
        return;
    }
    my $first_line = <$fh>;
    $fh->close();
    return if ( !$first_line );
    return $first_line =~ $PERL_SHEBANG_REGEX;
}

1;

__END__

#################### main pod documentation begin ###################
## Below is the stub of documentation for your module. 
## You better edit it!


#################### main pod documentation end ###################