| Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/PPI/Element.pm |
| Statements | Executed 1237739 statements in 4.31s |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 105472 | 9 | 4 | 1.08s | 1.77s | PPI::Element::__eq |
| 30261 | 10 | 4 | 519ms | 916ms | PPI::Element::snext_sibling |
| 94372 | 5 | 3 | 338ms | 389ms | PPI::Element::DESTROY |
| 104217 | 12 | 9 | 301ms | 2.04s | PPI::Element::__ne |
| 184039 | 17 | 6 | 163ms | 163ms | PPI::Element::significant |
| 165294 | 1 | 1 | 133ms | 133ms | PPI::Element::tokens |
| 23725 | 7 | 4 | 85.9ms | 98.7ms | PPI::Element::parent |
| 9763 | 5 | 4 | 47.2ms | 61.3ms | PPI::Element::location |
| 9763 | 1 | 1 | 14.1ms | 14.1ms | PPI::Element::_ensure_location_present |
| 286 | 5 | 2 | 5.54ms | 8.20ms | PPI::Element::statement |
| 339 | 5 | 3 | 5.42ms | 15.3ms | PPI::Element::sprevious_sibling |
| 226 | 2 | 1 | 2.79ms | 17.6ms | PPI::Element::next_sibling |
| 1 | 1 | 1 | 1.90ms | 2.06ms | PPI::Element::BEGIN@30 |
| 1 | 1 | 1 | 1.12ms | 1.57ms | PPI::Element::BEGIN@25 |
| 144 | 1 | 1 | 908µs | 3.55ms | PPI::Element::logical_filename |
| 1 | 1 | 1 | 736µs | 6.30ms | PPI::Element::BEGIN@28 |
| 198 | 8 | 1 | 721µs | 2.54ms | PPI::Element::logical_line_number |
| 1 | 1 | 1 | 462µs | 1.59ms | PPI::Element::BEGIN@29 |
| 3 | 1 | 1 | 102µs | 127µs | PPI::Element::top |
| 6 | 1 | 1 | 28µs | 83µs | PPI::Element::line_number |
| 1 | 1 | 1 | 15µs | 30µs | PPI::Element::BEGIN@46 |
| 1 | 1 | 1 | 11µs | 23µs | PPI::Element::BEGIN@24 |
| 1 | 1 | 1 | 8µs | 32µs | PPI::Element::BEGIN@26 |
| 1 | 1 | 1 | 8µs | 30µs | PPI::Element::BEGIN@41 |
| 1 | 1 | 1 | 7µs | 31µs | PPI::Element::BEGIN@27 |
| 1 | 1 | 1 | 7µs | 45µs | PPI::Element::BEGIN@32 |
| 1 | 1 | 1 | 6µs | 21µs | PPI::Element::BEGIN@44 |
| 1 | 1 | 1 | 6µs | 19µs | PPI::Element::BEGIN@43 |
| 1 | 1 | 1 | 5µs | 21µs | PPI::Element::BEGIN@42 |
| 1 | 1 | 1 | 5µs | 19µs | PPI::Element::BEGIN@45 |
| 1 | 1 | 1 | 4µs | 4µs | PPI::Element::BEGIN@33 |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::__ANON__[:346] |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::__ANON__[:369] |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::__ANON__[:394] |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::__ANON__[:417] |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::__equals |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::__insert_after |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::__insert_before |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::__nequals |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::_clear |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::_error |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::_flush_locations |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::_xml_attr |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::_xml_content |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::_xml_name |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::ancestor_of |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::class |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::clone |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::column_number |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::content |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::delete |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::descendant_of |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::document |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::first_token |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::last_token |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::next_token |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::previous_sibling |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::previous_token |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::remove |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::replace |
| 0 | 0 | 0 | 0s | 0s | PPI::Element::visual_column_number |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package PPI::Element; | ||||
| 2 | |||||
| 3 | =pod | ||||
| 4 | |||||
| 5 | =head1 NAME | ||||
| 6 | |||||
| 7 | PPI::Element - The abstract Element class, a base for all source objects | ||||
| 8 | |||||
| 9 | =head1 INHERITANCE | ||||
| 10 | |||||
| 11 | PPI::Element is the root of the PDOM tree | ||||
| 12 | |||||
| 13 | =head1 DESCRIPTION | ||||
| 14 | |||||
| 15 | The abstract C<PPI::Element> serves as a base class for all source-related | ||||
| 16 | objects, from a single whitespace token to an entire document. It provides | ||||
| 17 | a basic set of methods to provide a common interface and basic | ||||
| 18 | implementations. | ||||
| 19 | |||||
| 20 | =head1 METHODS | ||||
| 21 | |||||
| 22 | =cut | ||||
| 23 | |||||
| 24 | 2 | 19µs | 2 | 35µs | # spent 23µs (11+12) within PPI::Element::BEGIN@24 which was called:
# once (11µs+12µs) by PPI::Token::BEGIN@25 at line 24 # spent 23µs making 1 call to PPI::Element::BEGIN@24
# spent 12µs making 1 call to strict::import |
| 25 | 2 | 79µs | 1 | 1.57ms | # spent 1.57ms (1.12+445µs) within PPI::Element::BEGIN@25 which was called:
# once (1.12ms+445µs) by PPI::Token::BEGIN@25 at line 25 # spent 1.57ms making 1 call to PPI::Element::BEGIN@25 |
| 26 | 2 | 24µs | 2 | 56µs | # spent 32µs (8+24) within PPI::Element::BEGIN@26 which was called:
# once (8µs+24µs) by PPI::Token::BEGIN@25 at line 26 # spent 32µs making 1 call to PPI::Element::BEGIN@26
# spent 24µs making 1 call to Exporter::import |
| 27 | 2 | 20µs | 2 | 55µs | # spent 31µs (7+24) within PPI::Element::BEGIN@27 which was called:
# once (7µs+24µs) by PPI::Token::BEGIN@25 at line 27 # spent 31µs making 1 call to PPI::Element::BEGIN@27
# spent 24µs making 1 call to Exporter::import |
| 28 | 2 | 99µs | 1 | 6.30ms | # spent 6.30ms (736µs+5.56) within PPI::Element::BEGIN@28 which was called:
# once (736µs+5.56ms) by PPI::Token::BEGIN@25 at line 28 # spent 6.30ms making 1 call to PPI::Element::BEGIN@28 |
| 29 | 2 | 78µs | 1 | 1.59ms | # spent 1.59ms (462µs+1.13) within PPI::Element::BEGIN@29 which was called:
# once (462µs+1.13ms) by PPI::Token::BEGIN@25 at line 29 # spent 1.59ms making 1 call to PPI::Element::BEGIN@29 |
| 30 | 2 | 99µs | 1 | 2.06ms | # spent 2.06ms (1.90+163µs) within PPI::Element::BEGIN@30 which was called:
# once (1.90ms+163µs) by PPI::Token::BEGIN@25 at line 30 # spent 2.06ms making 1 call to PPI::Element::BEGIN@30 |
| 31 | |||||
| 32 | 2 | 32µs | 2 | 82µs | # spent 45µs (7+38) within PPI::Element::BEGIN@32 which was called:
# once (7µs+38µs) by PPI::Token::BEGIN@25 at line 32 # spent 45µs making 1 call to PPI::Element::BEGIN@32
# spent 38µs making 1 call to vars::import |
| 33 | # spent 4µs within PPI::Element::BEGIN@33 which was called:
# once (4µs+0s) by PPI::Token::BEGIN@25 at line 39 | ||||
| 34 | 1 | 400ns | $VERSION = '1.215'; | ||
| 35 | 1 | 200ns | $errstr = ''; | ||
| 36 | |||||
| 37 | # Master Child -> Parent index | ||||
| 38 | 1 | 4µs | %_PARENT = (); | ||
| 39 | 1 | 20µs | 1 | 4µs | } # spent 4µs making 1 call to PPI::Element::BEGIN@33 |
| 40 | |||||
| 41 | 2 | 24µs | 2 | 53µs | # spent 30µs (8+23) within PPI::Element::BEGIN@41 which was called:
# once (8µs+23µs) by PPI::Token::BEGIN@25 at line 41 # spent 30µs making 1 call to PPI::Element::BEGIN@41
# spent 23µs making 1 call to overload::import |
| 42 | 2 | 20µs | 2 | 37µs | # spent 21µs (5+16) within PPI::Element::BEGIN@42 which was called:
# once (5µs+16µs) by PPI::Token::BEGIN@25 at line 42 # spent 21µs making 1 call to PPI::Element::BEGIN@42
# spent 16µs making 1 call to overload::import |
| 43 | 2 | 29µs | 2 | 33µs | # spent 19µs (6+14) within PPI::Element::BEGIN@43 which was called:
# once (6µs+14µs) by PPI::Token::BEGIN@25 at line 43 # spent 19µs making 1 call to PPI::Element::BEGIN@43
# spent 14µs making 1 call to overload::import |
| 44 | 2 | 19µs | 2 | 36µs | # spent 21µs (6+15) within PPI::Element::BEGIN@44 which was called:
# once (6µs+15µs) by PPI::Token::BEGIN@25 at line 44 # spent 21µs making 1 call to PPI::Element::BEGIN@44
# spent 15µs making 1 call to overload::import |
| 45 | 2 | 28µs | 2 | 33µs | # spent 19µs (5+14) within PPI::Element::BEGIN@45 which was called:
# once (5µs+14µs) by PPI::Token::BEGIN@25 at line 45 # spent 19µs making 1 call to PPI::Element::BEGIN@45
# spent 14µs making 1 call to overload::import |
| 46 | 2 | 1.59ms | 2 | 44µs | # spent 30µs (15+14) within PPI::Element::BEGIN@46 which was called:
# once (15µs+14µs) by PPI::Token::BEGIN@25 at line 46 # spent 30µs making 1 call to PPI::Element::BEGIN@46
# spent 14µs making 1 call to overload::import |
| 47 | |||||
| - - | |||||
| 52 | ##################################################################### | ||||
| 53 | # General Properties | ||||
| 54 | |||||
| 55 | =pod | ||||
| 56 | |||||
| 57 | =head2 significant | ||||
| 58 | |||||
| 59 | Because we treat whitespace and other non-code items as Tokens (in order to | ||||
| 60 | be able to "round trip" the L<PPI::Document> back to a file) the | ||||
| 61 | C<significant> method allows us to distinguish between tokens that form a | ||||
| 62 | part of the code, and tokens that aren't significant, such as whitespace, | ||||
| 63 | POD, or the portion of a file after (and including) the C<__END__> token. | ||||
| 64 | |||||
| 65 | Returns true if the Element is significant, or false it not. | ||||
| 66 | |||||
| 67 | =cut | ||||
| 68 | |||||
| 69 | ### XS -> PPI/XS.xs:_PPI_Element__significant 0.845+ | ||||
| 70 | 184039 | 549ms | # spent 163ms within PPI::Element::significant which was called 184039 times, avg 883ns/call:
# 39289 times (36.3ms+0s) by PPI::Lexer::_lex_statement at line 608 of PPI/Lexer.pm, avg 925ns/call
# 33407 times (29.6ms+0s) by PPI::Node::schild at line 282 of PPI/Node.pm, avg 885ns/call
# 29775 times (24.6ms+0s) by PPI::Element::snext_sibling at line 370, avg 826ns/call
# 26762 times (25.1ms+0s) by PPI::Tokenizer::_previous_significant_tokens at line 699 of PPI/Tokenizer.pm, avg 940ns/call
# 13303 times (12.3ms+0s) by PPI::Lexer::_lex_structure at line 1321 of PPI/Lexer.pm, avg 923ns/call
# 10544 times (8.64ms+0s) by PPI::Node::schildren at line 232 of PPI/Node.pm, avg 819ns/call
# 10537 times (8.47ms+0s) by PPI::Node::schildren at line 229 of PPI/Node.pm, avg 804ns/call
# 7986 times (6.27ms+0s) by PPI::Statement::Variable::type at line 67 of PPI/Statement/Variable.pm, avg 785ns/call
# 6486 times (5.74ms+0s) by PPI::Node::schild at line 277 of PPI/Node.pm, avg 885ns/call
# 3024 times (2.95ms+0s) by PPI::Lexer::_lex_document at line 272 of PPI/Lexer.pm, avg 977ns/call
# 1022 times (844µs+0s) by PPI::Lexer::_statement at line 501 of PPI/Lexer.pm, avg 826ns/call
# 981 times (886µs+0s) by PPI::Lexer::_statement at line 543 of PPI/Lexer.pm, avg 903ns/call
# 321 times (283µs+0s) by Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions::_has_topic_side_effect at line 121 of Perl/Critic/Policy/ControlStructures/ProhibitMutatingListFunctions.pm, avg 882ns/call
# 218 times (193µs+0s) by PPI::Element::sprevious_sibling at line 418, avg 884ns/call
# 203 times (169µs+0s) by PPI::Lexer::_statement at line 430 of PPI/Lexer.pm, avg 834ns/call
# 129 times (120µs+0s) by PPI::Lexer::_curly at line 1264 of PPI/Lexer.pm, avg 926ns/call
# 52 times (46µs+0s) by PPI::Tokenizer::_last_significant_token at line 680 of PPI/Tokenizer.pm, avg 894ns/call | ||
| 71 | |||||
| 72 | =pod | ||||
| 73 | |||||
| 74 | =head2 class | ||||
| 75 | |||||
| 76 | The C<class> method is provided as a convenience, and really does nothing | ||||
| 77 | more than returning C<ref($self)>. However, some people have found that | ||||
| 78 | they appreciate the laziness of C<$Foo-E<gt>class eq 'whatever'>, so I | ||||
| 79 | have caved to popular demand and included it. | ||||
| 80 | |||||
| 81 | Returns the class of the Element as a string | ||||
| 82 | |||||
| 83 | =cut | ||||
| 84 | |||||
| 85 | sub class { ref($_[0]) } | ||||
| 86 | |||||
| 87 | =pod | ||||
| 88 | |||||
| 89 | =head2 tokens | ||||
| 90 | |||||
| 91 | The C<tokens> method returns a list of L<PPI::Token> objects for the | ||||
| 92 | Element, essentially getting back that part of the document as if it had | ||||
| 93 | not been lexed. | ||||
| 94 | |||||
| 95 | This also means there are no Statements and no Structures in the list, | ||||
| 96 | just the Token classes. | ||||
| 97 | |||||
| 98 | =cut | ||||
| 99 | |||||
| 100 | 165294 | 372ms | # spent 133ms within PPI::Element::tokens which was called 165294 times, avg 802ns/call:
# 165294 times (133ms+0s) by PPI::Node::tokens at line 666 of PPI/Node.pm, avg 802ns/call | ||
| 101 | |||||
| 102 | =pod | ||||
| 103 | |||||
| 104 | =head2 content | ||||
| 105 | |||||
| 106 | For B<any> C<PPI::Element>, the C<content> method will reconstitute the | ||||
| 107 | base code for it as a single string. This method is also the method used | ||||
| 108 | for overloading stringification. When an Element is used in a double-quoted | ||||
| 109 | string for example, this is the method that is called. | ||||
| 110 | |||||
| 111 | B<WARNING:> | ||||
| 112 | |||||
| 113 | You should be aware that because of the way that here-docs are handled, any | ||||
| 114 | here-doc content is not included in C<content>, and as such you should | ||||
| 115 | B<not> eval or execute the result if it contains any L<PPI::Token::HereDoc>. | ||||
| 116 | |||||
| 117 | The L<PPI::Document> method C<serialize> should be used to stringify a PDOM | ||||
| 118 | document into something that can be executed as expected. | ||||
| 119 | |||||
| 120 | Returns the basic code as a string (excluding here-doc content). | ||||
| 121 | |||||
| 122 | =cut | ||||
| 123 | |||||
| 124 | ### XS -> PPI/XS.xs:_PPI_Element__content 0.900+ | ||||
| 125 | sub content { '' } | ||||
| 126 | |||||
| - - | |||||
| 131 | ##################################################################### | ||||
| 132 | # Naigation Methods | ||||
| 133 | |||||
| 134 | =pod | ||||
| 135 | |||||
| 136 | =head2 parent | ||||
| 137 | |||||
| 138 | Elements themselves are not intended to contain other Elements, that is | ||||
| 139 | left to the L<PPI::Node> abstract class, a subclass of C<PPI::Element>. | ||||
| 140 | However, all Elements can be contained B<within> a parent Node. | ||||
| 141 | |||||
| 142 | If an Element is within a parent Node, the C<parent> method returns the | ||||
| 143 | Node. | ||||
| 144 | |||||
| 145 | =cut | ||||
| 146 | |||||
| 147 | 23725 | 120ms | 23725 | 12.8ms | # spent 98.7ms (85.9+12.8) within PPI::Element::parent which was called 23725 times, avg 4µs/call:
# 11584 times (43.0ms+5.87ms) by Perl::Critic::Utils::is_hash_key at line 716 of Perl/Critic/Utils.pm, avg 4µs/call
# 11584 times (40.9ms+6.45ms) by Perl::Critic::Utils::is_hash_key at line 714 of Perl/Critic/Utils.pm, avg 4µs/call
# 286 times (976µs+233µs) by Perl::Critic::Policy::TestingAndDebugging::RequireUseStrict::__ANON__[/Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Perl/Critic/Policy/TestingAndDebugging/RequireUseStrict.pm:116] at line 93 of Perl/Critic/Policy/TestingAndDebugging/RequireUseStrict.pm, avg 4µs/call
# 108 times (289µs+66µs) by PPI::Lexer::_curly at line 1253 of PPI/Lexer.pm, avg 3µs/call
# 61 times (314µs+52µs) by PPI::Lexer::_curly at line 1248 of PPI/Lexer.pm, avg 6µs/call
# 51 times (241µs+74µs) by Perl::Critic::Annotation::_init at line 68 of Perl/Critic/Annotation.pm, avg 6µs/call
# 51 times (144µs+27µs) by Perl::Critic::Annotation::_init at line 69 of Perl/Critic/Annotation.pm, avg 3µs/call # spent 12.8ms making 23725 calls to Scalar::Util::refaddr, avg 539ns/call |
| 148 | |||||
| 149 | =pod | ||||
| 150 | |||||
| 151 | =head2 descendant_of $element | ||||
| 152 | |||||
| 153 | Answers whether a C<PPI::Element> is contained within another one. | ||||
| 154 | |||||
| 155 | C<PPI::Element>s are considered to be descendants of themselves. | ||||
| 156 | |||||
| 157 | =begin testing descendant_of 9 | ||||
| 158 | |||||
| 159 | my $Document = PPI::Document->new( \'( [ thingy ] ); $blarg = 1' ); | ||||
| 160 | isa_ok( $Document, 'PPI::Document' ); | ||||
| 161 | ok( | ||||
| 162 | $Document->descendant_of($Document), | ||||
| 163 | 'Document is a descendant of itself.', | ||||
| 164 | ); | ||||
| 165 | |||||
| 166 | my $words = $Document->find('Token::Word'); | ||||
| 167 | is(scalar @{$words}, 1, 'Document contains 1 Word.'); | ||||
| 168 | my $word = $words->[0]; | ||||
| 169 | ok( | ||||
| 170 | $word->descendant_of($word), | ||||
| 171 | 'Word is a descendant of itself.', | ||||
| 172 | ); | ||||
| 173 | ok( | ||||
| 174 | $word->descendant_of($Document), | ||||
| 175 | 'Word is a descendant of the Document.', | ||||
| 176 | ); | ||||
| 177 | ok( | ||||
| 178 | ! $Document->descendant_of($word), | ||||
| 179 | 'Document is not a descendant of the Word.', | ||||
| 180 | ); | ||||
| 181 | |||||
| 182 | my $symbols = $Document->find('Token::Symbol'); | ||||
| 183 | is(scalar @{$symbols}, 1, 'Document contains 1 Symbol.'); | ||||
| 184 | my $symbol = $symbols->[0]; | ||||
| 185 | ok( | ||||
| 186 | ! $word->descendant_of($symbol), | ||||
| 187 | 'Word is not a descendant the Symbol.', | ||||
| 188 | ); | ||||
| 189 | ok( | ||||
| 190 | ! $symbol->descendant_of($word), | ||||
| 191 | 'Symbol is not a descendant the Word.', | ||||
| 192 | ); | ||||
| 193 | |||||
| 194 | =end testing | ||||
| 195 | |||||
| 196 | =cut | ||||
| 197 | |||||
| 198 | sub descendant_of { | ||||
| 199 | my $cursor = shift; | ||||
| 200 | my $parent = shift or return undef; | ||||
| 201 | while ( refaddr $cursor != refaddr $parent ) { | ||||
| 202 | $cursor = $_PARENT{refaddr $cursor} or return ''; | ||||
| 203 | } | ||||
| 204 | return 1; | ||||
| 205 | } | ||||
| 206 | |||||
| 207 | =pod | ||||
| 208 | |||||
| 209 | =head2 ancestor_of $element | ||||
| 210 | |||||
| 211 | Answers whether a C<PPI::Element> is contains another one. | ||||
| 212 | |||||
| 213 | C<PPI::Element>s are considered to be ancestors of themselves. | ||||
| 214 | |||||
| 215 | =begin testing ancestor_of 9 | ||||
| 216 | |||||
| 217 | my $Document = PPI::Document->new( \'( [ thingy ] ); $blarg = 1' ); | ||||
| 218 | isa_ok( $Document, 'PPI::Document' ); | ||||
| 219 | ok( | ||||
| 220 | $Document->ancestor_of($Document), | ||||
| 221 | 'Document is an ancestor of itself.', | ||||
| 222 | ); | ||||
| 223 | |||||
| 224 | my $words = $Document->find('Token::Word'); | ||||
| 225 | is(scalar @{$words}, 1, 'Document contains 1 Word.'); | ||||
| 226 | my $word = $words->[0]; | ||||
| 227 | ok( | ||||
| 228 | $word->ancestor_of($word), | ||||
| 229 | 'Word is an ancestor of itself.', | ||||
| 230 | ); | ||||
| 231 | ok( | ||||
| 232 | ! $word->ancestor_of($Document), | ||||
| 233 | 'Word is not an ancestor of the Document.', | ||||
| 234 | ); | ||||
| 235 | ok( | ||||
| 236 | $Document->ancestor_of($word), | ||||
| 237 | 'Document is an ancestor of the Word.', | ||||
| 238 | ); | ||||
| 239 | |||||
| 240 | my $symbols = $Document->find('Token::Symbol'); | ||||
| 241 | is(scalar @{$symbols}, 1, 'Document contains 1 Symbol.'); | ||||
| 242 | my $symbol = $symbols->[0]; | ||||
| 243 | ok( | ||||
| 244 | ! $word->ancestor_of($symbol), | ||||
| 245 | 'Word is not an ancestor the Symbol.', | ||||
| 246 | ); | ||||
| 247 | ok( | ||||
| 248 | ! $symbol->ancestor_of($word), | ||||
| 249 | 'Symbol is not an ancestor the Word.', | ||||
| 250 | ); | ||||
| 251 | |||||
| 252 | =end testing | ||||
| 253 | |||||
| 254 | =cut | ||||
| 255 | |||||
| 256 | sub ancestor_of { | ||||
| 257 | my $self = shift; | ||||
| 258 | my $cursor = shift or return undef; | ||||
| 259 | while ( refaddr $cursor != refaddr $self ) { | ||||
| 260 | $cursor = $_PARENT{refaddr $cursor} or return ''; | ||||
| 261 | } | ||||
| 262 | return 1; | ||||
| 263 | } | ||||
| 264 | |||||
| 265 | =pod | ||||
| 266 | |||||
| 267 | =head2 statement | ||||
| 268 | |||||
| 269 | For a C<PPI::Element> that is contained (at some depth) within a | ||||
| 270 | L<PPI::Statment>, the C<statement> method will return the first parent | ||||
| 271 | Statement object lexically 'above' the Element. | ||||
| 272 | |||||
| 273 | Returns a L<PPI::Statement> object, which may be the same Element if the | ||||
| 274 | Element is itself a L<PPI::Statement> object. | ||||
| 275 | |||||
| 276 | Returns false if the Element is not within a Statement and is not itself | ||||
| 277 | a Statement. | ||||
| 278 | |||||
| 279 | =cut | ||||
| 280 | |||||
| 281 | # spent 8.20ms (5.54+2.66) within PPI::Element::statement which was called 286 times, avg 29µs/call:
# 77 times (3.41ms+707µs) by Perl::Critic::Utils::is_included_module_name at line 744 of Perl/Critic/Utils.pm, avg 54µs/call
# 77 times (750µs+678µs) by Perl::Critic::Utils::is_label_pointer at line 765 of Perl/Critic/Utils.pm, avg 19µs/call
# 77 times (716µs+676µs) by Perl::Critic::Utils::is_package_declaration at line 808 of Perl/Critic/Utils.pm, avg 18µs/call
# 52 times (623µs+569µs) by Perl::Critic::Utils::is_subroutine_name at line 821 of Perl/Critic/Utils.pm, avg 23µs/call
# 3 times (34µs+30µs) by Perl::Critic::Violation::_line_containing_violation at line 303 of Perl/Critic/Violation.pm, avg 21µs/call | ||||
| 282 | 286 | 50µs | my $cursor = shift; | ||
| 283 | 286 | 1.64ms | 572 | 1.46ms | while ( ! _INSTANCE($cursor, 'PPI::Statement') ) { # spent 1.18ms making 286 calls to Params::Util::_INSTANCE, avg 4µs/call
# spent 279µs making 286 calls to UNIVERSAL::isa, avg 976ns/call |
| 284 | 286 | 6.09ms | 1430 | 1.65ms | $cursor = $_PARENT{refaddr $cursor} or return ''; # spent 1.01ms making 286 calls to Params::Util::_INSTANCE, avg 4µs/call
# spent 305µs making 572 calls to PPI::Util::TRUE, avg 533ns/call
# spent 174µs making 286 calls to Scalar::Util::refaddr, avg 607ns/call
# spent 166µs making 286 calls to UNIVERSAL::isa, avg 580ns/call |
| 285 | } | ||||
| 286 | 286 | 537µs | $cursor; | ||
| 287 | } | ||||
| 288 | |||||
| 289 | =pod | ||||
| 290 | |||||
| 291 | =head2 top | ||||
| 292 | |||||
| 293 | For a C<PPI::Element> that is contained within a PDOM tree, the C<top> method | ||||
| 294 | will return the top-level Node in the tree. Most of the time this should be | ||||
| 295 | a L<PPI::Document> object, however this will not always be so. For example, | ||||
| 296 | if a subroutine has been removed from its Document, to be moved to another | ||||
| 297 | Document. | ||||
| 298 | |||||
| 299 | Returns the top-most PDOM object, which may be the same Element, if it is | ||||
| 300 | not within any parent PDOM object. | ||||
| 301 | |||||
| 302 | =cut | ||||
| 303 | |||||
| 304 | # spent 127µs (102+25) within PPI::Element::top which was called 3 times, avg 42µs/call:
# 3 times (102µs+25µs) by Perl::Critic::Violation::new at line 85 of Perl/Critic/Violation.pm, avg 42µs/call | ||||
| 305 | 3 | 1µs | my $cursor = shift; | ||
| 306 | 3 | 119µs | 51 | 25µs | while ( my $parent = $_PARENT{refaddr $cursor} ) { # spent 14µs making 27 calls to Scalar::Util::refaddr, avg 519ns/call
# spent 11µs making 24 calls to PPI::Util::TRUE, avg 475ns/call |
| 307 | $cursor = $parent; | ||||
| 308 | } | ||||
| 309 | 3 | 7µs | $cursor; | ||
| 310 | } | ||||
| 311 | |||||
| 312 | =pod | ||||
| 313 | |||||
| 314 | =head2 document | ||||
| 315 | |||||
| 316 | For an Element that is contained within a L<PPI::Document> object, | ||||
| 317 | the C<document> method will return the top-level Document for the Element. | ||||
| 318 | |||||
| 319 | Returns the L<PPI::Document> for this Element, or false if the Element is not | ||||
| 320 | contained within a Document. | ||||
| 321 | |||||
| 322 | =cut | ||||
| 323 | |||||
| 324 | sub document { | ||||
| 325 | my $top = shift->top; | ||||
| 326 | _INSTANCE($top, 'PPI::Document') and $top; | ||||
| 327 | } | ||||
| 328 | |||||
| 329 | =pod | ||||
| 330 | |||||
| 331 | =head2 next_sibling | ||||
| 332 | |||||
| 333 | All L<PPI::Node> objects (specifically, our parent Node) contain a number of | ||||
| 334 | C<PPI::Element> objects. The C<next_sibling> method returns the C<PPI::Element> | ||||
| 335 | immediately after the current one, or false if there is no next sibling. | ||||
| 336 | |||||
| 337 | =cut | ||||
| 338 | |||||
| 339 | # spent 17.6ms (2.79+14.8) within PPI::Element::next_sibling which was called 226 times, avg 78µs/call:
# 216 times (2.68ms+14.7ms) by Perl::Critic::Annotation::_init at line 108 of Perl/Critic/Annotation.pm, avg 80µs/call
# 10 times (109µs+87µs) by Perl::Critic::Annotation::_init at line 119 of Perl/Critic/Annotation.pm, avg 20µs/call | ||||
| 340 | 226 | 42µs | my $self = shift; | ||
| 341 | 226 | 1.11ms | 452 | 241µs | my $parent = $_PARENT{refaddr $self} or return ''; # spent 121µs making 226 calls to Scalar::Util::refaddr, avg 535ns/call
# spent 120µs making 226 calls to PPI::Util::TRUE, avg 532ns/call |
| 342 | 226 | 460µs | 226 | 123µs | my $key = refaddr $self; # spent 123µs making 226 calls to Scalar::Util::refaddr, avg 545ns/call |
| 343 | 226 | 74µs | my $elements = $parent->{children}; | ||
| 344 | my $position = List::MoreUtils::firstidx { | ||||
| 345 | 5789 | 13.6ms | 5789 | 2.49ms | refaddr $_ == $key # spent 2.49ms making 5789 calls to Scalar::Util::refaddr, avg 430ns/call |
| 346 | 226 | 387µs | 226 | 14.3ms | } @$elements; # spent 14.3ms making 226 calls to List::MoreUtils::firstidx, avg 63µs/call |
| 347 | 226 | 2.64ms | 216 | 132µs | $elements->[$position + 1] || ''; # spent 132µs making 216 calls to PPI::Util::TRUE, avg 611ns/call |
| 348 | } | ||||
| 349 | |||||
| 350 | =pod | ||||
| 351 | |||||
| 352 | =head2 snext_sibling | ||||
| 353 | |||||
| 354 | As per the other 's' methods, the C<snext_sibling> method returns the next | ||||
| 355 | B<significant> sibling of the C<PPI::Element> object. | ||||
| 356 | |||||
| 357 | Returns a C<PPI::Element> object, or false if there is no 'next' significant | ||||
| 358 | sibling. | ||||
| 359 | |||||
| 360 | =cut | ||||
| 361 | |||||
| 362 | # spent 916ms (519+397) within PPI::Element::snext_sibling which was called 30261 times, avg 30µs/call:
# 14319 times (253ms+208ms) by Perl::Critic::Utils::_is_followed_by_parens at line 735 of Perl/Critic/Utils.pm, avg 32µs/call
# 11399 times (196ms+141ms) by Perl::Critic::Utils::is_hash_key at line 722 of Perl/Critic/Utils.pm, avg 30µs/call
# 2101 times (32.1ms+23.4ms) by Perl::Critic::Policy::Subroutines::ProhibitReturnSort::violates at line 39 of Perl/Critic/Policy/Subroutines/ProhibitReturnSort.pm, avg 26µs/call
# 2101 times (32.8ms+18.6ms) by Perl::Critic::Policy::Subroutines::ProhibitExplicitReturnUndef::violates at line 39 of Perl/Critic/Policy/Subroutines/ProhibitExplicitReturnUndef.pm, avg 24µs/call
# 105 times (1.45ms+2.07ms) by Perl::Critic::Utils::parse_arg_list at line 975 of Perl/Critic/Utils.pm, avg 34µs/call
# 77 times (1.14ms+1.24ms) by Perl::Critic::Utils::is_class_name at line 790 of Perl/Critic/Utils.pm, avg 31µs/call
# 66 times (989µs+1.13ms) by Perl::Critic::Utils::first_arg at line 922 of Perl/Critic/Utils.pm, avg 32µs/call
# 57 times (812µs+580µs) by Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions::_is_assignment_to_topic at line 136 of Perl/Critic/Policy/ControlStructures/ProhibitMutatingListFunctions.pm, avg 24µs/call
# 18 times (283µs+181µs) by Perl::Critic::Utils::parse_arg_list at line 939 of Perl/Critic/Utils.pm, avg 26µs/call
# 18 times (254µs+167µs) by Perl::Critic::Utils::parse_arg_list at line 970 of Perl/Critic/Utils.pm, avg 23µs/call | ||||
| 363 | 30261 | 5.35ms | my $self = shift; | ||
| 364 | 30261 | 167ms | 60522 | 33.7ms | my $parent = $_PARENT{refaddr $self} or return ''; # spent 17.5ms making 30261 calls to Scalar::Util::refaddr, avg 578ns/call
# spent 16.2ms making 30261 calls to PPI::Util::TRUE, avg 536ns/call |
| 365 | 30261 | 77.2ms | 30261 | 17.3ms | my $key = refaddr $self; # spent 17.3ms making 30261 calls to Scalar::Util::refaddr, avg 570ns/call |
| 366 | 30261 | 10.6ms | my $elements = $parent->{children}; | ||
| 367 | my $position = List::MoreUtils::firstidx { | ||||
| 368 | 95278 | 324ms | 95278 | 47.5ms | refaddr $_ == $key # spent 47.5ms making 95278 calls to Scalar::Util::refaddr, avg 498ns/call |
| 369 | 30261 | 56.8ms | 30261 | 294ms | } @$elements; # spent 294ms making 30261 calls to List::MoreUtils::firstidx, avg 10µs/call |
| 370 | 30261 | 151ms | 55005 | 51.3ms | while ( defined(my $it = $elements->[++$position]) ) { # spent 26.7ms making 25219 calls to PPI::Token::Whitespace::significant, avg 1µs/call
# spent 24.6ms making 29775 calls to PPI::Element::significant, avg 826ns/call
# spent 14µs making 11 calls to PPI::Token::Comment::significant, avg 1µs/call |
| 371 | return $it if $it->significant; | ||||
| 372 | } | ||||
| 373 | 486 | 1.07ms | ''; | ||
| 374 | } | ||||
| 375 | |||||
| 376 | =pod | ||||
| 377 | |||||
| 378 | =head2 previous_sibling | ||||
| 379 | |||||
| 380 | All L<PPI::Node> objects (specifically, our parent Node) contain a number of | ||||
| 381 | C<PPI::Element> objects. The C<previous_sibling> method returns the Element | ||||
| 382 | immediately before the current one, or false if there is no 'previous' | ||||
| 383 | C<PPI::Element> object. | ||||
| 384 | |||||
| 385 | =cut | ||||
| 386 | |||||
| 387 | sub previous_sibling { | ||||
| 388 | my $self = shift; | ||||
| 389 | my $parent = $_PARENT{refaddr $self} or return ''; | ||||
| 390 | my $key = refaddr $self; | ||||
| 391 | my $elements = $parent->{children}; | ||||
| 392 | my $position = List::MoreUtils::firstidx { | ||||
| 393 | refaddr $_ == $key | ||||
| 394 | } @$elements; | ||||
| 395 | $position and $elements->[$position - 1] or ''; | ||||
| 396 | } | ||||
| 397 | |||||
| 398 | =pod | ||||
| 399 | |||||
| 400 | =head2 sprevious_sibling | ||||
| 401 | |||||
| 402 | As per the other 's' methods, the C<sprevious_sibling> method returns | ||||
| 403 | the previous B<significant> sibling of the C<PPI::Element> object. | ||||
| 404 | |||||
| 405 | Returns a C<PPI::Element> object, or false if there is no 'previous' significant | ||||
| 406 | sibling. | ||||
| 407 | |||||
| 408 | =cut | ||||
| 409 | |||||
| 410 | # spent 15.3ms (5.42+9.88) within PPI::Element::sprevious_sibling which was called 339 times, avg 45µs/call:
# 77 times (1.26ms+3.01ms) by Perl::Critic::Utils::is_method_call at line 781 of Perl/Critic/Utils.pm, avg 56µs/call
# 77 times (1.15ms+1.26ms) by Perl::Critic::Utils::is_subroutine_name at line 819 of Perl/Critic/Utils.pm, avg 31µs/call
# 77 times (1.13ms+1.22ms) by Perl::Critic::Utils::is_label_pointer at line 768 of Perl/Critic/Utils.pm, avg 31µs/call
# 57 times (703µs+531µs) by Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions::_is_assignment_to_topic at line 141 of Perl/Critic/Policy/ControlStructures/ProhibitMutatingListFunctions.pm, avg 22µs/call
# 51 times (1.17ms+3.87ms) by Perl::Critic::Annotation::_is_single_line_annotation_on_simple_statement at line 188 of Perl/Critic/Annotation.pm, avg 99µs/call | ||||
| 411 | 339 | 72µs | my $self = shift; | ||
| 412 | 339 | 1.64ms | 678 | 368µs | my $parent = $_PARENT{refaddr $self} or return ''; # spent 192µs making 339 calls to PPI::Util::TRUE, avg 565ns/call
# spent 176µs making 339 calls to Scalar::Util::refaddr, avg 519ns/call |
| 413 | 339 | 731µs | 339 | 192µs | my $key = refaddr $self; # spent 192µs making 339 calls to Scalar::Util::refaddr, avg 567ns/call |
| 414 | 339 | 130µs | my $elements = $parent->{children}; | ||
| 415 | my $position = List::MoreUtils::firstidx { | ||||
| 416 | 2437 | 8.90ms | 2437 | 1.13ms | refaddr $_ == $key # spent 1.13ms making 2437 calls to Scalar::Util::refaddr, avg 464ns/call |
| 417 | 339 | 789µs | 339 | 8.81ms | } @$elements; # spent 8.81ms making 339 calls to List::MoreUtils::firstidx, avg 26µs/call |
| 418 | 339 | 1.43ms | 498 | 513µs | while ( $position-- and defined(my $it = $elements->[$position]) ) { # spent 309µs making 270 calls to PPI::Token::Whitespace::significant, avg 1µs/call
# spent 193µs making 218 calls to PPI::Element::significant, avg 884ns/call
# spent 12µs making 10 calls to PPI::Token::Comment::significant, avg 1µs/call |
| 419 | return $it if $it->significant; | ||||
| 420 | } | ||||
| 421 | 121 | 290µs | ''; | ||
| 422 | } | ||||
| 423 | |||||
| 424 | =pod | ||||
| 425 | |||||
| 426 | =head2 first_token | ||||
| 427 | |||||
| 428 | As a support method for higher-order algorithms that deal specifically with | ||||
| 429 | tokens and actual Perl content, the C<first_token> method finds the first | ||||
| 430 | PPI::Token object within or equal to this one. | ||||
| 431 | |||||
| 432 | That is, if called on a L<PPI::Node> subclass, it will descend until it | ||||
| 433 | finds a L<PPI::Token>. If called on a L<PPI::Token> object, it will return | ||||
| 434 | the same object. | ||||
| 435 | |||||
| 436 | Returns a L<PPI::Token> object, or dies on error (which should be extremely | ||||
| 437 | rare and only occur if an illegal empty L<PPI::Statement> exists below the | ||||
| 438 | current Element somewhere. | ||||
| 439 | |||||
| 440 | =cut | ||||
| 441 | |||||
| 442 | sub first_token { | ||||
| 443 | my $cursor = shift; | ||||
| 444 | while ( $cursor->isa('PPI::Node') ) { | ||||
| 445 | $cursor = $cursor->first_element | ||||
| 446 | or die "Found empty PPI::Node while getting first token"; | ||||
| 447 | } | ||||
| 448 | $cursor; | ||||
| 449 | } | ||||
| 450 | |||||
| 451 | |||||
| 452 | =pod | ||||
| 453 | |||||
| 454 | =head2 last_token | ||||
| 455 | |||||
| 456 | As a support method for higher-order algorithms that deal specifically with | ||||
| 457 | tokens and actual Perl content, the C<last_token> method finds the last | ||||
| 458 | PPI::Token object within or equal to this one. | ||||
| 459 | |||||
| 460 | That is, if called on a L<PPI::Node> subclass, it will descend until it | ||||
| 461 | finds a L<PPI::Token>. If called on a L<PPI::Token> object, it will return | ||||
| 462 | the itself. | ||||
| 463 | |||||
| 464 | Returns a L<PPI::Token> object, or dies on error (which should be extremely | ||||
| 465 | rare and only occur if an illegal empty L<PPI::Statement> exists below the | ||||
| 466 | current Element somewhere. | ||||
| 467 | |||||
| 468 | =cut | ||||
| 469 | |||||
| 470 | sub last_token { | ||||
| 471 | my $cursor = shift; | ||||
| 472 | while ( $cursor->isa('PPI::Node') ) { | ||||
| 473 | $cursor = $cursor->last_element | ||||
| 474 | or die "Found empty PPI::Node while getting first token"; | ||||
| 475 | } | ||||
| 476 | $cursor; | ||||
| 477 | } | ||||
| 478 | |||||
| 479 | =pod | ||||
| 480 | |||||
| 481 | =head2 next_token | ||||
| 482 | |||||
| 483 | As a support method for higher-order algorithms that deal specifically with | ||||
| 484 | tokens and actual Perl content, the C<next_token> method finds the | ||||
| 485 | L<PPI::Token> object that is immediately after the current Element, even if | ||||
| 486 | it is not within the same parent L<PPI::Node> as the one for which the | ||||
| 487 | method is being called. | ||||
| 488 | |||||
| 489 | Note that this is B<not> defined as a L<PPI::Token>-specific method, | ||||
| 490 | because it can be useful to find the next token that is after, say, a | ||||
| 491 | L<PPI::Statement>, although obviously it would be useless to want the | ||||
| 492 | next token after a L<PPI::Document>. | ||||
| 493 | |||||
| 494 | Returns a L<PPI::Token> object, or false if there are no more tokens after | ||||
| 495 | the Element. | ||||
| 496 | |||||
| 497 | =cut | ||||
| 498 | |||||
| 499 | sub next_token { | ||||
| 500 | my $cursor = shift; | ||||
| 501 | |||||
| 502 | # Find the next element, going upwards as needed | ||||
| 503 | while ( 1 ) { | ||||
| 504 | my $element = $cursor->next_sibling; | ||||
| 505 | if ( $element ) { | ||||
| 506 | return $element if $element->isa('PPI::Token'); | ||||
| 507 | return $element->first_token; | ||||
| 508 | } | ||||
| 509 | $cursor = $cursor->parent or return ''; | ||||
| 510 | if ( $cursor->isa('PPI::Structure') and $cursor->finish ) { | ||||
| 511 | return $cursor->finish; | ||||
| 512 | } | ||||
| 513 | } | ||||
| 514 | } | ||||
| 515 | |||||
| 516 | =pod | ||||
| 517 | |||||
| 518 | =head2 previous_token | ||||
| 519 | |||||
| 520 | As a support method for higher-order algorithms that deal specifically with | ||||
| 521 | tokens and actual Perl content, the C<previous_token> method finds the | ||||
| 522 | L<PPI::Token> object that is immediately before the current Element, even | ||||
| 523 | if it is not within the same parent L<PPI::Node> as this one. | ||||
| 524 | |||||
| 525 | Note that this is not defined as a L<PPI::Token>-only method, because it can | ||||
| 526 | be useful to find the token is before, say, a L<PPI::Statement>, although | ||||
| 527 | obviously it would be useless to want the next token before a | ||||
| 528 | L<PPI::Document>. | ||||
| 529 | |||||
| 530 | Returns a L<PPI::Token> object, or false if there are no more tokens before | ||||
| 531 | the C<Element>. | ||||
| 532 | |||||
| 533 | =cut | ||||
| 534 | |||||
| 535 | sub previous_token { | ||||
| 536 | my $cursor = shift; | ||||
| 537 | |||||
| 538 | # Find the previous element, going upwards as needed | ||||
| 539 | while ( 1 ) { | ||||
| 540 | my $element = $cursor->previous_sibling; | ||||
| 541 | if ( $element ) { | ||||
| 542 | return $element if $element->isa('PPI::Token'); | ||||
| 543 | return $element->last_token; | ||||
| 544 | } | ||||
| 545 | $cursor = $cursor->parent or return ''; | ||||
| 546 | if ( $cursor->isa('PPI::Structure') and $cursor->start ) { | ||||
| 547 | return $cursor->start; | ||||
| 548 | } | ||||
| 549 | } | ||||
| 550 | } | ||||
| 551 | |||||
| - - | |||||
| 556 | ##################################################################### | ||||
| 557 | # Manipulation | ||||
| 558 | |||||
| 559 | =pod | ||||
| 560 | |||||
| 561 | =head2 clone | ||||
| 562 | |||||
| 563 | As per the L<Clone> module, the C<clone> method makes a perfect copy of | ||||
| 564 | an Element object. In the generic case, the implementation is done using | ||||
| 565 | the L<Clone> module's mechanism itself. In higher-order cases, such as for | ||||
| 566 | Nodes, there is more work involved to keep the parent-child links intact. | ||||
| 567 | |||||
| 568 | =cut | ||||
| 569 | |||||
| 570 | sub clone { | ||||
| 571 | Clone::clone(shift); | ||||
| 572 | } | ||||
| 573 | |||||
| 574 | =pod | ||||
| 575 | |||||
| 576 | =head2 insert_before @Elements | ||||
| 577 | |||||
| 578 | The C<insert_before> method allows you to insert lexical perl content, in | ||||
| 579 | the form of C<PPI::Element> objects, before the calling C<Element>. You | ||||
| 580 | need to be very careful when modifying perl code, as it's easy to break | ||||
| 581 | things. | ||||
| 582 | |||||
| 583 | In its initial incarnation, this method allows you to insert a single | ||||
| 584 | Element, and will perform some basic checking to prevent you inserting | ||||
| 585 | something that would be structurally wrong (in PDOM terms). | ||||
| 586 | |||||
| 587 | In future, this method may be enhanced to allow the insertion of multiple | ||||
| 588 | Elements, inline-parsed code strings or L<PPI::Document::Fragment> objects. | ||||
| 589 | |||||
| 590 | Returns true if the Element was inserted, false if it can not be inserted, | ||||
| 591 | or C<undef> if you do not provide a L<PPI::Element> object as a parameter. | ||||
| 592 | |||||
| 593 | =begin testing __insert_before 6 | ||||
| 594 | |||||
| 595 | my $Document = PPI::Document->new( \"print 'Hello World';" ); | ||||
| 596 | isa_ok( $Document, 'PPI::Document' ); | ||||
| 597 | my $semi = $Document->find_first('Token::Structure'); | ||||
| 598 | isa_ok( $semi, 'PPI::Token::Structure' ); | ||||
| 599 | is( $semi->content, ';', 'Got expected token' ); | ||||
| 600 | my $foo = PPI::Token::Word->new('foo'); | ||||
| 601 | isa_ok( $foo, 'PPI::Token::Word' ); | ||||
| 602 | is( $foo->content, 'foo', 'Created Word token' ); | ||||
| 603 | $semi->__insert_before( $foo ); | ||||
| 604 | is( $Document->serialize, "print 'Hello World'foo;", | ||||
| 605 | '__insert_before actually inserts' ); | ||||
| 606 | |||||
| 607 | =end testing | ||||
| 608 | |||||
| 609 | =begin testing insert_before after __insert_before 6 | ||||
| 610 | |||||
| 611 | my $Document = PPI::Document->new( \"print 'Hello World';" ); | ||||
| 612 | isa_ok( $Document, 'PPI::Document' ); | ||||
| 613 | my $semi = $Document->find_first('Token::Structure'); | ||||
| 614 | isa_ok( $semi, 'PPI::Token::Structure' ); | ||||
| 615 | is( $semi->content, ';', 'Got expected token' ); | ||||
| 616 | my $foo = PPI::Token::Word->new('foo'); | ||||
| 617 | isa_ok( $foo, 'PPI::Token::Word' ); | ||||
| 618 | is( $foo->content, 'foo', 'Created Word token' ); | ||||
| 619 | $semi->insert_before( $foo ); | ||||
| 620 | is( $Document->serialize, "print 'Hello World'foo;", | ||||
| 621 | 'insert_before actually inserts' ); | ||||
| 622 | |||||
| 623 | =end testing | ||||
| 624 | |||||
| 625 | =cut | ||||
| 626 | |||||
| 627 | sub __insert_before { | ||||
| 628 | my $self = shift; | ||||
| 629 | $self->parent->__insert_before_child( $self, @_ ); | ||||
| 630 | } | ||||
| 631 | |||||
| 632 | =pod | ||||
| 633 | |||||
| 634 | =head2 insert_after @Elements | ||||
| 635 | |||||
| 636 | The C<insert_after> method allows you to insert lexical perl content, in | ||||
| 637 | the form of C<PPI::Element> objects, after the calling C<Element>. You need | ||||
| 638 | to be very careful when modifying perl code, as it's easy to break things. | ||||
| 639 | |||||
| 640 | In its initial incarnation, this method allows you to insert a single | ||||
| 641 | Element, and will perform some basic checking to prevent you inserting | ||||
| 642 | something that would be structurally wrong (in PDOM terms). | ||||
| 643 | |||||
| 644 | In future, this method may be enhanced to allow the insertion of multiple | ||||
| 645 | Elements, inline-parsed code strings or L<PPI::Document::Fragment> objects. | ||||
| 646 | |||||
| 647 | Returns true if the Element was inserted, false if it can not be inserted, | ||||
| 648 | or C<undef> if you do not provide a L<PPI::Element> object as a parameter. | ||||
| 649 | |||||
| 650 | =begin testing __insert_after 6 | ||||
| 651 | |||||
| 652 | my $Document = PPI::Document->new( \"print 'Hello World';" ); | ||||
| 653 | isa_ok( $Document, 'PPI::Document' ); | ||||
| 654 | my $string = $Document->find_first('Token::Quote'); | ||||
| 655 | isa_ok( $string, 'PPI::Token::Quote' ); | ||||
| 656 | is( $string->content, "'Hello World'", 'Got expected token' ); | ||||
| 657 | my $foo = PPI::Token::Word->new('foo'); | ||||
| 658 | isa_ok( $foo, 'PPI::Token::Word' ); | ||||
| 659 | is( $foo->content, 'foo', 'Created Word token' ); | ||||
| 660 | $string->__insert_after( $foo ); | ||||
| 661 | is( $Document->serialize, "print 'Hello World'foo;", | ||||
| 662 | '__insert_after actually inserts' ); | ||||
| 663 | |||||
| 664 | =end testing | ||||
| 665 | |||||
| 666 | =begin testing insert_after after __insert_after 6 | ||||
| 667 | |||||
| 668 | my $Document = PPI::Document->new( \"print 'Hello World';" ); | ||||
| 669 | isa_ok( $Document, 'PPI::Document' ); | ||||
| 670 | my $string = $Document->find_first('Token::Quote'); | ||||
| 671 | isa_ok( $string, 'PPI::Token::Quote' ); | ||||
| 672 | is( $string->content, "'Hello World'", 'Got expected token' ); | ||||
| 673 | my $foo = PPI::Token::Word->new('foo'); | ||||
| 674 | isa_ok( $foo, 'PPI::Token::Word' ); | ||||
| 675 | is( $foo->content, 'foo', 'Created Word token' ); | ||||
| 676 | $string->insert_after( $foo ); | ||||
| 677 | is( $Document->serialize, "print 'Hello World'foo;", | ||||
| 678 | 'insert_after actually inserts' ); | ||||
| 679 | |||||
| 680 | =end testing | ||||
| 681 | |||||
| 682 | =cut | ||||
| 683 | |||||
| 684 | sub __insert_after { | ||||
| 685 | my $self = shift; | ||||
| 686 | $self->parent->__insert_after_child( $self, @_ ); | ||||
| 687 | } | ||||
| 688 | |||||
| 689 | =pod | ||||
| 690 | |||||
| 691 | =head2 remove | ||||
| 692 | |||||
| 693 | For a given C<PPI::Element>, the C<remove> method will remove it from its | ||||
| 694 | parent B<intact>, along with all of its children. | ||||
| 695 | |||||
| 696 | Returns the C<Element> itself as a convenience, or C<undef> if an error | ||||
| 697 | occurs while trying to remove the C<Element>. | ||||
| 698 | |||||
| 699 | =cut | ||||
| 700 | |||||
| 701 | sub remove { | ||||
| 702 | my $self = shift; | ||||
| 703 | my $parent = $self->parent or return $self; | ||||
| 704 | $parent->remove_child( $self ); | ||||
| 705 | } | ||||
| 706 | |||||
| 707 | =pod | ||||
| 708 | |||||
| 709 | =head2 delete | ||||
| 710 | |||||
| 711 | For a given C<PPI::Element>, the C<delete> method will remove it from its | ||||
| 712 | parent, immediately deleting the C<Element> and all of its children (if it | ||||
| 713 | has any). | ||||
| 714 | |||||
| 715 | Returns true if the C<Element> was successfully deleted, or C<undef> if | ||||
| 716 | an error occurs while trying to remove the C<Element>. | ||||
| 717 | |||||
| 718 | =cut | ||||
| 719 | |||||
| 720 | sub delete { | ||||
| 721 | $_[0]->remove or return undef; | ||||
| 722 | $_[0]->DESTROY; | ||||
| 723 | 1; | ||||
| 724 | } | ||||
| 725 | |||||
| 726 | =pod | ||||
| 727 | |||||
| 728 | =head2 replace $Element | ||||
| 729 | |||||
| 730 | Although some higher level class support more exotic forms of replace, | ||||
| 731 | at the basic level the C<replace> method takes a single C<Element> as | ||||
| 732 | an argument and replaces the current C<Element> with it. | ||||
| 733 | |||||
| 734 | To prevent accidental damage to code, in this initial implementation the | ||||
| 735 | replacement element B<must> be of the same class (or a subclass) as the | ||||
| 736 | one being replaced. | ||||
| 737 | |||||
| 738 | =cut | ||||
| 739 | |||||
| 740 | sub replace { | ||||
| 741 | my $self = ref $_[0] ? shift : return undef; | ||||
| 742 | my $Element = _INSTANCE(shift, ref $self) or return undef; | ||||
| 743 | die "The ->replace method has not yet been implemented"; | ||||
| 744 | } | ||||
| 745 | |||||
| 746 | =pod | ||||
| 747 | |||||
| 748 | =head2 location | ||||
| 749 | |||||
| 750 | If the Element exists within a L<PPI::Document> that has | ||||
| 751 | indexed the Element locations using C<PPI::Document::index_locations>, the | ||||
| 752 | C<location> method will return the location of the first character of the | ||||
| 753 | Element within the Document. | ||||
| 754 | |||||
| 755 | Returns the location as a reference to a five-element array in the form C<[ | ||||
| 756 | $line, $rowchar, $col, $logical_line, $logical_file_name ]>. The values are in | ||||
| 757 | a human format, with the first character of the file located at C<[ 1, 1, 1, ?, | ||||
| 758 | 'something' ]>. | ||||
| 759 | |||||
| 760 | The second and third numbers are similar, except that the second is the | ||||
| 761 | literal horizontal character, and the third is the visual column, taking | ||||
| 762 | into account tabbing (see L<PPI::Document/"tab_width [ $width ]">). | ||||
| 763 | |||||
| 764 | The fourth number is the line number, taking into account any C<#line> | ||||
| 765 | directives. The fifth element is the name of the file that the element was | ||||
| 766 | found in, if available, taking into account any C<#line> directives. | ||||
| 767 | |||||
| 768 | Returns C<undef> on error, or if the L<PPI::Document> object has not been | ||||
| 769 | indexed. | ||||
| 770 | |||||
| 771 | =cut | ||||
| 772 | |||||
| 773 | # spent 61.3ms (47.2+14.1) within PPI::Element::location which was called 9763 times, avg 6µs/call:
# 9602 times (46.4ms+13.8ms) by PPI::Node::location at line 685 of PPI/Node.pm, avg 6µs/call
# 132 times (633µs+256µs) by PPI::Element::logical_line_number at line 932, avg 7µs/call
# 23 times (111µs+34µs) by PPI::Structure::location at line 265 of PPI/Structure.pm, avg 6µs/call
# 3 times (15µs+6µs) by PPI::Element::line_number at line 814, avg 7µs/call
# 3 times (11µs+3µs) by Perl::Critic::Violation::new at line 88 of Perl/Critic/Violation.pm, avg 5µs/call | ||||
| 774 | 9763 | 1.24ms | my $self = shift; | ||
| 775 | |||||
| 776 | 9763 | 7.72ms | 9763 | 14.1ms | $self->_ensure_location_present or return undef; # spent 14.1ms making 9763 calls to PPI::Element::_ensure_location_present, avg 1µs/call |
| 777 | |||||
| 778 | # Return a copy, not the original | ||||
| 779 | 9763 | 35.9ms | return [ @{$self->{_location}} ]; | ||
| 780 | } | ||||
| 781 | |||||
| 782 | =pod | ||||
| 783 | |||||
| 784 | =head2 line_number | ||||
| 785 | |||||
| 786 | If the Element exists within a L<PPI::Document> that has indexed the Element | ||||
| 787 | locations using C<PPI::Document::index_locations>, the C<line_number> method | ||||
| 788 | will return the line number of the first character of the Element within the | ||||
| 789 | Document. | ||||
| 790 | |||||
| 791 | Returns C<undef> on error, or if the L<PPI::Document> object has not been | ||||
| 792 | indexed. | ||||
| 793 | |||||
| 794 | =begin testing line_number 3 | ||||
| 795 | |||||
| 796 | my $document = PPI::Document->new(\<<'END_PERL'); | ||||
| 797 | |||||
| 798 | |||||
| 799 | foo | ||||
| 800 | END_PERL | ||||
| 801 | |||||
| 802 | isa_ok( $document, 'PPI::Document' ); | ||||
| 803 | my $words = $document->find('PPI::Token::Word'); | ||||
| 804 | is( scalar @{$words}, 1, 'Found expected word token.' ); | ||||
| 805 | is( $words->[0]->line_number, 3, 'Got correct line number.' ); | ||||
| 806 | |||||
| 807 | =end testing | ||||
| 808 | |||||
| 809 | =cut | ||||
| 810 | |||||
| 811 | # spent 83µs (28+55) within PPI::Element::line_number which was called 6 times, avg 14µs/call:
# 6 times (28µs+55µs) by Perl::Critic::Violation::_line_containing_violation at line 310 of Perl/Critic/Violation.pm, avg 14µs/call | ||||
| 812 | 6 | 1µs | my $self = shift; | ||
| 813 | |||||
| 814 | 6 | 8µs | 6 | 55µs | my $location = $self->location() or return undef; # spent 34µs making 3 calls to PPI::Node::location, avg 11µs/call
# spent 21µs making 3 calls to PPI::Element::location, avg 7µs/call |
| 815 | 6 | 14µs | return $location->[0]; | ||
| 816 | } | ||||
| 817 | |||||
| 818 | =pod | ||||
| 819 | |||||
| 820 | =head2 column_number | ||||
| 821 | |||||
| 822 | If the Element exists within a L<PPI::Document> that has indexed the Element | ||||
| 823 | locations using C<PPI::Document::index_locations>, the C<column_number> method | ||||
| 824 | will return the column number of the first character of the Element within the | ||||
| 825 | Document. | ||||
| 826 | |||||
| 827 | Returns C<undef> on error, or if the L<PPI::Document> object has not been | ||||
| 828 | indexed. | ||||
| 829 | |||||
| 830 | =begin testing column_number 3 | ||||
| 831 | |||||
| 832 | my $document = PPI::Document->new(\<<'END_PERL'); | ||||
| 833 | |||||
| 834 | |||||
| 835 | foo | ||||
| 836 | END_PERL | ||||
| 837 | |||||
| 838 | isa_ok( $document, 'PPI::Document' ); | ||||
| 839 | my $words = $document->find('PPI::Token::Word'); | ||||
| 840 | is( scalar @{$words}, 1, 'Found expected word token.' ); | ||||
| 841 | is( $words->[0]->column_number, 4, 'Got correct column number.' ); | ||||
| 842 | |||||
| 843 | =end testing | ||||
| 844 | |||||
| 845 | =cut | ||||
| 846 | |||||
| 847 | sub column_number { | ||||
| 848 | my $self = shift; | ||||
| 849 | |||||
| 850 | my $location = $self->location() or return undef; | ||||
| 851 | return $location->[1]; | ||||
| 852 | } | ||||
| 853 | |||||
| 854 | =pod | ||||
| 855 | |||||
| 856 | =head2 visual_column_number | ||||
| 857 | |||||
| 858 | If the Element exists within a L<PPI::Document> that has indexed the Element | ||||
| 859 | locations using C<PPI::Document::index_locations>, the C<visual_column_number> | ||||
| 860 | method will return the visual column number of the first character of the | ||||
| 861 | Element within the Document, according to the value of | ||||
| 862 | L<PPI::Document/"tab_width [ $width ]">. | ||||
| 863 | |||||
| 864 | Returns C<undef> on error, or if the L<PPI::Document> object has not been | ||||
| 865 | indexed. | ||||
| 866 | |||||
| 867 | =begin testing visual_column_number 3 | ||||
| 868 | |||||
| 869 | my $document = PPI::Document->new(\<<"END_PERL"); | ||||
| 870 | |||||
| 871 | |||||
| 872 | \t foo | ||||
| 873 | END_PERL | ||||
| 874 | |||||
| 875 | isa_ok( $document, 'PPI::Document' ); | ||||
| 876 | my $tab_width = 5; | ||||
| 877 | $document->tab_width($tab_width); # don't use a "usual" value. | ||||
| 878 | my $words = $document->find('PPI::Token::Word'); | ||||
| 879 | is( scalar @{$words}, 1, 'Found expected word token.' ); | ||||
| 880 | is( | ||||
| 881 | $words->[0]->visual_column_number, | ||||
| 882 | $tab_width + 2, | ||||
| 883 | 'Got correct visual column number.', | ||||
| 884 | ); | ||||
| 885 | |||||
| 886 | =end testing | ||||
| 887 | |||||
| 888 | =cut | ||||
| 889 | |||||
| 890 | sub visual_column_number { | ||||
| 891 | my $self = shift; | ||||
| 892 | |||||
| 893 | my $location = $self->location() or return undef; | ||||
| 894 | return $location->[2]; | ||||
| 895 | } | ||||
| 896 | |||||
| 897 | =pod | ||||
| 898 | |||||
| 899 | =head2 logical_line_number | ||||
| 900 | |||||
| 901 | If the Element exists within a L<PPI::Document> that has indexed the Element | ||||
| 902 | locations using C<PPI::Document::index_locations>, the C<logical_line_number> | ||||
| 903 | method will return the line number of the first character of the Element within | ||||
| 904 | the Document, taking into account any C<#line> directives. | ||||
| 905 | |||||
| 906 | Returns C<undef> on error, or if the L<PPI::Document> object has not been | ||||
| 907 | indexed. | ||||
| 908 | |||||
| 909 | =begin testing logical_line_number 3 | ||||
| 910 | |||||
| 911 | # Double quoted so that we don't really have a "#line" at the beginning and | ||||
| 912 | # errors in this file itself aren't affected by this. | ||||
| 913 | my $document = PPI::Document->new(\<<"END_PERL"); | ||||
| 914 | |||||
| 915 | |||||
| 916 | \#line 1 test-file | ||||
| 917 | foo | ||||
| 918 | END_PERL | ||||
| 919 | |||||
| 920 | isa_ok( $document, 'PPI::Document' ); | ||||
| 921 | my $words = $document->find('PPI::Token::Word'); | ||||
| 922 | is( scalar @{$words}, 1, 'Found expected word token.' ); | ||||
| 923 | is( $words->[0]->logical_line_number, 1, 'Got correct logical line number.' ); | ||||
| 924 | |||||
| 925 | =end testing | ||||
| 926 | |||||
| 927 | =cut | ||||
| 928 | |||||
| 929 | # spent 2.54ms (721µs+1.82) within PPI::Element::logical_line_number which was called 198 times, avg 13µs/call:
# 51 times (251µs+459µs) by Perl::Critic::Annotation::_init at line 67 of Perl/Critic/Annotation.pm, avg 14µs/call
# 51 times (149µs+261µs) by Perl::Critic::Annotation::_is_single_line_annotation_on_simple_statement at line 184 of Perl/Critic/Annotation.pm, avg 8µs/call
# 41 times (135µs+524µs) by Perl::Critic::Annotation::_is_single_line_annotation_on_simple_statement at line 193 of Perl/Critic/Annotation.pm, avg 16µs/call
# 13 times (44µs+76µs) by Perl::Critic::Annotation::_init at line 127 of Perl/Critic/Annotation.pm, avg 9µs/call
# 12 times (51µs+239µs) by Perl::Critic::Annotation::_init at line 91 of Perl/Critic/Annotation.pm, avg 24µs/call
# 12 times (32µs+118µs) by Perl::Critic::Annotation::_is_single_line_annotation_on_simple_statement at line 201 of Perl/Critic/Annotation.pm, avg 12µs/call
# 12 times (37µs+64µs) by Perl::Critic::Annotation::_is_single_line_annotation_on_simple_statement at line 209 of Perl/Critic/Annotation.pm, avg 8µs/call
# 6 times (21µs+82µs) by Perl::Critic::Annotation::_init at line 92 of Perl/Critic/Annotation.pm, avg 17µs/call | ||||
| 930 | 198 | 46µs | my $self = shift; | ||
| 931 | |||||
| 932 | 198 | 656µs | 198 | 1.82ms | return $self->location()->[3]; # spent 888µs making 132 calls to PPI::Element::location, avg 7µs/call
# spent 631µs making 51 calls to PPI::Node::location, avg 12µs/call
# spent 304µs making 15 calls to PPI::Structure::location, avg 20µs/call |
| 933 | } | ||||
| 934 | |||||
| 935 | =pod | ||||
| 936 | |||||
| 937 | =head2 logical_filename | ||||
| 938 | |||||
| 939 | If the Element exists within a L<PPI::Document> that has indexed the Element | ||||
| 940 | locations using C<PPI::Document::index_locations>, the C<logical_filename> | ||||
| 941 | method will return the logical file name containing the first character of the | ||||
| 942 | Element within the Document, taking into account any C<#line> directives. | ||||
| 943 | |||||
| 944 | Returns C<undef> on error, or if the L<PPI::Document> object has not been | ||||
| 945 | indexed. | ||||
| 946 | |||||
| 947 | =begin testing logical_filename 3 | ||||
| 948 | |||||
| 949 | # Double quoted so that we don't really have a "#line" at the beginning and | ||||
| 950 | # errors in this file itself aren't affected by this. | ||||
| 951 | my $document = PPI::Document->new(\<<"END_PERL"); | ||||
| 952 | |||||
| 953 | |||||
| 954 | \#line 1 test-file | ||||
| 955 | foo | ||||
| 956 | END_PERL | ||||
| 957 | |||||
| 958 | isa_ok( $document, 'PPI::Document' ); | ||||
| 959 | my $words = $document->find('PPI::Token::Word'); | ||||
| 960 | is( scalar @{$words}, 1, 'Found expected word token.' ); | ||||
| 961 | is( | ||||
| 962 | $words->[0]->logical_filename, | ||||
| 963 | 'test-file', | ||||
| 964 | 'Got correct logical line number.', | ||||
| 965 | ); | ||||
| 966 | |||||
| 967 | =end testing | ||||
| 968 | |||||
| 969 | =cut | ||||
| 970 | |||||
| 971 | # spent 3.55ms (908µs+2.64) within PPI::Element::logical_filename which was called 144 times, avg 25µs/call:
# 144 times (908µs+2.64ms) by Perl::Critic::Policy::Modules::RequireFilenameMatchesPackage::violates at line 56 of Perl/Critic/Policy/Modules/RequireFilenameMatchesPackage.pm, avg 25µs/call | ||||
| 972 | 144 | 63µs | my $self = shift; | ||
| 973 | |||||
| 974 | 144 | 345µs | 144 | 2.64ms | my $location = $self->location() or return undef; # spent 2.64ms making 144 calls to PPI::Node::location, avg 18µs/call |
| 975 | 144 | 518µs | return $location->[4]; | ||
| 976 | } | ||||
| 977 | |||||
| 978 | # spent 14.1ms within PPI::Element::_ensure_location_present which was called 9763 times, avg 1µs/call:
# 9763 times (14.1ms+0s) by PPI::Element::location at line 776, avg 1µs/call | ||||
| 979 | 9763 | 1.08ms | my $self = shift; | ||
| 980 | |||||
| 981 | 9763 | 4.28ms | unless ( exists $self->{_location} ) { | ||
| 982 | # Are we inside a normal document? | ||||
| 983 | my $Document = $self->document or return undef; | ||||
| 984 | if ( $Document->isa('PPI::Document::Fragment') ) { | ||||
| 985 | # Because they can't be serialized, document fragments | ||||
| 986 | # do not support the concept of location. | ||||
| 987 | return undef; | ||||
| 988 | } | ||||
| 989 | |||||
| 990 | # Generate the locations. If they need one location, then | ||||
| 991 | # the chances are they'll want more, and it's better that | ||||
| 992 | # everything is already pre-generated. | ||||
| 993 | $Document->index_locations or return undef; | ||||
| 994 | unless ( exists $self->{_location} ) { | ||||
| 995 | # erm... something went very wrong here | ||||
| 996 | return undef; | ||||
| 997 | } | ||||
| 998 | } | ||||
| 999 | |||||
| 1000 | 9763 | 21.0ms | return 1; | ||
| 1001 | } | ||||
| 1002 | |||||
| 1003 | # Although flush_locations is only publically a Document-level method, | ||||
| 1004 | # we are able to implement it at an Element level, allowing us to | ||||
| 1005 | # selectively flush only the part of the document that occurs after the | ||||
| 1006 | # element for which the flush is called. | ||||
| 1007 | sub _flush_locations { | ||||
| 1008 | my $self = shift; | ||||
| 1009 | unless ( $self == $self->top ) { | ||||
| 1010 | return $self->top->_flush_locations( $self ); | ||||
| 1011 | } | ||||
| 1012 | |||||
| 1013 | # Get the full list of all Tokens | ||||
| 1014 | my @Tokens = $self->tokens; | ||||
| 1015 | |||||
| 1016 | # Optionally allow starting from an arbitrary element (or rather, | ||||
| 1017 | # the first Token equal-to-or-within an arbitrary element) | ||||
| 1018 | if ( _INSTANCE($_[0], 'PPI::Element') ) { | ||||
| 1019 | my $start = shift->first_token; | ||||
| 1020 | while ( my $Token = shift @Tokens ) { | ||||
| 1021 | return 1 unless $Token->{_location}; | ||||
| 1022 | next unless refaddr($Token) == refaddr($start); | ||||
| 1023 | |||||
| 1024 | # Found the start. Flush it's location | ||||
| 1025 | delete $$Token->{_location}; | ||||
| 1026 | last; | ||||
| 1027 | } | ||||
| 1028 | } | ||||
| 1029 | |||||
| 1030 | # Iterate over any remaining Tokens and flush their location | ||||
| 1031 | foreach my $Token ( @Tokens ) { | ||||
| 1032 | delete $Token->{_location}; | ||||
| 1033 | } | ||||
| 1034 | |||||
| 1035 | 1; | ||||
| 1036 | } | ||||
| 1037 | |||||
| - - | |||||
| 1042 | ##################################################################### | ||||
| 1043 | # XML Compatibility Methods | ||||
| 1044 | |||||
| 1045 | sub _xml_name { | ||||
| 1046 | my $class = ref $_[0] || $_[0]; | ||||
| 1047 | my $name = lc join( '_', split /::/, $class ); | ||||
| 1048 | substr($name, 4); | ||||
| 1049 | } | ||||
| 1050 | |||||
| 1051 | sub _xml_attr { | ||||
| 1052 | return {}; | ||||
| 1053 | } | ||||
| 1054 | |||||
| 1055 | sub _xml_content { | ||||
| 1056 | defined $_[0]->{content} ? $_[0]->{content} : ''; | ||||
| 1057 | } | ||||
| 1058 | |||||
| - - | |||||
| 1063 | ##################################################################### | ||||
| 1064 | # Internals | ||||
| 1065 | |||||
| 1066 | # Set the error string | ||||
| 1067 | sub _error { | ||||
| 1068 | $errstr = $_[1]; | ||||
| 1069 | undef; | ||||
| 1070 | } | ||||
| 1071 | |||||
| 1072 | # Clear the error string | ||||
| 1073 | sub _clear { | ||||
| 1074 | $errstr = ''; | ||||
| 1075 | $_[0]; | ||||
| 1076 | } | ||||
| 1077 | |||||
| 1078 | # Being DESTROYed in this manner, rather than by an explicit | ||||
| 1079 | # ->delete means our reference count has probably fallen to zero. | ||||
| 1080 | # Therefore we don't need to remove ourselves from our parent, | ||||
| 1081 | # just the index ( just in case ). | ||||
| 1082 | ### XS -> PPI/XS.xs:_PPI_Element__DESTROY 0.900+ | ||||
| 1083 | 94372 | 500ms | 94372 | 51.4ms | # spent 389ms (338+51.4) within PPI::Element::DESTROY which was called 94372 times, avg 4µs/call:
# 82503 times (293ms+44.9ms) by PPI::Node::DESTROY at line 700 of PPI/Node.pm, avg 4µs/call
# 11578 times (43.2ms+6.05ms) by PPI::Node::DESTROY at line 704 of PPI/Node.pm, avg 4µs/call
# 144 times (994µs+311µs) by PPI::Token::Word::__TOKENIZER__commit at line 206 of PPI/Token/Whitespace.pm, avg 9µs/call
# 144 times (451µs+77µs) by PPI::Node::DESTROY at line 709 of PPI/Node.pm, avg 4µs/call
# 3 times (14µs+3µs) by PPI::Token::Magic::__TOKENIZER__on_char at line 176 of PPI/Token/Magic.pm, avg 6µs/call # spent 51.4ms making 94372 calls to Scalar::Util::refaddr, avg 544ns/call |
| 1084 | |||||
| 1085 | # Operator overloads | ||||
| 1086 | sub __equals { ref $_[1] and refaddr($_[0]) == refaddr($_[1]) } | ||||
| 1087 | sub __nequals { !__equals(@_) } | ||||
| 1088 | # spent 1.77s (1.08+684ms) within PPI::Element::__eq which was called 105472 times, avg 17µs/call:
# 104217 times (1.07s+675ms) by PPI::Element::__ne at line 1093, avg 17µs/call
# 904 times (12.4ms+6.41ms) by Perl::Critic::Utils::is_hash_key at line 724 of Perl/Critic/Utils.pm, avg 21µs/call
# 126 times (1.03ms+756µs) by List::MoreUtils::any at line 209 of Perl/Critic/Policy/ControlStructures/ProhibitMutatingListFunctions.pm, avg 14µs/call
# 83 times (817µs+605µs) by Perl::Critic::Policy::Variables::RequireLexicalLoopIterators::violates at line 61 of Perl/Critic/Policy/Variables/RequireLexicalLoopIterators.pm, avg 17µs/call
# 57 times (502µs+377µs) by Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions::_is_topic at line 48 of Perl/Critic/Policy/ControlStructures/ProhibitMutatingListFunctions.pm, avg 15µs/call
# 41 times (444µs+442µs) by Perl::Critic::Utils::split_nodes_on_comma at line 989 of Perl/Critic/Utils.pm, avg 22µs/call
# 40 times (352µs+265µs) by Perl::Critic::Utils::_is_dereference_operator at line 800 of Perl/Critic/Utils.pm, avg 15µs/call
# 3 times (34µs+39µs) by Perl::Critic::Utils::parse_arg_list at line 971 of Perl/Critic/Utils.pm, avg 24µs/call
# once (8µs+6µs) by Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions::_is_topic_mutating_func at line 217 of Perl/Critic/Policy/ControlStructures/ProhibitMutatingListFunctions.pm | ||||
| 1089 | 105472 | 1.07s | 421888 | 687ms | my $self = _INSTANCE($_[0], 'PPI::Element') ? $_[0]->content : $_[0]; # spent 428ms making 105472 calls to Params::Util::_INSTANCE, avg 4µs/call
# spent 141ms making 105472 calls to PPI::Token::content, avg 1µs/call
# spent 60.7ms making 105472 calls to UNIVERSAL::isa, avg 576ns/call
# spent 57.6ms making 105472 calls to PPI::Util::TRUE, avg 546ns/call |
| 1090 | 105472 | 287ms | 105560 | 57.8ms | my $other = _INSTANCE($_[1], 'PPI::Element') ? $_[1]->content : $_[1]; # spent 57.7ms making 105472 calls to Params::Util::_INSTANCE, avg 547ns/call
# spent 96µs making 88 calls to Readonly::Scalar::FETCH, avg 1µs/call |
| 1091 | 105472 | 225ms | $self eq $other; | ||
| 1092 | } | ||||
| 1093 | 104217 | 274ms | 104217 | 1.74s | # spent 2.04s (301ms+1.74) within PPI::Element::__ne which was called 104217 times, avg 20µs/call:
# 13481 times (37.5ms+251ms) by Perl::Critic::Policy::InputOutput::ProhibitTwoArgOpen::violates at line 44 of Perl/Critic/Policy/InputOutput/ProhibitTwoArgOpen.pm, avg 21µs/call
# 13481 times (36.7ms+233ms) by Perl::Critic::Policy::ClassHierarchies::ProhibitOneArgBless::violates at line 37 of Perl/Critic/Policy/ClassHierarchies/ProhibitOneArgBless.pm, avg 20µs/call
# 13481 times (42.0ms+227ms) by Perl::Critic::Policy::InputOutput::ProhibitBarewordFileHandles::violates at line 37 of Perl/Critic/Policy/InputOutput/ProhibitBarewordFileHandles.pm, avg 20µs/call
# 13481 times (41.4ms+225ms) by Perl::Critic::Policy::Subroutines::ProhibitExplicitReturnUndef::violates at line 36 of Perl/Critic/Policy/Subroutines/ProhibitExplicitReturnUndef.pm, avg 20µs/call
# 13481 times (38.5ms+218ms) by Perl::Critic::Policy::Subroutines::ProhibitReturnSort::violates at line 36 of Perl/Critic/Policy/Subroutines/ProhibitReturnSort.pm, avg 19µs/call
# 13481 times (36.9ms+218ms) by Perl::Critic::Policy::BuiltinFunctions::ProhibitSleepViaSelect::violates at line 38 of Perl/Critic/Policy/BuiltinFunctions/ProhibitSleepViaSelect.pm, avg 19µs/call
# 13481 times (35.7ms+209ms) by Perl::Critic::Policy::BuiltinFunctions::ProhibitStringyEval::violates at line 49 of Perl/Critic/Policy/BuiltinFunctions/ProhibitStringyEval.pm, avg 18µs/call
# 8379 times (28.3ms+139ms) by Perl::Critic::Policy::InputOutput::ProhibitInteractiveTest::violates at line 36 of Perl/Critic/Policy/InputOutput/ProhibitInteractiveTest.pm, avg 20µs/call
# 573 times (1.45ms+9.83ms) by Perl::Critic::Policy::Subroutines::ProhibitReturnSort::violates at line 42 of Perl/Critic/Policy/Subroutines/ProhibitReturnSort.pm, avg 20µs/call
# 573 times (1.45ms+8.15ms) by Perl::Critic::Policy::Subroutines::ProhibitExplicitReturnUndef::violates at line 42 of Perl/Critic/Policy/Subroutines/ProhibitExplicitReturnUndef.pm, avg 17µs/call
# 321 times (781µs+4.59ms) by Perl::Critic::Policy::ControlStructures::ProhibitMutatingListFunctions::_is_topic_mutating_substr at line 229 of Perl/Critic/Policy/ControlStructures/ProhibitMutatingListFunctions.pm, avg 17µs/call
# 4 times (10µs+54µs) by Perl::Critic::Policy::InputOutput::ProhibitBarewordFileHandles::violates at line 46 of Perl/Critic/Policy/InputOutput/ProhibitBarewordFileHandles.pm, avg 16µs/call # spent 1.74s making 104217 calls to PPI::Element::__eq, avg 17µs/call |
| 1094 | |||||
| 1095 | 1 | 2µs | 1; | ||
| 1096 | |||||
| 1097 | =pod | ||||
| 1098 | |||||
| 1099 | =head1 TO DO | ||||
| 1100 | |||||
| 1101 | It would be nice if C<location> could be used in an ad-hoc manner. That is, | ||||
| 1102 | if called on an Element within a Document that has not been indexed, it will | ||||
| 1103 | do a one-off calculation to find the location. It might be very painful if | ||||
| 1104 | someone started using it a lot, without remembering to index the document, | ||||
| 1105 | but it would be handy for things that are only likely to use it once, such | ||||
| 1106 | as error handlers. | ||||
| 1107 | |||||
| 1108 | =head1 SUPPORT | ||||
| 1109 | |||||
| 1110 | See the L<support section|PPI/SUPPORT> in the main module. | ||||
| 1111 | |||||
| 1112 | =head1 AUTHOR | ||||
| 1113 | |||||
| 1114 | Adam Kennedy E<lt>adamk@cpan.orgE<gt> | ||||
| 1115 | |||||
| 1116 | =head1 COPYRIGHT | ||||
| 1117 | |||||
| 1118 | Copyright 2001 - 2011 Adam Kennedy. | ||||
| 1119 | |||||
| 1120 | This program is free software; you can redistribute | ||||
| 1121 | it and/or modify it under the same terms as Perl itself. | ||||
| 1122 | |||||
| 1123 | The full text of the license can be found in the | ||||
| 1124 | LICENSE file included with this module. | ||||
| 1125 | |||||
| 1126 | =cut |