File Coverage

blib/lib/Test/Inline/Extract.pm
Criterion Covered Total %
statement 35 35 100.0
branch 9 14 64.2
condition n/a
subroutine 11 11 100.0
pod 2 2 100.0
total 57 62 91.9


line stmt bran cond sub pod time code
1             package Test::Inline::Extract;
2             # ABSTRACT: Extract relevant Pod sections from source code.
3              
4             #pod =pod
5             #pod
6             #pod =head1 DESCRIPTION
7             #pod
8             #pod The Test::Inline::Extract package extracts content interesting to
9             #pod L from source files.
10             #pod
11             #pod =head1 METHODS
12             #pod
13             #pod =cut
14              
15 13     13   122633 use strict;
  13         41  
  13         388  
16 13     13   73 use List::Util ();
  13         28  
  13         158  
17 13     13   67 use Path::Tiny ();
  13         29  
  13         315  
18 13     13   605 use Params::Util qw{_CLASS _INSTANCE _SCALAR};
  13         4606  
  13         3869  
19              
20             our $VERSION = '2.214';
21              
22              
23              
24              
25              
26             #####################################################################
27             # Constructor
28              
29             #pod =pod
30             #pod
31             #pod =head2 new $file | \$source
32             #pod
33             #pod The C constructor creates a new Extract object. It is passed either a
34             #pod file name from which the source code would be loaded, or a reference to a
35             #pod string that directly contains source code.
36             #pod
37             #pod Returns a new C object or C on error.
38             #pod
39             #pod =cut
40              
41             sub new {
42 22 50   22 1 1951 my $class = _CLASS(shift) or die '->new is a static method';
43              
44             # Get the source code to process, and clean it up
45 22 50       321 my $source = $class->_source(shift) or return undef;
46 22         57 $source = $$source;
47 22         1274 $source =~ s/(?:\015{1,2}\012|\015|\012)/\n/g;
48              
49             # Create the object
50 22         116 my $self = bless {
51             source => $source,
52             elements => undef,
53             }, $class;
54              
55 22         127 $self;
56             }
57              
58             sub _source {
59 22     22   47 my $self = shift;
60 22 50       63 return undef unless defined $_[0];
61 22 100       126 return shift if _SCALAR($_[0]);
62 1 50       4 return undef if ref $_[0];
63 1         6 my $content = Path::Tiny::path(shift)->slurp;
64 1         324 return \$content;
65             }
66              
67             #pod =pod
68             #pod
69             #pod =head2 elements
70             #pod
71             #pod my $elements = $Extract->elements;
72             #pod
73             #pod The C method extracts from the Pod any parts of the file that are
74             #pod relevant to the extraction and generation process of C.
75             #pod
76             #pod The elements will be either a package statements, or a section of inline
77             #pod unit tests. They will only be returned if there is at least one section
78             #pod of inline unit tests.
79             #pod
80             #pod Returns a reference to an array of package strings and sections of inline
81             #pod unit tests. Returns false if there are no sections containing inline
82             #pod unit tests.
83             #pod
84             #pod =cut
85              
86             # Define the search pattern we will use
87 13     13   124 use vars qw{$search};
  13         37  
  13         3823  
88             BEGIN {
89 13     13   2228 $search = qr/
90             (?:^|\n) # After the beginning of the string, or a newline
91             ( # ... start capturing
92             # EITHER
93             package\s+ # A package
94             [^\W\d]\w*(?:(?:\'|::)[^\W\d]\w*)* # ... with a name
95             \s*; # And a statement terminator
96             | # OR
97             =for[ \t]+example[ \t]+begin\n # ... when we find a =for example begin
98             .*? # ... and keep capturing
99             \n=for[ \t]+example[ \t]+end\s*? # ... until the =for example end
100             (?:\n|$) # ... at the end of file or a newline
101             | # OR
102             =begin[ \t]+(?:test|testing)\b # ... when we find a =begin test or testing
103             .*? # ... and keep capturing
104             \n=end[ \t]+(?:test|testing)\s*? # ... until an =end tag
105             (?:\n|$) # ... at the end of file or a newline
106             ) # ... and stop capturing
107             /isx;
108             }
109              
110             sub elements {
111             $_[0]->{elements} or
112 22 50   22 1 1308 $_[0]->{elements} = $_[0]->_elements;
113             }
114              
115             sub _elements {
116 22     22   43 my $self = shift;
117 22         61 my @elements = ();
118 22         236 while ( $self->{source} =~ m/$search/go ) {
119 83         850 push @elements, $1;
120             }
121 22 100   41   161 (List::Util::first { /^=/ } @elements) ? \@elements : '';
  41         319  
122             }
123              
124             1;
125              
126             __END__