.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "PPIx::Utils::Traversal 3pm" .TH PPIx::Utils::Traversal 3pm "2021-09-29" "perl v5.32.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" PPIx::Utils::Traversal \- Utility functions for traversing PPI documents .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use PPIx::Utils::Traversal \*(Aq:all\*(Aq; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This package is a component of PPIx::Utils that contains functions for traversal of \s-1PPI\s0 documents. .SH "FUNCTIONS" .IX Header "FUNCTIONS" All functions can be imported by name, or with the tag \f(CW\*(C`:all\*(C'\fR. .SS "first_arg" .IX Subsection "first_arg" .Vb 1 \& my $first_arg = first_arg($element); .Ve .PP Given a PPI::Element that is presumed to be a function call (which is usually a PPI::Token::Word), return the first argument. This is similar of \*(L"parse_arg_list\*(R" and follows the same logic. Note that for the code: .PP .Vb 1 \& int($x + 0.5) .Ve .PP this function will return just the \f(CW$x\fR, not the whole expression. This is different from the behavior of \*(L"parse_arg_list\*(R". Another caveat is: .PP .Vb 1 \& int(($x + $y) + 0.5) .Ve .PP which returns \f(CW\*(C`($x + $y)\*(C'\fR as a PPI::Structure::List instance. .SS "parse_arg_list" .IX Subsection "parse_arg_list" .Vb 1 \& my @args = parse_arg_list($element); .Ve .PP Given a PPI::Element that is presumed to be a function call (which is usually a PPI::Token::Word), splits the argument expressions into arrays of tokens. Returns a list containing references to each of those arrays. This is useful because parentheses are optional when calling a function, and \s-1PPI\s0 parses them very differently. So this method is a poor-man's parse tree of \s-1PPI\s0 nodes. It's not bullet-proof because it doesn't respect precedence. In general, I don't like the way this function works, so don't count on it to be stable (or even present). .SS "split_nodes_on_comma" .IX Subsection "split_nodes_on_comma" .Vb 1 \& my @args = split_nodes_on_comma(@nodes); .Ve .PP This has the same return type as \*(L"parse_arg_list\*(R" but expects to be passed the nodes that represent the interior of a list, like: .PP .Vb 1 \& \*(Aqfoo\*(Aq, 1, 2, \*(Aqbar\*(Aq .Ve .SS "get_next_element_in_same_simple_statement" .IX Subsection "get_next_element_in_same_simple_statement" .Vb 1 \& my $element = get_next_element_in_same_simple_statement($element); .Ve .PP Given a PPI::Element, this subroutine returns the next element in the same simple statement as defined by \&\*(L"is_ppi_simple_statement\*(R" in PPIx::Utils::Classification. If no next element can be found, this subroutine simply returns \f(CW\*(C`undef\*(C'\fR. .PP If the \f(CW$element\fR is undefined or unblessed, we simply return \f(CW\*(C`undef\*(C'\fR. .PP If the \f(CW$element\fR satisfies \&\*(L"is_ppi_simple_statement\*(R" in PPIx::Utils::Classification, we return \&\f(CW\*(C`undef\*(C'\fR, \fBunless\fR it has a parent which is a PPI::Structure::List. .PP If the \f(CW$element\fR is the last significant element in its PPI::Node, we replace it with its parent and iterate again. .PP Otherwise, we return \f(CW\*(C`$element\->snext_sibling()\*(C'\fR. .SS "get_previous_module_used_on_same_line" .IX Subsection "get_previous_module_used_on_same_line" .Vb 1 \& my $element = get_previous_module_used_on_same_line($element); .Ve .PP Given a PPI::Element, returns the PPI::Element representing the name of the module included by the previous \f(CW\*(C`use\*(C'\fR or \f(CW\*(C`require\*(C'\fR on the same line as the \f(CW$element\fR. If none is found, simply returns \&\f(CW\*(C`undef\*(C'\fR. .PP For example, with the line .PP .Vb 1 \& use version; our $VERSION = ...; .Ve .PP given the PPI::Token::Symbol instance for \f(CW$VERSION\fR, this will return \*(L"version\*(R". .PP If the given element is in a \f(CW\*(C`use\*(C'\fR or , the return is from the previous \f(CW\*(C`use\*(C'\fR or \f(CW\*(C`require\*(C'\fR on the line, if any. .SS "get_constant_name_elements_from_declaring_statement" .IX Subsection "get_constant_name_elements_from_declaring_statement" .Vb 1 \& my @constants = get_constant_name_elements_from_declaring_statement($statement); .Ve .PP Given a PPI::Statement, if the statement is a Readonly, ReadonlyX, or Const::Fast declaration statement or a \f(CW\*(C`use constant\*(C'\fR, returns the names of the things being defined. .PP Given .PP .Vb 1 \& use constant 1.16 FOO => \*(Aqbar\*(Aq; .Ve .PP this will return the PPI::Token::Word containing \f(CW\*(AqFOO\*(Aq\fR. Given .PP .Vb 1 \& use constant 1.16 { FOO => \*(Aqbar\*(Aq, \*(AqBAZ\*(Aq => \*(Aqburfle\*(Aq }; .Ve .PP this will return a list of the PPI::Tokens containing \f(CW\*(AqFOO\*(Aq\fR and \f(CW\*(AqBAZ\*(Aq\fR. Similarly, given .PP .Vb 1 \& Readonly::Hash my %FOO => ( bar => \*(Aqbaz\*(Aq ); .Ve .PP or .PP .Vb 1 \& const my %FOO => ( bar => \*(Aqbaz\*(Aq ); .Ve .PP this will return the PPI::Token::Symbol containing \f(CW\*(Aq%FOO\*(Aq\fR. .SS "split_ppi_node_by_namespace" .IX Subsection "split_ppi_node_by_namespace" .Vb 1 \& my $subtrees = split_ppi_node_by_namespace($node); .Ve .PP Returns the sub-trees for each namespace in the node as a reference to a hash of references to arrays of PPI::Nodes. Say we've got the following code: .PP .Vb 1 \& #!perl \& \& my $x = blah(); \& \& package Foo; \& \& my $y = blah_blah(); \& \& { \& say \*(AqWhee!\*(Aq; \& \& package Bar; \& \& something(); \& } \& \& thingy(); \& \& package Baz; \& \& da_da_da(); \& \& package Foo; \& \& foreach ( blrfl() ) { \& ... \& } .Ve .PP Calling this function on a PPI::Document for the above returns a value that looks like this, using multi-line string literals for the actual code parts instead of \s-1PPI\s0 trees to make this easier to read: .PP .Vb 4 \& { \& main => [ \& q< \& #!perl \& \& my $x = blah(); \& >, \& ], \& Foo => [ \& q< \& package Foo; \& \& my $y = blah_blah(); \& \& { \& say \*(AqWhee!\*(Aq; \& \& } \& \& thingy(); \& >, \& q< \& package Foo; \& \& foreach ( blrfl() ) { \& ... \& } \& >, \& ], \& Bar => [ \& q< \& package Bar; \& \& something(); \& >, \& ], \& Baz => [ \& q< \& package Baz; \& \& da_da_da(); \& >, \& ], \& } .Ve .PP Note that the return value contains copies of the original nodes, and not the original nodes themselves due to the need to handle namespaces that are not file-scoped. (Notice how the first element for \*(L"Foo\*(R" above differs from the original code.) .SH "BUGS" .IX Header "BUGS" Report any issues on the public bugtracker. .SH "AUTHOR" .IX Header "AUTHOR" Dan Book .PP Code originally from Perl::Critic::Utils by Jeffrey Ryan Thalhammer , Perl::Critic::Utils::PPI and PPIx::Utilities::Node by Elliot Shank , and PPIx::Utilities::Statement by Thomas R. Wyant, \s-1III\s0 .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2005\-2011 Imaginative Software Systems, 2007\-2011 Elliot Shank, 2009\-2010 Thomas R. Wyant, \s-1III, 2017\s0 Dan Book. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. .SH "SEE ALSO" .IX Header "SEE ALSO" Perl::Critic::Utils, Perl::Critic::Utils::PPI, PPIx::Utilities