← Index
NYTProf Performance Profile   « line view »
For /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/bin/perlcritic
  Run on Sat Mar 19 22:12:22 2016
Reported on Sat Mar 19 22:14:12 2016

Filename/Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/PPI/Normal.pm
StatementsExecuted 59 statements in 689µs
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
111472µs619µsPPI::Normal::::BEGIN@107PPI::Normal::BEGIN@107
11147µs60µsPPI::Normal::::registerPPI::Normal::register
11114µs26µsPPI::Normal::::BEGIN@37PPI::Normal::BEGIN@37
11110µs20µsPPI::Normal::::BEGIN@83PPI::Normal::BEGIN@83
11110µs46µsPPI::Normal::::BEGIN@40PPI::Normal::BEGIN@40
1117µs18µsPPI::Normal::::BEGIN@260PPI::Normal::BEGIN@260
1116µs33µsPPI::Normal::::BEGIN@43PPI::Normal::BEGIN@43
1115µs5µsPPI::Normal::::BEGIN@44PPI::Normal::BEGIN@44
5114µs4µsPPI::Normal::::CORE:matchPPI::Normal::CORE:match (opcode)
1113µs3µsPPI::Normal::::BEGIN@41PPI::Normal::BEGIN@41
1113µs3µsPPI::Normal::::BEGIN@38PPI::Normal::BEGIN@38
1113µs3µsPPI::Normal::::BEGIN@39PPI::Normal::BEGIN@39
0000s0sPPI::Normal::::__ANON__[:89]PPI::Normal::__ANON__[:89]
0000s0sPPI::Normal::::layerPPI::Normal::layer
0000s0sPPI::Normal::::newPPI::Normal::new
0000s0sPPI::Normal::::processPPI::Normal::process
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package PPI::Normal;
2
3=pod
4
5=head1 NAME
6
7PPI::Normal - Normalize Perl Documents
8
9=head2 DESCRIPTION
10
11Perl Documents, as created by PPI, are typically filled with all sorts of
12mess such as whitespace and comments and other things that don't effect
13the actual meaning of the code.
14
15In addition, because there is more than one way to do most things, and the
16syntax of Perl itself is quite flexible, there are many ways in which the
17"same" code can look quite different.
18
19PPI::Normal attempts to resolve this by providing a variety of mechanisms
20and algorithms to "normalize" Perl Documents, and determine a sort of base
21form for them (although this base form will be a memory structure, and
22not something that can be turned back into Perl source code).
23
24The process itself is quite complex, and so for convenience and
25extensibility it has been separated into a number of layers. At a later
26point, it will be possible to write Plugin classes to insert additional
27normalization steps into the various different layers.
28
29In addition, you can choose to do the normalization only as deep as a
30particular layer, depending on aggressively you want the normalization
31process to be.
32
33=head1 METHODS
34
35=cut
36
37219µs238µs
# spent 26µs (14+12) within PPI::Normal::BEGIN@37 which was called: # once (14µs+12µs) by PPI::BEGIN@27 at line 37
use strict;
# spent 26µs making 1 call to PPI::Normal::BEGIN@37 # spent 12µs making 1 call to strict::import
38215µs13µs
# spent 3µs within PPI::Normal::BEGIN@38 which was called: # once (3µs+0s) by PPI::BEGIN@27 at line 38
use Carp ();
# spent 3µs making 1 call to PPI::Normal::BEGIN@38
39217µs13µs
# spent 3µs within PPI::Normal::BEGIN@39 which was called: # once (3µs+0s) by PPI::BEGIN@27 at line 39
use List::MoreUtils ();
# spent 3µs making 1 call to PPI::Normal::BEGIN@39
40221µs282µs
# spent 46µs (10+36) within PPI::Normal::BEGIN@40 which was called: # once (10µs+36µs) by PPI::BEGIN@27 at line 40
use PPI::Util '_Document';
# spent 46µs making 1 call to PPI::Normal::BEGIN@40 # spent 36µs making 1 call to Exporter::import
41222µs13µs
# spent 3µs within PPI::Normal::BEGIN@41 which was called: # once (3µs+0s) by PPI::BEGIN@27 at line 41
use PPI::Document::Normalized ();
# spent 3µs making 1 call to PPI::Normal::BEGIN@41
42
43231µs260µs
# spent 33µs (6+27) within PPI::Normal::BEGIN@43 which was called: # once (6µs+27µs) by PPI::BEGIN@27 at line 43
use vars qw{$VERSION %LAYER};
# spent 33µs making 1 call to PPI::Normal::BEGIN@43 # spent 27µs making 1 call to vars::import
44
# spent 5µs within PPI::Normal::BEGIN@44 which was called: # once (5µs+0s) by PPI::BEGIN@27 at line 52
BEGIN {
451300ns $VERSION = '1.215';
46
47 # Registered function store
4815µs %LAYER = (
49 1 => [],
50 2 => [],
51 );
52142µs15µs}
# spent 5µs making 1 call to PPI::Normal::BEGIN@44
53
- -
58#####################################################################
59# Configuration
60
61=pod
62
63=head2 register $function => $layer, ...
64
65The C<register> method is used by normalization method providers to
66tell the normalization engines which functions need to be run, and
67in which layer they apply.
68
69Provide a set of key/value pairs, where the key is the full name of the
70function (in string form), and the value is the layer (see description
71of the layers above) in which it should be run.
72
73Returns true if all functions are registered, or C<undef> on error.
74
75=cut
76
77
# spent 60µs (47+13) within PPI::Normal::register which was called: # once (47µs+13µs) by PPI::Normal::Standard::import at line 43 of PPI/Normal/Standard.pm
sub register {
781400ns my $class = shift;
791300ns while ( @_ ) {
80 # Check the function
8151µs my $function = shift;
821300ns SCOPE: {
836117µs231µs
# spent 20µs (10+11) within PPI::Normal::BEGIN@83 which was called: # once (10µs+11µs) by PPI::BEGIN@27 at line 83
no strict 'refs';
# spent 20µs making 1 call to PPI::Normal::BEGIN@83 # spent 11µs making 1 call to strict::unimport
8454µs defined $function and defined &{"$function"}
85 or Carp::croak("Bad function name provided to PPI::Normal");
86 }
87
88 # Has it already been added?
89528µs58µs if ( List::MoreUtils::any { $_ eq $function } ) {
# spent 8µs making 5 calls to List::MoreUtils::any, avg 2µs/call
90 return 1;
91 }
92
93 # Check the layer to add it to
9451µs my $layer = shift;
95515µs54µs defined $layer and $layer =~ /^(?:1|2)$/
# spent 4µs making 5 calls to PPI::Normal::CORE:match, avg 900ns/call
96 or Carp::croak("Bad layer provided to PPI::Normal");
97
98 # Add to the layer data store
9955µs push @{ $LAYER{$layer} }, $function;
100 }
101
10213µs 1;
103}
104
105# With the registration mechanism in place, load in the main set of
106# normalization methods to initialize the store.
1072246µs2715µs
# spent 619µs (472+147) within PPI::Normal::BEGIN@107 which was called: # once (472µs+147µs) by PPI::BEGIN@27 at line 107
use PPI::Normal::Standard;
# spent 619µs making 1 call to PPI::Normal::BEGIN@107 # spent 97µs making 1 call to PPI::Normal::Standard::import
108
- -
113#####################################################################
114# Constructor and Accessors
115
116=pod
117
118=head2 new
119
120 my $level_1 = PPI::Normal->new;
121 my $level_2 = PPI::Normal->new(2);
122
123Creates a new normalization object, to which Document objects
124can be passed to be normalized.
125
126Of course, what you probably REALLY want is just to call
127L<PPI::Document>'s C<normalize> method.
128
129Takes an optional single parameter of the normalisation layer
130to use, which at this time can be either "1" or "2".
131
132Returns a new C<PPI::Normal> object, or C<undef> on error.
133
134=begin testing new after PPI::Document 12
135
136# Check we actually set the layer at creation
137my $layer_1 = PPI::Normal->new;
138isa_ok( $layer_1, 'PPI::Normal' );
139is( $layer_1->layer, 1, '->new creates a layer 1' );
140my $layer_1a = PPI::Normal->new(1);
141isa_ok( $layer_1a, 'PPI::Normal' );
142is( $layer_1a->layer, 1, '->new(1) creates a layer 1' );
143my $layer_2 = PPI::Normal->new(2);
144isa_ok( $layer_2, 'PPI::Normal' );
145is( $layer_2->layer, 2, '->new(2) creates a layer 2' );
146
147# Test bad things
148is( PPI::Normal->new(3), undef, '->new only allows up to layer 2' );
149is( PPI::Normal->new(undef), undef, '->new(evil) returns undef' );
150is( PPI::Normal->new("foo"), undef, '->new(evil) returns undef' );
151is( PPI::Normal->new(\"foo"), undef, '->new(evil) returns undef' );
152is( PPI::Normal->new([]), undef, '->new(evil) returns undef' );
153is( PPI::Normal->new({}), undef, '->new(evil) returns undef' );
154
155=end testing
156
157=cut
158
159sub new {
160 my $class = shift;
161 my $layer = @_ ?
162 (defined $_[0] and ! ref $_[0] and $_[0] =~ /^[12]$/) ? shift : return undef
163 : 1;
164
165 # Create the object
166 my $object = bless {
167 layer => $layer,
168 }, $class;
169
170 $object;
171}
172
173=pod
174
175=head1 layer
176
177The C<layer> accessor returns the normalisation layer of the object.
178
179=cut
180
181sub layer { $_[0]->{layer} }
182
- -
187#####################################################################
188# Main Methods
189
190=pod
191
192=head2 process
193
194The C<process> method takes anything that can be converted to a
195L<PPI::Document> (object, SCALAR ref, filename), loads it and
196applies the normalisation process to the document.
197
198Returns a L<PPI::Document::Normalized> object, or C<undef> on error.
199
200=begin testing process after new 15
201
202my $doc1 = PPI::Document->new(\'print "Hello World!\n";');
203isa_ok( $doc1, 'PPI::Document' );
204my $doc2 = \'print "Hello World!\n";';
205my $doc3 = \' print "Hello World!\n"; # comment';
206my $doc4 = \'print "Hello World!\n"';
207
208# Normalize them at level 1
209my $layer1 = PPI::Normal->new(1);
210isa_ok( $layer1, 'PPI::Normal' );
211my $nor11 = $layer1->process($doc1->clone);
212my $nor12 = $layer1->process($doc2);
213my $nor13 = $layer1->process($doc3);
214isa_ok( $nor11, 'PPI::Document::Normalized' );
215isa_ok( $nor12, 'PPI::Document::Normalized' );
216isa_ok( $nor13, 'PPI::Document::Normalized' );
217
218# The first 3 should be the same, the second not
219is_deeply( { %$nor11 }, { %$nor12 }, 'Layer 1: 1 and 2 match' );
220is_deeply( { %$nor11 }, { %$nor13 }, 'Layer 1: 1 and 3 match' );
221
222# Normalize them at level 2
223my $layer2 = PPI::Normal->new(2);
224isa_ok( $layer2, 'PPI::Normal' );
225my $nor21 = $layer2->process($doc1);
226my $nor22 = $layer2->process($doc2);
227my $nor23 = $layer2->process($doc3);
228my $nor24 = $layer2->process($doc4);
229isa_ok( $nor21, 'PPI::Document::Normalized' );
230isa_ok( $nor22, 'PPI::Document::Normalized' );
231isa_ok( $nor23, 'PPI::Document::Normalized' );
232isa_ok( $nor24, 'PPI::Document::Normalized' );
233
234# The first 3 should be the same, the second not
235is_deeply( { %$nor21 }, { %$nor22 }, 'Layer 2: 1 and 2 match' );
236is_deeply( { %$nor21 }, { %$nor23 }, 'Layer 2: 1 and 3 match' );
237is_deeply( { %$nor21 }, { %$nor24 }, 'Layer 2: 1 and 4 match' );
238
239=end testing
240
241=cut
242
243sub process {
244 my $self = ref $_[0] ? shift : shift->new;
245
246 # PPI::Normal objects are reusable, but not re-entrant
247 return undef if $self->{Document};
248
249 # Get or create the document
250 $self->{Document} = _Document(shift) or return undef;
251
252 # Work out what functions we need to call
253 my @functions = ();
254 foreach ( 1 .. $self->layer ) {
255 push @functions, @{ $LAYER{$_} };
256 }
257
258 # Execute each function
259 foreach my $function ( @functions ) {
260293µs228µs
# spent 18µs (7+10) within PPI::Normal::BEGIN@260 which was called: # once (7µs+10µs) by PPI::BEGIN@27 at line 260
no strict 'refs';
# spent 18µs making 1 call to PPI::Normal::BEGIN@260 # spent 10µs making 1 call to strict::unimport
261 &{"$function"}( $self->{Document} );
262 }
263
264 # Create the normalized Document object
265 my $Normalized = PPI::Document::Normalized->new(
266 Document => $self->{Document},
267 version => $VERSION,
268 functions => \@functions,
269 ) or return undef;
270
271 # Done, clean up
272 delete $self->{Document};
273 return $Normalized;
274}
275
27612µs1;
277
278=pod
279
280=head1 NOTES
281
282The following normalisation layers are implemented. When writing
283plugins, you should register each transformation function with the
284appropriate layer.
285
286=head2 Layer 1 - Insignificant Data Removal
287
288The basic step common to all normalization, layer 1 scans through the
289Document and removes all whitespace, comments, POD, and anything else
290that returns false for its C<significant> method.
291
292It also checks each Element and removes known-useless sub-element
293metadata such as the Element's physical position in the file.
294
295=head2 Layer 2 - Significant Element Removal
296
297After the removal of the insignificant data, Layer 2 removed larger, more
298complex, and superficially "significant" elements, that can be removed
299for the purposes of normalisation.
300
301Examples from this layer include pragmas, now-useless statement
302separators (since the PDOM tree is holding statement elements), and
303several other minor bits and pieces.
304
305=head2 Layer 3 - TO BE COMPLETED
306
307This version of the forward-port of the Perl::Compare functionality
308to the 0.900+ API of PPI only implements Layer 1 and 2 at this time.
309
310=head1 TO DO
311
312- Write the other 4-5 layers :)
313
314=head1 SUPPORT
315
316See the L<support section|PPI/SUPPORT> in the main module.
317
318=head1 AUTHOR
319
320Adam Kennedy E<lt>adamk@cpan.orgE<gt>
321
322=head1 COPYRIGHT
323
324Copyright 2005 - 2011 Adam Kennedy.
325
326This program is free software; you can redistribute
327it and/or modify it under the same terms as Perl itself.
328
329The full text of the license can be found in the
330LICENSE file included with this module.
331
332=cut
 
# spent 4µs within PPI::Normal::CORE:match which was called 5 times, avg 900ns/call: # 5 times (4µs+0s) by PPI::Normal::register at line 95, avg 900ns/call
sub PPI::Normal::CORE:match; # opcode