Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/PPIx/Utilities/Node.pm |
Statements | Executed 20 statements in 760µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 168µs | 384µs | BEGIN@16 | PPIx::Utilities::Node::
1 | 1 | 1 | 15µs | 15µs | BEGIN@3 | PPIx::Utilities::Node::
1 | 1 | 1 | 14µs | 26µs | BEGIN@12 | PPIx::Utilities::Node::
1 | 1 | 1 | 8µs | 139µs | BEGIN@19 | PPIx::Utilities::Node::
1 | 1 | 1 | 7µs | 27µs | BEGIN@9 | PPIx::Utilities::Node::
1 | 1 | 1 | 7µs | 18µs | BEGIN@4 | PPIx::Utilities::Node::
1 | 1 | 1 | 7µs | 11µs | BEGIN@5 | PPIx::Utilities::Node::
1 | 1 | 1 | 7µs | 26µs | BEGIN@13 | PPIx::Utilities::Node::
0 | 0 | 0 | 0s | 0s | _get_fragment_for_split_ppi_node | PPIx::Utilities::Node::
0 | 0 | 0 | 0s | 0s | _push_fragment | PPIx::Utilities::Node::
0 | 0 | 0 | 0s | 0s | _split_ppi_node_by_namespace_in_lexical_scope | PPIx::Utilities::Node::
0 | 0 | 0 | 0s | 0s | _split_ppi_node_by_namespace_single | PPIx::Utilities::Node::
0 | 0 | 0 | 0s | 0s | split_ppi_node_by_namespace | PPIx::Utilities::Node::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package PPIx::Utilities::Node; | ||||
2 | |||||
3 | 2 | 36µs | 1 | 15µs | # spent 15µs within PPIx::Utilities::Node::BEGIN@3 which was called:
# once (15µs+0s) by Perl::Critic::Document::BEGIN@22 at line 3 # spent 15µs making 1 call to PPIx::Utilities::Node::BEGIN@3 |
4 | 2 | 18µs | 2 | 30µs | # spent 18µs (7+11) within PPIx::Utilities::Node::BEGIN@4 which was called:
# once (7µs+11µs) by Perl::Critic::Document::BEGIN@22 at line 4 # spent 18µs making 1 call to PPIx::Utilities::Node::BEGIN@4
# spent 11µs making 1 call to strict::import |
5 | 2 | 26µs | 2 | 16µs | # spent 11µs (7+5) within PPIx::Utilities::Node::BEGIN@5 which was called:
# once (7µs+5µs) by Perl::Critic::Document::BEGIN@22 at line 5 # spent 11µs making 1 call to PPIx::Utilities::Node::BEGIN@5
# spent 5µs making 1 call to warnings::import |
6 | |||||
7 | 1 | 600ns | our $VERSION = '1.001000'; | ||
8 | |||||
9 | 2 | 27µs | 2 | 46µs | # spent 27µs (7+20) within PPIx::Utilities::Node::BEGIN@9 which was called:
# once (7µs+20µs) by Perl::Critic::Document::BEGIN@22 at line 9 # spent 27µs making 1 call to PPIx::Utilities::Node::BEGIN@9
# spent 20µs making 1 call to Exporter::import |
10 | |||||
11 | |||||
12 | 3 | 42µs | 2 | 38µs | # spent 26µs (14+12) within PPIx::Utilities::Node::BEGIN@12 which was called:
# once (14µs+12µs) by Perl::Critic::Document::BEGIN@22 at line 12 # spent 26µs making 1 call to PPIx::Utilities::Node::BEGIN@12
# spent 12µs making 1 call to UNIVERSAL::VERSION |
13 | 2 | 21µs | 2 | 46µs | # spent 26µs (7+20) within PPIx::Utilities::Node::BEGIN@13 which was called:
# once (7µs+20µs) by Perl::Critic::Document::BEGIN@22 at line 13 # spent 26µs making 1 call to PPIx::Utilities::Node::BEGIN@13
# spent 20µs making 1 call to Exporter::import |
14 | |||||
15 | |||||
16 | 2 | 91µs | 1 | 384µs | # spent 384µs (168+216) within PPIx::Utilities::Node::BEGIN@16 which was called:
# once (168µs+216µs) by Perl::Critic::Document::BEGIN@22 at line 16 # spent 384µs making 1 call to PPIx::Utilities::Node::BEGIN@16 |
17 | |||||
18 | |||||
19 | 2 | 494µs | 2 | 270µs | # spent 139µs (8+131) within PPIx::Utilities::Node::BEGIN@19 which was called:
# once (8µs+131µs) by Perl::Critic::Document::BEGIN@22 at line 19 # spent 139µs making 1 call to PPIx::Utilities::Node::BEGIN@19
# spent 131µs making 1 call to base::import |
20 | |||||
21 | 1 | 2µs | 1 | 28µs | Readonly::Array our @EXPORT_OK => qw< # spent 28µs making 1 call to Readonly::Array |
22 | split_ppi_node_by_namespace | ||||
23 | >; | ||||
24 | |||||
25 | |||||
26 | sub split_ppi_node_by_namespace { | ||||
27 | my ($node) = @_; | ||||
28 | |||||
29 | # Ensure we don't screw up the original. | ||||
30 | $node = $node->clone(); | ||||
31 | |||||
32 | # We want to make sure that we have locations prior to things being split | ||||
33 | # up, if we can, but don't worry about it if we don't. | ||||
34 | eval { $node->location(); }; ## no critic (RequireCheckingReturnValueOfEval) | ||||
35 | |||||
36 | if ( my $single_namespace = _split_ppi_node_by_namespace_single($node) ) { | ||||
37 | return $single_namespace; | ||||
38 | } # end if | ||||
39 | |||||
40 | my %nodes_by_namespace; | ||||
41 | _split_ppi_node_by_namespace_in_lexical_scope( | ||||
42 | $node, 'main', undef, \%nodes_by_namespace, | ||||
43 | ); | ||||
44 | |||||
45 | return \%nodes_by_namespace; | ||||
46 | } # end split_ppi_node_by_namespace() | ||||
47 | |||||
48 | |||||
49 | # Handle the case where there's only one. | ||||
50 | sub _split_ppi_node_by_namespace_single { | ||||
51 | my ($node) = @_; | ||||
52 | |||||
53 | my $package_statements = $node->find('PPI::Statement::Package'); | ||||
54 | |||||
55 | if ( not $package_statements or not @{$package_statements} ) { | ||||
56 | return { main => [$node] }; | ||||
57 | } # end if | ||||
58 | |||||
59 | if (@{$package_statements} == 1) { | ||||
60 | my $package_statement = $package_statements->[0]; | ||||
61 | my $package_address = refaddr $package_statement; | ||||
62 | |||||
63 | # Yes, child and not schild. | ||||
64 | my $first_child = $node->child(0); | ||||
65 | if ( | ||||
66 | $package_address == refaddr $node | ||||
67 | or $first_child and $package_address == refaddr $first_child | ||||
68 | ) { | ||||
69 | return { $package_statement->namespace() => [$node] }; | ||||
70 | } # end if | ||||
71 | } # end if | ||||
72 | |||||
73 | return; | ||||
74 | } # end _split_ppi_node_by_namespace_single() | ||||
75 | |||||
76 | |||||
77 | sub _split_ppi_node_by_namespace_in_lexical_scope { | ||||
78 | my ($node, $initial_namespace, $initial_fragment, $nodes_by_namespace) | ||||
79 | = @_; | ||||
80 | |||||
81 | my %scope_fragments_by_namespace; | ||||
82 | |||||
83 | # I certainly hope a value isn't going to exist at address 0. | ||||
84 | my $initial_fragment_address = refaddr $initial_fragment || 0; | ||||
85 | my ($namespace, $fragment) = ($initial_namespace, $initial_fragment); | ||||
86 | |||||
87 | if ($initial_fragment) { | ||||
88 | $scope_fragments_by_namespace{$namespace} = $initial_fragment; | ||||
89 | } # end if | ||||
90 | |||||
91 | foreach my $child ( $node->children() ) { | ||||
92 | if ( $child->isa('PPI::Statement::Package') ) { | ||||
93 | if ($fragment) { | ||||
94 | _push_fragment($nodes_by_namespace, $namespace, $fragment); | ||||
95 | |||||
96 | undef $fragment; | ||||
97 | } # end if | ||||
98 | |||||
99 | $namespace = $child->namespace(); | ||||
100 | } elsif ( | ||||
101 | $child->isa('PPI::Statement::Compound') | ||||
102 | or $child->isa('PPI::Statement::Given') | ||||
103 | or $child->isa('PPI::Statement::When') | ||||
104 | ) { | ||||
105 | my $block; | ||||
106 | my @components = $child->children(); | ||||
107 | while (not $block and my $component = shift @components) { | ||||
108 | if ( $component->isa('PPI::Structure::Block') ) { | ||||
109 | $block = $component; | ||||
110 | } # end if | ||||
111 | } # end while | ||||
112 | |||||
113 | if ($block) { | ||||
114 | if (not $fragment) { | ||||
115 | $fragment = _get_fragment_for_split_ppi_node( | ||||
116 | $nodes_by_namespace, | ||||
117 | \%scope_fragments_by_namespace, | ||||
118 | $namespace, | ||||
119 | ); | ||||
120 | } # end if | ||||
121 | |||||
122 | _split_ppi_node_by_namespace_in_lexical_scope( | ||||
123 | $block, $namespace, $fragment, $nodes_by_namespace, | ||||
124 | ); | ||||
125 | } # end if | ||||
126 | } # end if | ||||
127 | |||||
128 | $fragment = _get_fragment_for_split_ppi_node( | ||||
129 | $nodes_by_namespace, \%scope_fragments_by_namespace, $namespace, | ||||
130 | ); | ||||
131 | |||||
132 | if ($initial_fragment_address != refaddr $fragment) { | ||||
133 | # Need to fix these to use exceptions. Thankfully the P::C tests | ||||
134 | # will insist that this happens. | ||||
135 | $child->remove() | ||||
136 | or PPIx::Utilities::Exception::Bug->throw( | ||||
137 | 'Could not remove child from parent.' | ||||
138 | ); | ||||
139 | $fragment->add_element($child) | ||||
140 | or PPIx::Utilities::Exception::Bug->throw( | ||||
141 | 'Could not add child to fragment.' | ||||
142 | ); | ||||
143 | } # end if | ||||
144 | } # end foreach | ||||
145 | |||||
146 | return; | ||||
147 | } # end _split_ppi_node_by_namespace_in_lexical_scope() | ||||
148 | |||||
149 | |||||
150 | sub _get_fragment_for_split_ppi_node { | ||||
151 | my ($nodes_by_namespace, $scope_fragments_by_namespace, $namespace) = @_; | ||||
152 | |||||
153 | my $fragment; | ||||
154 | if ( not $fragment = $scope_fragments_by_namespace->{$namespace} ) { | ||||
155 | $fragment = PPI::Document::Fragment->new(); | ||||
156 | $scope_fragments_by_namespace->{$namespace} = $fragment; | ||||
157 | _push_fragment($nodes_by_namespace, $namespace, $fragment); | ||||
158 | } # end if | ||||
159 | |||||
160 | return $fragment; | ||||
161 | } # end _get_fragment_for_split_ppi_node() | ||||
162 | |||||
163 | |||||
164 | # Due to $fragment being passed into recursive calls to | ||||
165 | # _split_ppi_node_by_namespace_in_lexical_scope(), we can end up attempting to | ||||
166 | # put the same fragment into a namespace's nodes multiple times. | ||||
167 | sub _push_fragment { | ||||
168 | my ($nodes_by_namespace, $namespace, $fragment) = @_; | ||||
169 | |||||
170 | my $nodes = $nodes_by_namespace->{$namespace} ||= []; | ||||
171 | |||||
172 | if (not @{$nodes} or refaddr $nodes->[-1] != refaddr $fragment) { | ||||
173 | push @{$nodes}, $fragment; | ||||
174 | } # end if | ||||
175 | |||||
176 | return; | ||||
177 | } # end _push_fragment() | ||||
178 | |||||
179 | |||||
180 | 1 | 3µs | 1; | ||
181 | |||||
182 | __END__ |