Module::Checkstyle::Check - Base class for checks
Module::Checkstyle is extensible via a plug-in mechanism. This guide takes you through the basic steps in writing your own check.
Module::Checkstyle
To write a check you create a module that lives in the namespace Module::Checkstyle::Check:: and that extends Module::Checkstyle::Check. As an example we'll write a check that counts the length of a named subroutine.
Module::Checkstyle::Check::
Module::Checkstyle::Check
To begin with we create a module named Module::Checkstyle::Check::SubLength either via h2xs or Module::Starter.
h2xs
Module::Starter
In the file Module/Checkstyle/Check/SubLength.pm we enter the following code:
package Module::Checkstyle::Check::SubLength; use strict; use warnings; use Readonly; use Module::Checkstyle::Util qw(:args :problem); use base qw(Module::Checkstyle::Check);
Next we need to tell Module::Checkstyle what we want to recive events for. We do this by overriding the subroutine register which is called if the check is enabled in the configuration file.
register
sub register { return ('enter PPI::Statement::Sub' => \&enter_subroutine); }
The method register must return a hash with event => handler pairs (actually it's a list that is returned). The event is defined by an optional operation, enter or leave, followed by the type of PPI::Element we want to respond to, which in this case is PPI::Statement::Sub.
The plug-in is then instansiated by calling its new method. This method should read the configuration directives into the object itself because there can exist mulitple instances of the check with different configurations. The new method is supplied an instance of Module::Checkstyle::Config. Lets define the configuration-directive max-length as a readonly-variable and add a constructor that reads it into the instance.
new
Module::Checkstyle::Config
Readonly my $MAX_LENGTH => 'max-length'; sub new { my ($class, $config) = @_; $class = ref $class || $class; my $self = bless { config => $config }, $class; $self->{$MAX_LENGTH} = as_numeric($config->get_directive($MAX_LENGTH)); return $self; }
The function as_numeric is provided by Module::Checkstyle::Util via the tag args.
as_numeric
Module::Checkstyle::Util
Next we need to write our event handling code that is called when a named subroutine is found. Event-handlers retrieves three arguments: the instance of the plug-in, the PPI::Element and the path of the current file that is being processed.
PPI::Element
my enter_subroutine { my ($self, $subroutine, $file) = @_; my @problems; if ($self->{$MAX_LENGTH}) { # No need to run code if it's turned off my $block = $subroutine->block(); if ($block) { # It's not a forward declaration my $line = $subroutine->location->[0]; # The line the declartion is on my $last_line = $block->last_element->location->[0]; # The line where } is at my $length = $last_line - $line; if ($length > $self->{$MAX_LENGTH}) { my $name = $subroutine->name(); push @problems, make_problem($self->{config}->get_severity($MAX_LENGTH), "Subroutine '$name' is too long ($length)", $subroutine->location, $file); } } } return @problems; }
The function make_problem is exported by Module::Checkstyle::Util in the tag problem.
To finish up our module we write the documentation, see Module::Checkstyle::Check::Package for an example, write the tests and make sure the module returns a true value.
Default constructor that returns a hash-reference blessed to the subclass. The returned object will have the passed configuration object available under the key _config.
Abstract method that subclasses should override that provides the events it responds to.
Returns the config passed to new.
To install Module::Checkstyle, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Module::Checkstyle
CPAN shell
perl -MCPAN -e shell install Module::Checkstyle
For more information on module installation, please visit the detailed CPAN module installation guide.