Saturday, September 12, 2009

Adding house policies to Perl::Critic.

Recently on Stack Overflow, someone want code that could either modify Perl source code to remove comments that where on the same line as code, or warn him that comments were on the same line as code. Apparently he had a house style that needed to be enforced. I decided a Perl::Critic policy to warn him of the style violation was the way to go. I spent about fifteen minutes looking at the docs and writing code and I came up with this:
package Perl::Critic::Policy::CodeLayout::NoSideComments;

use strict;
use warnings;

use Readonly;

use Perl::Critic::Utils qw{ :severities :classification :ppi };
use parent 'Perl::Critic::Policy';

our $VERSION = 20090904;

Readonly::Scalar my $DESC => "side comments are not allowed";
Readonly::Scalar my $EXPL => "put the comment above the line, not next to it";

sub supported_parameters { return }
sub default_severity { return 5 }
sub default_themes { return qw( custom ) }
sub applies_to { return 'PPI::Token::Comment' }

sub violates {
my ($self, $elem) = @_;

#look backwards until you find whitespace that contains a
#newline (good) or something other than whitespace (error)

my $prev = $elem->previous_sibling;
while ($prev) {
return $self->violation( $DESC, $EXPL, $elem )
unless $prev->isa("PPI::Token::Whitespace");
return if $prev->content =~ /\n/;
$prev = $prev->previous_sibling;
}

#catch # after a block start, but leave the #! line alone
return $self->violation( $DESC, $EXPL, $elem )
unless $elem->parent->isa("PPI::Document");
return;
}

1;
I was surprised at just how easy PPI and Perl::Critic makes this.

No comments:

Post a Comment

Some limited HTML markup is allowed by blogger: strong, b, i, and a. You may also use em, but I have repurposed it through the magic of CSS to be behave very much like <tt><code></code></tt>.