Vim Filters: Documenting Exceptions

Ovid on 2008-12-17T16:29:55

Except in a couple of odd cases, our exceptions are spelled out explicitly in our code:

defined $arg_for->{foo}
  or X::Method::Argument::Missing->throw(...);

This means that it's trivial to find these exceptions with a regex, but not so trivial to find them in our docs since our docs usually don't list them.

Until now.

I wrote the following filter:

#!/usr/bin/env perl

use strict;
use warnings;
use List::MoreUtils 'uniq';

my $code = do { local $/;  };
my @exceptions = uniq sort ($code =~ /(X::[^-]+)->throw/g);
my $exceptions = join "\n        " => @exceptions;
print "\nThrows: $exceptions\n$code";

And then typed mapped this to a visual area:

vnoremap ,e :!./add_exceptions.pl 

And then I select the following bit of code (right before the =cut):

Pretend this is documentation ...

=cut

sub xml_diff {
    my ( $self, $old, $new ) = @_;

    return unless $old or $new;
    if ( $old and $new ) {
        unless ( $old->hasAttribute('href') and $new->hasAttribute('href') ) {
            X::Internal::XMLDiff::MissingHrefs->throw(
                old_xml => $old->serialize(1), new_xml => $new->serialize(1),
            );
        }

        unless ( $old->getAttribute('href') eq $new->getAttribute('href') ) {
            X::Internal::XMLDiff::DifferentHrefs->throw(
                old_xml => $old->serialize(1), new_xml => $new->serialize(1),
            );
        }
        if ($old->hasAttribute('revision') && $new->hasAttribute('revision')) {
            my $old_revision = $old->getAttribute('revision');
            if ($old_revision eq $new->getAttribute('revision')) {
                X::Internal::XMLDiff::IdenticalRevisions->throw(
                    revision => $old_revision,
                );
            }
        }
    } 
    # more code
}

And then when I type ,e, I get the following text inserted right before =cut

Throws: X::Internal::XMLDiff::DifferentHrefs
        X::Internal::XMLDiff::IdenticalRevisions
        X::Internal::XMLDiff::MissingHrefs

About ten minutes later, I've now added this documentation to tons of modules. Vim filters rock.

Update: I screwed up. jplindstrom pointed out that the final line of the filter should look like this:

print "\nThrows:\n\n        $exceptions\n$code";

That makes the pod look like this, making it render correctly in HTML:

Throws:

        X::Internal::XMLDiff::DifferentHrefs
        X::Internal::XMLDiff::IdenticalRevisions
        X::Internal::XMLDiff::MissingHrefs