Formatting-preserving pretty printing
harikt opened this issue · comments
Hari K T commented
Hi,
I am trying to add a few comments to below code
<?php
return [
// Inline comments
'a' => 'A',
'b' => [
'c1' => 'C1', // # b.c1 #
'c2' => 'C2',
'c3' => 'C3',
],
/**
* Multiline comments
*/
'g' => [
'h' => [
'k1' => 'L1', // # g.h.k1 #
'k2' => 'L2'
]
]
];
so that the modified one will add a few comments as below.
<?php
return [
// Inline comments
// # a #
'a' => 'A',
// # b #
'b' => [
// # b.c1 #
'c1' => 'C1', // # b.c1 #
// # b.c2 #
'c2' => 'C2',
// # b.c3 #
'c3' => 'C3',
],
/**
* Multiline comments
*/
// # g #
'g' => [
// # g.h #
'h' => [
// # g.h.k1 #
'k1' => 'L1', // # g.h.k1 #
// # g.h.k2 #
'k2' => 'L2'
]
]
];
The code that run to modify the AST is as
<?php
require __DIR__ . '/vendor/autoload.php';
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter;
use PhpParser\Lexer;
use PhpParser\Node;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor;
use PhpParser\NodeVisitorAbstract;
$lexer = new Lexer\Emulative([
'usedAttributes' => [
'comments',
'startLine', 'endLine',
'startTokenPos', 'endTokenPos',
],
]);
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7, $lexer);
$code = file_get_contents(__DIR__ . '/src/Config/Test.php');
$traverser = new NodeTraverser();
// $traverser->addVisitor(new NodeVisitor\CloningVisitor());
$oldStmts = $parser->parse($code);
$oldTokens = $lexer->getTokens();
$newStmts = $traverser->traverse($oldStmts);
$traverser = new NodeTraverser();
$traverser->addVisitor(new class extends NodeVisitorAbstract {
protected $item_value = '';
protected $item_values = [];
public function enterNode(Node $node)
{
if ($node instanceof Node\Expr\Array_)
{
if ($this->item_value)
{
$this->item_values[] = $this->item_value;
}
}
if ($node instanceof Node\Expr\ArrayItem)
{
$this->item_value = $node->key->value;
}
return $node;
}
public function leaveNode(Node $node)
{
if ($node instanceof Node\Expr\Array_)
{
if ($this->item_values)
{
array_pop($this->item_values);
}
}
if ($node instanceof Node\Expr\ArrayItem)
{
$key = $node->key->value;
if ($this->item_values)
{
$key = implode('.', $this->item_values) . "." . $node->key->value;
}
$comments = $node->getComments();
$comments[] = new PhpParser\Comment\Doc("// # {$key} #", $node->getStartLine(), $node->getStartFilePos(), $node->getStartTokenPos(), $node->getEndLine(), $node->getEndFilePos(), $node->getEndTokenPos());
$node->setAttribute('comments', $comments);
}
return $node;
}
});
$newStmts2 = $traverser->traverse($newStmts);
$prettyPrinter = new PrettyPrinter\Standard();
echo $prettyPrinter->printFormatPreserving($newStmts2, $newStmts, $oldTokens);
From the docs it mentions to add NodeVisitor\CloningVisitor
. I have tried that also, but the formatting is not as the original.
Below is the output when I have used CloningVisitor
.
Below is the output when I comment out CloningVisitor
. But the new lines are removed in that case.
I am not sure if this is a bug or is caused by the code I have.
Thank you.