Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formatting-preserving pretty printing #931

Open
harikt opened this issue Jul 8, 2023 · 0 comments
Open

Formatting-preserving pretty printing #931

harikt opened this issue Jul 8, 2023 · 0 comments

Comments

@harikt
Copy link

harikt commented Jul 8, 2023

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 .

Screenshot 2023-07-08 at 5 16 17 PM

Below is the output when I comment out CloningVisitor . But the new lines are removed in that case.

Screenshot 2023-07-08 at 5 17 17 PM

I am not sure if this is a bug or is caused by the code I have.

Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant