File Coverage

blib/lib/Perl/ToPerl6/Document.pm
Criterion Covered Total %
statement 205 269 76.2
branch 48 108 44.4
condition 33 45 73.3
subroutine 43 50 86.0
pod 21 21 100.0
total 350 493 70.9


line stmt bran cond sub pod time code
1             package Perl::ToPerl6::Document;
2              
3 13     13   3519 use 5.006001;
  13         44  
4 13     13   64 use strict;
  13         16  
  13         352  
5 13     13   59 use warnings;
  13         22  
  13         429  
6              
7 13     13   55 use Carp qw< confess >;
  13         19  
  13         811  
8              
9 13     13   63 use List::Util qw< reduce >;
  13         26  
  13         829  
10 13     13   61 use Scalar::Util qw< blessed refaddr weaken >;
  13         22  
  13         733  
11 13     13   6251 use version;
  13         20456  
  13         78  
12              
13 13     13   6319 use PPI::Document;
  13         469320  
  13         509  
14 13     13   92 use PPI::Document::File;
  13         22  
  13         346  
15 13     13   7794 use PPIx::Utilities::Node qw< split_ppi_node_by_namespace >;
  13         37863  
  13         275  
16              
17 13     13   6586 use Perl::ToPerl6::Annotation;
  13         32  
  13         513  
18 13     13   5839 use Perl::ToPerl6::Exception::Parse qw< throw_parse >;
  13         27  
  13         236  
19 13     13   705 use Perl::ToPerl6::Utils qw< :booleans :characters shebang_line >;
  13         21  
  13         681  
20              
21 13     13   10271 use PPIx::Regexp 0.010 qw< >;
  13         891854  
  13         26231  
