PPIx::U...aversal(3)
π NAME π
so like, hi bestie π«Ά you just opened the manual page for PPIx::Utils::Traversal(3), and ngl it's kind of a vibe. This is a whole collection of utility functions for traversing PPI documents β think of it as your lil tour guide through the syntax tree, holding your hand and being like "this way queen π".
β¨ SYNOPSIS β¨
use PPIx::Utils::Traversal ':all';
that's it. that's the whole thing. load it up and you get everything π
πΈ DESCRIPTION πΈ
This package is literally one component of PPIx::Utils, and what it brings to the group chat is functions for traversal of PPI documents. walking the tree, finding the next thing, splitting stuff up. main character behavior fr fr.
π¦ FUNCTIONS π¦
okay so every single one of these can be imported by name, or you can just grab the whole set with the tag :all. no gatekeeping here β¨
first_arg
my $first_arg = first_arg($element);
You hand it a PPI::Element that you're presuming is a function call (which, let's be real, is usually a PPI::Token::Word), and it gives you back the first argument. It's similar to parse_arg_list and follows the same logic, but listen up because there are caveats.
So for this code:
int($x + 0.5)
this function returns just the $x, not the whole entire expression. That is different from how parse_arg_list behaves, okay? Don't mix them up. π
And another caveat, bestie:
int(($x + $y) + 0.5)
this one returns ($x + $y) as a PPI::Structure::List instance. iconic, honestly.
parse_arg_list
my @args = parse_arg_list($element);
Give it a PPI::Element that's presumed to be a function call (again, usually a PPI::Token::Word), and it splits the argument expressions into arrays of tokens. What you get back is a list containing references to each of those arrays. π«
Why is this useful? Because parentheses are optional when you're calling a function, and PPI parses those two situations very differently. So this method is basically a poor-man's parse tree of PPI nodes. It's not bullet-proof because it doesn't respect precedence.
and like, real talk: in general I don't like the way this function works, so do not count on it to be stable (or even present). π
split_nodes_on_comma
my @args = split_nodes_on_comma(@nodes);
Same return type as parse_arg_list, but this one expects you to pass in the nodes representing the interior of a list, like:
'foo', 1, 2, 'bar'
get_next_element_in_same_simple_statement
my $element = get_next_element_in_same_simple_statement($element);
Given a PPI::Element, this subroutine returns the next element in the same simple statement, as defined by is_ppi_simple_statement in PPIx::Utils::Classification. If there's no next element to be found, it just returns undef. no drama, no fuss π
Here's the full rundown of the lore:
- If the
$elementis undefined or unblessed, we simply returnundef. - If the
$elementsatisfiesis_ppi_simple_statementinPPIx::Utils::Classification, we returnundefβ unless it has a parent which is aPPI::Structure::List. - If the
$elementis the last significant element in itsPPI::Node, we replace it with its parent and iterate again. π - Otherwise, we return
$element->snext_sibling().
get_previous_module_used_on_same_line
my $element = get_previous_module_used_on_same_line($element);
Given a PPI::Element, this returns the PPI::Element representing the name of the module that was included by the previous use or require on the same line as the $element. If none is found, it simply returns undef. sorry bestie π
For example, with the line
use version; our $VERSION = ...;
given the PPI::Token::Symbol instance for $VERSION, this will return "version".
And if the given element is in a use or require, the return comes from the previous use or require on the line, if any. π§
get_constant_name_elements_from_declaring_statement
my @constants = get_constant_name_elements_from_declaring_statement($statement);
Given a PPI::Statement, if that statement is a Readonly, ReadonlyX, or Const::Fast declaration statement, or a use constant, this returns the names of the things being defined. slay. β¨
Given
use constant 1.16 FOO => 'bar';
this will return the PPI::Token::Word containing 'FOO'.
Given
use constant 1.16 { FOO => 'bar', 'BAZ' => 'burfle' };
this will return a list of the PPI::Tokens containing 'FOO' and 'BAZ'.
And similarly, given
Readonly::Hash my %FOO => ( bar => 'baz' );
or
const my %FOO => ( bar => 'baz' );
this will return the PPI::Token::Symbol containing '%FOO'. π
split_ppi_node_by_namespace
my $subtrees = split_ppi_node_by_namespace($node);
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:
#!perl
my $x = blah();
package Foo;
my $y = blah_blah();
{
say 'Whee!';
package Bar;
something();
}
thingy();
package Baz;
da_da_da();
package Foo;
foreach ( blrfl() ) {
...
}
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 PPI trees, to make it easier to read:
{
main => [
q<
#!perl
my $x = blah();
>,
],
Foo => [
q<
package Foo;
my $y = blah_blah();
{
say 'Whee!';
}
thingy();
>,
q<
package Foo;
foreach ( blrfl() ) {
...
}
>,
],
Bar => [
q<
package Bar;
something();
>,
],
Baz => [
q<
package Baz;
da_da_da();
>,
],
}
Important note bestie: the return value contains copies of the original nodes, not the original nodes themselves β that's because it needs to handle namespaces that aren't file-scoped. (Notice how the first element for "Foo" above differs from the original code. π)
π BUGS π
Report any issues on the public bugtracker. pls and thank u π
π AUTHOR π
Dan Book <dbook@cpan.org>
Code originally from Perl::Critic::Utils by Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>, Perl::Critic::Utils::PPI and PPIx::Utilities::Node by Elliot Shank <perl@galumph.com>, and PPIx::Utilities::Statement by Thomas R. Wyant, III <wyant@cpan.org>
the way this page has a whole lineage, we love a collaborative queen ππ
π COPYRIGHT AND LICENSE π
This software is copyright (c) 2005-2011 Imaginative Software Systems, 2007-2011 Elliot Shank, 2009-2010 Thomas R. Wyant, III, 2017 Dan Book.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. π«Ά
π SEE ALSO π
Perl::Critic::UtilsPerl::Critic::Utils::PPIPPIx::Utilities
and that's the whole page bestie, we ate and left no crumbs πβ¨ this was perl v5.42.0, dated 2025-08-05, from the PPIx::Utils::Traversal(3) manual β go forth and traverse those documents, you absolute icon πππ¦
π¦ where this page comes from
- fedora 43: perl-PPIx-Utils 0.004-1.fc43 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms