Skip to content

Commit

Permalink
Support upcoming PHP-Parser 5.x
Browse files Browse the repository at this point in the history
(Mostly just switching away from things already deprecated in 4.x)
  • Loading branch information
bobthecow committed Nov 3, 2023
1 parent 56a8504 commit 671768c
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 26 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"ext-tokenizer": "*",
"symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4",
"symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4",
"nikic/php-parser": "^4.0"
"nikic/php-parser": "^5.0 || ^4.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.2"
Expand Down
4 changes: 2 additions & 2 deletions src/CodeCleaner/ListPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ public function enterNode(Node $node)
/**
* Validate whether a given item in an array is valid for short assignment.
*
* @param Expr $item
* @param Node $item
*/
private static function isValidArrayItem(Expr $item): bool
private static function isValidArrayItem(Node $item): bool
{
$value = ($item instanceof ArrayItem) ? $item->value : $item;

Expand Down
22 changes: 17 additions & 5 deletions src/CodeCleaner/NamespaceAwarePass.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function beforeTraverse(array $nodes)
public function enterNode(Node $node)
{
if ($node instanceof Namespace_) {
$this->namespace = isset($node->name) ? $node->name->parts : [];
$this->namespace = isset($node->name) ? $this->getParts($node->name) : [];
}
}

Expand All @@ -61,13 +61,25 @@ public function enterNode(Node $node)
protected function getFullyQualifiedName($name): string
{
if ($name instanceof FullyQualifiedName) {
return \implode('\\', $name->parts);
} elseif ($name instanceof Name) {
$name = $name->parts;
return \implode('\\', $this->getParts($name));
}

if ($name instanceof Name) {
$name = $this->getParts($name);
} elseif (!\is_array($name)) {
$name = [$name];
}

return \implode('\\', \array_merge($this->namespace, $name));
}
}

/**
* Backwards compatibility shim for PHP-Parser 4.x
*
* At some point we might want to make $namespace a plain string, to match how Name works?
*/
protected function getParts(Name $name): array
{
return method_exists($name, 'getParts') ? $name->getParts() : $name->parts;
}
}
12 changes: 11 additions & 1 deletion src/CodeCleaner/NamespacePass.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ public function beforeTraverse(array $nodes)
private function setNamespace($namespace)
{
$this->namespace = $namespace;
$this->cleaner->setNamespace($namespace === null ? null : $namespace->parts);
$this->cleaner->setNamespace($namespace === null ? null : $this->getParts($namespace));
}

/**
* Backwards compatibility shim for PHP-Parser 4.x
*
* At some point we might want to make the namespace a plain string, to match how Name works?
*/
protected function getParts(Name $name): array
{
return method_exists($name, 'getParts') ? $name->getParts() : $name->parts;
}
}
18 changes: 9 additions & 9 deletions src/CodeCleaner/UseStatementPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseItem;
use PhpParser\Node\Stmt\UseUse;
use PhpParser\NodeTraverser;

Expand Down Expand Up @@ -72,21 +73,19 @@ public function leaveNode(Node $node)
{
// Store a reference to every "use" statement, because we'll need them in a bit.
if ($node instanceof Use_) {
foreach ($node->uses as $use) {
$alias = $use->alias ?: \end($use->name->parts);
$this->aliases[\strtolower($alias)] = $use->name;
foreach ($node->uses as $useItem) {
$this->aliases[\strtolower($useItem->getAlias())] = $useItem->name;
}

return NodeTraverser::REMOVE_NODE;
}

// Expand every "use" statement in the group into a full, standalone "use" and store 'em with the others.
if ($node instanceof GroupUse) {
foreach ($node->uses as $use) {
$alias = $use->alias ?: \end($use->name->parts);
$this->aliases[\strtolower($alias)] = Name::concat($node->prefix, $use->name, [
foreach ($node->uses as $useItem) {
$this->aliases[\strtolower($useItem->getAlias())] = Name::concat($node->prefix, $useItem->name, [
'startLine' => $node->prefix->getAttribute('startLine'),
'endLine' => $use->name->getAttribute('endLine'),
'endLine' => $useItem->name->getAttribute('endLine'),
]);
}

Expand All @@ -102,8 +101,9 @@ public function leaveNode(Node $node)
return;
}

// Do nothing with UseUse; this an entry in the list of uses in the use statement.
if ($node instanceof UseUse) {
// Do nothing with UseItem; this an entry in the list of uses in the use statement.
// @todo Remove UseUse once we drop support for PHP-Parser 4.x
if ($node instanceof UseUse || $node instanceof UseItem) {
return;
}

Expand Down
13 changes: 12 additions & 1 deletion src/CodeCleaner/ValidConstructorPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Psy\CodeCleaner;

use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Namespace_;
Expand Down Expand Up @@ -55,7 +56,7 @@ public function beforeTraverse(array $nodes)
public function enterNode(Node $node)
{
if ($node instanceof Namespace_) {
$this->namespace = isset($node->name) ? $node->name->parts : [];
$this->namespace = isset($node->name) ? $this->getParts($node->name) : [];
} elseif ($node instanceof Class_) {
$constructor = null;
foreach ($node->stmts as $stmt) {
Expand Down Expand Up @@ -107,4 +108,14 @@ private function validateConstructor(Node $constructor, Node $classNode)
throw new FatalErrorException($msg, 0, \E_ERROR, null, $classNode->getLine());
}
}

/**
* Backwards compatibility shim for PHP-Parser 4.x
*
* At some point we might want to make $namespace a plain string, to match how Name works?
*/
protected function getParts(Name $name): array
{
return method_exists($name, 'getParts') ? $name->getParts() : $name->parts;
}
}
5 changes: 3 additions & 2 deletions src/Command/ThrowUpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Expr\Throw_;
use PhpParser\Node\Name\FullyQualified as FullyQualifiedName;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Throw_;
use PhpParser\Node\Stmt\Expression;
use PhpParser\PrettyPrinter\Standard as Printer;
use Psy\Exception\ThrowUpException;
use Psy\Input\CodeArgument;
Expand Down Expand Up @@ -78,7 +79,7 @@ protected function configure()
protected function execute(InputInterface $input, OutputInterface $output): int
{
$args = $this->prepareArgs($input->getArgument('exception'));
$throwStmt = new Throw_(new New_(new FullyQualifiedName(ThrowUpException::class), $args));
$throwStmt = new Expression(new Throw_(new New_(new FullyQualifiedName(ThrowUpException::class), $args)));
$throwCode = $this->printer->prettyPrint([$throwStmt]);

$shell = $this->getApplication();
Expand Down
16 changes: 11 additions & 5 deletions src/Exception/ParseErrorException.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@ class ParseErrorException extends \PhpParser\Error implements Exception
/**
* Constructor!
*
* @param string $message (default: "")
* @param int $line (default: -1)
* @param string $message (default: '')
* @param array|int $attributes Attributes of node/token where error occurred
* (or start line of error -- deprecated)
*/
public function __construct(string $message = '', int $line = -1)
public function __construct(string $message = '', $attributes = [])
{
$message = \sprintf('PHP Parse error: %s', $message);
parent::__construct($message, $line);

if (!is_array($attributes)) {
$attributes = ['startLine' => $attributes];
}

parent::__construct($message, $attributes);
}

/**
Expand All @@ -35,6 +41,6 @@ public function __construct(string $message = '', int $line = -1)
*/
public static function fromParseError(\PhpParser\Error $e): self
{
return new self($e->getRawMessage(), $e->getStartLine());
return new self($e->getRawMessage(), $e->getAttributes());
}
}

0 comments on commit 671768c

Please sign in to comment.