mirror of
https://github.com/phabelio/PHP-Parser.git
synced 2025-01-22 21:31:14 +01:00
a0c216bf4b
Adding this as an option to avoid breaking people's tests. Some of the test results show pretty clearly that we are incorrectly assigning the same comment multiple times for nested nodes (mentioned in #36).
167 lines
4.9 KiB
PHP
Executable File
167 lines
4.9 KiB
PHP
Executable File
#!/usr/bin/env php
|
|
<?php
|
|
|
|
foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
|
|
if (file_exists($file)) {
|
|
require $file;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ini_set('xdebug.max_nesting_level', 3000);
|
|
|
|
// Disable XDebug var_dump() output truncation
|
|
ini_set('xdebug.var_display_max_children', -1);
|
|
ini_set('xdebug.var_display_max_data', -1);
|
|
ini_set('xdebug.var_display_max_depth', -1);
|
|
|
|
list($operations, $files, $attributes) = parseArgs($argv);
|
|
|
|
/* Dump nodes by default */
|
|
if (empty($operations)) {
|
|
$operations[] = 'dump';
|
|
}
|
|
|
|
if (empty($files)) {
|
|
showHelp("Must specify at least one file.");
|
|
}
|
|
|
|
$lexer = new PhpParser\Lexer\Emulative(array('usedAttributes' => array(
|
|
'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments'
|
|
)));
|
|
$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7, $lexer);
|
|
$dumper = new PhpParser\NodeDumper(['dumpComments' => true]);
|
|
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
|
|
$serializer = new PhpParser\Serializer\XML;
|
|
|
|
$traverser = new PhpParser\NodeTraverser();
|
|
$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
|
|
|
|
foreach ($files as $file) {
|
|
if (strpos($file, '<?php') === 0) {
|
|
$code = $file;
|
|
echo "====> Code $code\n";
|
|
} else {
|
|
if (!file_exists($file)) {
|
|
die("File $file does not exist.\n");
|
|
}
|
|
|
|
$code = file_get_contents($file);
|
|
echo "====> File $file:\n";
|
|
}
|
|
|
|
try {
|
|
$stmts = $parser->parse($code);
|
|
} catch (PhpParser\Error $e) {
|
|
if ($attributes['with-column-info'] && $e->hasColumnInfo()) {
|
|
$startLine = $e->getStartLine();
|
|
$endLine = $e->getEndLine();
|
|
$startColumn = $e->getStartColumn($code);
|
|
$endColumn = $e->getEndColumn($code);
|
|
$message .= $e->getRawMessage() . " from $startLine:$startColumn to $endLine:$endColumn";
|
|
} else {
|
|
$message = $e->getMessage();
|
|
}
|
|
|
|
die($message . "\n");
|
|
}
|
|
|
|
foreach ($operations as $operation) {
|
|
if ('dump' === $operation) {
|
|
echo "==> Node dump:\n";
|
|
echo $dumper->dump($stmts), "\n";
|
|
} elseif ('pretty-print' === $operation) {
|
|
echo "==> Pretty print:\n";
|
|
echo $prettyPrinter->prettyPrintFile($stmts), "\n";
|
|
} elseif ('serialize-xml' === $operation) {
|
|
echo "==> Serialized XML:\n";
|
|
echo $serializer->serialize($stmts), "\n";
|
|
} elseif ('var-dump' === $operation) {
|
|
echo "==> var_dump():\n";
|
|
var_dump($stmts);
|
|
} elseif ('resolve-names' === $operation) {
|
|
echo "==> Resolved names.\n";
|
|
$stmts = $traverser->traverse($stmts);
|
|
}
|
|
}
|
|
}
|
|
|
|
function showHelp($error) {
|
|
die($error . "\n\n" .
|
|
<<<OUTPUT
|
|
Usage: php-parse [operations] file1.php [file2.php ...]
|
|
or: php-parse [operations] "<?php code"
|
|
Turn PHP source code into an abstract syntax tree.
|
|
|
|
Operations is a list of the following options (--dump by default):
|
|
|
|
-d, --dump Dump nodes using NodeDumper
|
|
-p, --pretty-print Pretty print file using PrettyPrinter\Standard
|
|
--serialize-xml Serialize nodes using Serializer\XML
|
|
--var-dump var_dump() nodes (for exact structure)
|
|
-N, --resolve-names Resolve names using NodeVisitor\NameResolver
|
|
-c, --with-column-info Show column-numbers for errors (if available)
|
|
|
|
Example:
|
|
php-parse -d -p -N -d file.php
|
|
|
|
Dumps nodes, pretty prints them, then resolves names and dumps them again.
|
|
|
|
|
|
OUTPUT
|
|
);
|
|
}
|
|
|
|
function parseArgs($args) {
|
|
$operations = array();
|
|
$files = array();
|
|
$attributes = array(
|
|
'with-column-info' => false,
|
|
);
|
|
|
|
array_shift($args);
|
|
$parseOptions = true;
|
|
foreach ($args as $arg) {
|
|
if (!$parseOptions) {
|
|
$files[] = $arg;
|
|
continue;
|
|
}
|
|
|
|
switch ($arg) {
|
|
case '--dump':
|
|
case '-d':
|
|
$operations[] = 'dump';
|
|
break;
|
|
case '--pretty-print':
|
|
case '-p':
|
|
$operations[] = 'pretty-print';
|
|
break;
|
|
case '--serialize-xml':
|
|
$operations[] = 'serialize-xml';
|
|
break;
|
|
case '--var-dump':
|
|
$operations[] = 'var-dump';
|
|
break;
|
|
case '--resolve-names':
|
|
case '-N';
|
|
$operations[] = 'resolve-names';
|
|
break;
|
|
case '--with-column-info':
|
|
case '-c';
|
|
$attributes['with-column-info'] = true;
|
|
break;
|
|
case '--':
|
|
$parseOptions = false;
|
|
break;
|
|
default:
|
|
if ($arg[0] === '-') {
|
|
showHelp("Invalid operation $arg.");
|
|
} else {
|
|
$files[] = $arg;
|
|
}
|
|
}
|
|
}
|
|
|
|
return array($operations, $files, $attributes);
|
|
}
|