File Coverage

blib/lib/Pod/Inherit.pm
Criterion Covered Total %
statement 346 405 85.4
branch 164 252 65.0
condition 41 63 65.0
subroutine 34 41 82.9
pod 3 4 75.0
total 588 765 76.8


line stmt bran cond sub pod time code
1             # *sigh* Pod::Tree does this with a simple get_deep_text method...
2              
3             ### TODO: This should probably be its own distro ###
4             package Pod::POM::View::TextStrip;
5              
6 6     6   77452 use parent 'Pod::POM::View::Text';
  6         1117  
  6         47  
7              
8 0     0   0 sub view_seq_bold { $_[1] }
9 0     0   0 sub view_seq_italic { $_[1] }
10 1     1   80 sub view_seq_code { $_[1] }
11 0     0   0 sub view_seq_file { $_[1] }
12 0     0   0 sub view_verbatim { $_[1] }
13             sub view_seq_link {
14 0     0   0 my ($self, $link) = @_;
15 0         0 $link =~ s/^.*?\|//;
16 0         0 return $link;
17             }
18              
19             1;
20              
21             package Pod::Inherit;
22              
23 6     6   91932 use warnings;
  6         19  
  6         224  
24 6     6   50 use strict;
  6         12  
  6         228  
25              
26 6     6   6025 use MRO::Compat;
  6         23604  
  6         184  
27 6     6   5416 use Sub::Identify;
  6         6981  
  6         306  
28 6     6   6862 use Pod::POM;
  6         267174  
  6         379  
29 6     6   14699 use List::AllUtils qw(any first firstidx);
  6         33962  
  6         685  
30 6     6   8984 use Class::Load;
  6         211751  
  6         358  
31 6     6   60 use Carp;
  6         13  
  6         547  
32              
33             our $DEBUG = 0;
34              
35             # Eww, monkeypatching. Also, eww, replacing Perl's exception handling... poorly.
36             BEGIN {
37 6     6   903 delete $Pod::POM::Node::{error};
38             }
39             sub Pod::POM::Node::error {
40 0     0 0 0 my ($self, @rest) = @_;
41 0         0 print STDERR Carp::longmess;
42 0         0 die "->error on Pod::POM::Node: @rest";
43             }
44              
45 6     6   5497 use Path::Class;
  6         235036  
  6         423  
46 6     6   51 use Scalar::Util 'refaddr';
  6         14  
  6         11592  