22              
23             #-----------------------------------------------------------------------------
24              
25             our $VERSION = '0.03';
26              
27             #-----------------------------------------------------------------------------
28              
29             our $AUTOLOAD;
30             sub AUTOLOAD {
31 154     154   1128 my ( $function_name ) = $AUTOLOAD =~ m/ ([^:\']+) \z /xms;
32 154 50       387 return if $function_name eq 'DESTROY';
33 154         196 my $self = shift;
34 154         633 return $self->{_doc}->$function_name(@_);
35             }
36              
37             #-----------------------------------------------------------------------------
38              
39             sub new {
40 50     50 1 60242 my ($class, @args) = @_;
41              
42 50         128 my $self = bless {}, $class;
43              
44 50         139 $self->_init_common();
45 50         128 $self->_init_from_external_source(@args);
46              
47 50         149 return $self;
48             }
49              
50             #-----------------------------------------------------------------------------
51              
52             sub _new_for_parent_document {
53 4     4   5 my ($class, $ppi_document, $parent_document) = @_;
54              
55 4         9 my $self = bless {}, $class;
56              
57 4         9 $self->_init_common();
58              
59 4         7 $self->{_doc} = $ppi_document;
60 4         9 $self->{_is_module} = $parent_document->is_module();
61              
62 4         17 return $self;
63             }
64              
65             #-----------------------------------------------------------------------------
66              
67             sub _init_common {
68 54     54   74 my ($self) = @_;
69              
70 54         173 $self->{_annotations} = [];
71 54         101 $self->{_suppressed_transformations} = [];
72 54         90 $self->{_disabled_line_map} = {};
73              
74 54         84 return;
75             }
76              
77             #-----------------------------------------------------------------------------
78              
79             sub _init_from_external_source {
80 50     50   74 my $self = shift;
81 50         58 my %args;
82              
83 50 50       132 if (@_ == 1) {
84 0         0 warnings::warnif(
85             'deprecated',
86             'Perl::ToPerl6::Document->new($source) deprecated, use Perl::ToPerl6::Document->new(-source => $source) instead.'
87             );
88 0         0 %args = ('-source' => shift);
89             } else {
90 50         119 %args = @_;
91             }
92              
93 50         72 my $source_code = $args{'-source'};
94              
95             # $source_code can be a file name, or a reference to a
96             # PPI::Document, or a reference to a scalar containing source
97             # code. In the last case, PPI handles the translation for us.
98              
99 50 50       103 my $ppi_document =
    100          
100             _is_ppi_doc($source_code)
101             ? $source_code
102             : ref $source_code
103             ? PPI::Document->new($source_code)
104             : PPI::Document::File->new($source_code);
105              
106             # Bail on error
107 50 50       47130 if (not defined $ppi_document) {
108 0         0 my $errstr = PPI::Document::errstr();
109 0 0       0 my $file = ref $source_code ? undef : $source_code;
110 0         0 throw_parse
111             message => qq<Can't parse code: $errstr>,
112             file_name => $file;
113             }
114              
115 50         102 $self->{_doc} = $ppi_document;
116 50         337 $self->index_locations();
117 50         13803 $self->_disable_shebang_fix();
118 50         155 $self->{_filename_override} = $args{'-filename-override'};
119 50         142 $self->{_is_module} = $self->_determine_is_module(\%args);
120              
121 50         107 return;
122             }
123              
124             #-----------------------------------------------------------------------------
125              
126             sub _is_ppi_doc {
127 50     50   60 my ($ref) = @_;
128 50   66     500 return blessed($ref) && $ref->isa('PPI::Document');
129             }
130              
131             #-----------------------------------------------------------------------------
132              
133             sub ppi_document {
134 3     3 1 5 my ($self) = @_;
135 3         8 return $self->{_doc};
136             }
137              
138             #-----------------------------------------------------------------------------
139              
140             sub isa {
141 5     5 1 743 my ($self, @args) = @_;
142             return $self->SUPER::isa(@args)
143 5   66     63 || ( (ref $self) && $self->{_doc} && $self->{_doc}->isa(@args) );
144             }
145              
146             #-----------------------------------------------------------------------------
147              
148             sub find {
149 196     196 1 1589 my ($self, $wanted, @more_args) = @_;
150              
151             # This method can only find elements by their class names. For
152             # other types of searches, delegate to the PPI::Document
153 196 100 100     902 if ( ( ref $wanted ) || !$wanted || $wanted !~ m/ \A PPI:: /xms ) {
      100        
154 116         321 return $self->{_doc}->find($wanted, @more_args);
155             }
156              
157             # Build the class cache if it doesn't exist. This happens at most
158             # once per Perl::ToPerl6::Document instance. %elements of will be
159             # populated as a side-effect of calling the $finder_sub coderef
160             # that is produced by the caching_finder() closure.
161 80 100       165 if ( !$self->{_elements_of} ) {
162              
163 18         70 my %cache = ( 'PPI::Document' => [ $self ] );
164              
165             # The cache refers to $self, and $self refers to the cache. This
166             # creates a circular reference that leaks memory (i.e. $self is not
167             # destroyed until execution is complete). By weakening the reference,
168             # we allow perl to collect the garbage properly.
169 18         70 weaken( $cache{'PPI::Document'}->[0] );
170              
171 18         55 my $finder_coderef = _caching_finder( \%cache );
172 18         102 $self->{_doc}->find( $finder_coderef );
173 18         345 $self->{_elements_of} = \%cache;
174             }
175              
176             # find() must return false-but-defined on fail
177 80   100     468 return $self->{_elements_of}->{$wanted} || q{};
178             }
179              
180             #-----------------------------------------------------------------------------
181              
182             sub find_first {
183 28     28 1 1696 my ($self, $wanted, @more_args) = @_;
184              
185             # This method can only find elements by their class names. For
186             # other types of searches, delegate to the PPI::Document
187 28 100 100     127 if ( ( ref $wanted ) || !$wanted || $wanted !~ m/ \A PPI:: /xms ) {
      100        
188 27         93 return $self->{_doc}->find_first($wanted, @more_args);
189             }
190              
191 1         3 my $result = $self->find($wanted);
192 1 50       4 return $result ? $result->[0] : $result;
193             }
194              
195             #-----------------------------------------------------------------------------
196              
197             sub find_any {
198 4     4 1 1415 my ($self, $wanted, @more_args) = @_;
199              
200             # This method can only find elements by their class names. For
201             # other types of searches, delegate to the PPI::Document
202 4 100 100     26 if ( ( ref $wanted ) || !$wanted || $wanted !~ m/ \A PPI:: /xms ) {
      100        
203 3         15 return $self->{_doc}->find_any($wanted, @more_args);
204             }
205              
206 1         4 my $result = $self->find($wanted);
207 1 50       5 return $result ? 1 : $result;
208             }
209              
210             #-----------------------------------------------------------------------------
211              
212             sub namespaces {
213 2     2 1 282 my ($self) = @_;
214              
215 2         3 return keys %{ $self->_nodes_by_namespace() };
  2         7  
216             }
217              
218             #-----------------------------------------------------------------------------
219              
220             sub subdocuments_for_namespace {
221 0     0 1 0 my ($self, $namespace) = @_;
222              
223 0         0 my $subdocuments = $self->_nodes_by_namespace()->{$namespace};
224              
225 0 0       0 return $subdocuments ? @{$subdocuments} : ();
  0         0  
226             }
227              
228             #-----------------------------------------------------------------------------
229              
230             sub ppix_regexp_from_element {
231 0     0 1 0 my ( $self, $element ) = @_;
232              
233 0 0 0     0 if ( blessed( $element ) && $element->isa( 'PPI::Element' ) ) {
234 0         0 my $addr = refaddr( $element );
235             return $self->{_ppix_regexp_from_element}{$addr}
236 0 0       0 if exists $self->{_ppix_regexp_from_element}{$addr};
237 0         0 return ( $self->{_ppix_regexp_from_element}{$addr} =
238             PPIx::Regexp->new( $element,
239             default_modifiers =>
240             $self->_find_use_re_modifiers_in_scope_from_element(
241             $element ),
242             ) );
243             } else {
244 0         0 return PPIx::Regexp->new( $element );
245             }
246             }
247              
248             sub _find_use_re_modifiers_in_scope_from_element {
249 0     0   0 my ( $self, $elem ) = @_;
250 0         0 my @found;
251 0 0       0 foreach my $use_re ( @{ $self->find( 'PPI::Statement::Include' ) || [] } )
  0         0  
252             {
253 0 0       0 're' eq $use_re->module()
254             or next;
255 0 0       0 $self->element_is_in_lexical_scope_after_statement_containing(
256             $elem, $use_re )
257             or next;
258 0 0       0 my $prefix = 'no' eq $use_re->type() ? q{-} : $EMPTY;
259             push @found,
260 0         0 map { "$prefix$_" }
261 0         0 grep { m{ \A / }smx }
262             map {
263 0 0       0 $_->isa( 'PPI::Token::Quote' ) ? $_->string() :
  0 0       0  
264             $_->isa( 'PPI::Token::QuoteLike::Words' ) ? $_->literal() :
265             $_->content() }
266             $use_re->schildren();
267             }
268 0         0 return \@found;
269             }
270              
271             #-----------------------------------------------------------------------------
272              
273             # This got hung on the Perl::ToPerl6::Document, rather than living in
274             # Perl::ToPerl6::Utils::PPI, because of the possibility that caching of scope
275             # objects would turn out to be desirable.
276              
277             sub element_is_in_lexical_scope_after_statement_containing {
278 0     0 1 0 my ( $self, $inner_elem, $outer_elem ) = @_;
279              
280             # If the outer element defines a scope, we're true if and only if
281             # the outer element contains the inner element.
282 0 0       0 $outer_elem->scope()
283             and return $inner_elem->descendant_of( $outer_elem );
284              
285             # In the more general case:
286              
287             # The last element of the statement containing the outer element
288             # must be before the inner element. If not, we know we're false,
289             # without walking the parse tree.
290              
291 0 0       0 my $stmt = $outer_elem->statement()
292             or return;
293 0 0       0 my $last_elem = $stmt->last_element()
294             or return;
295              
296 0 0       0 my $stmt_loc = $last_elem->location()
297             or return;
298              
299 0 0       0 my $inner_loc = $inner_elem->location()
300             or return;
301              
302 0 0       0 $stmt_loc->[0] > $inner_loc->[0]
303             and return;
304 0 0 0     0 $stmt_loc->[0] == $inner_loc->[0]
305             and $stmt_loc->[1] > $inner_loc->[1]
306             and return;
307              
308             # Since we know the inner element is after the outer element, find
309             # the element that defines the scope of the statement that contains
310             # the outer element.
311              
312 0         0 my $parent = $stmt;
313 0         0 while ( ! $parent->scope() ) {
314 0 0       0 $parent = $parent->parent()
315             or return;
316             }
317              
318             # We're true if and only if the scope of the outer element contains
319             # the inner element.
320              
321 0         0 return $inner_elem->descendant_of( $parent );
322              
323             }
324              
325             #-----------------------------------------------------------------------------
326              
327             sub filename {
328 51     51 1 69 my ($self) = @_;
329              
330 51 100       127 if (defined $self->{_filename_override}) {
331 2         7 return $self->{_filename_override};
332             }
333             else {
334 49         73 my $doc = $self->{_doc};
335 49 50       209 return $doc->can('filename') ? $doc->filename() : undef;
336             }
337             }
338              
339             #-----------------------------------------------------------------------------
340              
341             sub highest_explicit_perl_version {
342 6     6 1 25 my ($self) = @_;
343              
344             my $highest_explicit_perl_version =
345 6         12 $self->{_highest_explicit_perl_version};
346              
347 6 50       16 if ( not exists $self->{_highest_explicit_perl_version} ) {
348 6         18 my $includes = $self->find( \&_is_a_version_statement );
349              
350 6 100       76 if ($includes) {
351             # Note: this doesn't use List::Util::max() because that function
352             # doesn't use the overloaded ">=" etc of a version object. The
353             # reduce() style lets version.pm take care of all comparing.
354             #
355             # For reference, max() ends up looking at the string converted to
356             # an NV, or something like that. An underscore like "5.005_04"
357             # provokes a warning and is chopped off at "5.005" thus losing the
358             # minor part from the comparison.
359             #
360             # An underscore "5.005_04" is supposed to mean an alpha release
361             # and shouldn't be used in a perl version. But it's shown in
362             # perlfunc under "use" (as a number separator), and appears in
363             # several modules supplied with perl 5.10.0 (like version.pm
364             # itself!). At any rate if version.pm can understand it then
365             # that's enough for here.
366             $highest_explicit_perl_version =
367 4 100   4   111 reduce { $a >= $b ? $a : $b }
368 9         146 map { version->new( $_->version() ) }
369 5         24 @{$includes};
  5         13  
370             }
371             else {
372 1         2 $highest_explicit_perl_version = undef;
373             }
374              
375             $self->{_highest_explicit_perl_version} =
376 6         147 $highest_explicit_perl_version;
377             }
378              
379 6 100       99 return $highest_explicit_perl_version if $highest_explicit_perl_version;
380 1         8 return;
381             }
382              
383             #-----------------------------------------------------------------------------
384              
385             sub uses_module {
386 3     3 1 72 my ($self, $module_name) = @_;
387              
388 3         9 return exists $self->_modules_used()->{$module_name};
389             }
390              
391             #-----------------------------------------------------------------------------
392              
393             sub process_annotations {
394 4     4 1 6 my ($self) = @_;
395              
396 4         26 my @annotations = Perl::ToPerl6::Annotation->create_annotations($self);
397 4         14 $self->add_annotation(@annotations);
398 4         9 return $self;
399             }
400              
401             #-----------------------------------------------------------------------------
402              
403             sub line_is_disabled_for_transformer {
404 19     19 1 32 my ($self, $line, $transformer) = @_;
405 19   33     52 my $transformer_name = ref $transformer || $transformer;
406              
407             # HACK: This Transformer is special. If it is active, it cannot be
408             # disabled by a "## no mogrify" annotation. Rather than create a general
409             # hook in Transformer.pm for enabling this behavior, we chose to hack
410             # it here, since this isn't the kind of thing that most transformers do
411              
412 19 50       64 return 0 if $transformer_name eq
413             'Perl::ToPerl6::Transformer::Miscellanea::ProhibitUnrestrictedNoCritic';
414              
415 19 50       44 return 0 unless $line;
416 19 50       64 return 1 if $self->{_disabled_line_map}->{$line}->{$transformer_name};
417 19 50       48 return 1 if $self->{_disabled_line_map}->{$line}->{ALL};
418 19         62 return 0;
419             }
420              
421             #-----------------------------------------------------------------------------
422              
423             sub add_annotation {
424 4     4 1 8 my ($self, @annotations) = @_;
425              
426             # Add annotation to our private map for quick lookup
427 4         12 for my $annotation (@annotations) {
428              
429 0         0 my ($start, $end) = $annotation->effective_range();
430 0 0       0 my @affected_transformers = $annotation->disables_all_transformers ?
431             qw(ALL) : $annotation->disabled_transformers();
432              
433             # TODO: Find clever way to do this with hash slices
434 0         0 for my $line ($start .. $end) {
435 0         0 for my $transformer (@affected_transformers) {
436 0         0 $self->{_disabled_line_map}->{$line}->{$transformer} = 1;
437             }
438             }
439             }
440              
441 4         6 push @{ $self->{_annotations} }, @annotations;
  4         10  
442 4         8 return $self;
443             }
444              
445             #-----------------------------------------------------------------------------
446              
447             sub annotations {
448 0     0 1 0 my ($self) = @_;
449 0         0 return @{ $self->{_annotations} };
  0         0  
450             }
451              
452             #-----------------------------------------------------------------------------
453              
454             sub add_suppressed_transformation {
455 0     0 1 0 my ($self, $transformation) = @_;
456 0         0 push @{$self->{_suppressed_transformations}}, $transformation;
  0         0  
457 0         0 return $self;
458             }
459              
460             #-----------------------------------------------------------------------------
461              
462             sub suppressed_transformations {
463 0     0 1 0 my ($self) = @_;
464 0         0 return @{ $self->{_suppressed_transformations} };
  0         0  
465             }
466              
467             #-----------------------------------------------------------------------------
468              
469             sub is_program {
470 1     1 1 2 my ($self) = @_;
471              
472 1         3 return not $self->is_module();
473             }
474              
475             #-----------------------------------------------------------------------------
476              
477             sub is_module {
478 7     7 1 9 my ($self) = @_;
479              
480 7         26 return $self->{_is_module};
481             }
482              
483             #-----------------------------------------------------------------------------
484             # PRIVATE functions & methods
485              
486             sub _is_a_version_statement {
487 54     54   806 my (undef, $element) = @_;
488              
489 54 100       262 return 0 if not $element->isa('PPI::Statement::Include');
490 9 50       40 return 1 if $element->version();
491 0         0 return 0;
492             }
493              
494             #-----------------------------------------------------------------------------
495              
496             sub _caching_finder {
497 18     18   28 my $cache_ref = shift; # These vars will persist for the life
498 18         27 my %isa_cache = (); # of the code ref that this sub returns
499              
500              
501             # Gather up all the PPI elements and sort by @ISA. Note: if any
502             # instances used multiple inheritance, this implementation would
503             # lead to multiple copies of $element in the $elements_of lists.
504             # However, PPI::* doesn't do multiple inheritance, so we are safe
505              
506             return sub {
507 223     223   2099 my (undef, $element) = @_;
508 223         323 my $classes = $isa_cache{ref $element};
509 223 100       481 if ( !$classes ) {
510 102         172 $classes = [ ref $element ];
511             # Use a C-style loop because we append to the classes array inside
512 102         126 for ( my $i = 0; $i < @{$classes}; $i++ ) {
  459         745  
513 13     13   126 no strict 'refs';
  13         21  
  13         8641  
514 357         259 push @{$classes}, @{"$classes->[$i]::ISA"};
  357         321  
  357         1112  
515 357   100     1101 $cache_ref->{$classes->[$i]} ||= [];
516             }
517 102         162 $isa_cache{$classes->[0]} = $classes;
518             }
519              
520 223         190 for my $class ( @{$classes} ) {
  223         306  
521 729         501 push @{$cache_ref->{$class}}, $element;
  729         1126  
522             }
523              
524 223         414 return 0; # 0 tells find() to keep traversing, but not to store this $element
525 18         101 };
526             }
527              
528             #-----------------------------------------------------------------------------
529              
530             sub _disable_shebang_fix {
531 50     50   83 my ($self) = @_;
532              
533             # When you install a program using ExtUtils::MakeMaker or Module::Build, it
534             # inserts some magical code into the top of the file (just after the
535             # shebang). This code allows people to call your program using a shell,
536             # like `sh my_script`. Unfortunately, this code causes several Transformer
537             # transformations, so we disable them as if they had "## no mogrify" annotations.
538              
539 50   100     255 my $first_stmnt = $self->schild(0) || return;
540              
541             # Different versions of MakeMaker and Build use slightly different shebang
542             # fixing strings. This matches most of the ones I've found in my own Perl
543             # distribution, but it may not be bullet-proof.
544              
545 48         933 my $fixin_rx = qr<^eval 'exec .* \$0 \$[{]1[+]"\$@"}'\s*[\r\n]\s*if.+;>ms; ## no mogrify (ExtendedFormatting)
546 48 50       230 if ( $first_stmnt =~ $fixin_rx ) {
547 0         0 my $line = $first_stmnt->location->[0];
548 0         0 $self->{_disabled_line_map}->{$line}->{ALL} = 1;
549 0         0 $self->{_disabled_line_map}->{$line + 1}->{ALL} = 1;
550             }
551              
552 48         1463 return $self;
553             }
554              
555             #-----------------------------------------------------------------------------
556              
557             sub _determine_is_module {
558 50     50   76 my ($self, $args) = @_;
559              
560 50         126 my $file_name = $self->filename();
561 50 50 66     158 if (
562             defined $file_name
563             and ref $args->{'-program-extensions'} eq 'ARRAY'
564             ) {
565 0         0 foreach my $ext ( @{ $args->{'-program-extensions'} } ) {
  0         0  
566 0 0       0 my $regex =
567             ref $ext eq 'Regexp'
568             ? $ext
569 0         0 : qr< @{ [ quotemeta $ext ] } \z >xms;
570              
571 0 0       0 return $FALSE if $file_name =~ m/$regex/smx;
572             }
573             }
574              
575 50 100       177 return $FALSE if shebang_line($self);
576 49 100 66     155 return $FALSE if defined $file_name && $file_name =~ m/ [.] PL \z /smx;
577              
578 48         121 return $TRUE;
579             }
580              
581             #-----------------------------------------------------------------------------
582              
583             sub _nodes_by_namespace {
584 2     2   3 my ($self) = @_;
585              
586 2         4 my $nodes = $self->{_nodes_by_namespace};
587              
588 2 50       6 return $nodes if $nodes;
589              
590 2         6 my $ppi_document = $self->ppi_document();
591 2 50       9 if (not $ppi_document) {
592 0         0 return $self->{_nodes_by_namespace} = {};
593             }
594              
595 2         11 my $raw_nodes_map = split_ppi_node_by_namespace($ppi_document);
596              
597 2         2350 my %wrapped_nodes;
598 2         4 while ( my ($namespace, $raw_nodes) = each %{$raw_nodes_map} ) {
  6         25  
599             $wrapped_nodes{$namespace} = [
600 4         14 map { __PACKAGE__->_new_for_parent_document($_, $self) }
601 4         5 @{$raw_nodes}
  4         7  
602             ];
603             }
604              
605 2         422 return $self->{_nodes_by_namespace} = \%wrapped_nodes;
606             }
607              
608             #-----------------------------------------------------------------------------
609              
610             # Note: must use exists on return value to determine membership because all
611             # the values are false, unlike the result of hashify().
612             sub _modules_used {
613 3     3   4 my ($self) = @_;
614              
615 3         6 my $mapping = $self->{_modules_used};
616              
617 3 100       13 return $mapping if $mapping;
618              
619 2         6 my $includes = $self->find('PPI::Statement::Include');
620 2 100       9 if (not $includes) {
621 1         9 return $self->{_modules_used} = {};
622             }
623              
624 1         2 my %mapping;
625 1         2 for my $module (
626 1 50       42 grep { $_ } map { $_->module() || $_->pragma() } @{$includes}
  1         6  
  1         3  
627             ) {
628             # Significanly ess memory than $h{$k} => 1. Thanks Mr. Lembark.
629 1         4 $mapping{$module} = ();
630             }
631              
632 1         11 return $self->{_modules_used} = \%mapping;
633             }
634              
635             #-----------------------------------------------------------------------------
636              
637             1;
638              
639             __END__
640              
641             =pod
642              
643             =for stopwords pre-caches
644              
645             =head1 NAME
646              
647             Perl::ToPerl6::Document - Caching wrapper around a PPI::Document.
648              
649              
650             =head1 SYNOPSIS
651              
652             use PPI::Document;
653             use Perl::ToPerl6::Document;
654             my $doc = PPI::Document->new('Foo.pm');
655             $doc = Perl::ToPerl6::Document->new(-source => $doc);
656             ## Then use the instance just like a PPI::Document
657              
658              
659             =head1 DESCRIPTION
660              
661             Perl::ToPerl6 does a lot of iterations over the PPI document tree via
662             the C<PPI::Document::find()> method. To save some time, this class
663             pre-caches a lot of the common C<find()> calls in a single traversal.
664             Then, on subsequent requests we return the cached data.
665              
666             This is implemented as a facade, where method calls are handed to the
667             stored C<PPI::Document> instance.
668              
669              
670             =head1 CAVEATS
671              
672             This facade does not implement the overloaded operators from
673             L<PPI::Document|PPI::Document> (that is, the C<use overload ...>
674             work). Therefore, users of this facade must not rely on that syntactic
675             sugar. So, for example, instead of C<my $source = "$doc";> you should
676             write C<< my $source = $doc->content(); >>
677              
678             Perhaps there is a CPAN module out there which implements a facade
679             better than we do here?
680              
681              
682             =head1 INTERFACE SUPPORT
683              
684             This is considered to be a public class. Any changes to its interface
685             will go through a deprecation cycle.
686              
687              
688             =head1 CONSTRUCTOR
689              
690             =over
691              
692             =item C<< new(-source => $source_code, '-filename-override' => $filename, '-program-extensions' => [program_extensions]) >>
693              
694             Create a new instance referencing a PPI::Document instance. The
695             C<$source_code> can be the name of a file, a reference to a scalar
696             containing actual source code, or a L<PPI::Document|PPI::Document> or
697             L<PPI::Document::File|PPI::Document::File>.
698              
699             In the event that C<$source_code> is a reference to a scalar containing actual
700             source code or a L<PPI::Document|PPI::Document>, the resulting
701             L<Perl::ToPerl6::Document|Perl::ToPerl6::Document> will not have a filename.
702             This may cause L<Perl::ToPerl6::Document|Perl::ToPerl6::Document> to incorrectly
703             classify the source code as a module or script. To avoid this problem, you
704             can optionally set the C<-filename-override> to force the
705             L<Perl::ToPerl6::Document|Perl::ToPerl6::Document> to have a particular
706             C<$filename>. Do not use this option if C<$source_code> is already the name
707             of a file, or is a reference to a L<PPI::Document::File|PPI::Document::File>.
708              
709             The '-program-extensions' argument is optional, and is a reference to a list
710             of strings and/or regular expressions. The strings will be made into regular
711             expressions matching the end of a file name, and any document whose file name
712             matches one of the regular expressions will be considered a program.
713              
714             If -program-extensions is not specified, or if it does not determine the
715             document type, the document will be considered to be a program if the source
716             has a shebang line or its file name (if any) matches C<< m/ [.] PL \z /smx >>.
717              
718             =back
719              
720             =head1 METHODS
721              
722             =over
723              
724             =item C<< ppi_document() >>
725              
726             Accessor for the wrapped PPI::Document instance. Note that altering
727             this instance in any way can cause unpredictable failures in
728             Perl::ToPerl6's subsequent analysis because some caches may fall out of
729             date.
730              
731              
732             =item C<< find($wanted) >>
733              
734             =item C<< find_first($wanted) >>
735              
736             =item C<< find_any($wanted) >>
737              
738             Caching wrappers around the PPI methods. If C<$wanted> is a simple PPI class
739             name, then the cache is employed. Otherwise we forward the call to the
740             corresponding method of the C<PPI::Document> instance.
741              
742              
743             =item C<< namespaces() >>
744              
745             Returns a list of the namespaces (package names) in the document.
746              
747              
748             =item C<< subdocuments_for_namespace($namespace) >>
749              
750             Returns a list of sub-documents containing the elements in the given
751             namespace. For example, given that the current document is for the source
752              
753             foo();
754             package Foo;
755             package Bar;
756             package Foo;
757              
758             this method will return two L<Perl::ToPerl6::Document|Perl::ToPerl6::Document>s
759             for a parameter of C<"Foo">. For more, see
760             L<PPIx::Utilities::Node/split_ppi_node_by_namespace>.
761              
762              
763             =item C<< ppix_regexp_from_element($element) >>
764              
765             Caching wrapper around C<< PPIx::Regexp->new($element) >>. If
766             C<$element> is a C<PPI::Element> the cache is employed, otherwise it
767             just returns the results of C<< PPIx::Regexp->new() >>. In either case,
768             it returns C<undef> unless the argument is something that
769             L<PPIx::Regexp|PPIx::Regexp> actually understands.
770              
771             =item C<< element_is_in_lexical_scope_after_statement_containing( $inner, $outer ) >>
772              
773             Is the C<$inner> element in lexical scope after the statement containing
774             the C<$outer> element?
775              
776             In the case where C<$outer> is itself a scope-defining element, returns true
777             if C<$outer> contains C<$inner>. In any other case, C<$inner> must be
778             after the last element of the statement containing C<$outer>, and the
779             innermost scope for C<$outer> also contains C<$inner>.
780              
781             This is not the same as asking whether C<$inner> is visible from
782             C<$outer>.
783              
784              
785             =item C<< filename() >>
786              
787             Returns the filename for the source code if applicable
788             (PPI::Document::File) or C<undef> otherwise (PPI::Document).
789              
790              
791             =item C<< isa( $classname ) >>
792              
793             To be compatible with other modules that expect to get a
794             PPI::Document, the Perl::ToPerl6::Document class masquerades as the
795             PPI::Document class.
796              
797              
798             =item C<< highest_explicit_perl_version() >>
799              
800             Returns a L<version|version> object for the highest Perl version
801             requirement declared in the document via a C<use> or C<require>
802             statement. Returns nothing if there is no version statement.
803              
804              
805             =item C<< uses_module($module_or_pragma_name) >>
806              
807             Answers whether there is a C<use>, C<require>, or C<no> of the given name in
808             this document. Note that there is no differentiation of modules vs. pragmata
809             here.
810              
811              
812             =item C<< process_annotations() >>
813              
814             Causes this Document to scan itself and mark which lines &
815             transformers are disabled by the C<"## no mogrify"> annotations.
816              
817              
818             =item C<< line_is_disabled_for_transformer($line, $transformer_object) >>
819              
820             Returns true if the given C<$transformer_object> or C<$transformer_name> has
821             been disabled for at C<$line> in this Document. Otherwise, returns false.
822              
823              
824             =item C<< add_annotation( $annotation ) >>
825              
826             Adds an C<$annotation> object to this Document.
827              
828              
829             =item C<< annotations() >>
830              
831             Returns a list containing all the
832             L<Perl::ToPerl6::Annotation|Perl::ToPerl6::Annotation>s that
833             were found in this Document.
834              
835              
836             =item C<< add_suppressed_transformation($transformation) >>
837              
838             Informs this Document that a C<$transformation> was found but not reported
839             because it fell on a line that had been suppressed by a C<"## no mogrify">
840             annotation. Returns C<$self>.
841              
842              
843             =item C<< suppressed_transformations() >>
844              
845             Returns a list of references to all the
846             L<Perl::ToPerl6::Transformation|Perl::ToPerl6::Transformation>s
847             that were found in this Document but were suppressed.
848              
849              
850             =item C<< is_program() >>
851              
852             Returns whether this document is considered to be a program.
853              
854              
855             =item C<< is_module() >>
856              
857             Returns whether this document is considered to be a Perl module.
858              
859             =back
860              
861             =head1 AUTHOR
862              
863             Chris Dolan <cdolan@cpan.org>
864              
865             =head1 COPYRIGHT
866              
867             Copyright (c) 2006-2011 Chris Dolan.
868              
869             This program is free software; you can redistribute it and/or modify
870             it under the same terms as Perl itself. The full text of this license
871             can be found in the LICENSE file included with this module.
872              
873             =cut
874              
875             ##############################################################################
876             # Local Variables:
877             # mode: cperl
878             # cperl-indent-level: 4
879             # fill-column: 78
880             # indent-tabs-mode: nil
881             # c-indentation-style: bsd
882             # End:
883             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :