File Coverage

blib/lib/App/Midgen/Role/UseModule.pm
Criterion Covered Total %
statement 21 144 14.5
branch 0 110 0.0
condition 0 14 0.0
subroutine 7 17 41.1
pod 1 1 100.0
total 29 286 10.1


line stmt bran cond sub pod time code
1             package App::Midgen::Role::UseModule;
2              
3 2         183 use constant {BLANK => q{ }, TRUE => 1, FALSE => 0, NONE => q{}, TWO => 2,
4 2     2   1112 THREE => 3,};
  2         3  
5              
6 2     2   10 use Moo::Role;
  2         3  
  2         12  
7             requires
8             qw( ppi_document debug verbose format xtest _process_found_modules develop meta2 );
9              
10             our $VERSION = '0.33_05';
11             $VERSION = eval $VERSION; ## no critic
12              
13 2     2   3678 use PPI;
  2         2  
  2         40  
14 2     2   8 use Data::Printer {caller_info => 1,};
  2         164  
  2         22  
15 2     2   1591 use Try::Tiny;
  2         2  
  2         115  
16 2     2   7 use Tie::Static qw(static);
  2         2  
  2         3551  
17              
18              
19             #######
20             # composed method - _xtests_in_single_quote
21             #######
22             sub xtests_use_module {
23 0     0 1   my $self = shift;
24 0   0       my $phase_relationship = shift || NONE;
25              
26 0           my @modules;
27             my @version_strings;
28              
29             # bug out if there is no Include for Module::Runtime found
30 0 0         return if $self->_is_module_runtime() eq FALSE;
31              
32             ## say 'Option 1: use_module( M::N )...';
33              
34             #
35             # use_module("Math::BigInt", 1.31)->new("1_234");
36             #
37             #PPI::Document
38             # PPI::Statement
39             # PPI::Token::Whitespace ' '
40             # PPI::Token::Word 'use_module'
41             # PPI::Structure::List ( ... )
42             # PPI::Statement::Expression
43             # PPI::Token::Quote::Double '"Math::BigInt"'
44             # PPI::Token::Operator ','
45             # PPI::Token::Whitespace ' '
46             # PPI::Token::Number::Float '1.31'
47             # PPI::Token::Operator '->'
48             # PPI::Token::Word 'new'
49             # PPI::Structure::List ( ... )
50             # PPI::Statement::Expression
51             # PPI::Token::Quote::Double '"1_234"'
52             # PPI::Token::Structure ';'
53             # PPI::Token::Whitespace '\n'
54              
55             try {
56 0     0     my @chunks1 = @{$self->ppi_document->find('PPI::Statement')};
  0            
57              
58 0           foreach my $chunk (@chunks1) {
59              
60 0 0         if (not $chunk->find(sub { $_[1]->isa('PPI::Token::Symbol') })) {
  0            
61              
62             # test for module-runtime key-words
63 0 0         if (
64             $chunk->find(
65             sub {
66 0 0         $_[1]->isa('PPI::Token::Word')
67             and $_[1]->content
68             =~ m{\A[Module::Runtime::]*(?:use_module|use_package_optimistically|require_module)\z};
69             }
70             )
71             )
72             {
73 0 0         if (
74             not $chunk->find(
75             sub {
76 0 0         $_[1]->isa('PPI::Token::Word')
77             and $_[1]->content =~ m{\A(?:return)\z};
78             }
79             )
80             )
81             {
82              
83 0           for (0 .. $#{$chunk->{children}}) {
  0            
84              
85             # find all ppi_sl
86 0 0         if ($chunk->{children}[$_]->isa('PPI::Structure::List')) {
87              
88             my $ppi_sl = $chunk->{children}[$_]
89 0 0         if $chunk->{children}[$_]->isa('PPI::Structure::List');
90              
91 0 0         print "Option 1: use_module( M::N )...\n" if $self->debug;
92 0           $self->_module_names_ppi_sl($ppi_sl, \@modules,
93             \@version_strings);
94             }
95             }
96             }
97             }
98             }
99             }
100 0           };
101              
102              
103             ## say 'Option 2: my $q = use_module( M::N )...';
104              
105              
106             #
107             # my $bi = use_module("Math::BigInt", 1.31)->new("1_234");
108             #
109             #PPI::Document
110             # PPI::Statement::Variable
111             # PPI::Token::Word 'my'
112             # PPI::Token::Whitespace ' '
113             # PPI::Token::Symbol '$bi'
114             # PPI::Token::Whitespace ' '
115             # PPI::Token::Operator '='
116             # PPI::Token::Whitespace ' '
117             # PPI::Token::Word 'use_module'
118             # PPI::Structure::List ( ... )
119             # PPI::Statement::Expression
120             # PPI::Token::Quote::Double '"Math::BigInt"'
121             # PPI::Token::Operator ','
122             # PPI::Token::Whitespace ' '
123             # PPI::Token::Number::Float '1.31'
124             # PPI::Token::Operator '->'
125             # PPI::Token::Word 'new'
126             # PPI::Structure::List ( ... )
127             # PPI::Statement::Expression
128             # PPI::Token::Quote::Double '"1_234"'
129             # PPI::Token::Structure ';'
130             # PPI::Token::Whitespace '\n'
131              
132              
133             try {
134             # let's extract all ppi_sv
135 0     0     my @chunks2 = @{$self->ppi_document->find('PPI::Statement::Variable')};
  0            
136 0           foreach my $chunk (@chunks2) {
137              
138             # test for my
139 0 0         if (
140             $chunk->find(
141             sub {
142 0 0         $_[1]->isa('PPI::Token::Word')
143             and $_[1]->content =~ m{\A(?:my)\z};
144             }
145             )
146             )
147             {
148             # test for module-runtime key-words
149 0 0         if (
150             $chunk->find(
151             sub {
152 0 0         $_[1]->isa('PPI::Token::Word')
153             and $_[1]->content
154             =~ m{\A[Module::Runtime::]*(?:use_module|use_package_optimistically)\z};
155             }
156             )
157             )
158             {
159 0           for (0 .. $#{$chunk->{children}}) {
  0            
160              
161             # find all ppi_sl
162 0 0         if ($chunk->{children}[$_]->isa('PPI::Structure::List')) {
163              
164             my $ppi_sl = $chunk->{children}[$_]
165 0 0         if $chunk->{children}[$_]->isa('PPI::Structure::List');
166              
167 0 0         print "Option 2: my \$q = use_module( M::N )...\n"
168             if $self->debug;
169 0           $self->_module_names_ppi_sl($ppi_sl, \@modules,
170             \@version_strings);
171              
172              
173             }
174             }
175             }
176             }
177             }
178 0           };
179              
180              
181             ## say 'Option 3: $q = use_module( M::N )...';
182              
183             #
184             # $bi = use_module("Math::BigInt", 1.31)->new("1_234");
185             #
186             #PPI::Document
187             # PPI::Statement
188             # PPI::Token::Symbol '$bi'
189             # PPI::Token::Whitespace ' '
190             # PPI::Token::Operator '='
191             # PPI::Token::Whitespace ' '
192             # PPI::Token::Word 'use_module'
193             # PPI::Structure::List ( ... )
194             # PPI::Statement::Expression
195             # PPI::Token::Quote::Double '"Math::BigInt"'
196             # PPI::Token::Operator ','
197             # PPI::Token::Whitespace ' '
198             # PPI::Token::Number::Float '1.31'
199             # PPI::Token::Operator '->'
200             # PPI::Token::Word 'new'
201             # PPI::Structure::List ( ... )
202             # PPI::Statement::Expression
203             # PPI::Token::Quote::Double '"1_234"'
204             # PPI::Token::Structure ';'
205             # PPI::Token::Whitespace '\n'
206              
207             try {
208 0     0     my @chunks1 = @{$self->ppi_document->find('PPI::Statement')};
  0            
209              
210 0           foreach my $chunk (@chunks1) {
211              
212             # test for not my
213 0 0         if (
214             not $chunk->find(
215             sub {
216 0 0         $_[1]->isa('PPI::Token::Word')
217             and $_[1]->content =~ m{\A(?:my)\z};
218             }
219             )
220             )
221             {
222              
223 0 0         if ($chunk->find(sub { $_[1]->isa('PPI::Token::Symbol') })) {
  0            
224              
225 0 0         if (
226             $chunk->find(
227             sub {
228 0 0         $_[1]->isa('PPI::Token::Operator') and $_[1]->content eq '=';
229             }
230             )
231             )
232             {
233              
234             # test for module-runtime key-words
235 0 0         if (
236             $chunk->find(
237             sub {
238 0 0         $_[1]->isa('PPI::Token::Word')
239             and $_[1]->content
240             =~ m{\A[Module::Runtime::]*(?:use_module|use_package_optimistically)\z};
241             }
242             )
243             )
244             {
245 0           for (0 .. $#{$chunk->{children}}) {
  0            
246              
247             # find all ppi_sl
248 0 0         if ($chunk->{children}[$_]->isa('PPI::Structure::List')) {
249              
250             my $ppi_sl = $chunk->{children}[$_]
251 0 0         if $chunk->{children}[$_]->isa('PPI::Structure::List');
252              
253 0 0         print "Option 3: \$q = use_module( M::N )...\n"
254             if $self->debug;
255 0           $self->_module_names_ppi_sl($ppi_sl, \@modules,
256             \@version_strings);
257              
258             }
259             }
260             }
261             }
262             }
263             }
264             }
265 0           };
266              
267              
268             ## say 'Option 4: return use_module( M::N )...';
269              
270             #
271             # return use_module(\'App::SCS::PageSet\')->new(
272             # base_dir => $self->share_dir->catdir(\'pages\'),
273             # plugin_config => $self->page_plugin_config,
274             # );
275             #
276             #PPI::Document
277             # PPI::Statement::Break
278             # PPI::Token::Word 'return'
279             # PPI::Token::Whitespace ' '
280             # PPI::Token::Word 'use_module'
281             # PPI::Structure::List ( ... )
282             # PPI::Statement::Expression
283             # PPI::Token::Quote::Single ''App::SCS::PageSet''
284             # PPI::Token::Operator '->'
285             # PPI::Token::Word 'new'
286             # PPI::Structure::List ( ... )
287             # PPI::Token::Whitespace '\n'
288             # PPI::Token::Whitespace ' '
289             # PPI::Statement::Expression
290             # PPI::Token::Word 'base_dir'
291             # PPI::Token::Whitespace ' '
292             # PPI::Token::Operator '=>'
293             # PPI::Token::Whitespace ' '
294             # PPI::Token::Symbol '$self'
295             # PPI::Token::Operator '->'
296             # PPI::Token::Word 'share_dir'
297             # PPI::Token::Operator '->'
298             # PPI::Token::Word 'catdir'
299             # PPI::Structure::List ( ... )
300             # PPI::Statement::Expression
301             # PPI::Token::Quote::Single ''pages''
302             # PPI::Token::Operator ','
303             # PPI::Token::Whitespace '\n'
304             # PPI::Token::Whitespace ' '
305             # PPI::Token::Word 'plugin_config'
306             # PPI::Token::Whitespace ' '
307             # PPI::Token::Operator '=>'
308             # PPI::Token::Whitespace ' '
309             # PPI::Token::Symbol '$self'
310             # PPI::Token::Operator '->'
311             # PPI::Token::Word 'page_plugin_config'
312             # PPI::Token::Operator ','
313             # PPI::Token::Whitespace '\n'
314             # PPI::Token::Whitespace ' '
315             # PPI::Token::Structure ';'
316              
317             try {
318 0     0     my @chunks4 = @{$self->ppi_document->find('PPI::Statement::Break')};
  0            
319              
320 0           for my $chunk (@chunks4) {
321              
322 0 0         if (
323             $chunk->find(
324             sub {
325 0 0         $_[1]->isa('PPI::Token::Word')
326             and $_[1]->content =~ m{\A(?:return)\z};
327             }
328             )
329             )
330             {
331              
332 0 0         if (
333             $chunk->find(
334             sub {
335 0 0         $_[1]->isa('PPI::Token::Word')
336             and $_[1]->content
337             =~ m{\A[Module::Runtime::]*(?:use_module|use_package_optimistically)\z};
338             }
339             )
340             )
341             {
342 0           for (0 .. $#{$chunk->{children}}) {
  0            
343              
344             # find all ppi_sl
345 0 0         if ($chunk->{children}[$_]->isa('PPI::Structure::List')) {
346             my $ppi_sl = $chunk->{children}[$_]
347 0 0         if $chunk->{children}[$_]->isa('PPI::Structure::List');
348 0 0         print "Option 4: return use_module( M::N )...\n"
349             if $self->debug;
350 0           $self->_module_names_ppi_sl($ppi_sl, \@modules,
351             \@version_strings,);
352              
353              
354             }
355             }
356             }
357             }
358             }
359 0           };
360              
361             # p @version_strings;
362 0 0         @version_strings = map { defined $_ ? $_ : 0 } @version_strings;
  0            
363 0 0         p @modules if $self->debug;
364 0 0         p @version_strings if $self->debug;
365 0 0         if (scalar @modules > 0) {
366              
367 0           for (0 .. $#modules) {
368 0 0         print "Info: UseModule -> Sending $modules[$_] - $version_strings[$_]\n"
369             if ($self->verbose == TWO);
370             try {
371 0     0     $self->_process_found_modules(
372             $phase_relationship, $modules[$_], $version_strings[$_],
373             __PACKAGE__, $phase_relationship,
374             );
375 0           };
376             }
377             }
378              
379 0           return;
380             }
381              
382              
383             #######
384             # composed method test for include Module::Runtime
385             #######
386             sub _is_module_runtime {
387 0     0     my $self = shift;
388 0           my $module_runtime_include_found = FALSE;
389              
390             #PPI::Document
391             # PPI::Statement::Include
392             # PPI::Token::Word 'use'
393             # PPI::Token::Whitespace ' '
394             # PPI::Token::Word 'Module::Runtime'
395              
396             try {
397 0     0     my $includes = $self->ppi_document->find('PPI::Statement::Include');
398 0 0         if ($includes) {
399 0           foreach my $include (@{$includes}) {
  0            
400 0 0         next if $include->type eq 'no';
401 0 0         if (not $include->pragma) {
402 0           my $module = $include->module;
403              
404 0 0         if ($module eq 'Module::Runtime') {
405 0           $module_runtime_include_found = TRUE;
406 0 0         p $module if $self->debug;
407             }
408             }
409             }
410             }
411 0           };
412 0 0         p $module_runtime_include_found if $self->debug;
413 0           return $module_runtime_include_found;
414              
415             }
416              
417              
418             #######
419             # composed method extract module name from PPI::Structure::List
420             #######
421             sub _module_names_ppi_sl {
422 0     0     my ($self, $ppi_sl, $mn_ref, $mv_ref) = @_;
423              
424              
425 0 0         if ($ppi_sl->isa('PPI::Structure::List')) {
426              
427 0           static \my $previous_module;
428 0           foreach my $ppi_se (@{$ppi_sl->{children}}) {
  0            
429 0           for (0 .. $#{$ppi_se->{children}}) {
  0            
430              
431 0 0 0       if ( $ppi_se->{children}[$_]->isa('PPI::Token::Quote::Single')
432             || $ppi_se->{children}[$_]->isa('PPI::Token::Quote::Double'))
433             {
434 0           my $module = $ppi_se->{children}[$_]->content;
435 0           $module =~ s/(?:['|"])//g;
436 0 0         if ($module =~ m{\A(?:[a-zA-Z])}) {
437 0 0         print "found module - $module\n" if $self->debug;
438 0           push @{$mn_ref}, $module;
  0            
439 0           $mv_ref->[$#{$mn_ref}] = undef;
  0            
440 0 0         p @{$mn_ref} if $self->debug;
  0            
441 0           $previous_module = $module;
442             }
443             }
444 0 0 0       if ( $ppi_se->{children}[$_]->isa('PPI::Token::Number::Float')
      0        
      0        
445             || $ppi_se->{children}[$_]->isa('PPI::Token::Number::Version')
446             || $ppi_se->{children}[$_]->isa('PPI::Token::Quote::Single')
447             || $ppi_se->{children}[$_]->isa('PPI::Token::Quote::Double'))
448             {
449 0           my $version_string = $ppi_se->{children}[$_]->content;
450 0           $version_string =~ s/(?:['|"])//g;
451 0 0         next if $version_string !~ m{\A[\d|v]};
452              
453 0 0         $version_string
454             = version::is_lax($version_string) ? $version_string : 0;
455              
456 0 0         print "Info: UseModule found version_string - $version_string\n"
457             if $self->debug;
458              
459             try {
460 0 0   0     if ($previous_module) {
461 0           $self->{found_version}{$previous_module} = $version_string;
462 0           $mv_ref->[$#{$mn_ref}] = $version_string;
  0            
463             }
464 0 0         p $version_string if $self->debug;
465 0           $previous_module = undef;
466 0           };
467             }
468             }
469             }
470             }
471             }
472              
473              
474 2     2   14 no Moo::Role;
  2         3  
  2         11  
475              
476             1;
477              
478             __END__
479              
480             =pod
481              
482             =encoding UTF-8
483              
484             =head1 NAME
485              
486             App::Midgen::Roles::UseModule - looking for methods with Module::Runtime
487             includes, used by L<App::Midgen>
488              
489             =head1 VERSION
490              
491             version: 0.33_05
492              
493              
494             =head1 METHODS
495              
496             =over 4
497              
498             =item * xtests_use_module
499              
500             Checking for the following, extracting module name and version strings.
501              
502             use_module("Module::Name", x.xx)->new( ... );
503             require_module( 'Module::Name');
504             use_package_optimistically("Module::Name", x.xx)->new( ... );
505              
506             my $abc = use_module("Module::Name", x.xx)->new( ... );
507             my $abc = use_package_optimistically("Module::Name", x.xx)->new( ... );
508              
509             $abc = use_module("Module::Name", x.xx)->new( ... );
510             $abc = use_package_optimistically("Module::Name", x.xx)->new( ... );
511              
512             return use_module( 'Module::Name', x,xx )->new( ... );
513             return use_package_optimisticall( 'Module::Name', x.xx )->new( ... );
514              
515             We also support the prefix C<Module::Runtime::...> in the above.
516              
517             =back
518              
519             =head1 AUTHOR
520              
521             See L<App::Midgen>
522              
523             =head2 CONTRIBUTORS
524              
525             See L<App::Midgen>
526              
527             =head1 COPYRIGHT
528              
529             See L<App::Midgen>
530              
531             =head1 LICENSE
532              
533             This library is free software; you can redistribute it and/or modify
534             it under the same terms as Perl itself.
535              
536             =cut