Subject: | add_element_at method for PPI::Node |
I'm working on some refactoring tools built on top of PPI, and being able to add a child in the middle of a node would be really helpful. I've attached a patch accomplishing this, I'm happy to incorporate any suggestions you have.
Subject: | add_element_at.patch |
Index: t/04_element.t
===================================================================
--- t/04_element.t (revision 15837)
+++ t/04_element.t (working copy)
@@ -16,7 +16,7 @@
use PPI::Lexer ();
# Execute the tests
-use Test::More tests => 221;
+use Test::More tests => 222;
use Test::NoWarnings;
use Scalar::Util 'refaddr';
@@ -450,6 +450,14 @@
is( $k3, $k1, 'PARENT keys returns to original on DESTROY' );
}
+# Then, add an element in the middle of a node
+SCOPE: {
+ my $d = PPI::Lexer->lex_source("1 + 1;\n2 + 2;");
+ my $Token = PPI::Token::Number->new( '1' );
+ $d->add_element_at(1, $Token);
+ is( $Token, $d->child(1), 'add_element_at should insert at the specified position' );
+}
+
# Repeat for an entire (large) file
SCOPE: {
my $k1 = scalar keys %PPI::Element::_PARENT;
Index: lib/PPI.pm
===================================================================
--- lib/PPI.pm (revision 15837)
+++ lib/PPI.pm (working copy)
@@ -8,7 +8,7 @@
# Set the version for CPAN
use vars qw{$VERSION $XS_COMPATIBLE @XS_EXCLUDE};
BEGIN {
- $VERSION = '1.216_01';
+ $VERSION = '1.216_02';
$XS_COMPATIBLE = '0.845';
@XS_EXCLUDE = ();
}
Index: lib/PPI/Node.pm
===================================================================
--- lib/PPI/Node.pm (revision 15837)
+++ lib/PPI/Node.pm (working copy)
@@ -134,6 +134,36 @@
=pod
+=head2 add_element_at $index, $Element
+
+The C<add_element_at> method adds a L<PPI::Element> object to a
+C<PPI::Node> between the elements at positions $index-1 and $index.
+
+Returns true if the L<PPI::Element> was added. Returns C<undef> if the
+Element was already within another Node, or the method is not passed
+a L<PPI::Element> object.
+
+=cut
+
+sub add_element_at {
+ my $self = shift;
+ my $index = shift;
+
+ # Check the element
+ my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
+ $_PARENT{refaddr $Element} and return undef;
+
+ # Add the argument to the elements
+ splice @{$self->{children}}, $index, 0, $Element;
+ Scalar::Util::weaken(
+ $_PARENT{refaddr $Element} = $self
+ );
+
+ 1;
+}
+
+=pod
+
=head2 elements
The C<elements> method accesses all child elements B<structurally> within