Can useful documentation be derived from perl source, by source analysis alone? This would mean parsing perl, which is said to be hard.
As it turns out , PPI solves that messy perl parsing business - leaving only the challenge of deriving meaning from patterns of elements in a PPI document. Isn't that what perlcritic does ?
Don't get me wrong. I like pod , my pod is forever improving - however when confronted with the horror of one particular brand of home grown, half baked XML class doc dangling beyond __END__ markers or lurking inside =pod/=cut , I cannot help but ponder documentation, self documentation and (save me) auto documentation.
Some months ago , in the throes of hacking on a large OO-ish perl codebase , thwarted by lack of pod and an overabundance of outdated XML fluff - I returned to the source only to find it a descent through layers and layers of subclasses of classes inheriting frameworks of further classes and subclasses.
First consider that My::Class::Foo's method 'load' is failing and the problem appears to be with $path. Seeing that variable is returned by the object method 'canonpath' , we can go look for that method.
package My::Class::Foo; use base 'My::Class'; sub load { my ($self,$file) = @_; my $path = $self->canonpath( $file ); # ... some special load } 1;
Seems that canonpath must be inherited since it is not defined in My::Class::Foo , which leads on a search discovering ...
package My::Class; use base 'More::Generic'; sub save { my ($self,$file) = @_; my $path = $self->canonpath( $file ); # ... some special save } 1;
Nuts! , no joy with My::Class either , the documentation is no help - pod missing presumed dead - XML fluff only tells me what I can plainly see which is My::Class::Foo inherits from My::Class which inherits from More::Generic , with heavy heart let us open More::Generic in anticipation of an end to this pursuit.
package More::Generic; use base qw( File::Spec ); sub twiddle_thumbs { # etc # } 1;
Closer. Since the familiar File::Spec is the parent class here, we can finally resort to the mystical practice of documentation perusal, perldoc File::Spec
This is a rather contrived example (and my apologies to File::Spec) . My frustration at being faced with this combination of deep inheritance and missing documentation lead to a short brutal script that attempted to find and chase instances of 'use base' and outputting short pod sections like
=pod =head INHERITS =head2 L<My::Class> =head3 L<More::Generic> L<File::Spec> =cut
After some experimentation I believe that when expressed as PPI elements , the use base qw(Classname); idiom can be matched and used to derive meaningful documentation about perl source. In fact this idiom is a special case of importing behaviour - like use POSIX qw( strftime );. To PPI , these are include statement elements with trailing data, albeit often very different trailing data with specific meaning with respect to the package being imported.
In processing perl source, allow a plugin to capture the include of a chosen module and any import arguments. Add new plugins for more meaningful output
package DerivePod::Includes::base; use base qw( DerivePod::Plugin ); sub process { my ($plugin,$statement,$ppi_doc) = @_; my $parent_class = $statement->find_first('PPI::Token::QuoteLike::Wo +rds'); $plugin->output( qq|=head INHERITS L<$parent_class> |; }
I'm compelled to try writing a parser which turns perl source into a document describing the nature of that source code, dependencies, ancestors, imported and exported symbols. This document's interface would be used by a formatter / processor to produce or embelish existing documentation. So far I have a terrible document model, a lame parser and a missing original script.Their namespace is Macropod , as in Big and Foot.
First meditation in ages. be kind
|
|---|