Skip to content

Instantly share code, notes, and snippets.

@nikic
Created December 26, 2016 20:54
Show Gist options
  • Save nikic/3229644ada5576622d7d538f6bff2098 to your computer and use it in GitHub Desktop.
Save nikic/3229644ada5576622d7d538f6bff2098 to your computer and use it in GitHub Desktop.
Demo for format preserving AST transformation
<?php
/* This demo replaces all unqualified function calls and namespaced lookups
* with fully qualified ones. Apart from this change all formatting should
* be preserved. */
use PhpParser\Lexer;
use PhpParser\Parser;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor;
use PhpParser\NodeVisitorAbstract;
use PhpParser\PrettyPrinter;
use PhpParser\Error;
use PhpParser\Node;
$dir = /* directory to operate on */;
require __DIR__ . '/vendor/autoload.php';
class NameFullyQualifier extends NodeVisitorAbstract {
public function leaveNode(Node $node) {
if ($node instanceof Node\Name
&& $node->hasAttribute('namespacedName')
&& !in_array(strtolower($node), ['true', 'false', 'null'])
) {
return new Node\Name\FullyQualified($node);
}
return null;
}
}
$lexer = new Lexer\Emulative([
'usedAttributes' => [
'comments',
'startLine', 'endLine',
'startTokenPos', 'endTokenPos',
],
]);
$parser = new Parser\Php7($lexer, [
'useIdentifierNodes' => true,
'useConsistentVariableNodes' => true,
'useExpressionStatements' => true,
'useNopStatements' => false,
]);
$nameResolver = new NodeVisitor\NameResolver(null, [
'replaceNodes' => false
]);
$traverser = new NodeTraverser();
$traverser->addVisitor(new NodeVisitor\CloningVisitor());
$traverser->addVisitor($nameResolver);
$traverser->addVisitor(new NameFullyQualifier());
$printer = new PrettyPrinter\Standard();
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($it as $file) {
if (!preg_match('/\.php$/', $file)) {
continue;
}
try {
$code = file_get_contents($file);
$origStmts = $parser->parse($code);
$newCode = $printer->printFormatPreserving(
$traverser->traverse($origStmts),
$origStmts,
$lexer->getTokens()
);
file_put_contents($file, $newCode);
} catch (Error $e) {
echo "Parser error in $file: {$e->getMessage()}\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment