upgraded dependencies
This commit is contained in:
124
vendor/psy/psysh/src/CodeCleaner.php
vendored
124
vendor/psy/psysh/src/CodeCleaner.php
vendored
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2018 Justin Hileman
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -18,24 +18,26 @@ use Psy\CodeCleaner\AbstractClassPass;
|
||||
use Psy\CodeCleaner\AssignThisVariablePass;
|
||||
use Psy\CodeCleaner\CalledClassPass;
|
||||
use Psy\CodeCleaner\CallTimePassByReferencePass;
|
||||
use Psy\CodeCleaner\EmptyArrayDimFetchPass;
|
||||
use Psy\CodeCleaner\ExitPass;
|
||||
use Psy\CodeCleaner\FinalClassPass;
|
||||
use Psy\CodeCleaner\FunctionContextPass;
|
||||
use Psy\CodeCleaner\FunctionReturnInWriteContextPass;
|
||||
use Psy\CodeCleaner\ImplicitReturnPass;
|
||||
use Psy\CodeCleaner\InstanceOfPass;
|
||||
use Psy\CodeCleaner\IssetPass;
|
||||
use Psy\CodeCleaner\LabelContextPass;
|
||||
use Psy\CodeCleaner\LeavePsyshAlonePass;
|
||||
use Psy\CodeCleaner\LegacyEmptyPass;
|
||||
use Psy\CodeCleaner\ListPass;
|
||||
use Psy\CodeCleaner\LoopContextPass;
|
||||
use Psy\CodeCleaner\MagicConstantsPass;
|
||||
use Psy\CodeCleaner\NamespacePass;
|
||||
use Psy\CodeCleaner\PassableByReferencePass;
|
||||
use Psy\CodeCleaner\RequirePass;
|
||||
use Psy\CodeCleaner\ReturnTypePass;
|
||||
use Psy\CodeCleaner\StrictTypesPass;
|
||||
use Psy\CodeCleaner\UseStatementPass;
|
||||
use Psy\CodeCleaner\ValidClassNamePass;
|
||||
use Psy\CodeCleaner\ValidConstantPass;
|
||||
use Psy\CodeCleaner\ValidConstructorPass;
|
||||
use Psy\CodeCleaner\ValidFunctionNamePass;
|
||||
use Psy\Exception\ParseErrorException;
|
||||
@@ -46,6 +48,7 @@ use Psy\Exception\ParseErrorException;
|
||||
*/
|
||||
class CodeCleaner
|
||||
{
|
||||
private $yolo = false;
|
||||
private $parser;
|
||||
private $printer;
|
||||
private $traverser;
|
||||
@@ -54,19 +57,22 @@ class CodeCleaner
|
||||
/**
|
||||
* CodeCleaner constructor.
|
||||
*
|
||||
* @param Parser $parser A PhpParser Parser instance. One will be created if not explicitly supplied
|
||||
* @param Printer $printer A PhpParser Printer instance. One will be created if not explicitly supplied
|
||||
* @param NodeTraverser $traverser A PhpParser NodeTraverser instance. One will be created if not explicitly supplied
|
||||
* @param Parser|null $parser A PhpParser Parser instance. One will be created if not explicitly supplied
|
||||
* @param Printer|null $printer A PhpParser Printer instance. One will be created if not explicitly supplied
|
||||
* @param NodeTraverser|null $traverser A PhpParser NodeTraverser instance. One will be created if not explicitly supplied
|
||||
* @param bool $yolo run without input validation
|
||||
*/
|
||||
public function __construct(Parser $parser = null, Printer $printer = null, NodeTraverser $traverser = null)
|
||||
public function __construct(Parser $parser = null, Printer $printer = null, NodeTraverser $traverser = null, bool $yolo = false)
|
||||
{
|
||||
$this->yolo = $yolo;
|
||||
|
||||
if ($parser === null) {
|
||||
$parserFactory = new ParserFactory();
|
||||
$parser = $parserFactory->createParser();
|
||||
$parser = $parserFactory->createParser();
|
||||
}
|
||||
|
||||
$this->parser = $parser;
|
||||
$this->printer = $printer ?: new Printer();
|
||||
$this->parser = $parser;
|
||||
$this->printer = $printer ?: new Printer();
|
||||
$this->traverser = $traverser ?: new NodeTraverser();
|
||||
|
||||
foreach ($this->getDefaultPasses() as $pass) {
|
||||
@@ -74,15 +80,29 @@ class CodeCleaner
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this CodeCleaner is in YOLO mode.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function yolo(): bool
|
||||
{
|
||||
return $this->yolo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default CodeCleaner passes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getDefaultPasses()
|
||||
private function getDefaultPasses(): array
|
||||
{
|
||||
if ($this->yolo) {
|
||||
return $this->getYoloPasses();
|
||||
}
|
||||
|
||||
$useStatementPass = new UseStatementPass();
|
||||
$namespacePass = new NamespacePass($this);
|
||||
$namespacePass = new NamespacePass($this);
|
||||
|
||||
// Try to add implicit `use` statements and an implicit namespace,
|
||||
// based on the file in which the `debug` call was made.
|
||||
@@ -98,11 +118,14 @@ class CodeCleaner
|
||||
new FunctionContextPass(),
|
||||
new FunctionReturnInWriteContextPass(),
|
||||
new InstanceOfPass(),
|
||||
new IssetPass(),
|
||||
new LabelContextPass(),
|
||||
new LeavePsyshAlonePass(),
|
||||
new LegacyEmptyPass(),
|
||||
new ListPass(),
|
||||
new LoopContextPass(),
|
||||
new PassableByReferencePass(),
|
||||
new ReturnTypePass(),
|
||||
new EmptyArrayDimFetchPass(),
|
||||
new ValidConstructorPass(),
|
||||
|
||||
// Rewriting shenanigans
|
||||
@@ -116,11 +139,40 @@ class CodeCleaner
|
||||
|
||||
// Namespace-aware validation (which depends on aforementioned shenanigans)
|
||||
new ValidClassNamePass(),
|
||||
new ValidConstantPass(),
|
||||
new ValidFunctionNamePass(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of code cleaner passes that don't try to do any validation, and
|
||||
* only do minimal rewriting to make things work inside the REPL.
|
||||
*
|
||||
* This list should stay in sync with the "rewriting shenanigans" in
|
||||
* getDefaultPasses above.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getYoloPasses(): array
|
||||
{
|
||||
$useStatementPass = new UseStatementPass();
|
||||
$namespacePass = new NamespacePass($this);
|
||||
|
||||
// Try to add implicit `use` statements and an implicit namespace,
|
||||
// based on the file in which the `debug` call was made.
|
||||
$this->addImplicitDebugContext([$useStatementPass, $namespacePass]);
|
||||
|
||||
return [
|
||||
new LeavePsyshAlonePass(),
|
||||
$useStatementPass, // must run before the namespace pass
|
||||
new ExitPass(),
|
||||
new ImplicitReturnPass(),
|
||||
new MagicConstantsPass(),
|
||||
$namespacePass, // must run after the implicit return pass
|
||||
new RequirePass(),
|
||||
new StrictTypesPass(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* "Warm up" code cleaner passes when we're coming from a debug call.
|
||||
*
|
||||
@@ -157,8 +209,6 @@ class CodeCleaner
|
||||
$traverser->traverse($stmts);
|
||||
} catch (\Throwable $e) {
|
||||
// Don't care.
|
||||
} catch (\Exception $e) {
|
||||
// Still don't care.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +219,7 @@ class CodeCleaner
|
||||
*/
|
||||
private static function getDebugFile()
|
||||
{
|
||||
$trace = \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
$trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
|
||||
foreach (\array_reverse($trace) as $stackFrame) {
|
||||
if (!self::isDebugCall($stackFrame)) {
|
||||
@@ -193,13 +243,13 @@ class CodeCleaner
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function isDebugCall(array $stackFrame)
|
||||
private static function isDebugCall(array $stackFrame): bool
|
||||
{
|
||||
$class = isset($stackFrame['class']) ? $stackFrame['class'] : null;
|
||||
$class = isset($stackFrame['class']) ? $stackFrame['class'] : null;
|
||||
$function = isset($stackFrame['function']) ? $stackFrame['function'] : null;
|
||||
|
||||
return ($class === null && $function === 'Psy\debug') ||
|
||||
($class === 'Psy\Shell' && $function === 'debug');
|
||||
return ($class === null && $function === 'Psy\\debug') ||
|
||||
($class === Shell::class && $function === 'debug');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,9 +262,9 @@ class CodeCleaner
|
||||
*
|
||||
* @return string|false Cleaned PHP code, False if the input is incomplete
|
||||
*/
|
||||
public function clean(array $codeLines, $requireSemicolons = false)
|
||||
public function clean(array $codeLines, bool $requireSemicolons = false)
|
||||
{
|
||||
$stmts = $this->parse('<?php ' . \implode(PHP_EOL, $codeLines) . PHP_EOL, $requireSemicolons);
|
||||
$stmts = $this->parse('<?php '.\implode(\PHP_EOL, $codeLines).\PHP_EOL, $requireSemicolons);
|
||||
if ($stmts === false) {
|
||||
return false;
|
||||
}
|
||||
@@ -223,13 +273,13 @@ class CodeCleaner
|
||||
$stmts = $this->traverser->traverse($stmts);
|
||||
|
||||
// Work around https://github.com/nikic/PHP-Parser/issues/399
|
||||
$oldLocale = \setlocale(LC_NUMERIC, 0);
|
||||
\setlocale(LC_NUMERIC, 'C');
|
||||
$oldLocale = \setlocale(\LC_NUMERIC, 0);
|
||||
\setlocale(\LC_NUMERIC, 'C');
|
||||
|
||||
$code = $this->printer->prettyPrint($stmts);
|
||||
|
||||
// Now put the locale back
|
||||
\setlocale(LC_NUMERIC, $oldLocale);
|
||||
\setlocale(\LC_NUMERIC, $oldLocale);
|
||||
|
||||
return $code;
|
||||
}
|
||||
@@ -237,9 +287,9 @@ class CodeCleaner
|
||||
/**
|
||||
* Set the current local namespace.
|
||||
*
|
||||
* @param null|array $namespace (default: null)
|
||||
* @param array|null $namespace (default: null)
|
||||
*
|
||||
* @return null|array
|
||||
* @return array|null
|
||||
*/
|
||||
public function setNamespace(array $namespace = null)
|
||||
{
|
||||
@@ -249,7 +299,7 @@ class CodeCleaner
|
||||
/**
|
||||
* Get the current local namespace.
|
||||
*
|
||||
* @return null|array
|
||||
* @return array|null
|
||||
*/
|
||||
public function getNamespace()
|
||||
{
|
||||
@@ -269,7 +319,7 @@ class CodeCleaner
|
||||
*
|
||||
* @return array|false A set of statements, or false if incomplete
|
||||
*/
|
||||
protected function parse($code, $requireSemicolons = false)
|
||||
protected function parse(string $code, bool $requireSemicolons = false)
|
||||
{
|
||||
try {
|
||||
return $this->parser->parse($code);
|
||||
@@ -296,14 +346,14 @@ class CodeCleaner
|
||||
|
||||
try {
|
||||
// Unexpected EOF, try again with an implicit semicolon
|
||||
return $this->parser->parse($code . ';');
|
||||
return $this->parser->parse($code.';');
|
||||
} catch (\PhpParser\Error $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function parseErrorIsEOF(\PhpParser\Error $e)
|
||||
private function parseErrorIsEOF(\PhpParser\Error $e): bool
|
||||
{
|
||||
$msg = $e->getRawMessage();
|
||||
|
||||
@@ -322,27 +372,27 @@ class CodeCleaner
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function parseErrorIsUnclosedString(\PhpParser\Error $e, $code)
|
||||
private function parseErrorIsUnclosedString(\PhpParser\Error $e, string $code): bool
|
||||
{
|
||||
if ($e->getRawMessage() !== 'Syntax error, unexpected T_ENCAPSED_AND_WHITESPACE') {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->parser->parse($code . "';");
|
||||
} catch (\Exception $e) {
|
||||
$this->parser->parse($code."';");
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function parseErrorIsUnterminatedComment(\PhpParser\Error $e, $code)
|
||||
private function parseErrorIsUnterminatedComment(\PhpParser\Error $e, $code): bool
|
||||
{
|
||||
return $e->getRawMessage() === 'Unterminated comment';
|
||||
}
|
||||
|
||||
private function parseErrorIsTrailingComma(\PhpParser\Error $e, $code)
|
||||
private function parseErrorIsTrailingComma(\PhpParser\Error $e, $code): bool
|
||||
{
|
||||
return ($e->getRawMessage() === 'A trailing comma is not allowed here') && (\substr(\rtrim($code), -1) === ',');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user