Aggiornato Composer
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -28,6 +28,8 @@ class AbstractClassPass extends CodeCleanerPass
|
||||
* @throws FatalErrorException if the node is an abstract function with a body
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -41,7 +43,7 @@ class AbstractClassPass extends CodeCleanerPass
|
||||
|
||||
if ($node->stmts !== null) {
|
||||
$msg = \sprintf('Abstract function %s cannot contain body', $name);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +53,8 @@ class AbstractClassPass extends CodeCleanerPass
|
||||
* @throws FatalErrorException if the node is a non-abstract class with abstract methods
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
@@ -64,7 +68,7 @@ class AbstractClassPass extends CodeCleanerPass
|
||||
($count === 1) ? '' : 's',
|
||||
\implode(', ', $this->abstractMethods)
|
||||
);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -29,11 +29,13 @@ class AssignThisVariablePass extends CodeCleanerPass
|
||||
* @throws FatalErrorException if the user assign the `$this` variable
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
if ($node instanceof Assign && $node->var instanceof Variable && $node->var->name === 'this') {
|
||||
throw new FatalErrorException('Cannot re-assign $this', 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException('Cannot re-assign $this', 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -35,6 +35,8 @@ class CallTimePassByReferencePass extends CodeCleanerPass
|
||||
* @throws FatalErrorException if the user used call-time pass-by-reference
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -48,7 +50,7 @@ class CallTimePassByReferencePass extends CodeCleanerPass
|
||||
}
|
||||
|
||||
if ($arg->byRef) {
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -30,6 +30,8 @@ class CalledClassPass extends CodeCleanerPass
|
||||
|
||||
/**
|
||||
* @param array $nodes
|
||||
*
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
@@ -40,6 +42,8 @@ class CalledClassPass extends CodeCleanerPass
|
||||
* @throws ErrorException if get_class or get_called_class is called without an object from outside a class
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -62,13 +66,15 @@ class CalledClassPass extends CodeCleanerPass
|
||||
$name = \strtolower($node->name);
|
||||
if (\in_array($name, ['get_class', 'get_called_class'])) {
|
||||
$msg = \sprintf('%s() called without object from outside a class', $name);
|
||||
throw new ErrorException($msg, 0, \E_USER_WARNING, null, $node->getLine());
|
||||
throw new ErrorException($msg, 0, \E_USER_WARNING, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -14,6 +14,8 @@ namespace Psy\CodeCleaner;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\AssignRef;
|
||||
use PhpParser\Node\Stmt\Foreach_;
|
||||
use Psy\Exception\FatalErrorException;
|
||||
|
||||
/**
|
||||
@@ -25,25 +27,39 @@ class EmptyArrayDimFetchPass extends CodeCleanerPass
|
||||
|
||||
private $theseOnesAreFine = [];
|
||||
|
||||
/**
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
$this->theseOnesAreFine = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FatalErrorException if the user used empty empty array dim fetch outside of assignment
|
||||
* @throws FatalErrorException if the user used empty array dim fetch outside of assignment
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
if ($node instanceof Assign && $node->var instanceof ArrayDimFetch) {
|
||||
$this->theseOnesAreFine[] = $node->var;
|
||||
} elseif ($node instanceof AssignRef && $node->expr instanceof ArrayDimFetch) {
|
||||
$this->theseOnesAreFine[] = $node->expr;
|
||||
} elseif ($node instanceof Foreach_ && $node->valueVar instanceof ArrayDimFetch) {
|
||||
$this->theseOnesAreFine[] = $node->valueVar;
|
||||
} elseif ($node instanceof ArrayDimFetch && $node->var instanceof ArrayDimFetch) {
|
||||
// $a[]['b'] = 'c'
|
||||
if (\in_array($node, $this->theseOnesAreFine)) {
|
||||
$this->theseOnesAreFine[] = $node->var;
|
||||
}
|
||||
}
|
||||
|
||||
if ($node instanceof ArrayDimFetch && $node->dim === null) {
|
||||
if (!\in_array($node, $this->theseOnesAreFine)) {
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, $node->getLine());
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -23,6 +23,8 @@ class ExitPass extends CodeCleanerPass
|
||||
* Converts exit calls to BreakExceptions.
|
||||
*
|
||||
* @param \PhpParser\Node $node
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -24,6 +24,8 @@ class FinalClassPass extends CodeCleanerPass
|
||||
|
||||
/**
|
||||
* @param array $nodes
|
||||
*
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
@@ -34,6 +36,8 @@ class FinalClassPass extends CodeCleanerPass
|
||||
* @throws FatalErrorException if the node is a class that extends a final class
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -42,7 +46,7 @@ class FinalClassPass extends CodeCleanerPass
|
||||
$extends = (string) $node->extends;
|
||||
if ($this->isFinalClass($extends)) {
|
||||
$msg = \sprintf('Class %s may not inherit from final class (%s)', $node->name, $extends);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +58,6 @@ class FinalClassPass extends CodeCleanerPass
|
||||
|
||||
/**
|
||||
* @param string $name Class name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isFinalClass(string $name): bool
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -23,12 +23,17 @@ class FunctionContextPass extends CodeCleanerPass
|
||||
|
||||
/**
|
||||
* @param array $nodes
|
||||
*
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
$this->functionDepth = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
if ($node instanceof FunctionLike) {
|
||||
@@ -45,12 +50,14 @@ class FunctionContextPass extends CodeCleanerPass
|
||||
// It causes fatal error.
|
||||
if ($node instanceof Yield_) {
|
||||
$msg = 'The "yield" expression can only be used inside a function';
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \PhpParser\Node $node
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -40,6 +40,8 @@ class FunctionReturnInWriteContextPass extends CodeCleanerPass
|
||||
* @throws FatalErrorException if a value is assigned to a function
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -51,7 +53,7 @@ class FunctionReturnInWriteContextPass extends CodeCleanerPass
|
||||
}
|
||||
|
||||
if ($item && $item->byRef && $this->isCallNode($item->value)) {
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
} elseif ($node instanceof Isset_ || $node instanceof Unset_) {
|
||||
@@ -61,10 +63,10 @@ class FunctionReturnInWriteContextPass extends CodeCleanerPass
|
||||
}
|
||||
|
||||
$msg = $node instanceof Isset_ ? self::ISSET_MESSAGE : self::EXCEPTION_MESSAGE;
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
} elseif ($node instanceof Assign && $this->isCallNode($node->var)) {
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -77,15 +77,14 @@ class ImplicitReturnPass extends CodeCleanerPass
|
||||
} elseif ($last instanceof Expr && !($last instanceof Exit_)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
$nodes[\count($nodes) - 1] = new Return_($last, [
|
||||
'startLine' => $last->getLine(),
|
||||
'endLine' => $last->getLine(),
|
||||
'startLine' => $last->getStartLine(),
|
||||
'endLine' => $last->getEndLine(),
|
||||
]);
|
||||
// @codeCoverageIgnoreEnd
|
||||
} elseif ($last instanceof Expression && !($last->expr instanceof Exit_)) {
|
||||
// For PHP Parser 4.x
|
||||
$nodes[\count($nodes) - 1] = new Return_($last->expr, [
|
||||
'startLine' => $last->getLine(),
|
||||
'endLine' => $last->getLine(),
|
||||
'startLine' => $last->getStartLine(),
|
||||
'endLine' => $last->getEndLine(),
|
||||
]);
|
||||
} elseif ($last instanceof Namespace_) {
|
||||
$last->stmts = $this->addImplicitReturn($last->stmts);
|
||||
@@ -115,8 +114,6 @@ class ImplicitReturnPass extends CodeCleanerPass
|
||||
* we'll exclude them here.
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function isNonExpressionStmt(Node $node): bool
|
||||
{
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\CodeCleaner;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\BinaryOp;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\Instanceof_;
|
||||
use PhpParser\Node\Scalar;
|
||||
use PhpParser\Node\Scalar\Encapsed;
|
||||
use Psy\Exception\FatalErrorException;
|
||||
|
||||
/**
|
||||
* Validate that the instanceof statement does not receive a scalar value or a non-class constant.
|
||||
*
|
||||
* @author Martin Hasoň <martin.hason@gmail.com>
|
||||
*/
|
||||
class InstanceOfPass extends CodeCleanerPass
|
||||
{
|
||||
const EXCEPTION_MSG = 'instanceof expects an object instance, constant given';
|
||||
|
||||
private $atLeastPhp73;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->atLeastPhp73 = \version_compare(\PHP_VERSION, '7.3', '>=');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the instanceof statement does not receive a scalar value or a non-class constant.
|
||||
*
|
||||
* @throws FatalErrorException if a scalar or a non-class constant is given
|
||||
*
|
||||
* @param Node $node
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
// Basically everything is allowed in PHP 7.3 :)
|
||||
if ($this->atLeastPhp73) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$node instanceof Instanceof_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (($node->expr instanceof Scalar && !$node->expr instanceof Encapsed) ||
|
||||
$node->expr instanceof BinaryOp ||
|
||||
$node->expr instanceof Array_ ||
|
||||
$node->expr instanceof ConstFetch ||
|
||||
$node->expr instanceof ClassConstFetch
|
||||
) {
|
||||
throw new FatalErrorException(self::EXCEPTION_MSG, 0, \E_ERROR, null, $node->getLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -31,6 +31,8 @@ class IssetPass extends CodeCleanerPass
|
||||
* @throws FatalErrorException
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -40,7 +42,7 @@ class IssetPass extends CodeCleanerPass
|
||||
|
||||
foreach ($node->vars as $var) {
|
||||
if (!$var instanceof Variable && !$var instanceof ArrayDimFetch && !$var instanceof PropertyFetch && !$var instanceof NullsafePropertyFetch) {
|
||||
throw new FatalErrorException(self::EXCEPTION_MSG, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException(self::EXCEPTION_MSG, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -41,6 +41,8 @@ class LabelContextPass extends CodeCleanerPass
|
||||
|
||||
/**
|
||||
* @param array $nodes
|
||||
*
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
@@ -49,6 +51,9 @@ class LabelContextPass extends CodeCleanerPass
|
||||
$this->labelGotos = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
if ($node instanceof FunctionLike) {
|
||||
@@ -63,14 +68,16 @@ class LabelContextPass extends CodeCleanerPass
|
||||
}
|
||||
|
||||
if ($node instanceof Goto_) {
|
||||
$this->labelGotos[\strtolower($node->name)] = $node->getLine();
|
||||
$this->labelGotos[\strtolower($node->name)] = $node->getStartLine();
|
||||
} elseif ($node instanceof Label) {
|
||||
$this->labelDeclarations[\strtolower($node->name)] = $node->getLine();
|
||||
$this->labelDeclarations[\strtolower($node->name)] = $node->getStartLine();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \PhpParser\Node $node
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
@@ -79,6 +86,9 @@ class LabelContextPass extends CodeCleanerPass
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function afterTraverse(array $nodes)
|
||||
{
|
||||
foreach ($this->labelGotos as $name => $line) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -26,6 +26,8 @@ class LeavePsyshAlonePass extends CodeCleanerPass
|
||||
* @throws RuntimeException if the user is messing with $__psysh__
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
|
||||
34
vendor/psy/psysh/src/CodeCleaner/ListPass.php
vendored
34
vendor/psy/psysh/src/CodeCleaner/ListPass.php
vendored
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -12,9 +12,9 @@
|
||||
namespace Psy\CodeCleaner;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
// @todo Switch to PhpParser\Node\ArrayItem once we drop support for PHP-Parser 4.x
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
@@ -29,19 +29,14 @@ use Psy\Exception\ParseErrorException;
|
||||
*/
|
||||
class ListPass extends CodeCleanerPass
|
||||
{
|
||||
private $atLeastPhp71;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->atLeastPhp71 = \version_compare(\PHP_VERSION, '7.1', '>=');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate use of list assignment.
|
||||
*
|
||||
* @throws ParseErrorException if the user used empty with anything but a variable
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -53,16 +48,11 @@ class ListPass extends CodeCleanerPass
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->atLeastPhp71 && $node->var instanceof Array_) {
|
||||
$msg = "syntax error, unexpected '='";
|
||||
throw new ParseErrorException($msg, $node->expr->getLine());
|
||||
}
|
||||
|
||||
// Polyfill for PHP-Parser 2.x
|
||||
$items = isset($node->var->items) ? $node->var->items : $node->var->vars;
|
||||
|
||||
if ($items === [] || $items === [null]) {
|
||||
throw new ParseErrorException('Cannot use empty list', $node->var->getLine());
|
||||
throw new ParseErrorException('Cannot use empty list', ['startLine' => $node->var->getStartLine(), 'endLine' => $node->var->getEndLine()]);
|
||||
}
|
||||
|
||||
$itemFound = false;
|
||||
@@ -73,15 +63,9 @@ class ListPass extends CodeCleanerPass
|
||||
|
||||
$itemFound = true;
|
||||
|
||||
// List_->$vars in PHP-Parser 2.x is Variable instead of ArrayItem.
|
||||
if (!$this->atLeastPhp71 && $item instanceof ArrayItem && $item->key !== null) {
|
||||
$msg = 'Syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting \',\' or \')\'';
|
||||
throw new ParseErrorException($msg, $item->key->getLine());
|
||||
}
|
||||
|
||||
if (!self::isValidArrayItem($item)) {
|
||||
$msg = 'Assignments can only happen to writable values';
|
||||
throw new ParseErrorException($msg, $item->getLine());
|
||||
throw new ParseErrorException($msg, ['startLine' => $item->getStartLine(), 'endLine' => $item->getEndLine()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,11 +77,9 @@ class ListPass extends CodeCleanerPass
|
||||
/**
|
||||
* Validate whether a given item in an array is valid for short assignment.
|
||||
*
|
||||
* @param Expr $item
|
||||
*
|
||||
* @return bool
|
||||
* @param Node $item
|
||||
*/
|
||||
private static function isValidArrayItem(Expr $item): bool
|
||||
private static function isValidArrayItem(Node $item): bool
|
||||
{
|
||||
$value = ($item instanceof ArrayItem) ? $item->value : $item;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -32,6 +32,8 @@ class LoopContextPass extends CodeCleanerPass
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
@@ -45,6 +47,8 @@ class LoopContextPass extends CodeCleanerPass
|
||||
* @throws FatalErrorException if the node is a break or continue and has an argument less than 1
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -63,23 +67,24 @@ class LoopContextPass extends CodeCleanerPass
|
||||
|
||||
if ($this->loopDepth === 0) {
|
||||
$msg = \sprintf("'%s' not in the 'loop' or 'switch' context", $operator);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
|
||||
// @todo Rename to Int_ and Float_ once we drop support for PHP-Parser 4.x
|
||||
if ($node->num instanceof LNumber || $node->num instanceof DNumber) {
|
||||
$num = $node->num->value;
|
||||
if ($node->num instanceof DNumber || $num < 1) {
|
||||
$msg = \sprintf("'%s' operator accepts only positive numbers", $operator);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
|
||||
if ($num > $this->loopDepth) {
|
||||
$msg = \sprintf("Cannot '%s' %d levels", $operator, $num);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
} elseif ($node->num) {
|
||||
$msg = \sprintf("'%s' operator with non-constant operand is no longer supported", $operator);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -87,6 +92,8 @@ class LoopContextPass extends CodeCleanerPass
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -29,6 +29,8 @@ abstract class NamespaceAwarePass extends CodeCleanerPass
|
||||
* use afterTraverse or call parent::beforeTraverse() when overloading.
|
||||
*
|
||||
* Reset the namespace and the current scope before beginning analysis
|
||||
*
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
@@ -41,11 +43,13 @@ abstract class NamespaceAwarePass extends CodeCleanerPass
|
||||
* leaveNode or call parent::enterNode() when overloading
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
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) : [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,19 +57,29 @@ abstract class NamespaceAwarePass extends CodeCleanerPass
|
||||
* Get a fully-qualified name (class, function, interface, etc).
|
||||
*
|
||||
* @param mixed $name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Psy\CodeCleaner;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use Psy\CodeCleaner;
|
||||
@@ -46,6 +47,8 @@ class NamespacePass extends CodeCleanerPass
|
||||
* is encountered.
|
||||
*
|
||||
* @param array $nodes
|
||||
*
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
@@ -83,6 +86,16 @@ class NamespacePass extends CodeCleanerPass
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -25,8 +25,6 @@ class NoReturnValue
|
||||
{
|
||||
/**
|
||||
* Get PhpParser AST expression for creating a new NoReturnValue.
|
||||
*
|
||||
* @return New_
|
||||
*/
|
||||
public static function create(): New_
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -34,6 +34,8 @@ class PassableByReferencePass extends CodeCleanerPass
|
||||
* @throws FatalErrorException if non-variables are passed by reference
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -61,7 +63,7 @@ class PassableByReferencePass extends CodeCleanerPass
|
||||
if (\array_key_exists($key, $node->args)) {
|
||||
$arg = $node->args[$key];
|
||||
if ($param->isPassedByReference() && !$this->isPassableByReference($arg)) {
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,7 +112,7 @@ class PassableByReferencePass extends CodeCleanerPass
|
||||
} elseif (++$nonPassable > 2) {
|
||||
// There can be *at most* two non-passable-by-reference args in a row. This is about
|
||||
// as close as we can get to validating the arguments for this function :-/
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
vendor/psy/psysh/src/CodeCleaner/RequirePass.php
vendored
15
vendor/psy/psysh/src/CodeCleaner/RequirePass.php
vendored
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -29,6 +29,8 @@ class RequirePass extends CodeCleanerPass
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $origNode)
|
||||
{
|
||||
@@ -47,10 +49,11 @@ class RequirePass extends CodeCleanerPass
|
||||
*
|
||||
* $foo = require \Psy\CodeCleaner\RequirePass::resolve($bar)
|
||||
*/
|
||||
// @todo Rename LNumber to Int_ once we drop support for PHP-Parser 4.x
|
||||
$node->expr = new StaticCall(
|
||||
new FullyQualifiedName(self::class),
|
||||
'resolve',
|
||||
[new Arg($origNode->expr), new Arg(new LNumber($origNode->getLine()))],
|
||||
[new Arg($origNode->expr), new Arg(new LNumber($origNode->getStartLine()))],
|
||||
$origNode->getAttributes()
|
||||
);
|
||||
|
||||
@@ -69,11 +72,11 @@ class RequirePass extends CodeCleanerPass
|
||||
* @throws ErrorException if $file is empty and E_WARNING is included in error_reporting level
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $lineNumber Line number of the original require expression
|
||||
* @param int $startLine Line number of the original require expression
|
||||
*
|
||||
* @return string Exactly the same as $file, unless $file collides with a path in the currently running phar
|
||||
*/
|
||||
public static function resolve($file, $lineNumber = null): string
|
||||
public static function resolve($file, $startLine = null): string
|
||||
{
|
||||
$file = (string) $file;
|
||||
|
||||
@@ -82,7 +85,7 @@ class RequirePass extends CodeCleanerPass
|
||||
// fake the file and line number, but we can't call it statically.
|
||||
// So we're duplicating some of the logics here.
|
||||
if (\E_WARNING & \error_reporting()) {
|
||||
ErrorException::throwException(\E_WARNING, 'Filename cannot be empty', null, $lineNumber);
|
||||
ErrorException::throwException(\E_WARNING, 'Filename cannot be empty', null, $startLine);
|
||||
}
|
||||
// @todo trigger an error as fallback? this is pretty ugly…
|
||||
// trigger_error('Filename cannot be empty', E_USER_WARNING);
|
||||
@@ -91,7 +94,7 @@ class RequirePass extends CodeCleanerPass
|
||||
$resolvedPath = \stream_resolve_include_path($file);
|
||||
if ($file === '' || !$resolvedPath) {
|
||||
$msg = \sprintf("Failed opening required '%s'", $file);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $lineNumber);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $startLine);
|
||||
}
|
||||
|
||||
// Special case: if the path is not already relative or absolute, and it would resolve to
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -18,6 +18,7 @@ use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\NullableType;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PhpParser\Node\UnionType;
|
||||
use Psy\Exception\FatalErrorException;
|
||||
|
||||
/**
|
||||
@@ -31,23 +32,15 @@ class ReturnTypePass extends CodeCleanerPass
|
||||
const VOID_NULL_MESSAGE = 'A void function must not return a value (did you mean "return;" instead of "return null;"?)';
|
||||
const NULLABLE_VOID_MESSAGE = 'Void type cannot be nullable';
|
||||
|
||||
private $atLeastPhp71;
|
||||
private $returnTypeStack = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->atLeastPhp71 = \version_compare(\PHP_VERSION, '7.1', '>=');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
if (!$this->atLeastPhp71) {
|
||||
return; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if ($this->isFunctionNode($node)) {
|
||||
$this->returnTypeStack[] = $node->returnType;
|
||||
|
||||
@@ -79,20 +72,18 @@ class ReturnTypePass extends CodeCleanerPass
|
||||
}
|
||||
|
||||
if ($msg !== null) {
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
if (!$this->atLeastPhp71) {
|
||||
return; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if (!empty($this->returnTypeStack) && $this->isFunctionNode($node)) {
|
||||
\array_pop($this->returnTypeStack);
|
||||
}
|
||||
@@ -105,6 +96,10 @@ class ReturnTypePass extends CodeCleanerPass
|
||||
|
||||
private function typeName(Node $node): string
|
||||
{
|
||||
if ($node instanceof UnionType) {
|
||||
return \implode('|', \array_map([$this, 'typeName'], $node->types));
|
||||
}
|
||||
|
||||
if ($node instanceof NullableType) {
|
||||
return \strtolower($node->type->name);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace Psy\CodeCleaner;
|
||||
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Stmt\Declare_;
|
||||
use PhpParser\Node\Stmt\DeclareDeclare;
|
||||
@@ -33,6 +33,14 @@ class StrictTypesPass extends CodeCleanerPass
|
||||
|
||||
private $strictTypes = false;
|
||||
|
||||
/**
|
||||
* @param bool $strictTypes enforce strict types by default
|
||||
*/
|
||||
public function __construct(bool $strictTypes = false)
|
||||
{
|
||||
$this->strictTypes = $strictTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is a standalone strict types declaration, remember it for later.
|
||||
*
|
||||
@@ -42,6 +50,8 @@ class StrictTypesPass extends CodeCleanerPass
|
||||
* @throws FatalErrorException if an invalid `strict_types` declaration is found
|
||||
*
|
||||
* @param array $nodes
|
||||
*
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
@@ -50,12 +60,11 @@ class StrictTypesPass extends CodeCleanerPass
|
||||
foreach ($nodes as $node) {
|
||||
if ($node instanceof Declare_) {
|
||||
foreach ($node->declares as $declare) {
|
||||
// For PHP Parser 4.x
|
||||
$declareKey = $declare->key instanceof Identifier ? $declare->key->toString() : $declare->key;
|
||||
if ($declareKey === 'strict_types') {
|
||||
if ($declare->key->toString() === 'strict_types') {
|
||||
$value = $declare->value;
|
||||
// @todo Rename LNumber to Int_ once we drop support for PHP-Parser 4.x
|
||||
if (!$value instanceof LNumber || ($value->value !== 0 && $value->value !== 1)) {
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException(self::EXCEPTION_MESSAGE, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
|
||||
$this->strictTypes = $value->value === 1;
|
||||
@@ -67,6 +76,8 @@ class StrictTypesPass extends CodeCleanerPass
|
||||
if ($prependStrictTypes) {
|
||||
$first = \reset($nodes);
|
||||
if (!$first instanceof Declare_) {
|
||||
// @todo Switch to PhpParser\Node\DeclareItem once we drop support for PHP-Parser 4.x
|
||||
// @todo Rename LNumber to Int_ once we drop support for PHP-Parser 4.x
|
||||
$declare = new Declare_([new DeclareDeclare('strict_types', new LNumber(1))]);
|
||||
\array_unshift($nodes, $declare);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -17,6 +17,7 @@ use PhpParser\Node\Name\FullyQualified as FullyQualifiedName;
|
||||
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;
|
||||
|
||||
@@ -44,6 +45,8 @@ class UseStatementPass extends CodeCleanerPass
|
||||
* work like you'd expect.
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -63,29 +66,31 @@ class UseStatementPass extends CodeCleanerPass
|
||||
* remembered aliases to the code.
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
// @todo Rename to Node_Visitor::REMOVE_NODE once we drop support for PHP-Parser 4.x
|
||||
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'),
|
||||
]);
|
||||
}
|
||||
|
||||
// @todo Rename to Node_Visitor::REMOVE_NODE once we drop support for PHP-Parser 4.x
|
||||
return NodeTraverser::REMOVE_NODE;
|
||||
}
|
||||
|
||||
@@ -98,8 +103,9 @@ class UseStatementPass extends CodeCleanerPass
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -46,6 +46,8 @@ class ValidClassNamePass extends NamespaceAwarePass
|
||||
* trait methods.
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -70,13 +72,13 @@ class ValidClassNamePass extends NamespaceAwarePass
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
if (self::isConditional($node)) {
|
||||
$this->conditionalScopes--;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,35 +259,12 @@ class ValidClassNamePass extends NamespaceAwarePass
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a symbol type key for storing in the scope name cache.
|
||||
*
|
||||
* @deprecated No longer used. Scope type should be passed into ensureCanDefine directly.
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param Stmt $stmt
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getScopeType(Stmt $stmt): string
|
||||
{
|
||||
if ($stmt instanceof Class_) {
|
||||
return self::CLASS_TYPE;
|
||||
} elseif ($stmt instanceof Interface_) {
|
||||
return self::INTERFACE_TYPE;
|
||||
} elseif ($stmt instanceof Trait_) {
|
||||
return self::TRAIT_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a class exists, or has been defined in the current code snippet.
|
||||
*
|
||||
* Gives `self`, `static` and `parent` a free pass.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function classExists(string $name): bool
|
||||
{
|
||||
@@ -303,8 +282,6 @@ class ValidClassNamePass extends NamespaceAwarePass
|
||||
* Check whether an interface exists, or has been defined in the current code snippet.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function interfaceExists(string $name): bool
|
||||
{
|
||||
@@ -315,8 +292,6 @@ class ValidClassNamePass extends NamespaceAwarePass
|
||||
* Check whether a trait exists, or has been defined in the current code snippet.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function traitExists(string $name): bool
|
||||
{
|
||||
@@ -343,11 +318,9 @@ class ValidClassNamePass extends NamespaceAwarePass
|
||||
*
|
||||
* @param string $msg
|
||||
* @param Stmt $stmt
|
||||
*
|
||||
* @return FatalErrorException
|
||||
*/
|
||||
protected function createError(string $msg, Stmt $stmt): FatalErrorException
|
||||
{
|
||||
return new FatalErrorException($msg, 0, \E_ERROR, null, $stmt->getLine());
|
||||
return new FatalErrorException($msg, 0, \E_ERROR, null, $stmt->getStartLine());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace Psy\CodeCleaner;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
@@ -35,6 +35,9 @@ class ValidConstructorPass extends CodeCleanerPass
|
||||
{
|
||||
private $namespace;
|
||||
|
||||
/**
|
||||
* @return Node[]|null Array of nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
$this->namespace = [];
|
||||
@@ -47,11 +50,13 @@ class ValidConstructorPass extends CodeCleanerPass
|
||||
* @throws FatalErrorException the constructor function has a return type
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
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) {
|
||||
@@ -86,27 +91,31 @@ class ValidConstructorPass extends CodeCleanerPass
|
||||
private function validateConstructor(Node $constructor, Node $classNode)
|
||||
{
|
||||
if ($constructor->isStatic()) {
|
||||
// For PHP Parser 4.x
|
||||
$className = $classNode->name instanceof Identifier ? $classNode->name->toString() : $classNode->name;
|
||||
|
||||
$msg = \sprintf(
|
||||
'Constructor %s::%s() cannot be static',
|
||||
\implode('\\', \array_merge($this->namespace, (array) $className)),
|
||||
\implode('\\', \array_merge($this->namespace, (array) $classNode->name->toString())),
|
||||
$constructor->name
|
||||
);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $classNode->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $classNode->getStartLine());
|
||||
}
|
||||
|
||||
if (\method_exists($constructor, 'getReturnType') && $constructor->getReturnType()) {
|
||||
// For PHP Parser 4.x
|
||||
$className = $classNode->name instanceof Identifier ? $classNode->name->toString() : $classNode->name;
|
||||
|
||||
$msg = \sprintf(
|
||||
'Constructor %s::%s() cannot declare a return type',
|
||||
\implode('\\', \array_merge($this->namespace, (array) $className)),
|
||||
\implode('\\', \array_merge($this->namespace, (array) $classNode->name->toString())),
|
||||
$constructor->name
|
||||
);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $classNode->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $classNode->getStartLine());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
* (c) 2012-2023 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -35,6 +35,8 @@ class ValidFunctionNamePass extends NamespaceAwarePass
|
||||
* @throws FatalErrorException if a function is redefined in a non-conditional scope
|
||||
*
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|null Replacement node (or special return value)
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
@@ -51,7 +53,7 @@ class ValidFunctionNamePass extends NamespaceAwarePass
|
||||
if (\function_exists($name) ||
|
||||
isset($this->currentScope[\strtolower($name)])) {
|
||||
$msg = \sprintf('Cannot redeclare %s()', $name);
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getLine());
|
||||
throw new FatalErrorException($msg, 0, \E_ERROR, null, $node->getStartLine());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +63,8 @@ class ValidFunctionNamePass extends NamespaceAwarePass
|
||||
|
||||
/**
|
||||
* @param Node $node
|
||||
*
|
||||
* @return int|Node|Node[]|null Replacement node (or special return value)
|
||||
*/
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user