PPI::Transform::Doxygen - PPI::Transform class for generating Doxygen input
use PPI; use PPI::Transform::Doxygen; my $transform = PPI::Transform::Doxygen->new(); # appends Doxygen Docs after __END__ (default when no output is given) $transform->file('Module.pm'); # prints Doxygen docs for use as a doxygen filter $transform->file('Module.pm' => \*STDOUT);
This module is normally used by the script ppi_transform_doxygen that is part of this distribution and acts as a doxygen input filter (look for INPUT_FILTER in the Doxygen docs).
There is already Doxygen::Filter::Perl doing roughly the same task, but it uses special doxygen comments.
The goal of PPI::Transform::Doxygen is to use only POD documentation with a minimal amount of special syntax, while still producing decent results with doxygen.
As doxygen is not able to parse perl directly, the input filter will convert the source so that it will look like C++.
The only thing really needed, is documenting your methods and functions with a POD tag =head2 that contains a function string with parentheses ( it has to match the regular expression /[\w:]+\(.*\)/) like so:
=head2 do_things() This function does things =cut sub do_things { print "Hi!\n"; }
or so:
=head2 class_method $obj THINGY::new(%args) Creates a new THINGY object =cut sub new { my($class, %args) = @_; return bless(\%args, $class); }
All other POD documentation (including other =head2 tags) is added as HTML (provided by Pod::POM::View::HTML) into the Doxygen section named Detailed Description. IMHO it looks better when this is at the top of the doxygen docs. Look under "DETAILS ON TOP" on how to do that.
The complete syntax of a =head2 function description is:
=head2 [<category>] [<return_value>] <name>(<parameters>)
The category defines the type of the function definition. The values function and class_method result in the function being tagged as static for Doxygen. Other values will be ignored, which will result interpreting the function as method.
function
class_method
Since Doxygen expects C++ input, a return value is mandatory and will default to void. A given string will be passed to Doxygen as is, so be careful with non word characters.
The function name with optional package name e.g. My::Module::test. The module will try to map the function name to the current package when none is given. If your code is correctly parsable with PPI, then this should work.
My::Module::test
If the corresponding subroutine is not found it will be tagged as virtual to Doxygen. This is useful for dynamically generated functions (e.g via AUTOLOAD). Yes this has nothing to do with the C++ virtual keyword, but so what? If you want to have the virtual subroutine mapped to the correct namespace you will have to add it to the subs name (e.g. MyClass::mysub() )
MyClass::mysub()
Subroutine names with leading underscore will be tagged as private for Doxygen.
If there is no package declaration, the subroutine is created in the main namespace, named <script_or_module_name>_main.
<script_or_module_name>_main
The subroutine's comma separated parameter list. References are given in dereference syntax so %$varname specifies a hash reference. This will be given as type name to Doxygen e.g. subname(hash_ref varname).
%$varname
type name
subname(hash_ref varname)
If you are using subroutine signatures, they will be parsed for information and you can put the pod after the sub declaration like so:
sub my_sig_sub ($self, $first = 'default', $second=[], %args) { =for method $self Sub documentation. =cut print join(' ', $first, @$second), "\n"; return $self; }
In that case there is no redundant information you'll have to synchronize on each change. In that case the first parameter behind the =for has to be method, function or class_method. The second parameter specifies the return value. Both parameters must be present because the =for tag requires them. There are no defaults.
method
A conflicting =head2 declaration for the same subroutine will take precedence.
For having the non subroutine POD documentation at the top of the Doxygen page do the following:
Create a doxygen layout XML file with doxygen -l
doxygen -l
Edit the XML file. Move <detaileddescription title=""/> up to the line directly behind <briefdescription visible="yes"/>
<detaileddescription title=""/>
<briefdescription visible="yes"/>
Specify the file under LAYOUT_FILE in your Doxyfile.
LAYOUT_FILE
Constructor
There are 3 optional arguments for extracting a version number, a revision number and the parent class. Their values have to consist of a regex with one capture group. The key <overwrite> defines the behaviour when there is no output device on calling <file()>. Default behaviour is to append the doxygen docs after an __END__ Token. Setting overwrite to a true value will overwrite the input file.
<overwrite
<file()
The defaults are:
rx_version => qr/our\s*\$VERSION\s*=\s*["']([\d\.]+)/, rx_revision => qr/\$(?:Id|Rev|Revision|LastChangedRevision)\:\s*(\d+)\s*\$/, rx_parent => qr/use\s+(?:base|parent|Mojo::Base)\s+["']?([\w:]+)["']?/, overwrite => 0,
Start the transformation reading from $in and saving to $out. $in has to be a filename and $out can be a filename or a filehandle. If $out is not given, behaviour is defined by the parameter overwrite (see new()).
$in
$out
new()
This is normally called by file() (see the docs for PPI::Transform). It will convert a PPI::Document object in place.
file()
Thomas Kratz <tomk@cpan.org>
https://github.com/tomk3003/ppi-transform-doxygen
Copyright 2016-2018 Thomas Kratz.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install PPI::Transform::Doxygen, copy and paste the appropriate command in to your terminal.
cpanm
cpanm PPI::Transform::Doxygen
CPAN shell
perl -MCPAN -e shell install PPI::Transform::Doxygen
For more information on module installation, please visit the detailed CPAN module installation guide.