mirror of https://github.com/rectorphp/rector.git
91 lines
2.6 KiB
PHP
91 lines
2.6 KiB
PHP
<?php
|
|
|
|
declare (strict_types=1);
|
|
namespace Rector\PhpParser\Parser;
|
|
|
|
use RectorPrefix202402\Nette\Utils\FileSystem;
|
|
use PhpParser\Node;
|
|
use PhpParser\Node\Stmt\Expression;
|
|
use PhpParser\NodeTraverser;
|
|
use PhpParser\Parser;
|
|
use PhpParser\ParserFactory;
|
|
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\AssignedToNodeVisitor;
|
|
use Throwable;
|
|
final class SimplePhpParser
|
|
{
|
|
/**
|
|
* @readonly
|
|
* @var \PhpParser\Parser
|
|
*/
|
|
private $phpParser;
|
|
/**
|
|
* @readonly
|
|
* @var \PhpParser\NodeTraverser
|
|
*/
|
|
private $nodeTraverser;
|
|
public function __construct()
|
|
{
|
|
$parserFactory = new ParserFactory();
|
|
$this->phpParser = $parserFactory->create(ParserFactory::ONLY_PHP7);
|
|
$this->nodeTraverser = new NodeTraverser();
|
|
$this->nodeTraverser->addVisitor(new AssignedToNodeVisitor());
|
|
}
|
|
/**
|
|
* @api tests
|
|
* @return Node[]
|
|
*/
|
|
public function parseFile(string $filePath) : array
|
|
{
|
|
$fileContent = FileSystem::read($filePath);
|
|
return $this->parseString($fileContent);
|
|
}
|
|
/**
|
|
* @return Node[]
|
|
*/
|
|
public function parseString(string $fileContent) : array
|
|
{
|
|
$fileContent = $this->ensureFileContentsHasOpeningTag($fileContent);
|
|
$hasAddedSemicolon = \false;
|
|
try {
|
|
$nodes = $this->phpParser->parse($fileContent);
|
|
} catch (Throwable $exception) {
|
|
// try adding missing closing semicolon ;
|
|
$fileContent .= ';';
|
|
$hasAddedSemicolon = \true;
|
|
$nodes = $this->phpParser->parse($fileContent);
|
|
}
|
|
if ($nodes === null) {
|
|
return [];
|
|
}
|
|
$nodes = $this->restoreExpressionPreWrap($nodes, $hasAddedSemicolon);
|
|
return $this->nodeTraverser->traverse($nodes);
|
|
}
|
|
private function ensureFileContentsHasOpeningTag(string $fileContent) : string
|
|
{
|
|
if (\strncmp(\trim($fileContent), '<?php', \strlen('<?php')) !== 0) {
|
|
// prepend with PHP opening tag to make parse PHP code
|
|
return '<?php ' . $fileContent;
|
|
}
|
|
return $fileContent;
|
|
}
|
|
/**
|
|
* @param Node[] $nodes
|
|
* @return Node[]
|
|
*/
|
|
private function restoreExpressionPreWrap(array $nodes, bool $hasAddedSemicolon) : array
|
|
{
|
|
if (!$hasAddedSemicolon) {
|
|
return $nodes;
|
|
}
|
|
if (\count($nodes) !== 1) {
|
|
return $nodes;
|
|
}
|
|
// remove added semicolon to be honest about Expression
|
|
$onlyStmt = $nodes[0];
|
|
if (!$onlyStmt instanceof Expression) {
|
|
return $nodes;
|
|
}
|
|
return [$onlyStmt->expr];
|
|
}
|
|
}
|