views:

359

answers:

4

My department is currently settling on some general code best practices, which we would like to somewhat enforce, providing developers with Perl::Tidy and Perl::Critic configurations.

Now we are having problems with side comments. The side comment is this:

my $counter = 0;  # Reset counter

We would prefer to not have side comments at all, since in most cases they can be written above the code in question, where they are more easily read. If at all possible, a Perl::Tidy solution would be perfect, which would move a side comment to the line above it, second-best would be a Perl::Critic policy (which I haven't found at CPAN either) and third-best and last would be developers taking care to point those comments out when they do code reviews.

Is it possible to implement with Perl::Tidy or Perl::Critic?

+3  A: 

I don't think there is any mechanism for actually moving side comments in Perl::Tidy or in Perl::Critic. You can, of course, remove them completely using -dsc or --delete-side-comments, but you probably don't want to do that.

However, it's definitely possible to extend Perl::Critic to do this, see in particular Perl::Critic::DEVELOPER which describes how this is accomplished.

You could also reference some of the smaller extensions others have written, such as the source to Perl::Critic::Policy::CodeLayout::RequireASCII, part of Perl::Critic::More.

Adam Bellaire
+15  A: 

I think this should work for you (if I understood what you want):

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;
Chas. Owens
Thanks, looks like a good start!
rassie
/golfclap Nicely done! :)
Adam Bellaire
Poorly done, I left out the POD, but I ran out of tuits.
Chas. Owens
Fixed two bugs (skipped a token and didn't catch side comments on the start of a block)
Chas. Owens
+2  A: 

Not all side comments are bad. For instance, in my answer to How do I check for a sub-subdirectory in Perl, they stay out of the way and allow people to see the parallel structure in the code more easily. That's why we put them over to the side: they are minor players that enhance a statement without calling a lot of attention to it.

I use comments on lines by their own for much more detailed explanations of motivation, special cases, and so on. I use these to interrupt the code flow to ensure the developer reads them because they have very important extra-code information.

And, if you are using Perl::Critic, you're going to want the side comments sometimes :)

 ....; ## no critic
brian d foy
Humorously, `## no critic` passes the Perl::Critic rule I created in my answer. `## no critic even more text` also passes, I don't know if this should be considered a bug.
Chas. Owens
A: 

re brian d foy's "Not all side comments are bad" -- Agreed, side comments are will appear frequently in your code if you use Smart::Comments.

Ether
If you want to use smart comments with the Perl::Critic rule I created in my answer, then you just need to add this line near the top: `return if $elem->content =~ /^\s*###/;`. It will cause the rule to ignore comments that start with at least three octothorpes.
Chas. Owens