Глядя на источник PPI::Statement
:
# As above, you can insert a statement, or a non-significant token
sub insert_after {
my $self = shift;
my $Element = _INSTANCE(shift, 'PPI::Element') or return undef;
if ( $Element->isa('PPI::Statement') ) {
return $self->__insert_after($Element);
} elsif ( $Element->isa('PPI::Token') and ! $Element->significant ) {
return $self->__insert_after($Element);
}
'';
}
"Незначительный токен" - это что-то вроде пробела или комментария.
Выпопытка вставить один значимый токен на верхнем уровне (после оператора).Это не разрешено.
Вам нужно будет создать полный PPI::Statement::Include
элемент.
Вот некоторый (довольно некрасивый) код подтверждения концепции:
# ...
diag 'Trying to insert after ' . $second_last->module;
{
my $insertion_point = $second_last;
for my $new_element (
do {
my $synthetic_use = PPI::Statement::Include->new;
for my $child (
PPI::Token::Word->new('use'),
PPI::Token::Whitespace->new(' '),
PPI::Token::Word->new('Test::Differences'),
PPI::Token::Whitespace->new(' '),
PPI::Token::Quote::Single->new("'eq_or_diff'"),
PPI::Token::Structure->new(';'),
) {
ok $synthetic_use->add_element($child);
}
$synthetic_use
},
PPI::Token::Whitespace->new("\n"),
) {
ok $insertion_point->insert_after($new_element);
}
}
diag $doc->serialize;
Но гораздо проще позволить PPI проанализировать данный фрагмент и просто использовать эти объекты:
diag 'Trying to insert after ' . $second_last->module;
{
my $insertion_point = $second_last;
for my $new_element (
reverse PPI::Document->new(\ "\nuse Test::Differences qw( eq_or_diff );")->elements
) {
ok $insertion_point->insert_after($new_element->remove);
}
}
diag $doc->serialize;
Осторожно: крайне важно использовать $new_element->remove
вместо $new_element
.Вам необходимо отсоединить $new_element
от старого содержащего его документа, поскольку в противном случае временный экземпляр PPI::Document
уничтожит все дочерние элементы, включая те, которые уже добавлены в $doc
.