File Coverage

blib/lib/Perl/Critic/Document.pm
Criterion Covered Total %
statement 235 296 79.3
branch 65 130 50.0
condition 36 57 63.1
subroutine 47 52 90.3
pod 21 21 100.0
total 404 556 72.6


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