';
$doc .= "
- Author:
- $info->{author}
"
if $info->{author};
$doc .= "
- Version:
- $info->{Version}
"
if $info->{Version};
$doc .= "
- Since:
- $info->{since}
"
if $info->{since};
$doc .= join('', "
- See Also:
- ", _makeSeeLinks($info->{see}, $pathpfx), "
")
if $info->{see};
$doc .= "
Class instances are $info->{instance} references.
"
if $info->{instance};
$doc .= "
Unless otherwise noted, $info->{self} is the object instance variable.
"
if $info->{self};
#
# process imports
#
$doc .= join('', "
| Imported Symbols |
", _makeExportDesc($info->{imports}, '_i_'), "
")
if $info->{imports};
#
# process exports
#
$doc .= join('', "
| Exported Symbols |
", _makeExportDesc($info->{exports}, '_e_'), "
")
if $info->{exports};
#
# process members
#
$doc .= join('', "
| Public Instance Members |
", _makeExportDesc($info->{member}, '_m_'), "
")
if $info->{member};
#
# collect method map info before processing
#
my %methodmap = ();
while (my($sub, $methodinfo) = each %{$info->{Methods}}) {
$methodmap{$sub} = [ $methodinfo->{File}, $methodinfo->{Line} ]
unless (!$use_private) &&
(substr($sub, 0, 1) eq '_') &&
(!$methodinfo->{constructor});
}
#
# process constructors. Scan for methods with descriptions with '@constructor'
#
$doc .= "
";
my %constructors = ();
my $constructor;
my $anchored;
foreach (sort keys %{$info->{Methods}}) {
next
unless exists $info->{Methods}{$_}{constructor};
$anchored = 1,
$doc .= "
",
unless $anchored;
$doc .= "
| Constructor Summary |
"
unless $constructor;
$constructor = $constructors{$_} = delete $info->{Methods}{$_};
$doc .= join('', "
$_", _makeParamList($constructor->{param}), "
");
if ($constructor->{deprecated}) {
$doc .= '
Deprecated. ' .
(($constructor->{deprecated} ne '1') ? "$constructor->{deprecated}" : '');
}
elsif ($constructor->{Description}) {
my $descr = $constructor->{Description};
my $brief = _briefDescription(($descr=~/^\s*Constructor\.\s*(.*)$/s) ? $1 : $descr);
$doc .= "
$brief
";
}
$doc .= " |
\n";
} # end for constructors
$info->{constructors} = \%constructors;
if ($constructor) {
$doc .= "
\n"
}
else {
$doc=~s!CONSTR!CONSTR!;
$doc=~s!CONSTR!CONSTR!;
}
#
# process methods
#
my @methods = sort keys %methodmap;
my $methcount = @methods;
if ($methcount) {
$doc .= "
| Method Summary |
";
foreach (@methods) {
my $method = $info->{Methods}{$_};
$doc .= join('', "
$_", _makeParamList($method->{param}), "
");
if ($method->{deprecated}) {
$doc .= '
Deprecated. ' .
(($method->{deprecated} ne '1') ? "$method->{deprecated}" : '');
}
elsif ($method->{Description}) {
my $descr = ($method->{static} ? "(class method) " : '') . $method->{Description};
my $brief = _briefDescription($descr);
$doc .= "
$brief
";
}
$doc .= " |
\n";
}
$doc .= "
";
}
else {
$doc=~s!METHOD!METHOD!;
$doc=~s!METHOD!METHOD!;
}
if (keys %constructors) {
$doc .= "
";
foreach (sort keys %constructors) {
my $method = $constructors{$_};
my $returns = $method->{return};
my $descr = $method->{Description} || ' ';
$descr=~s/^\s*Constructor\.\s*//;
$doc .= join('', "
$_
$_", _makeParamList($method->{param}), "
- $descr
");
$doc .= join('', "- Parameters:\n", _makeParamDesc($method->{param}))
if $method->{param};
$doc .= "
- Returns:
- $returns
\n"
if $returns;
$doc .= "- Since:
- $method->{since}
\n"
if $method->{since};
$doc .= join('', "- See Also:
- ", _makeSeeLinks($method->{see}, $pathpfx), "
\n")
if $method->{see};
$doc .= "
\n";
}
$doc .= "\n\n";
} # end if constructor
if ($methcount) {
$doc .= "
";
foreach (@methods) {
my $method = $info->{Methods}{$_};
my $returns = $method->{return};
my $returnlist = $method->{returnlist};
my $descr = ($method->{static} ? "(class method) " : '') .
($method->{Description} || ' ');
$doc .= join('', "
$_
$_", _makeParamList($method->{param}), "
- $descr
");
if ($method->{simplex}) {
$doc .= ($method->{urgent} ?
"- Simplex, Urgent
\n" :
"- Simplex
\n");
}
elsif ($method->{urgent}) {
$doc .= "- Urgent
\n";
}
$doc .= join('', "- Parameters:\n", _makeParamDesc($method->{param}))
if $method->{param};
if ($returns) {
$doc .= ($returnlist ?
"
- In scalar context, returns:
- $returns
\n" :
"- Returns:
- $returns
\n");
}
$doc .= ($returns ?
"- In list context, returns:
- ($returnlist)
\n" :
"- Returns:
- ($returnlist)
\n")
if $returnlist;
$doc .= "- Since:
- $method->{since}
\n"
if $method->{since};
$doc .= join('', "- See Also:
- ", _makeSeeLinks($method->{see}, $pathpfx), "
\n")
if $method->{see};
$doc .= "
\n";
} # end foreach method
} # end if methods
#
# finish up
#
my $tstamp = scalar localtime();
$doc .= "
Generated by POD::ClassDoc $VERSION on $tstamp
";
return [ $doc, $info->{File}, $info->{Line}, \%methodmap ];
}
#
# generate a path from a class, along with
# an updir path from the class
#
sub _pathFromClass {
my $class = shift;
my @parts = split /\:\:/, $class;
pop @parts;
return ( '../' x (scalar @parts), join('/', @parts));
}
sub _parseTags {
my ($self, $class, $info, $validtags) = @_;
#
# expand all , , , and tags
# NOTE: need a nesting level to construct updir prefixes
#
my ($updir, $path) = _pathFromClass($class);
my @parts = ();
my $method;
$updir ||= '';
$info->{Description}=~s!([^<]+)!$1!g;
$info->{Description}=~s!<(export|import|method|member)>(\w+)(?:export|import|method|member)>!$2!g;
$info->{Description}=~s!<(export|import|method|member|package)>([\w\:]+)(?:export|import|method|member|package)>!
{ @parts = split('\:\:', $2); $method = ($1 eq 'package') ? '' : pop @parts;
"$2" }!egx;
#
# process classdoc sections
#
my $desc = '';
my @lines = split /\n/, $info->{Description};
my $tag = 'Description';
my $param;
my ($ttag, $tdesc);
my $sep = "\n";
foreach (@lines) {
s/^#\*?\s*//;
$desc .= "$_$sep",
next
unless /^\@(\w+)(\s+(.*))?$/ && $validtags->{$1};
($ttag, $tdesc) = ($1, $3);
if (($tag eq 'param') || ($tag eq 'optional') || ($tag eq 'exports') || ($tag eq 'imports') || ($tag eq 'member')) {
($param, $desc) = ($desc=~/^\s*((?:[\\]?[\$\%\@\*\&])?[\w\:]+)\s*(.*)$/s);
$tag = 'param',
$desc = '(optional)' . $desc
if ($tag eq 'optional');
push @{$info->{$tag}}, $param, $desc;
}
elsif ($tag eq 'see') {
push @{$info->{$tag}}, $desc;
}
else {
chop $desc, chop $desc if ($sep ne "\n");
$info->{$tag} = $desc;
}
$tag = $ttag;
$desc = $tdesc || 1;
$sep = ($validtags->{$tag} == 1) ? "\n" : ",\n";
$desc .= $sep;
}
#
# don't forget the last one!
#
if (($tag eq 'param') || ($tag eq 'optional') || ($tag eq 'exports') || ($tag eq 'imports') || ($tag eq 'member')) {
($param, $desc) = ($desc=~/^\s*((?:[\\]?[\$\%\@\*\&])?[\w\:]+)\s*(.*)$/s);
$tag = 'param',
$desc = '(optional)' . $desc
if ($tag eq 'optional');
push @{$info->{$tag}}, $param, $desc;
}
elsif ($tag eq 'see') {
push @{$info->{$tag}}, $desc;
}
else {
chop $desc, chop $desc if ($sep ne "\n");
$info->{$tag} = $desc;
}
}
sub _makeParamList {
my $params = shift;
my $p = '(';
my $t;
my $i = 0;
$t = $params->[$i++],
$i++,
$p .= ($t=~/^[\\]?[\$\%\@\*\&]/) ? "$t, " : "$t => value, "
while ($i < $#$params);
chop $p,
chop $p
if (length($p) > 1);
return "$p)";
}
sub _makeParamDesc {
my $params = shift;
my $p = '';
my ($t, $d, $sep);
my $i = 0;
$t = $params->[$i++],
$d = $params->[$i++],
$sep = ($t=~/^[\\]?[\$\%\@\*\&]/) ? ' - ' : ' => ',
$p .= "$t | $sep | $d |
\n"
while ($i < $#$params);
return $p . "
\n";
}
sub _makeExportDesc {
my ($params, $pfx) = @_;
my $p = '';
my %t = @$params;
return join("\n",
map "$_ | $t{$_} |
", sort keys %t) . "\n";
}
sub _getSubDirs {
my ($self, $path) = @_;
$@ = "$path directory not found",
return undef
unless opendir(PATH, $path);
push @{$self->{_dirs}}, $path;
#
# glob the directory for all subdirs
#
my @files = readdir PATH;
closedir PATH;
foreach (@files) {
push(@{$self->{_dirs}}, "$path/$_")
if ($_ ne '.') && ($_ ne '..') && (-d "$path/$_");
}
return $self;
}
sub _makeSeeLinks {
$_[0][-1]=~s/,\n$/\n/;
return join("
\n", @{$_[0]}) . "\n";
}
sub _briefDescription {
my $descr = shift;
while ($descr=~/\G.*?((?:]*>[^<]*<\/a>)|\.|\?|\!)/igcs) {
return substr($descr, 0, $+[1]) if ($1 eq '.') || ($1 eq '?') || ($1 eq '!');
}
return $descr;
}
1;