47             our $VERSION = '0.91';
48              
49             =head1 NAME
50              
51             Pod::Inherit - auto-create POD sections listing inherited methods
52              
53             =head1 SYNOPSIS
54              
55             use Pod::Inherit;
56              
57             my $config = {
58             out_dir => "/usr/src/perl/dbix-class/bast/DBIx-Class/0.08/trunk/doc",
59             input_files => ['/usr/src/perl/dbix-class/bast/DBIx-Class/0.08/trunk/lib/'],
60             skip_underscored => 1,
61             class_map => {
62             'DBIx::Class::Relationship::HasMany' => 'DBIx::Class::Relationship',
63             'DBIx::Class::Relationship::HasOne' => 'DBIx::Class::Relationship',
64             'DBIx::Class::Relationship::BelongsTo' => 'DBIx::Class::Relationship',
65             'DBIx::Class::Relationship::ManyToMany' => 'DBIx::Class::Relationship',
66             'DBIx::Class::ResultSourceProxy' => 'DBIx::Class::ResultSource',
67             'DBIx::Class::ResultSourceProxy::Table' => 'DBIx::Class::ResultSource',
68             },
69             skip_classes => [
70             'lib/DBIx/Class/Serialize/Storable.pm',
71             'DBIx::Class::Serialize::Storable',
72             ],
73             skip_inherits => [ qw/
74             DBIx::Class::Componentised
75             Class::C3::Componentised
76             / ],
77             force_inherits => {
78             'lib/DBIx/Class/ResultClass.pod' => 'DBIx::Class::Core',
79             'DBIx::Class::AccessorGroup' => [
80             'Class::Accessor',
81             'Class::Accessor::Grouped'
82             ]
83             },
84             method_format => 'L<%m|%c/%m>',
85             dead_links => '',
86             debug => 1,
87             };
88              
89             my $pi = Pod::Inherit->new( $config });
90             $pi->write_pod;
91              
92             =head1 DESCRIPTION
93              
94             Ever written a module distribution with base classes and dependencies,
95             that had the POD for the various methods next to them, but hard to
96             find for the user of your modules? Ever wished POD could be
97             inheritable? Now it can.
98              
99             This module will B each of the classes in the list of input
100             files or directories given (default: C<@ARGV>), auto-discover which
101             methods each class provides, locate the actual class the method is
102             defined in, and produce a list in POD.
103              
104             The resulting documentation is written out to a separate F<.pod> file
105             for each class (F<.pm>) encountered. The new file contains the
106             original POD from the Perl Module file, plus a section called
107             C. The new section lists each class that the
108             current class inherits from, plus each method that can be used in the
109             current class as a result.
110              
111             By default, methods beginning with an underscore, C<_> are skipped, as
112             by convention these are private methods.
113              
114             =head2 METHODS
115              
116             =head3 new
117              
118             =over
119              
120             =item B \%config
121              
122             =item B Pod::Inherit object
123              
124             =back
125              
126             Create a new Pod::Inherit object.
127              
128             =head3 \%config
129              
130             The config hashref can contain the following keys:
131              
132             =head4 skip_underscored
133              
134             =over
135              
136             =item B boolean
137              
138             =item B true
139              
140             =back
141              
142             Do not display inherited methods that begin with an underscore. Set to
143             0 to display these as well.
144              
145             =head4 input_files
146              
147             =over
148              
149             =item B [ @directories ] | $directory
150              
151             =item B [ @ARGV ]
152              
153             =back
154              
155             Arrayref of directories to search for F<.pm> files in, or a list of
156             F<.pm> files or a mixture.
157              
158             =head4 out_dir
159              
160             =over
161              
162             =item B $directory
163              
164             =item B Same as input_files
165              
166             =back
167              
168             A directory to output the results into. If not supplied, the F<.pod>
169             file is created alongside the F<.pm> file it came from.
170              
171             =head4 force_permissions
172              
173             =over
174              
175             =item B boolean
176              
177             =item B false
178              
179             =back
180              
181             ExtUtils::MakeMaker makes directories in blib read-only before we'd
182             like to write into them. If this is set to a true value, we'll catch
183             permission denied errors, and try to make the directory writeable,
184             write the file, and then set it back to how it was before.
185              
186             =head4 class_map
187              
188             =over
189              
190             =item B { $class_only => $class_only, ... }
191              
192             =item B none
193              
194             =back
195              
196             The keys represent classes in which inherited methods will be found;
197             the values are the classes which it should link to in the new POD for
198             the actual POD of the methods.
199              
200             Some distributions will already have noticed the plight of the users,
201             and documented the methods of some of their base classes further up
202             the inheritance chain. This config option lets you tell Pod::Inherit
203             where you moved the POD to.
204              
205             =head4 skip_classes
206              
207             =over
208              
209             =item B [ @class_or_pm_files ] | $class_or_pm_file
210              
211             =item B none
212              
213             =back
214              
215             Any class/file found in the list will be skipped for POD creation.
216              
217             =head4 skip_inherits
218              
219             =over
220              
221             =item B [ @classes_only ] | $classes_only
222              
223             =item B none
224              
225             =back
226              
227             This is a list of classes that shouldn't show up in any of the
228             C sections. Good candidates include:
229              
230             Class::C3::Componentised
231             Any other *::Componentised
232             Class::Accessor::Grouped
233             Moose::Object or most Moose stuff
234             Exporter
235              
236             =head4 force_inherits
237              
238             =over
239              
240             =item B { $class_or_pmpod_file => $class_only | [ @classes_only ], ... }
241              
242             =item B none
243              
244             =back
245              
246             A hashref of arrayrefs. Like the opposite of skip_inherits, this
247             will forcefully add the classes listed to the C
248             sections, except this will only work on a per-class basis. The keys
249             represent the classes affected; the values are arrayrefs (or single
250             strings) specifying which classes to add.
251              
252             In order to access the methods for the new modules, we'll need to
253             load them manually after the main class is loaded. If there are
254             some sort of weird conflicts, this may cause undesirable results.
255             Also, any methods that the NEW module inherits will also be added
256             to the method list.
257              
258             You can also use this option to add a C to a
259             separate POD file. Note that this is the B case where a POD
260             would get loaded and read, since it really can't work otherwise.
261             Also, be sure to specify a different output directory, else you will
262             likely overwrite your existing POD.
263              
264             =head4 method_format
265              
266             =over
267              
268             =item B $format_string
269              
270             =item B '%m'
271              
272             =back
273              
274             A string with a few custom percent-encoded variables. This string
275             will be used on each method name found when writing the new POD
276             section. The custom variables are:
277              
278             %m = method name
279             %c = class name
280             %% = literal percent sign
281              
282             Thus, the default just prints out the method name, unaltered.
283              
284             This string can be used to add method links to the POD files (like
285             C<'LZ<><%m|%c/%m>'>), or to change the formatting (like C<'CZ<><%m>'>).
286              
287             =head4 dead_links
288              
289             =over
290              
291             =item B $format_string
292              
293             =item B undef
294              
295             =back
296              
297             A string with the same format as C. This is the
298             string used for methods that don't exist in the inherited module's
299             documentation. A blank string (C<''>) will remove any dead links.
300             The default is to not check for dead links.
301              
302             This option typically only makes sense if C is a
303             link, but it can be used to automatically remove undocumented
304             methods or present them in a different manner.
305              
306             =head4 debug
307              
308             =over
309              
310             =item B 0|1|2
311              
312             =item B 0
313              
314             =back
315              
316             A debug level of 1 will print out a managable level of debug
317             information per module. To get POD outputs, set this to 2.
318              
319             This used to be set with C<$Pod::Inherit::DEBUG>, but this property
320             is now preferred. However, the old method still works for
321             backwards-compatibility.
322              
323             =cut
324              
325             sub new {
326 27     27 1 142773 my ($class, $args) = @_;
327 27 50       527 $args = {
328             skip_underscored => 1,
329             input_files => [], # \@ARGV,
330             out_dir => '',
331             class_map => {},
332             skip_classes => [],
333             skip_inherits => [],
334             force_inherits => {},
335             method_format => '%m',
336 27         136 %{ $args || {} },
337             };
338              
339 27   50     261 $DEBUG = $args->{debug} || 0;
340 27 50       204 if ($DEBUG >= 2) {
341 0         0 require Data::Dump::Streamer;
342 0         0 Data::Dump::Streamer->import('Dump');
343             }
344              
345             # Accept just a single filename in here -- OR A SINGLE Path::Class::File!
346 27         116 for (qw/input_files skip_classes skip_inherits/) {
347 81 100       392 $args->{$_} = [$args->{$_}] if not ref($args->{$_}) eq 'ARRAY';
348             }
349 27 50       138 if (my $fi = $args->{force_inherits}) {
350 27         193 for (keys %$fi) {
351 4 100       21 $fi->{$_} = [$fi->{$_}] if not ref($fi->{$_}) eq 'ARRAY';
352             }
353             }
354              
355 27         107 my $self = bless($args, $class);
356              
357             # deep cleaning of the "any" types: skip_classes & force_inherits keys
358 27         60 @{$self->{skip_classes}} = grep { ref } map { $self->_any_to_type_array($_, 0, 'skip_classes'); } @{$self->{skip_classes}};
  27         92  
  6         10  
  6         35  
  27         101  
359              
360 27 50       127 if (my $fi = $self->{force_inherits}) {
361 27         152 $self->{force_inherits_type} = {}; # we can't just put an ARRAYREF on a key
362 27         230 my @fi_keys = keys %$fi;
363              
364 27         71 foreach my $dest_doc (@fi_keys) {
365 4         51 my $type_any = $self->_any_to_type_array($dest_doc, 1, 'force_inherits keys');
366 4 50       28 unless ($type_any) {
367 0         0 delete $fi->{$dest_doc};
368 0         0 next;
369             }
370              
371 4         11 my ($type, $any) = @$type_any;
372 4         12 $self->{force_inherits_type}{$any} = $type;
373              
374             # need to delete the old key after adding the new one
375 4 50       86 if ($dest_doc ne $any) {
376             # if $fi->{$any} already exists, combine them
377 0 0       0 $fi->{$any} = $fi->{$any} ? [ @{$fi->{$any}}, @{$fi->{$dest_doc}} ] : $fi->{$dest_doc};
  0         0  
  0         0  
378 0         0 delete $fi->{$dest_doc};
379             }
380             }
381             }
382              
383 27         134 return $self;
384             }
385              
386             =head3 write_pod
387              
388             =over
389              
390             =item B none
391              
392             =item B 1 on success
393              
394             =back
395              
396             Run the pod creation stage.
397              
398             =cut
399              
400             sub write_pod {
401 27     27 1 19569 my ($self) = @_;
402              
403 27         162 my ($fi, $fit) = ($self->{force_inherits}, $self->{force_inherits_type});
404 26 100       1067 my @targets = map {
405             # The origtarget needs to be a directory; if it's a file, lie and claim to the rest
406             # of the code that the user passed the directory containing this file.
407 27         81 -d $_ ? [$_, $_] : [$_, Path::Class::File->new($_)->dir]
408 27         58 } @{ $self->{input_files} };
409              
410 27 100       4189 die "no targets" if (!@targets);
411              
412 26         89 while (@targets) {
413 102         180 my ($target, $origtarget) = @{shift @targets};
  102         272  
414 102 50       323 print "target=$target origtarget=$origtarget \n" if ($DEBUG);
415              
416 102 100       1113 my $filename = (-d $target ? Path::Class::Dir->new($target) : Path::Class::File->new($target))->cleanup->resolve;
417 101         133886 my $classname = $self->_pure_filename_to_classname( $filename->relative($origtarget) );
418              
419             # Check skip list before we do anything
420 101 100   144   1105 if ( my $skipped = first { $self->_match_filename_to_type_array($classname, $filename, $_); } @{$self->{skip_classes}} ) {
  144         3550  
  101         569  
421 6 0       184 print " target skipped per skip_classes: ".(ref $skipped ? $skipped->[1] : $skipped)."\n" if ($DEBUG);
    50          
422 6         63 next;
423             }
424              
425 95 100       3266 if (-d $target) {
426 6 50       100 print " directory: adding children as new targets\n" if ($DEBUG);
427 6         29 unshift @targets, map { [$_, $origtarget] } ($filename->children);
  76         14433  
428 6         48 next;
429             }
430              
431 89         3470 my $should_process = 0;
432 89 100       33773 $should_process = 1 if ($target =~ m/\.pm$/);
433 89 100       2638 if ($target =~ m/\.pod$/) {
434 9 50       320 print " POD: found\n" if ($DEBUG);
435 9 100   10   80 if (my $forced = first { $self->_match_filename_to_type_array($classname, $filename, [$fit->{$_}, $_]); } keys %$fi) {
  10         118  
436 4 50       80 print " POD: processing due to force_inherits match: $forced\n" if ($DEBUG);
437 4         9 $should_process = 1;
438             }
439             }
440              
441 89 100       2119 if ($should_process) {
442 81 100       356 my $output_filename = $self->{out_dir} ? $filename->relative($origtarget)->absolute($self->{out_dir}) : $filename;
443              
444 81         32887 $output_filename =~ s/\.pm$/.pod/;
445 81         5895 $output_filename = Path::Class::File->new($output_filename);
446              
447 81 100       6910 if ($self->_is_ours($output_filename)) {
448 80         326 my $allpod = $self->create_pod($target, $origtarget);
449             # Don't create the output file if there would be nothing in it!
450 80 100       296 if (!$allpod) {
451 41 50       150 print " not creating empty file $output_filename\n" if ($DEBUG);
452 41         410 next;
453             }
454              
455 39         187 my $dir = $output_filename->dir;
456 39         412 my $ret = $dir->mkpath;
457              
458 39         8201 my ($outfh, $oldperm);
459 39 50       145 print " Writing $output_filename\n" if ($DEBUG);
460 39 50       214 unless ( $outfh = $output_filename->open('w') ) {
461 0 0 0     0 if ($!{EACCES} and $self->{force_permissions} ) {
462 0         0 $output_filename->remove;
463 0         0 $oldperm = $dir->stat->mode;
464 0 0       0 chmod $oldperm | 0200, $dir or die "Can't chmod ".$dir." (or write into it)";
465 0 0       0 $outfh = $output_filename->open('w') or die "Can't open $output_filename for output (even after chmodding it's parent directory): $!";
466             } else {
467 0         0 die "Can't open $output_filename for output: $!";
468             }
469             }
470              
471 39         20852 $outfh->print($allpod);
472 39         8526 $outfh->close;
473 39 50       19378 if (defined $oldperm) {
474 0 0       0 chmod $oldperm, $dir or die sprintf "Can't chmod %s back to 0%o", $dir, $oldperm;
475             }
476             }
477             }
478             }
479              
480 25         122 return 1;
481             }
482              
483             =pod
484              
485             =head3 create_pod
486              
487             =over
488              
489             =item B $src, $root_dir?
490              
491             =item B $pod_text | undef
492              
493             =back
494              
495             Creates a POD file. Actually, this just outputs the text of the
496             resulting file, so it's up to you to write this somewhere. If the POD
497             wouldn't produce a C, this will return undef.
498              
499             Strange situations, such as non-existant files, do/require problems,
500             etc. will warn and return undef as well.
501              
502             The optional $root_dir would basically be whatever lib/blib directory
503             is in the $src, used mainly for POD->Class conversion. That part of
504             the directory would still need to be on $src.
505              
506             =cut
507              
508             sub create_pod {
509 80     80 1 172 my ($self, $src, $root_dir) = @_;
510 80         175 my $class_map = $self->{class_map};
511 80 50       284 die "create_pod needs a source file argument!" unless ($src);
512              
513             # Canonize src; not only does not doing it produce a minor testing & prettiness problem
514             # with the generated-data comment, far more importantly, it will keep require from
515             # knowing that t/lib//foo and t/lib/foo are the same library, leading to "redefined"
516             # warnings.
517 80         676 $src = Path::Class::File->new($src)->cleanup->resolve;
518              
519 80         79084 my ($fi, $fit) = ($self->{force_inherits}, $self->{force_inherits_type});
520 80         139 my ($tt_stash, $classname, @isa_flattened);
521              
522 80 100       271 unless ($src =~ m/\.pod$/) {
523 76   100     2656 $classname = $tt_stash->{classname} = $self->_require_class($src) || return;
524 73         137 @isa_flattened = @{mro::get_linear_isa($classname)};
  73         696  
525             }
526             # here be PODs
527             else {
528 4 50       158 $classname = $tt_stash->{classname} = $self->_pure_filename_to_classname( $root_dir ? $src->relative($root_dir) : $src );
529 4         29 $self->_check_pod_sections($src, $classname);
530             }
531              
532             # Check for force inherits to add
533 77   100 70   939 my $force_inherits = (first { $self->_match_filename_to_type_array($classname, $src, [$fit->{$_}, $_]); } keys %$fi) || '';
  70         970  
534 77         1059 $force_inherits = $fi->{$force_inherits};
535 77 100       533 if ($force_inherits) {
536             # Forced inherits still need to be loaded manually
537 4         15 foreach my $class (@$force_inherits) {
538 6 50       18 print " Found force inherit: $class\n" if ($DEBUG);
539 6 50       22 $self->_require_class(undef, $class) || return;
540 6         11 push @isa_flattened, @{mro::get_linear_isa($class)};
  6         60  
541             }
542             }
543              
544             # Now for ones to skip (including its own class)
545 77         127 foreach my $s ( @{ $self->{skip_inherits} }, $classname ) {
  77         268  
546 113         358 for (my $i = 0; $i < @isa_flattened; $i++) {
547 178 100       624 if ($s eq $isa_flattened[$i]) {
548 81 50       194 print " Skipped per skip_inherits: $s\n" if ($DEBUG);
549 81         398 splice(@isa_flattened, $i--, 1);
550             }
551             }
552             }
553              
554             # We can't possibly find anything. Just short-circuit and save ourselves a lot of trouble.
555 77 100       255 if (!@isa_flattened) {
556 33 50       73 print " No parent classes\n" if ($DEBUG);
557 33         143 return;
558             }
559 44         140 $tt_stash->{isa_flattened} = \@isa_flattened;
560              
561             # Read POD sections for new classes
562 44 100       167 if (exists $self->{dead_links}) {
563 6         11 foreach my $class (@isa_flattened) {
564 8         18 $self->_check_pod_sections(undef, $class);
565             }
566             }
567              
568 44         107 my %seen;
569 44         125 for my $parent_class (@isa_flattened) {
570 57 50       245 print " Parent class: $parent_class\n" if ($DEBUG);
571 57         81 my $stash;
572             {
573 6     6   44 no strict 'refs';
  6         12  
  6         18688  
  57         74  
574 57         73 $stash = \%{"$parent_class\::"};
  57         207  
575             }
576             # There's something subtle and brain-melting going on here, but I think it works.
577 57         143 my $local_config = $stash->{_pod_inherit_config};
578 57 100       180 if (not exists $local_config->{skip_underscored}) {
579 45         140 $local_config->{skip_underscored} = $self->{skip_underscored};
580             }
581 57   66     257 $local_config->{class_map} ||= $class_map;
582              
583 57         370 for my $globname (sort keys %$stash) {
584 167 100 100     688 next if ($local_config->{skip_underscored} and $globname =~ m/^_/);
585 158 100       366 next if $seen{$globname};
586              
587             # Skip the typical UPPERCASE sub blocks that aren't really user-friendly methods
588 149 100       695 next if ($globname =~ m/^(?:AUTOLOAD|CLONE|DESTROY|BEGIN|UNITCHECK|CHECK|INIT|END)$/);
589              
590 92         434 my $glob = $stash->{$globname};
591             # Skip over things that aren't *code* globs, and cache entries.
592             # (You might think that ->can will return false for non-code globs. You'd be right. It'll return true
593             # for cache globs, and we want to skip those, so that we'll get them later.)
594 92         138 my $exists;
595 92         239 eval {
596             # Don't next here directly, it'll cause a warning.
597 92         191 $exists = exists &$glob;
598             };
599 92 50       304 if ($@) {
600             # This specific error happens in DBIx::Class::Storage O_LARGEFILE, which is exported from IO::File
601             # (I loose track of exactly how...)
602             # Strange, considering O_LARGEFILE clearly *is* a subroutine...
603 0 0       0 if ($@ =~ /Not a subroutine reference/) {
604 0 0       0 print " Got not a subref for $globname in $parent_class; it is probably imported accidentally.\n" if ($DEBUG);
605 0         0 $exists=0;
606             } else {
607 0         0 die "While checking if $parent_class $globname is a sub: $@";
608             }
609             }
610 92 100       253 next unless ($exists);
611              
612             # This should probably be in the template.
613 62         775 my $nice_name;
614 62 100       285 if ($globname eq '()') {
    100          
615 6         15 $nice_name = 'I';
616             } elsif ($globname =~ m/^\((.*)/) {
617 11         32 my $sort = $1;
618 11         53 $sort =~ s/(.)/sprintf "E<%d>", ord $1/ge;
  11         58  
619 11         37 $nice_name = "I<$sort overloading>";
620             } else {
621 45         78 $nice_name = $globname;
622             }
623              
624 62         797 my $subref = $classname->can($globname);
625 62 100 66     218 if ($force_inherits && !$subref) { # forced inherits may be the ones with the methods...
626 6         14 foreach my $class (@$force_inherits) {
627 10 100       95 $subref = $class->can($globname)
628             unless defined $subref;
629             }
630             }
631             # Must not be a method, but some other strange beastie.
632 62 50       152 next if !$subref;
633              
634 62         326 my $identify_name = Sub::Identify::stash_name($subref);
635             # No reason to list it, really. Then again, no reason not to,
636             # really... Yes there is. It's just noise for anybody who actually knows perl.
637 62 50       841 next if $identify_name eq 'UNIVERSAL';
638              
639 62 100       162 if ($identify_name ne $parent_class) {
640             # warn "Probable unexpected import of $nice_name from $identify_name into $parent_class"
641             # if $] >= 5.010;
642 14         71 next;
643             }
644             # Note that this needs to happen *after* we determine if it's a cache entry, so that we *will* get them later.
645 48         101 $seen{$globname} = $parent_class;
646             # push @derived, { $parent_class => $nice_name };
647              
648 48   66     221 my $doc_parent_class = $local_config->{class_map}->{$parent_class} || $parent_class;
649              
650             # Dead link checks
651 48 100       149 if (exists $self->{dead_links}) {
652             # Tolerate grandparent documentation for methods (but check parent first)
653 9         11 my $found_doc = 0;
654 9         12 foreach my $class ($parent_class, @isa_flattened, @{mro::get_linear_isa($parent_class)}) {
  9         33  
655 22 50   22   70 next if (first { $_ eq $class } @{ $self->{skip_inherits} });
  22         57  
  22         67  
656 22   66     107 my $map_class = $local_config->{class_map}->{$class} || $class;
657              
658             # Mapped class might have not been read for POD sections yet
659 22         45 $self->_check_pod_sections(undef, $map_class);
660              
661             # Found it!
662 22 100       75 if ($self->{pod_sections}{$map_class}{$globname}) {
663 3 50 33     12 print " Method documentation on grandparent: $map_class"."::$globname\n"
664             if ($DEBUG && $doc_parent_class ne $map_class);
665              
666 3         7 $doc_parent_class = $map_class;
667 3         3 $found_doc = 1;
668 3         7 last;
669             }
670             }
671              
672             # Skip over undocumented methods if dead_links is set to ''
673 9 100 66     51 if ($self->{dead_links} eq '' && !$found_doc) {
674 6 50       17 print " Skipped due to lack of documentation: $globname\n" if ($DEBUG);
675 6         27 next;
676             }
677             }
678              
679 42         60 push @{$tt_stash->{methods}{$doc_parent_class}}, $nice_name;
  42         228  
680 7     16   57 splice(@isa_flattened, (firstidx { $_ eq $parent_class } @isa_flattened), 0, $doc_parent_class)
  45         498  
681 42 100       332 unless (any {$_ eq $doc_parent_class} @isa_flattened);
682             }
683             }
684              
685             # There were parent classes, but we don't inherit any methods from them. Don't insert an empty section.
686 44 100       117 return if !keys %{$tt_stash->{methods}};
  44         220  
687              
688             # We used to use TT here, but TT doesn't like hash elements that have
689             # names beginning with underscores.
690              
691 39         75 my $new_pod = <<'__END_POD__';
692             =head1 INHERITED METHODS
693              
694             =over
695              
696             __END_POD__
697              
698             # Indent, so doesn't show up as POD::Inherit's own POD.
699 39         254 $new_pod =~ s/^ //mg;
700              
701 39         85 for my $class (@{$tt_stash->{isa_flattened}}) {
  39         141  
702 52 100       167 next unless ($tt_stash->{methods}{$class});
703 40         108 $new_pod .= "=item L<$class>\n\n";
704              
705             # Put in the method format
706 42         73 $new_pod .= join(", ", map {
707 40         128 my $method = $_;
708 42 50 33     616 my $mlf = (exists $self->{dead_links} && $self->{dead_links} ne '' && !$self->{pod_sections}{$class}{$method}) ?
709             $self->{dead_links} : $self->{method_format};
710 42         371 $mlf =~ s/\%m/$method/g;
711 42         108 $mlf =~ s/\%c/$class/g;
712 42         75 $mlf =~ s/\%\%/\%/g;
713 42         230 $mlf;
714 40         77 } @{$tt_stash->{methods}{$class}}) . "\n\n";
715             }
716              
717 39         79 $new_pod .= "=back\n\n=cut\n\n";
718              
719 39 50       110 print "New pod, before Pod::POMification: \n", $new_pod if ($DEBUG >= 2);
720              
721 39         446 my $parser = Pod::POM->new;
722 39 50       965 $new_pod = $parser->parse_text($new_pod)
723             or die "Generated pod invalid?";
724              
725             # examine any warnings raised
726 39         42819 foreach my $warning ($parser->warnings()) {
727 0         0 warn "Generated pod warning: $warning\n";
728             }
729              
730 39 50       476 if ($DEBUG >= 2) {
731 0         0 print "New pod, after Pod::POMification: \n";
732 0         0 print $new_pod->dump;
733             }
734              
735 39         153 $parser = Pod::POM->new;
736 39 50       733 my $pod = $parser->parse_file($src->stringify) # Make it a string again, because otherwise Pod::Parser gets confused.
737             or die "Couldn't parse existing pod in $src: ".$parser->error;
738 39         41764 my $outstr = $self->_get_inherit_header($classname, $src);
739              
740             # If set, we should go *before* the insertion point.
741             # Otherwise we should go *after*.
742 39         1385 my $before;
743             # What is the index of the section that we should be going before / after?
744             my $insertion_point;
745              
746 39         88 my $i = 0;
747 39         465 for (reverse $pod->content) {
748 13         286 $i--;
749 13 50       107 next unless $_->isa('Pod::POM::Node::Head1');
750              
751 13         78 my $title = $_->title;
752             # This should be a list of all POD sections that should be "at the end of the file".
753             # That is, things that we should go before.
754             ### TODO: Config variable? ###
755 13 100       193 if (grep {$title eq $_} qw, 'SEE ALSO', 'ALSO SEE', 'WHERE TO GO NEXT', 'COPYRIGHT AND LICENSE') {
  156         6223  
756 8 50       292 print " Fount head $title at index $i, going before that section\n" if $DEBUG;
757 8         17 $insertion_point = $i;
758 8         19 $before = 1;
759 8         16 last;
760             } else {
761 5 50       200 print " Found head $title at index $i, going after that section\n" if $DEBUG;
762 5         12 $insertion_point = $i;
763 5         11 $before = 0;
764 5         16 last;
765             }
766             }
767              
768              
769 39 100 66     1085 if (!$insertion_point and $pod->content) {
770 26 50       591 print " Going at end\n" if $DEBUG;
771 26         47 $insertion_point = -1;
772 26         42 $before = 0;
773             }
774 39 50       120 if (!$insertion_point) {
775 0 0       0 print " Going as only section\n" if $DEBUG;
776 0         0 $insertion_point = $pod;
777 0         0 $outstr .= $new_pod;
778 0         0 return $outstr;
779             }
780              
781 39 100 66     226 if (not $before and $insertion_point == -1) {
    50          
782 31         47 push @{$pod->{content}}, $new_pod;
  31         105  
783             } elsif ($before) {
784 8         15 splice(@{$pod->content}, $insertion_point-1, 0, $new_pod);
  8         76  
785             } else {
786 0         0 splice(@{$pod->content}, $insertion_point, 0, $new_pod);
  0         0  
787             }
788              
789 39         384 $outstr .= $pod;
790              
791 39         34359 return $outstr;
792             }
793              
794             ### TODO: These need to be a separate module someday ###
795             sub _file_to_package {
796 76     76   148 my ($self, $file) = @_;
797 76 50       1045 open my $fh, "<", $file or die "Can't open $file: $!";
798 76         10003 while (<$fh>) {
799 82 100       2338 return $1 if (m/^package\s+([A-Za-z0-9_:]+);/);
800 9 50       54 if (m/^package\b/) { # still not immune to "hide from PAUSE" tricks
801 0 0       0 print " Package hidden with anti-PAUSE tricks in $file\n" if ($DEBUG);
802 0         0 return undef;
803             }
804             }
805              
806 3 50       11 print " Couldn't find any package statement in $file\n" if ($DEBUG);
807 3         66 return undef;
808             }
809              
810             sub _pure_filename_to_classname {
811 105     105   23714 my ($self, $pure_filename) = @_;
812 105         331 $pure_filename =~ s/\.p(?:m|od)$//i;
813 105         2304 return join '::', split(/::|\/|\\/, $pure_filename);
814             }
815              
816             sub _any_to_pm_filename {
817 100     100   209 my ($self, $any) = @_;
818 100         314 $any =~ s/\.p(?:m|od)$//i;
819 100         1090 return Path::Class::File->new( split(/::|\/|\\/, $any.'.pm') )->cleanup;
820             }
821              
822             sub _any_to_real_file {
823 17     17   274 my ($self, $any, $try_pods, $try_dirs) = @_;
824 17         42 my $filename = $self->_any_to_pm_filename($any);
825              
826 17         3202 foreach my $d (@{ $self->{input_files} }, '.') { # include "current directory" last, wherever that is
  17         50  
827 24 50       407 my $pd = -d $d ? $d : Path::Class::File->new($d)->dir;
828 24         123 my $f = Path::Class::File->new($pd, $filename)->cleanup;
829 24 100       8914 return $f->resolve if (-f $f);
830              
831 14 100       600 next unless $try_pods;
832 8         23 $f =~ s/m$/od/;
833 8 100       600 return Path::Class::File->new($f)->resolve if (-f $f);
834              
835 4 50       15 next unless $try_dirs;
836 4         19 $f =~ s/\.pod$//;
837 4 50       45 return Path::Class::Dir->new($f)->resolve if (-d $f);
838             }
839 3         18 return undef;
840             }
841              
842             sub _any_to_type_array {
843 10     10   59 my ($self, $any, $try_pods, $value_type) = @_;
844 10 50       27 return undef unless defined $any;
845 10         9 my $type;
846 10 50       33 $value_type = $value_type ? "[Found in $value_type] " : '';
847              
848             # figure out what 'any' is
849 10         79 my $crossplat_any = Path::Class::File->new( split(/\/|\\/, $any) )->cleanup->stringify;
850 10         1837 my $real_file = $self->_any_to_real_file($any, $try_pods, 1);
851              
852 10 50       4187 if ($any =~ /::/) { $type = 'c'; } # has to be a class with ::
  0 100       0  
    100          
    50          
    50          
    50          
853 4         9 elsif ($any =~ /\.p(?:m|od)$/i) { $type = 'f'; } # has to be a file with .pm/.pod
854 2         4 elsif (-d $crossplat_any) { $type = 'd'; } # might also be a class, but take priority on existing dirs relative to .
855 0         0 elsif (-e $crossplat_any) { $type = 'f'; } # has to be a file
856             elsif ($any =~ /\/|\\/) { # assume is a file/dir that (maybe) we can't find
857 0 0       0 unless ($real_file) {
858 0         0 warn $value_type."Appears to be a file/dir, but it doesn't exist: $any";
859 0         0 return undef;
860             }
861 0 0       0 $type = -d $real_file ? 'd' : 'f';
862             }
863 4         25 elsif ($real_file) { $type = 'c'; } # this leaves top-level classes, so check to see if it exists
864             else {
865 0         0 warn $value_type."Cannot even guess to what this is, as it doesn't exist anywhere: $any";
866 0         0 return undef;
867             }
868              
869             # classes should remain as-is; file/dir should match the exact file
870 10 100 66     62 return [$type, ($type eq 'c') ? $any : ($real_file || $crossplat_any)];
871             }
872              
873             sub _match_filename_to_type_array {
874 224     224   384 my ($self, $classname, $full_filename, $type_any) = @_;
875 224 50       487 $type_any = $self->_any_to_type_array($type_any) unless ref $type_any; # this should have already been done...
876 224         360 my ($type, $any) = @$type_any;
877              
878 224 100       805 return $classname eq $any if ($type eq 'c');
879 136 100       507 return $full_filename eq $any if ($type eq 'f');
880 46 50       334 return $full_filename =~ /^\Q$any\E/ if ($type eq 'd'); # treat these as recursive matches
881 0         0 return undef;
882             }
883              
884             sub _require_class {
885 82     82   158 my ($self, $src, $classname) = @_;
886              
887 82   100     430 $classname ||= $self->_file_to_package($src) || return undef;
      66        
888 79   66     522 $src ||= $self->_any_to_real_file($classname);
889              
890             # What we had here was hack on top of hack on top of hack, and still didn't work.
891             # Fuckit. Rewrite.
892 79         4058 my $class_as_filename = $self->_any_to_pm_filename($classname);
893              
894             # Let's just snuff this one right away
895 6     6   55 no warnings 'redefine';
  6         21  
  6         5504  
896              
897 79         7739 local $|=1;
898 79         246 my $old_sig_warn = $SIG{__WARN__};
899             local $SIG{__WARN__} = sub {
900             # Still getting these; we need to filter here...
901 0 0   0   0 return if ($_[0] =~ /^(?:Constant )?[Ss]ubroutine [\w\:]+ redefined /);
902              
903 0         0 my $warning = " While loading $src: ".$_[0];
904 0 0       0 $old_sig_warn ? $old_sig_warn->($warning) : warn $warning;
905 79         739 };
906              
907             # Just like require, except without that pesky checking @INC thing,
908             # but making sure we put the "right" thing in %INC.
909 79 100       278 unless (exists $INC{$class_as_filename}) {
910             # Still no source? Great... we'll have to pray that require will work...
911 55 50 33     640 print "Still no source found for $classname; forced to use 'require'\n" if ($DEBUG && !$src);
912 55 50       154 my $did_it = $src ? do $src : Class::Load::load_optional_class($classname);
913 55 50       77888 unless ($did_it) {
914 0         0 my $err = $@;
915 0         0 $err =~ s/ \(\@INC contains: .*\)//;
916 0         0 $SIG{__WARN__} = $old_sig_warn; # only need it for the do/require
917              
918 0         0 warn "Couldn't autogenerate documentation for $src: $err\n";
919 0         0 return undef;
920             }
921             }
922             # There's what is arguably a bug in perl itself lurking here: Foo.pm
923             # dies during complation (IE not because it wasn't in @INC). An
924             # undef entry is left in %INC, but it's a READONLY undef, which
925             # means that you can't just assign something else to the slot.
926 79 100       621 $INC{$class_as_filename} = $src unless (exists $INC{$class_as_filename});
927              
928             # While we are here, check the POD text for sections
929 79         1652 $self->_check_pod_sections($src, $classname);
930              
931 79         1072 return $classname;
932             }
933              
934             sub _check_pod_sections {
935 113     113   220 my ($self, $src, $classname) = @_;
936 113 50       272 return 0 unless ($classname);
937 113 100 100     632 return 0 unless (exists $self->{dead_links} && not $self->{pod_sections}{$classname});
938              
939 21   100     67 $src ||=
      66        
940             $INC{ $self->_any_to_pm_filename($classname) } ||
941             $self->_any_to_real_file($classname, 1, 1) ||
942             return 0
943             ;
944              
945 20         576 my $hash = $self->{pod_sections}{$classname} = {};
946              
947 20         142 my $p = Pod::POM->new;
948 20   50     309 my $pom = $p->parse_file("$src") || die $p->error(); # again, Pod::POM has issues with Path::Class objects
949 20         17419 $self->_find_pod_headers($pom, $hash);
950              
951 20 50       337 if ($DEBUG) {
952 0         0 print " Found ".scalar(keys %$hash)." POD sections in $classname:\n";
953 0         0 print " ".join(', ', keys %$hash)."\n";
954             }
955              
956 20         318 return 1;
957             }
958              
959             sub _find_pod_headers {
960 73     73   116 my ($self, $top, $hash) = @_;
961              
962 73 100       396 $hash->{ $top->title->present('Pod::POM::View::TextStrip') } = 1 if ($top->type =~ /head/i);
963 73         11753 foreach my $item ($top->content) {
964 53         1219 $self->_find_pod_headers($item, $hash);
965             }
966             }
967              
968             sub _is_ours {
969 81     81   324 my ($self, $outfn) = @_;
970              
971             # If it already exists, make sure it's one of ours
972 81 100       301 if (-e $outfn) {
973 1 50       70 open my $outfh, '<', $outfn
974             or die "Can't open pre-existing $outfn for reading: $!";
975             # FIXME: Should probably check past the first line for this, in case something else placed it's autogenerated marker before ours.
976 1 50       121 if (<$outfh> ne "=for comment POD_DERIVED_INDEX_GENERATED\n") {
977 1         5 warn "$outfn already exists, and it doesn't look like we generated it. Skipping this file";
978 1         358 return 0;
979             }
980             # print "Output file already exists, but seems to be one of ours, overwriting it\n";
981             }
982              
983 80         8196 return 1;
984             }
985              
986              
987             sub _get_inherit_header {
988 39     39   110 my ($self, $classname, $src) = @_;
989              
990             # Always give source paths as unix, so the tests don't need to
991             # vary depending on what OS the user is running on. This may be
992             # construed as a bug. If you care, patches are welcome, if they
993             # fix the tests, too.
994 39         340 $src = Path::Class::File->new($src)->as_foreign('Unix');
995              
996 39         16404 return <<__END_HEADER__;
997             =for comment POD_DERIVED_INDEX_GENERATED
998             The following documentation is automatically generated. Please do not edit
999             this file, but rather the original, inline with $classname
1000             at $src
1001             (on the system that originally ran this).
1002             If you do edit this file, and don't want your changes to be removed, make
1003             sure you change the first line.
1004              
1005             =cut
1006              
1007             __END_HEADER__
1008              
1009             }
1010              
1011             1;
1012             __END__