composer update
This commit is contained in:
@@ -183,7 +183,7 @@ final class BuilderHelpers
|
||||
}
|
||||
|
||||
$builtinTypes = [
|
||||
'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object'
|
||||
'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object', 'mixed'
|
||||
];
|
||||
|
||||
$lowerType = strtolower($type);
|
||||
@@ -197,6 +197,10 @@ final class BuilderHelpers
|
||||
throw new \LogicException('void type cannot be nullable');
|
||||
}
|
||||
|
||||
if ($nullable && (string) $type === 'mixed') {
|
||||
throw new \LogicException('mixed type cannot be nullable');
|
||||
}
|
||||
|
||||
return $nullable ? new NullableType($type) : $type;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ use PhpParser\Node\Expr;
|
||||
*/
|
||||
class PrintableNewAnonClassNode extends Expr
|
||||
{
|
||||
/** @var Node\AttributeGroup[] PHP attribute groups */
|
||||
public $attrGroups;
|
||||
/** @var Node\Arg[] Arguments */
|
||||
public $args;
|
||||
/** @var null|Node\Name Name of extended class */
|
||||
@@ -27,9 +29,11 @@ class PrintableNewAnonClassNode extends Expr
|
||||
public $stmts;
|
||||
|
||||
public function __construct(
|
||||
array $args, Node\Name $extends = null, array $implements, array $stmts, array $attributes
|
||||
array $attrGroups, array $args, Node\Name $extends = null, array $implements,
|
||||
array $stmts, array $attributes
|
||||
) {
|
||||
parent::__construct($attributes);
|
||||
$this->attrGroups = $attrGroups;
|
||||
$this->args = $args;
|
||||
$this->extends = $extends;
|
||||
$this->implements = $implements;
|
||||
@@ -42,7 +46,7 @@ class PrintableNewAnonClassNode extends Expr
|
||||
// We don't assert that $class->name is null here, to allow consumers to assign unique names
|
||||
// to anonymous classes for their own purposes. We simplify ignore the name here.
|
||||
return new self(
|
||||
$newNode->args, $class->extends, $class->implements,
|
||||
$class->attrGroups, $newNode->args, $class->extends, $class->implements,
|
||||
$class->stmts, $newNode->getAttributes()
|
||||
);
|
||||
}
|
||||
@@ -52,6 +56,6 @@ class PrintableNewAnonClassNode extends Expr
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['args', 'extends', 'implements', 'stmts'];
|
||||
return ['attrGroups', 'args', 'extends', 'implements', 'stmts'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class TokenStream
|
||||
* @return bool
|
||||
*/
|
||||
public function haveParens(int $startPos, int $endPos) : bool {
|
||||
return $this->haveTokenImmediativelyBefore($startPos, '(')
|
||||
return $this->haveTokenImmediatelyBefore($startPos, '(')
|
||||
&& $this->haveTokenImmediatelyAfter($endPos, ')');
|
||||
}
|
||||
|
||||
@@ -46,7 +46,8 @@ class TokenStream
|
||||
* @return bool
|
||||
*/
|
||||
public function haveBraces(int $startPos, int $endPos) : bool {
|
||||
return $this->haveTokenImmediativelyBefore($startPos, '{')
|
||||
return ($this->haveTokenImmediatelyBefore($startPos, '{')
|
||||
|| $this->haveTokenImmediatelyBefore($startPos, T_CURLY_OPEN))
|
||||
&& $this->haveTokenImmediatelyAfter($endPos, '}');
|
||||
}
|
||||
|
||||
@@ -60,7 +61,7 @@ class TokenStream
|
||||
*
|
||||
* @return bool Whether the expected token was found
|
||||
*/
|
||||
public function haveTokenImmediativelyBefore(int $pos, $expectedTokenType) : bool {
|
||||
public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool {
|
||||
$tokens = $this->tokens;
|
||||
$pos--;
|
||||
for (; $pos >= 0; $pos--) {
|
||||
@@ -170,7 +171,7 @@ class TokenStream
|
||||
return $pos;
|
||||
}
|
||||
|
||||
public function findRight($pos, $findTokenType) {
|
||||
public function findRight(int $pos, $findTokenType) {
|
||||
$tokens = $this->tokens;
|
||||
for ($count = \count($tokens); $pos < $count; $pos++) {
|
||||
$type = $tokens[$pos][0];
|
||||
@@ -181,6 +182,30 @@ class TokenStream
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given position range contains a certain token type.
|
||||
*
|
||||
* @param int $startPos Starting position (inclusive)
|
||||
* @param int $endPos Ending position (exclusive)
|
||||
* @param int|string $tokenType Token type to look for
|
||||
* @return bool Whether the token occurs in the given range
|
||||
*/
|
||||
public function haveTokenInRange(int $startPos, int $endPos, $tokenType) {
|
||||
$tokens = $this->tokens;
|
||||
for ($pos = $startPos; $pos < $endPos; $pos++) {
|
||||
if ($tokens[$pos][0] === $tokenType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function haveBracesInRange(int $startPos, int $endPos) {
|
||||
return $this->haveTokenInRange($startPos, $endPos, '{')
|
||||
|| $this->haveTokenInRange($startPos, $endPos, T_CURLY_OPEN)
|
||||
|| $this->haveTokenInRange($startPos, $endPos, '}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get indentation before token position.
|
||||
*
|
||||
|
||||
187
vendor/nikic/php-parser/lib/PhpParser/Lexer.php
vendored
187
vendor/nikic/php-parser/lib/PhpParser/Lexer.php
vendored
@@ -15,6 +15,7 @@ class Lexer
|
||||
|
||||
protected $tokenMap;
|
||||
protected $dropTokens;
|
||||
protected $identifierTokens;
|
||||
|
||||
private $attributeStartLineUsed;
|
||||
private $attributeEndLineUsed;
|
||||
@@ -34,13 +35,10 @@ class Lexer
|
||||
* first three. For more info see getNextToken() docs.
|
||||
*/
|
||||
public function __construct(array $options = []) {
|
||||
// map from internal tokens to PhpParser tokens
|
||||
// Create Map from internal tokens to PhpParser tokens.
|
||||
$this->defineCompatibilityTokens();
|
||||
$this->tokenMap = $this->createTokenMap();
|
||||
|
||||
// Compatibility define for PHP < 7.4
|
||||
if (!defined('T_BAD_CHARACTER')) {
|
||||
\define('T_BAD_CHARACTER', -1);
|
||||
}
|
||||
$this->identifierTokens = $this->createIdentifierTokenMap();
|
||||
|
||||
// map of tokens to drop while lexing (the map is only used for isset lookup,
|
||||
// that's why the value is simply set to 1; the value is never actually used.)
|
||||
@@ -87,9 +85,8 @@ class Lexer
|
||||
|
||||
$scream = ini_set('xdebug.scream', '0');
|
||||
|
||||
error_clear_last();
|
||||
$this->tokens = @token_get_all($code);
|
||||
$this->handleErrors($errorHandler);
|
||||
$this->postprocessTokens($errorHandler);
|
||||
|
||||
if (false !== $scream) {
|
||||
ini_set('xdebug.scream', $scream);
|
||||
@@ -131,40 +128,16 @@ class Lexer
|
||||
&& substr($token[1], -2) !== '*/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an error *may* have occurred during tokenization.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function errorMayHaveOccurred() : bool {
|
||||
if (defined('HHVM_VERSION')) {
|
||||
// In HHVM token_get_all() does not throw warnings, so we need to conservatively
|
||||
// assume that an error occurred
|
||||
return true;
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID >= 80000) {
|
||||
// PHP 8 converts the "bad character" case into a parse error, rather than treating
|
||||
// it as a lexing warning. To preserve previous behavior, we need to assume that an
|
||||
// error occurred.
|
||||
// TODO: We should handle this the same way as PHP 8: Only generate T_BAD_CHARACTER
|
||||
// token here (for older PHP versions) and leave generationg of the actual parse error
|
||||
// to the parser. This will also save the full token scan on PHP 8 here.
|
||||
return true;
|
||||
}
|
||||
|
||||
return null !== error_get_last();
|
||||
}
|
||||
|
||||
protected function handleErrors(ErrorHandler $errorHandler) {
|
||||
if (!$this->errorMayHaveOccurred()) {
|
||||
return;
|
||||
}
|
||||
|
||||
protected function postprocessTokens(ErrorHandler $errorHandler) {
|
||||
// PHP's error handling for token_get_all() is rather bad, so if we want detailed
|
||||
// error information we need to compute it ourselves. Invalid character errors are
|
||||
// detected by finding "gaps" in the token array. Unterminated comments are detected
|
||||
// by checking if a trailing comment has a "*/" at the end.
|
||||
//
|
||||
// Additionally, we canonicalize to the PHP 8 comment format here, which does not include
|
||||
// the trailing whitespace anymore.
|
||||
//
|
||||
// We also canonicalize to the PHP 8 T_NAME_* tokens.
|
||||
|
||||
$filePos = 0;
|
||||
$line = 1;
|
||||
@@ -178,6 +151,63 @@ class Lexer
|
||||
$this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler);
|
||||
}
|
||||
|
||||
if ($token[0] === \T_COMMENT && substr($token[1], 0, 2) !== '/*'
|
||||
&& preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) {
|
||||
$trailingNewline = $matches[0];
|
||||
$token[1] = substr($token[1], 0, -strlen($trailingNewline));
|
||||
$this->tokens[$i] = $token;
|
||||
if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) {
|
||||
// Move trailing newline into following T_WHITESPACE token, if it already exists.
|
||||
$this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1];
|
||||
$this->tokens[$i + 1][2]--;
|
||||
} else {
|
||||
// Otherwise, we need to create a new T_WHITESPACE token.
|
||||
array_splice($this->tokens, $i + 1, 0, [
|
||||
[\T_WHITESPACE, $trailingNewline, $line],
|
||||
]);
|
||||
$numTokens++;
|
||||
}
|
||||
}
|
||||
|
||||
// Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING
|
||||
// into a single token.
|
||||
if (\is_array($token)
|
||||
&& ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) {
|
||||
$lastWasSeparator = $token[0] === \T_NS_SEPARATOR;
|
||||
$text = $token[1];
|
||||
for ($j = $i + 1; isset($this->tokens[$j]); $j++) {
|
||||
if ($lastWasSeparator) {
|
||||
if (!isset($this->identifierTokens[$this->tokens[$j][0]])) {
|
||||
break;
|
||||
}
|
||||
$lastWasSeparator = false;
|
||||
} else {
|
||||
if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) {
|
||||
break;
|
||||
}
|
||||
$lastWasSeparator = true;
|
||||
}
|
||||
$text .= $this->tokens[$j][1];
|
||||
}
|
||||
if ($lastWasSeparator) {
|
||||
// Trailing separator is not part of the name.
|
||||
$j--;
|
||||
$text = substr($text, 0, -1);
|
||||
}
|
||||
if ($j > $i + 1) {
|
||||
if ($token[0] === \T_NS_SEPARATOR) {
|
||||
$type = \T_NAME_FULLY_QUALIFIED;
|
||||
} else if ($token[0] === \T_NAMESPACE) {
|
||||
$type = \T_NAME_RELATIVE;
|
||||
} else {
|
||||
$type = \T_NAME_QUALIFIED;
|
||||
}
|
||||
$token = [$type, $text, $line];
|
||||
array_splice($this->tokens, $i, $j - $i, [$token]);
|
||||
$numTokens -= $j - $i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
$tokenValue = \is_string($token) ? $token : $token[1];
|
||||
$tokenLen = \strlen($tokenValue);
|
||||
|
||||
@@ -373,6 +403,61 @@ class Lexer
|
||||
return substr($textAfter, strlen($matches[0]));
|
||||
}
|
||||
|
||||
private function defineCompatibilityTokens() {
|
||||
static $compatTokensDefined = false;
|
||||
if ($compatTokensDefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
$compatTokens = [
|
||||
// PHP 7.4
|
||||
'T_BAD_CHARACTER',
|
||||
'T_FN',
|
||||
'T_COALESCE_EQUAL',
|
||||
// PHP 8.0
|
||||
'T_NAME_QUALIFIED',
|
||||
'T_NAME_FULLY_QUALIFIED',
|
||||
'T_NAME_RELATIVE',
|
||||
'T_MATCH',
|
||||
'T_NULLSAFE_OBJECT_OPERATOR',
|
||||
'T_ATTRIBUTE',
|
||||
];
|
||||
|
||||
// PHP-Parser might be used together with another library that also emulates some or all
|
||||
// of these tokens. Perform a sanity-check that all already defined tokens have been
|
||||
// assigned a unique ID.
|
||||
$usedTokenIds = [];
|
||||
foreach ($compatTokens as $token) {
|
||||
if (\defined($token)) {
|
||||
$tokenId = \constant($token);
|
||||
$clashingToken = $usedTokenIds[$tokenId] ?? null;
|
||||
if ($clashingToken !== null) {
|
||||
throw new \Error(sprintf(
|
||||
'Token %s has same ID as token %s, ' .
|
||||
'you may be using a library with broken token emulation',
|
||||
$token, $clashingToken
|
||||
));
|
||||
}
|
||||
$usedTokenIds[$tokenId] = $token;
|
||||
}
|
||||
}
|
||||
|
||||
// Now define any tokens that have not yet been emulated. Try to assign IDs from -1
|
||||
// downwards, but skip any IDs that may already be in use.
|
||||
$newTokenId = -1;
|
||||
foreach ($compatTokens as $token) {
|
||||
if (!\defined($token)) {
|
||||
while (isset($usedTokenIds[$newTokenId])) {
|
||||
$newTokenId--;
|
||||
}
|
||||
\define($token, $newTokenId);
|
||||
$newTokenId--;
|
||||
}
|
||||
}
|
||||
|
||||
$compatTokensDefined = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the token map.
|
||||
*
|
||||
@@ -417,6 +502,32 @@ class Lexer
|
||||
$tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING;
|
||||
}
|
||||
|
||||
// Assign tokens for which we define compatibility constants, as token_name() does not know them.
|
||||
$tokenMap[\T_FN] = Tokens::T_FN;
|
||||
$tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL;
|
||||
$tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED;
|
||||
$tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED;
|
||||
$tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE;
|
||||
$tokenMap[\T_MATCH] = Tokens::T_MATCH;
|
||||
$tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR;
|
||||
$tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE;
|
||||
|
||||
return $tokenMap;
|
||||
}
|
||||
|
||||
private function createIdentifierTokenMap(): array {
|
||||
// Based on semi_reserved production.
|
||||
return array_fill_keys([
|
||||
\T_STRING,
|
||||
\T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC,
|
||||
\T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND,
|
||||
\T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE,
|
||||
\T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH,
|
||||
\T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO,
|
||||
\T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT,
|
||||
\T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS,
|
||||
\T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN,
|
||||
\T_MATCH,
|
||||
], true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,61 +5,85 @@ namespace PhpParser\Lexer;
|
||||
use PhpParser\Error;
|
||||
use PhpParser\ErrorHandler;
|
||||
use PhpParser\Lexer;
|
||||
use PhpParser\Lexer\TokenEmulator\AttributeEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\MatchTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\TokenEmulatorInterface;
|
||||
use PhpParser\Lexer\TokenEmulator\ReverseEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\TokenEmulator;
|
||||
use PhpParser\Parser\Tokens;
|
||||
|
||||
class Emulative extends Lexer
|
||||
{
|
||||
const PHP_7_3 = '7.3.0dev';
|
||||
const PHP_7_4 = '7.4.0dev';
|
||||
|
||||
const T_COALESCE_EQUAL = 1007;
|
||||
const T_FN = 1008;
|
||||
|
||||
const FLEXIBLE_DOC_STRING_REGEX = <<<'REGEX'
|
||||
/<<<[ \t]*(['"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\1\r?\n
|
||||
(?:.*\r?\n)*?
|
||||
(?<indentation>\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x
|
||||
REGEX;
|
||||
const PHP_7_3 = '7.3dev';
|
||||
const PHP_7_4 = '7.4dev';
|
||||
const PHP_8_0 = '8.0dev';
|
||||
|
||||
/** @var mixed[] Patches used to reverse changes introduced in the code */
|
||||
private $patches = [];
|
||||
|
||||
/** @var TokenEmulatorInterface[] */
|
||||
private $tokenEmulators = [];
|
||||
/** @var TokenEmulator[] */
|
||||
private $emulators = [];
|
||||
|
||||
/** @var string */
|
||||
private $targetPhpVersion;
|
||||
|
||||
/**
|
||||
* @param mixed[] $options
|
||||
* @param mixed[] $options Lexer options. In addition to the usual options,
|
||||
* accepts a 'phpVersion' string that specifies the
|
||||
* version to emulated. Defaults to newest supported.
|
||||
*/
|
||||
public function __construct(array $options = [])
|
||||
{
|
||||
$this->targetPhpVersion = $options['phpVersion'] ?? Emulative::PHP_8_0;
|
||||
unset($options['phpVersion']);
|
||||
|
||||
parent::__construct($options);
|
||||
|
||||
$this->tokenEmulators[] = new FnTokenEmulator();
|
||||
$this->tokenEmulators[] = new CoaleseEqualTokenEmulator();
|
||||
$this->tokenEmulators[] = new NumericLiteralSeparatorEmulator();
|
||||
$emulators = [
|
||||
new FlexibleDocStringEmulator(),
|
||||
new FnTokenEmulator(),
|
||||
new MatchTokenEmulator(),
|
||||
new CoaleseEqualTokenEmulator(),
|
||||
new NumericLiteralSeparatorEmulator(),
|
||||
new NullsafeTokenEmulator(),
|
||||
new AttributeEmulator(),
|
||||
];
|
||||
|
||||
$this->tokenMap[self::T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL;
|
||||
$this->tokenMap[self::T_FN] = Tokens::T_FN;
|
||||
// Collect emulators that are relevant for the PHP version we're running
|
||||
// and the PHP version we're targeting for emulation.
|
||||
foreach ($emulators as $emulator) {
|
||||
$emulatorPhpVersion = $emulator->getPhpVersion();
|
||||
if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) {
|
||||
$this->emulators[] = $emulator;
|
||||
} else if ($this->isReverseEmulationNeeded($emulatorPhpVersion)) {
|
||||
$this->emulators[] = new ReverseEmulator($emulator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function startLexing(string $code, ErrorHandler $errorHandler = null) {
|
||||
$this->patches = [];
|
||||
$emulators = array_filter($this->emulators, function($emulator) use($code) {
|
||||
return $emulator->isEmulationNeeded($code);
|
||||
});
|
||||
|
||||
if ($this->isEmulationNeeded($code) === false) {
|
||||
if (empty($emulators)) {
|
||||
// Nothing to emulate, yay
|
||||
parent::startLexing($code, $errorHandler);
|
||||
return;
|
||||
}
|
||||
|
||||
$collector = new ErrorHandler\Collecting();
|
||||
$this->patches = [];
|
||||
foreach ($emulators as $emulator) {
|
||||
$code = $emulator->preprocessCode($code, $this->patches);
|
||||
}
|
||||
|
||||
// 1. emulation of heredoc and nowdoc new syntax
|
||||
$preparedCode = $this->processHeredocNowdoc($code);
|
||||
parent::startLexing($preparedCode, $collector);
|
||||
$collector = new ErrorHandler\Collecting();
|
||||
parent::startLexing($code, $collector);
|
||||
$this->sortPatches();
|
||||
$this->fixupTokens();
|
||||
|
||||
$errors = $collector->getErrors();
|
||||
@@ -70,78 +94,28 @@ REGEX;
|
||||
}
|
||||
}
|
||||
|
||||
// add token emulation
|
||||
foreach ($this->tokenEmulators as $emulativeToken) {
|
||||
if ($emulativeToken->isEmulationNeeded($code)) {
|
||||
$this->tokens = $emulativeToken->emulate($code, $this->tokens);
|
||||
}
|
||||
foreach ($emulators as $emulator) {
|
||||
$this->tokens = $emulator->emulate($code, $this->tokens);
|
||||
}
|
||||
}
|
||||
|
||||
private function isHeredocNowdocEmulationNeeded(string $code): bool
|
||||
{
|
||||
// skip version where this works without emulation
|
||||
if (version_compare(\PHP_VERSION, self::PHP_7_3, '>=')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strpos($code, '<<<') !== false;
|
||||
private function isForwardEmulationNeeded(string $emulatorPhpVersion): bool {
|
||||
return version_compare(\PHP_VERSION, $emulatorPhpVersion, '<')
|
||||
&& version_compare($this->targetPhpVersion, $emulatorPhpVersion, '>=');
|
||||
}
|
||||
|
||||
private function processHeredocNowdoc(string $code): string
|
||||
{
|
||||
if ($this->isHeredocNowdocEmulationNeeded($code) === false) {
|
||||
return $code;
|
||||
}
|
||||
|
||||
if (!preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) {
|
||||
// No heredoc/nowdoc found
|
||||
return $code;
|
||||
}
|
||||
|
||||
// Keep track of how much we need to adjust string offsets due to the modifications we
|
||||
// already made
|
||||
$posDelta = 0;
|
||||
foreach ($matches as $match) {
|
||||
$indentation = $match['indentation'][0];
|
||||
$indentationStart = $match['indentation'][1];
|
||||
|
||||
$separator = $match['separator'][0];
|
||||
$separatorStart = $match['separator'][1];
|
||||
|
||||
if ($indentation === '' && $separator !== '') {
|
||||
// Ordinary heredoc/nowdoc
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($indentation !== '') {
|
||||
// Remove indentation
|
||||
$indentationLen = strlen($indentation);
|
||||
$code = substr_replace($code, '', $indentationStart + $posDelta, $indentationLen);
|
||||
$this->patches[] = [$indentationStart + $posDelta, 'add', $indentation];
|
||||
$posDelta -= $indentationLen;
|
||||
}
|
||||
|
||||
if ($separator === '') {
|
||||
// Insert newline as separator
|
||||
$code = substr_replace($code, "\n", $separatorStart + $posDelta, 0);
|
||||
$this->patches[] = [$separatorStart + $posDelta, 'remove', "\n"];
|
||||
$posDelta += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $code;
|
||||
private function isReverseEmulationNeeded(string $emulatorPhpVersion): bool {
|
||||
return version_compare(\PHP_VERSION, $emulatorPhpVersion, '>=')
|
||||
&& version_compare($this->targetPhpVersion, $emulatorPhpVersion, '<');
|
||||
}
|
||||
|
||||
private function isEmulationNeeded(string $code): bool
|
||||
private function sortPatches()
|
||||
{
|
||||
foreach ($this->tokenEmulators as $emulativeToken) {
|
||||
if ($emulativeToken->isEmulationNeeded($code)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->isHeredocNowdocEmulationNeeded($code);
|
||||
// Patches may be contributed by different emulators.
|
||||
// Make sure they are sorted by increasing patch position.
|
||||
usort($this->patches, function($p1, $p2) {
|
||||
return $p1[0] <=> $p2[0];
|
||||
});
|
||||
}
|
||||
|
||||
private function fixupTokens()
|
||||
@@ -160,7 +134,20 @@ REGEX;
|
||||
for ($i = 0, $c = \count($this->tokens); $i < $c; $i++) {
|
||||
$token = $this->tokens[$i];
|
||||
if (\is_string($token)) {
|
||||
// We assume that patches don't apply to string tokens
|
||||
if ($patchPos === $pos) {
|
||||
// Only support replacement for string tokens.
|
||||
assert($patchType === 'replace');
|
||||
$this->tokens[$i] = $patchText;
|
||||
|
||||
// Fetch the next patch
|
||||
$patchIdx++;
|
||||
if ($patchIdx >= \count($this->patches)) {
|
||||
// No more patches, we're done
|
||||
return;
|
||||
}
|
||||
list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
|
||||
}
|
||||
|
||||
$pos += \strlen($token);
|
||||
continue;
|
||||
}
|
||||
@@ -188,6 +175,11 @@ REGEX;
|
||||
$token[1], $patchText, $patchPos - $pos + $posDelta, 0
|
||||
);
|
||||
$posDelta += $patchTextLen;
|
||||
} else if ($patchType === 'replace') {
|
||||
// Replace inside the token string
|
||||
$this->tokens[$i][1] = substr_replace(
|
||||
$token[1], $patchText, $patchPos - $pos + $posDelta, $patchTextLen
|
||||
);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
@@ -234,7 +226,7 @@ REGEX;
|
||||
if ($patchType === 'add') {
|
||||
$posDelta += strlen($patchText);
|
||||
$lineDelta += substr_count($patchText, "\n");
|
||||
} else {
|
||||
} else if ($patchType === 'remove') {
|
||||
$posDelta -= strlen($patchText);
|
||||
$lineDelta -= substr_count($patchText, "\n");
|
||||
}
|
||||
|
||||
56
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php
vendored
Normal file
56
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class AttributeEmulator extends TokenEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_8_0;
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
{
|
||||
return strpos($code, '#[') !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
// We need to manually iterate and manage a count because we'll change
|
||||
// the tokens array on the way.
|
||||
$line = 1;
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
if ($tokens[$i] === '#' && isset($tokens[$i + 1]) && $tokens[$i + 1] === '[') {
|
||||
array_splice($tokens, $i, 2, [
|
||||
[\T_ATTRIBUTE, '#[', $line]
|
||||
]);
|
||||
$c--;
|
||||
continue;
|
||||
}
|
||||
if (\is_array($tokens[$i])) {
|
||||
$line += substr_count($tokens[$i][1], "\n");
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
// TODO
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function preprocessCode(string $code, array &$patches): string {
|
||||
$pos = 0;
|
||||
while (false !== $pos = strpos($code, '#[', $pos)) {
|
||||
// Replace #[ with %[
|
||||
$code[$pos] = '%';
|
||||
$patches[] = [$pos, 'replace', '#'];
|
||||
$pos += 2;
|
||||
}
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,15 @@ namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class CoaleseEqualTokenEmulator implements TokenEmulatorInterface
|
||||
final class CoaleseEqualTokenEmulator extends TokenEmulator
|
||||
{
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
// skip version where this is supported
|
||||
if (version_compare(\PHP_VERSION, Emulative::PHP_7_4, '>=')) {
|
||||
return false;
|
||||
}
|
||||
return Emulative::PHP_7_4;
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code): bool
|
||||
{
|
||||
return strpos($code, '??=') !== false;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ final class CoaleseEqualTokenEmulator implements TokenEmulatorInterface
|
||||
if (isset($tokens[$i + 1])) {
|
||||
if ($tokens[$i][0] === T_COALESCE && $tokens[$i + 1] === '=') {
|
||||
array_splice($tokens, $i, 2, [
|
||||
[Emulative::T_COALESCE_EQUAL, '??=', $line]
|
||||
[\T_COALESCE_EQUAL, '??=', $line]
|
||||
]);
|
||||
$c--;
|
||||
continue;
|
||||
@@ -38,4 +38,10 @@ final class CoaleseEqualTokenEmulator implements TokenEmulatorInterface
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
// ??= was not valid code previously, don't bother.
|
||||
return $tokens;
|
||||
}
|
||||
}
|
||||
|
||||
76
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php
vendored
Normal file
76
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class FlexibleDocStringEmulator extends TokenEmulator
|
||||
{
|
||||
const FLEXIBLE_DOC_STRING_REGEX = <<<'REGEX'
|
||||
/<<<[ \t]*(['"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\1\r?\n
|
||||
(?:.*\r?\n)*?
|
||||
(?<indentation>\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x
|
||||
REGEX;
|
||||
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_7_3;
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
{
|
||||
return strpos($code, '<<<') !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
// Handled by preprocessing + fixup.
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
// Not supported.
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function preprocessCode(string $code, array &$patches): string {
|
||||
if (!preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) {
|
||||
// No heredoc/nowdoc found
|
||||
return $code;
|
||||
}
|
||||
|
||||
// Keep track of how much we need to adjust string offsets due to the modifications we
|
||||
// already made
|
||||
$posDelta = 0;
|
||||
foreach ($matches as $match) {
|
||||
$indentation = $match['indentation'][0];
|
||||
$indentationStart = $match['indentation'][1];
|
||||
|
||||
$separator = $match['separator'][0];
|
||||
$separatorStart = $match['separator'][1];
|
||||
|
||||
if ($indentation === '' && $separator !== '') {
|
||||
// Ordinary heredoc/nowdoc
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($indentation !== '') {
|
||||
// Remove indentation
|
||||
$indentationLen = strlen($indentation);
|
||||
$code = substr_replace($code, '', $indentationStart + $posDelta, $indentationLen);
|
||||
$patches[] = [$indentationStart + $posDelta, 'add', $indentation];
|
||||
$posDelta -= $indentationLen;
|
||||
}
|
||||
|
||||
if ($separator === '') {
|
||||
// Insert newline as separator
|
||||
$code = substr_replace($code, "\n", $separatorStart + $posDelta, 0);
|
||||
$patches[] = [$separatorStart + $posDelta, 'remove', "\n"];
|
||||
$posDelta += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
@@ -4,50 +4,20 @@ namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class FnTokenEmulator implements TokenEmulatorInterface
|
||||
final class FnTokenEmulator extends KeywordEmulator
|
||||
{
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
// skip version where this is supported
|
||||
if (version_compare(\PHP_VERSION, Emulative::PHP_7_4, '>=')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strpos($code, 'fn') !== false;
|
||||
return Emulative::PHP_7_4;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
public function getKeywordString(): string
|
||||
{
|
||||
// We need to manually iterate and manage a count because we'll change
|
||||
// the tokens array on the way
|
||||
foreach ($tokens as $i => $token) {
|
||||
if ($token[0] === T_STRING && $token[1] === 'fn') {
|
||||
$previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i);
|
||||
if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === T_OBJECT_OPERATOR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens[$i][0] = Emulative::T_FN;
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
return 'fn';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $tokens
|
||||
* @return mixed[]|null
|
||||
*/
|
||||
private function getPreviousNonSpaceToken(array $tokens, int $start)
|
||||
public function getKeywordToken(): int
|
||||
{
|
||||
for ($i = $start - 1; $i >= 0; --$i) {
|
||||
if ($tokens[$i][0] === T_WHITESPACE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $tokens[$i];
|
||||
}
|
||||
|
||||
return null;
|
||||
return \T_FN;
|
||||
}
|
||||
}
|
||||
}
|
||||
60
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php
vendored
Normal file
60
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
abstract class KeywordEmulator extends TokenEmulator
|
||||
{
|
||||
abstract function getKeywordString(): string;
|
||||
abstract function getKeywordToken(): int;
|
||||
|
||||
public function isEmulationNeeded(string $code): bool
|
||||
{
|
||||
return strpos(strtolower($code), $this->getKeywordString()) !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
$keywordString = $this->getKeywordString();
|
||||
foreach ($tokens as $i => $token) {
|
||||
if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString) {
|
||||
$previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $i);
|
||||
if ($previousNonSpaceToken !== null && $previousNonSpaceToken[0] === \T_OBJECT_OPERATOR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens[$i][0] = $this->getKeywordToken();
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $tokens
|
||||
* @return mixed[]|null
|
||||
*/
|
||||
private function getPreviousNonSpaceToken(array $tokens, int $start)
|
||||
{
|
||||
for ($i = $start - 1; $i >= 0; --$i) {
|
||||
if ($tokens[$i][0] === T_WHITESPACE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $tokens[$i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
$keywordToken = $this->getKeywordToken();
|
||||
foreach ($tokens as $i => $token) {
|
||||
if ($token[0] === $keywordToken) {
|
||||
$tokens[$i][0] = \T_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
}
|
||||
23
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php
vendored
Normal file
23
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class MatchTokenEmulator extends KeywordEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_8_0;
|
||||
}
|
||||
|
||||
public function getKeywordString(): string
|
||||
{
|
||||
return 'match';
|
||||
}
|
||||
|
||||
public function getKeywordToken(): int
|
||||
{
|
||||
return \T_MATCH;
|
||||
}
|
||||
}
|
||||
67
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php
vendored
Normal file
67
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class NullsafeTokenEmulator extends TokenEmulator
|
||||
{
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_8_0;
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code): bool
|
||||
{
|
||||
return strpos($code, '?->') !== false;
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array
|
||||
{
|
||||
// We need to manually iterate and manage a count because we'll change
|
||||
// the tokens array on the way
|
||||
$line = 1;
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) {
|
||||
array_splice($tokens, $i, 2, [
|
||||
[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line]
|
||||
]);
|
||||
$c--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle ?-> inside encapsed string.
|
||||
if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1])
|
||||
&& $tokens[$i - 1][0] === \T_VARIABLE
|
||||
&& preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $tokens[$i][1], $matches)
|
||||
) {
|
||||
$replacement = [
|
||||
[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line],
|
||||
[\T_STRING, $matches[1], $line],
|
||||
];
|
||||
if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) {
|
||||
$replacement[] = [
|
||||
\T_ENCAPSED_AND_WHITESPACE,
|
||||
\substr($tokens[$i][1], \strlen($matches[0])),
|
||||
$line
|
||||
];
|
||||
}
|
||||
array_splice($tokens, $i, 1, $replacement);
|
||||
$c += \count($replacement) - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (\is_array($tokens[$i])) {
|
||||
$line += substr_count($tokens[$i][1], "\n");
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
// ?-> was not valid code previously, don't bother.
|
||||
return $tokens;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class NumericLiteralSeparatorEmulator implements TokenEmulatorInterface
|
||||
final class NumericLiteralSeparatorEmulator extends TokenEmulator
|
||||
{
|
||||
const BIN = '(?:0b[01]+(?:_[01]+)*)';
|
||||
const HEX = '(?:0x[0-9a-f]+(?:_[0-9a-f]+)*)';
|
||||
@@ -14,13 +14,13 @@ final class NumericLiteralSeparatorEmulator implements TokenEmulatorInterface
|
||||
const FLOAT = '(?:' . self::SIMPLE_FLOAT . self::EXP . '?|' . self::DEC . self::EXP . ')';
|
||||
const NUMBER = '~' . self::FLOAT . '|' . self::BIN . '|' . self::HEX . '|' . self::DEC . '~iA';
|
||||
|
||||
public function getPhpVersion(): string
|
||||
{
|
||||
return Emulative::PHP_7_4;
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
{
|
||||
// skip version where this is supported
|
||||
if (version_compare(\PHP_VERSION, Emulative::PHP_7_4, '>=')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return preg_match('~[0-9]_[0-9]~', $code)
|
||||
|| preg_match('~0x[0-9a-f]+_[0-9a-f]~i', $code);
|
||||
}
|
||||
@@ -96,4 +96,10 @@ final class NumericLiteralSeparatorEmulator implements TokenEmulatorInterface
|
||||
|
||||
return is_float($num) ? T_DNUMBER : T_LNUMBER;
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array
|
||||
{
|
||||
// Numeric separators were not legal code previously, don't bother.
|
||||
return $tokens;
|
||||
}
|
||||
}
|
||||
|
||||
36
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php
vendored
Normal file
36
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
/**
|
||||
* Reverses emulation direction of the inner emulator.
|
||||
*/
|
||||
final class ReverseEmulator extends TokenEmulator
|
||||
{
|
||||
/** @var TokenEmulator Inner emulator */
|
||||
private $emulator;
|
||||
|
||||
public function __construct(TokenEmulator $emulator) {
|
||||
$this->emulator = $emulator;
|
||||
}
|
||||
|
||||
public function getPhpVersion(): string {
|
||||
return $this->emulator->getPhpVersion();
|
||||
}
|
||||
|
||||
public function isEmulationNeeded(string $code): bool {
|
||||
return $this->emulator->isEmulationNeeded($code);
|
||||
}
|
||||
|
||||
public function emulate(string $code, array $tokens): array {
|
||||
return $this->emulator->reverseEmulate($code, $tokens);
|
||||
}
|
||||
|
||||
public function reverseEmulate(string $code, array $tokens): array {
|
||||
return $this->emulator->emulate($code, $tokens);
|
||||
}
|
||||
|
||||
public function preprocessCode(string $code, array &$patches): string {
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
25
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php
vendored
Normal file
25
vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
/** @internal */
|
||||
abstract class TokenEmulator
|
||||
{
|
||||
abstract public function getPhpVersion(): string;
|
||||
|
||||
abstract public function isEmulationNeeded(string $code): bool;
|
||||
|
||||
/**
|
||||
* @return array Modified Tokens
|
||||
*/
|
||||
abstract public function emulate(string $code, array $tokens): array;
|
||||
|
||||
/**
|
||||
* @return array Modified Tokens
|
||||
*/
|
||||
abstract public function reverseEmulate(string $code, array $tokens): array;
|
||||
|
||||
public function preprocessCode(string $code, array &$patches): string {
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
/** @internal */
|
||||
interface TokenEmulatorInterface
|
||||
{
|
||||
public function isEmulationNeeded(string $code): bool;
|
||||
|
||||
/**
|
||||
* @return array Modified Tokens
|
||||
*/
|
||||
public function emulate(string $code, array $tokens): array;
|
||||
}
|
||||
@@ -6,6 +6,8 @@ use PhpParser\NodeAbstract;
|
||||
|
||||
class Arg extends NodeAbstract
|
||||
{
|
||||
/** @var Identifier|null Parameter name (for named parameters) */
|
||||
public $name;
|
||||
/** @var Expr Value to pass */
|
||||
public $value;
|
||||
/** @var bool Whether to pass by ref */
|
||||
@@ -20,16 +22,21 @@ class Arg extends NodeAbstract
|
||||
* @param bool $byRef Whether to pass by ref
|
||||
* @param bool $unpack Whether to unpack the argument
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Identifier|null $name Parameter name (for named parameters)
|
||||
*/
|
||||
public function __construct(Expr $value, bool $byRef = false, bool $unpack = false, array $attributes = []) {
|
||||
public function __construct(
|
||||
Expr $value, bool $byRef = false, bool $unpack = false, array $attributes = [],
|
||||
Identifier $name = null
|
||||
) {
|
||||
$this->attributes = $attributes;
|
||||
$this->name = $name;
|
||||
$this->value = $value;
|
||||
$this->byRef = $byRef;
|
||||
$this->unpack = $unpack;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['value', 'byRef', 'unpack'];
|
||||
return ['name', 'value', 'byRef', 'unpack'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
34
vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php
vendored
Normal file
34
vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeAbstract;
|
||||
|
||||
class Attribute extends NodeAbstract
|
||||
{
|
||||
/** @var Name Attribute name */
|
||||
public $name;
|
||||
|
||||
/** @var Arg[] Attribute arguments */
|
||||
public $args;
|
||||
|
||||
/**
|
||||
* @param Node\Name $name Attribute name
|
||||
* @param Arg[] $args Attribute arguments
|
||||
* @param array $attributes Additional node attributes
|
||||
*/
|
||||
public function __construct(Name $name, array $args = [], array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->name = $name;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['name', 'args'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Attribute';
|
||||
}
|
||||
}
|
||||
29
vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php
vendored
Normal file
29
vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeAbstract;
|
||||
|
||||
class AttributeGroup extends NodeAbstract
|
||||
{
|
||||
/** @var Attribute[] Attributes */
|
||||
public $attrs;
|
||||
|
||||
/**
|
||||
* @param Attribute[] $attrs PHP attributes
|
||||
* @param array $attributes Additional node attributes
|
||||
*/
|
||||
public function __construct(array $attrs, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->attrs = $attrs;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['attrs'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'AttributeGroup';
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace PhpParser\Node;
|
||||
use PhpParser\NodeAbstract;
|
||||
|
||||
/**
|
||||
* @property Name $namespacedName Namespaced name (for class constants, if using NameResolver)
|
||||
* @property Name $namespacedName Namespaced name (for global constants, if using NameResolver)
|
||||
*/
|
||||
class Const_ extends NodeAbstract
|
||||
{
|
||||
|
||||
@@ -10,13 +10,13 @@ class Array_ extends Expr
|
||||
const KIND_LONG = 1; // array() syntax
|
||||
const KIND_SHORT = 2; // [] syntax
|
||||
|
||||
/** @var ArrayItem[] Items */
|
||||
/** @var (ArrayItem|null)[] Items */
|
||||
public $items;
|
||||
|
||||
/**
|
||||
* Constructs an array node.
|
||||
*
|
||||
* @param ArrayItem[] $items Items of the array
|
||||
* @param (ArrayItem|null)[] $items Items of the array
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $items = [], array $attributes = []) {
|
||||
|
||||
@@ -22,6 +22,8 @@ class ArrowFunction extends Expr implements FunctionLike
|
||||
|
||||
/** @var Expr */
|
||||
public $expr;
|
||||
/** @var Node\AttributeGroup[] */
|
||||
public $attrGroups;
|
||||
|
||||
/**
|
||||
* @param array $subNodes Array of the following optional subnodes:
|
||||
@@ -30,6 +32,7 @@ class ArrowFunction extends Expr implements FunctionLike
|
||||
* 'params' => array() : Parameters
|
||||
* 'returnType' => null : Return type
|
||||
* 'expr' => Expr : Expression body
|
||||
* 'attrGroups' => array() : PHP attribute groups
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $subNodes = [], array $attributes = []) {
|
||||
@@ -40,10 +43,11 @@ class ArrowFunction extends Expr implements FunctionLike
|
||||
$returnType = $subNodes['returnType'] ?? null;
|
||||
$this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
|
||||
$this->expr = $subNodes['expr'] ?? null;
|
||||
$this->attrGroups = $subNodes['attrGroups'] ?? [];
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['static', 'byRef', 'params', 'returnType', 'expr'];
|
||||
return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr'];
|
||||
}
|
||||
|
||||
public function returnsByRef() : bool {
|
||||
@@ -58,6 +62,10 @@ class ArrowFunction extends Expr implements FunctionLike
|
||||
return $this->returnType;
|
||||
}
|
||||
|
||||
public function getAttrGroups() : array {
|
||||
return $this->attrGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Node\Stmt\Return_[]
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,8 @@ class Closure extends Expr implements FunctionLike
|
||||
public $returnType;
|
||||
/** @var Node\Stmt[] Statements */
|
||||
public $stmts;
|
||||
/** @var Node\AttributeGroup[] PHP attribute groups */
|
||||
public $attrGroups;
|
||||
|
||||
/**
|
||||
* Constructs a lambda function node.
|
||||
@@ -31,6 +33,7 @@ class Closure extends Expr implements FunctionLike
|
||||
* 'uses' => array(): use()s
|
||||
* 'returnType' => null : Return type
|
||||
* 'stmts' => array(): Statements
|
||||
* 'attrGroups' => array(): PHP attributes groups
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $subNodes = [], array $attributes = []) {
|
||||
@@ -42,10 +45,11 @@ class Closure extends Expr implements FunctionLike
|
||||
$returnType = $subNodes['returnType'] ?? null;
|
||||
$this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
|
||||
$this->stmts = $subNodes['stmts'] ?? [];
|
||||
$this->attrGroups = $subNodes['attrGroups'] ?? [];
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['static', 'byRef', 'params', 'uses', 'returnType', 'stmts'];
|
||||
return ['attrGroups', 'static', 'byRef', 'params', 'uses', 'returnType', 'stmts'];
|
||||
}
|
||||
|
||||
public function returnsByRef() : bool {
|
||||
@@ -64,7 +68,11 @@ class Closure extends Expr implements FunctionLike
|
||||
public function getStmts() : array {
|
||||
return $this->stmts;
|
||||
}
|
||||
|
||||
|
||||
public function getAttrGroups() : array {
|
||||
return $this->attrGroups;
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_Closure';
|
||||
}
|
||||
|
||||
31
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php
vendored
Normal file
31
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node\Expr;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\MatchArm;
|
||||
|
||||
class Match_ extends Node\Expr
|
||||
{
|
||||
/** @var Node\Expr */
|
||||
public $cond;
|
||||
/** @var MatchArm[] */
|
||||
public $arms;
|
||||
|
||||
/**
|
||||
* @param MatchArm[] $arms
|
||||
*/
|
||||
public function __construct(Node\Expr $cond, array $arms = [], array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->cond = $cond;
|
||||
$this->arms = $arms;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['cond', 'arms'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_Match';
|
||||
}
|
||||
}
|
||||
40
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php
vendored
Normal file
40
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node\Expr;
|
||||
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Identifier;
|
||||
|
||||
class NullsafeMethodCall extends Expr
|
||||
{
|
||||
/** @var Expr Variable holding object */
|
||||
public $var;
|
||||
/** @var Identifier|Expr Method name */
|
||||
public $name;
|
||||
/** @var Arg[] Arguments */
|
||||
public $args;
|
||||
|
||||
/**
|
||||
* Constructs a nullsafe method call node.
|
||||
*
|
||||
* @param Expr $var Variable holding object
|
||||
* @param string|Identifier|Expr $name Method name
|
||||
* @param Arg[] $args Arguments
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, $name, array $args = [], array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['var', 'name', 'args'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_NullsafeMethodCall';
|
||||
}
|
||||
}
|
||||
35
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php
vendored
Normal file
35
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node\Expr;
|
||||
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Identifier;
|
||||
|
||||
class NullsafePropertyFetch extends Expr
|
||||
{
|
||||
/** @var Expr Variable holding object */
|
||||
public $var;
|
||||
/** @var Identifier|Expr Property name */
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* Constructs a nullsafe property fetch node.
|
||||
*
|
||||
* @param Expr $var Variable holding object
|
||||
* @param string|Identifier|Expr $name Property name
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, $name, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['var', 'name'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_NullsafePropertyFetch';
|
||||
}
|
||||
}
|
||||
30
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php
vendored
Normal file
30
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node\Expr;
|
||||
|
||||
use PhpParser\Node;
|
||||
|
||||
class Throw_ extends Node\Expr
|
||||
{
|
||||
/** @var Node\Expr Expression */
|
||||
public $expr;
|
||||
|
||||
/**
|
||||
* Constructs a throw expression node.
|
||||
*
|
||||
* @param Node\Expr $expr Expression
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Node\Expr $expr, array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['expr'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_Throw';
|
||||
}
|
||||
}
|
||||
@@ -16,21 +16,28 @@ interface FunctionLike extends Node
|
||||
/**
|
||||
* List of parameters
|
||||
*
|
||||
* @return Node\Param[]
|
||||
* @return Param[]
|
||||
*/
|
||||
public function getParams() : array;
|
||||
|
||||
/**
|
||||
* Get the declared return type or null
|
||||
*
|
||||
* @return null|Identifier|Node\Name|Node\NullableType|Node\UnionType
|
||||
* @return null|Identifier|Name|NullableType|UnionType
|
||||
*/
|
||||
public function getReturnType();
|
||||
|
||||
/**
|
||||
* The function body
|
||||
*
|
||||
* @return Node\Stmt[]|null
|
||||
* @return Stmt[]|null
|
||||
*/
|
||||
public function getStmts();
|
||||
|
||||
/**
|
||||
* Get PHP attribute groups.
|
||||
*
|
||||
* @return AttributeGroup[]
|
||||
*/
|
||||
public function getAttrGroups() : array;
|
||||
}
|
||||
|
||||
31
vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php
vendored
Normal file
31
vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeAbstract;
|
||||
|
||||
class MatchArm extends NodeAbstract
|
||||
{
|
||||
/** @var null|Node\Expr[] */
|
||||
public $conds;
|
||||
/** @var Node\Expr */
|
||||
public $body;
|
||||
|
||||
/**
|
||||
* @param null|Node\Expr[] $conds
|
||||
*/
|
||||
public function __construct($conds, Node\Expr $body, array $attributes = []) {
|
||||
$this->conds = $conds;
|
||||
$this->body = $body;
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['conds', 'body'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'MatchArm';
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class Name extends NodeAbstract
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the name itself, without taking taking the name type into
|
||||
* Returns a string representation of the name itself, without taking the name type into
|
||||
* account (e.g., not including a leading backslash for fully qualified names).
|
||||
*
|
||||
* @return string String representation
|
||||
|
||||
@@ -16,6 +16,10 @@ class Param extends NodeAbstract
|
||||
public $var;
|
||||
/** @var null|Expr Default value */
|
||||
public $default;
|
||||
/** @var int */
|
||||
public $flags;
|
||||
/** @var AttributeGroup[] PHP attribute groups */
|
||||
public $attrGroups;
|
||||
|
||||
/**
|
||||
* Constructs a parameter node.
|
||||
@@ -26,10 +30,15 @@ class Param extends NodeAbstract
|
||||
* @param bool $byRef Whether is passed by reference
|
||||
* @param bool $variadic Whether this is a variadic argument
|
||||
* @param array $attributes Additional attributes
|
||||
* @param int $flags Optional visibility flags
|
||||
* @param AttributeGroup[] $attrGroups PHP attribute groups
|
||||
*/
|
||||
public function __construct(
|
||||
$var, Expr $default = null, $type = null,
|
||||
bool $byRef = false, bool $variadic = false, array $attributes = []
|
||||
bool $byRef = false, bool $variadic = false,
|
||||
array $attributes = [],
|
||||
int $flags = 0,
|
||||
array $attrGroups = []
|
||||
) {
|
||||
$this->attributes = $attributes;
|
||||
$this->type = \is_string($type) ? new Identifier($type) : $type;
|
||||
@@ -37,10 +46,12 @@ class Param extends NodeAbstract
|
||||
$this->variadic = $variadic;
|
||||
$this->var = $var;
|
||||
$this->default = $default;
|
||||
$this->flags = $flags;
|
||||
$this->attrGroups = $attrGroups;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['type', 'byRef', 'variadic', 'var', 'default'];
|
||||
return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
@@ -9,7 +9,7 @@ class Catch_ extends Node\Stmt
|
||||
{
|
||||
/** @var Node\Name[] Types of exceptions to catch */
|
||||
public $types;
|
||||
/** @var Expr\Variable Variable for exception */
|
||||
/** @var Expr\Variable|null Variable for exception */
|
||||
public $var;
|
||||
/** @var Node\Stmt[] Statements */
|
||||
public $stmts;
|
||||
@@ -17,13 +17,13 @@ class Catch_ extends Node\Stmt
|
||||
/**
|
||||
* Constructs a catch node.
|
||||
*
|
||||
* @param Node\Name[] $types Types of exceptions to catch
|
||||
* @param Expr\Variable $var Variable for exception
|
||||
* @param Node\Stmt[] $stmts Statements
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Node\Name[] $types Types of exceptions to catch
|
||||
* @param Expr\Variable|null $var Variable for exception
|
||||
* @param Node\Stmt[] $stmts Statements
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(
|
||||
array $types, Expr\Variable $var, array $stmts = [], array $attributes = []
|
||||
array $types, Expr\Variable $var = null, array $stmts = [], array $attributes = []
|
||||
) {
|
||||
$this->attributes = $attributes;
|
||||
$this->types = $types;
|
||||
@@ -34,7 +34,7 @@ class Catch_ extends Node\Stmt
|
||||
public function getSubNodeNames() : array {
|
||||
return ['types', 'var', 'stmts'];
|
||||
}
|
||||
|
||||
|
||||
public function getType() : string {
|
||||
return 'Stmt_Catch';
|
||||
}
|
||||
|
||||
@@ -10,22 +10,31 @@ class ClassConst extends Node\Stmt
|
||||
public $flags;
|
||||
/** @var Node\Const_[] Constant declarations */
|
||||
public $consts;
|
||||
/** @var Node\AttributeGroup[] */
|
||||
public $attrGroups;
|
||||
|
||||
/**
|
||||
* Constructs a class const list node.
|
||||
*
|
||||
* @param Node\Const_[] $consts Constant declarations
|
||||
* @param int $flags Modifiers
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Node\Const_[] $consts Constant declarations
|
||||
* @param int $flags Modifiers
|
||||
* @param array $attributes Additional attributes
|
||||
* @param Node\AttributeGroup[] $attrGroups PHP attribute groups
|
||||
*/
|
||||
public function __construct(array $consts, int $flags = 0, array $attributes = []) {
|
||||
public function __construct(
|
||||
array $consts,
|
||||
int $flags = 0,
|
||||
array $attributes = [],
|
||||
array $attrGroups = []
|
||||
) {
|
||||
$this->attributes = $attributes;
|
||||
$this->flags = $flags;
|
||||
$this->consts = $consts;
|
||||
$this->attrGroups = $attrGroups;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['flags', 'consts'];
|
||||
return ['attrGroups', 'flags', 'consts'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +64,7 @@ class ClassConst extends Node\Stmt
|
||||
public function isPrivate() : bool {
|
||||
return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
|
||||
}
|
||||
|
||||
|
||||
public function getType() : string {
|
||||
return 'Stmt_ClassConst';
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ abstract class ClassLike extends Node\Stmt
|
||||
public $name;
|
||||
/** @var Node\Stmt[] Statements */
|
||||
public $stmts;
|
||||
/** @var Node\AttributeGroup[] PHP attribute groups */
|
||||
public $attrGroups;
|
||||
|
||||
/**
|
||||
* @return TraitUse[]
|
||||
|
||||
@@ -19,6 +19,8 @@ class ClassMethod extends Node\Stmt implements FunctionLike
|
||||
public $returnType;
|
||||
/** @var Node\Stmt[]|null Statements */
|
||||
public $stmts;
|
||||
/** @var Node\AttributeGroup[] PHP attribute groups */
|
||||
public $attrGroups;
|
||||
|
||||
private static $magicNames = [
|
||||
'__construct' => true,
|
||||
@@ -48,6 +50,7 @@ class ClassMethod extends Node\Stmt implements FunctionLike
|
||||
* 'params' => array() : Parameters
|
||||
* 'returnType' => null : Return type
|
||||
* 'stmts' => array() : Statements
|
||||
* 'attrGroups' => array() : PHP attribute groups
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $subNodes = [], array $attributes = []) {
|
||||
@@ -59,10 +62,11 @@ class ClassMethod extends Node\Stmt implements FunctionLike
|
||||
$returnType = $subNodes['returnType'] ?? null;
|
||||
$this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
|
||||
$this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : [];
|
||||
$this->attrGroups = $subNodes['attrGroups'] ?? [];
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['flags', 'byRef', 'name', 'params', 'returnType', 'stmts'];
|
||||
return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'returnType', 'stmts'];
|
||||
}
|
||||
|
||||
public function returnsByRef() : bool {
|
||||
@@ -81,6 +85,10 @@ class ClassMethod extends Node\Stmt implements FunctionLike
|
||||
return $this->stmts;
|
||||
}
|
||||
|
||||
public function getAttrGroups() : array {
|
||||
return $this->attrGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the method is explicitly or implicitly public.
|
||||
*
|
||||
@@ -120,7 +128,7 @@ class ClassMethod extends Node\Stmt implements FunctionLike
|
||||
|
||||
/**
|
||||
* Whether the method is final.
|
||||
*
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFinal() : bool {
|
||||
@@ -144,7 +152,7 @@ class ClassMethod extends Node\Stmt implements FunctionLike
|
||||
public function isMagic() : bool {
|
||||
return isset(self::$magicNames[$this->name->toLowerString()]);
|
||||
}
|
||||
|
||||
|
||||
public function getType() : string {
|
||||
return 'Stmt_ClassMethod';
|
||||
}
|
||||
|
||||
@@ -28,10 +28,11 @@ class Class_ extends ClassLike
|
||||
*
|
||||
* @param string|Node\Identifier|null $name Name
|
||||
* @param array $subNodes Array of the following optional subnodes:
|
||||
* 'flags' => 0 : Flags
|
||||
* 'extends' => null : Name of extended class
|
||||
* 'implements' => array(): Names of implemented interfaces
|
||||
* 'stmts' => array(): Statements
|
||||
* 'flags' => 0 : Flags
|
||||
* 'extends' => null : Name of extended class
|
||||
* 'implements' => array(): Names of implemented interfaces
|
||||
* 'stmts' => array(): Statements
|
||||
* '$attrGroups' => array(): PHP attribute groups
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $subNodes = [], array $attributes = []) {
|
||||
@@ -41,10 +42,11 @@ class Class_ extends ClassLike
|
||||
$this->extends = $subNodes['extends'] ?? null;
|
||||
$this->implements = $subNodes['implements'] ?? [];
|
||||
$this->stmts = $subNodes['stmts'] ?? [];
|
||||
$this->attrGroups = $subNodes['attrGroups'] ?? [];
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['flags', 'name', 'extends', 'implements', 'stmts'];
|
||||
return ['attrGroups', 'flags', 'name', 'extends', 'implements', 'stmts'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,8 @@ class Function_ extends Node\Stmt implements FunctionLike
|
||||
public $returnType;
|
||||
/** @var Node\Stmt[] Statements */
|
||||
public $stmts;
|
||||
/** @var Node\AttributeGroup[] PHP attribute groups */
|
||||
public $attrGroups;
|
||||
|
||||
/**
|
||||
* Constructs a function node.
|
||||
@@ -30,6 +32,7 @@ class Function_ extends Node\Stmt implements FunctionLike
|
||||
* 'params' => array(): Parameters
|
||||
* 'returnType' => null : Return type
|
||||
* 'stmts' => array(): Statements
|
||||
* 'attrGroups' => array(): PHP attribute groups
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $subNodes = [], array $attributes = []) {
|
||||
@@ -40,10 +43,11 @@ class Function_ extends Node\Stmt implements FunctionLike
|
||||
$returnType = $subNodes['returnType'] ?? null;
|
||||
$this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
|
||||
$this->stmts = $subNodes['stmts'] ?? [];
|
||||
$this->attrGroups = $subNodes['attrGroups'] ?? [];
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['byRef', 'name', 'params', 'returnType', 'stmts'];
|
||||
return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts'];
|
||||
}
|
||||
|
||||
public function returnsByRef() : bool {
|
||||
@@ -58,11 +62,15 @@ class Function_ extends Node\Stmt implements FunctionLike
|
||||
return $this->returnType;
|
||||
}
|
||||
|
||||
public function getAttrGroups() : array {
|
||||
return $this->attrGroups;
|
||||
}
|
||||
|
||||
/** @return Node\Stmt[] */
|
||||
public function getStmts() : array {
|
||||
return $this->stmts;
|
||||
}
|
||||
|
||||
|
||||
public function getType() : string {
|
||||
return 'Stmt_Function';
|
||||
}
|
||||
|
||||
@@ -14,8 +14,9 @@ class Interface_ extends ClassLike
|
||||
*
|
||||
* @param string|Node\Identifier $name Name
|
||||
* @param array $subNodes Array of the following optional subnodes:
|
||||
* 'extends' => array(): Name of extended interfaces
|
||||
* 'stmts' => array(): Statements
|
||||
* 'extends' => array(): Name of extended interfaces
|
||||
* 'stmts' => array(): Statements
|
||||
* 'attrGroups' => array(): PHP attribute groups
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $subNodes = [], array $attributes = []) {
|
||||
@@ -23,10 +24,11 @@ class Interface_ extends ClassLike
|
||||
$this->name = \is_string($name) ? new Node\Identifier($name) : $name;
|
||||
$this->extends = $subNodes['extends'] ?? [];
|
||||
$this->stmts = $subNodes['stmts'] ?? [];
|
||||
$this->attrGroups = $subNodes['attrGroups'] ?? [];
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['name', 'extends', 'stmts'];
|
||||
return ['attrGroups', 'name', 'extends', 'stmts'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
@@ -16,6 +16,8 @@ class Property extends Node\Stmt
|
||||
public $props;
|
||||
/** @var null|Identifier|Name|NullableType|UnionType Type declaration */
|
||||
public $type;
|
||||
/** @var Node\AttributeGroup[] PHP attribute groups */
|
||||
public $attrGroups;
|
||||
|
||||
/**
|
||||
* Constructs a class property list node.
|
||||
@@ -24,16 +26,18 @@ class Property extends Node\Stmt
|
||||
* @param PropertyProperty[] $props Properties
|
||||
* @param array $attributes Additional attributes
|
||||
* @param null|string|Identifier|Name|NullableType|UnionType $type Type declaration
|
||||
* @param Node\AttributeGroup[] $attrGroups PHP attribute groups
|
||||
*/
|
||||
public function __construct(int $flags, array $props, array $attributes = [], $type = null) {
|
||||
public function __construct(int $flags, array $props, array $attributes = [], $type = null, array $attrGroups = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->flags = $flags;
|
||||
$this->props = $props;
|
||||
$this->type = \is_string($type) ? new Identifier($type) : $type;
|
||||
$this->attrGroups = $attrGroups;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['flags', 'type', 'props'];
|
||||
return ['attrGroups', 'flags', 'type', 'props'];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@ class Throw_ extends Node\Stmt
|
||||
public $expr;
|
||||
|
||||
/**
|
||||
* Constructs a throw node.
|
||||
* Constructs a legacy throw statement node.
|
||||
*
|
||||
* @param Node\Expr $expr Expression
|
||||
* @param array $attributes Additional attributes
|
||||
|
||||
@@ -11,17 +11,19 @@ class Trait_ extends ClassLike
|
||||
*
|
||||
* @param string|Node\Identifier $name Name
|
||||
* @param array $subNodes Array of the following optional subnodes:
|
||||
* 'stmts' => array(): Statements
|
||||
* 'stmts' => array(): Statements
|
||||
* 'attrGroups' => array(): PHP attribute groups
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $subNodes = [], array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->name = \is_string($name) ? new Node\Identifier($name) : $name;
|
||||
$this->stmts = $subNodes['stmts'] ?? [];
|
||||
$this->attrGroups = $subNodes['attrGroups'] ?? [];
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['name', 'stmts'];
|
||||
return ['attrGroups', 'name', 'stmts'];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
|
||||
@@ -75,6 +75,7 @@ class NameResolver extends NodeVisitorAbstract
|
||||
$interface = $this->resolveClassName($interface);
|
||||
}
|
||||
|
||||
$this->resolveAttrGroups($node);
|
||||
if (null !== $node->name) {
|
||||
$this->addNamespacedName($node);
|
||||
}
|
||||
@@ -83,25 +84,32 @@ class NameResolver extends NodeVisitorAbstract
|
||||
$interface = $this->resolveClassName($interface);
|
||||
}
|
||||
|
||||
$this->resolveAttrGroups($node);
|
||||
$this->addNamespacedName($node);
|
||||
} elseif ($node instanceof Stmt\Trait_) {
|
||||
$this->resolveAttrGroups($node);
|
||||
$this->addNamespacedName($node);
|
||||
} elseif ($node instanceof Stmt\Function_) {
|
||||
$this->addNamespacedName($node);
|
||||
$this->resolveSignature($node);
|
||||
$this->resolveAttrGroups($node);
|
||||
$this->addNamespacedName($node);
|
||||
} elseif ($node instanceof Stmt\ClassMethod
|
||||
|| $node instanceof Expr\Closure
|
||||
|| $node instanceof Expr\ArrowFunction
|
||||
) {
|
||||
$this->resolveSignature($node);
|
||||
$this->resolveAttrGroups($node);
|
||||
} elseif ($node instanceof Stmt\Property) {
|
||||
if (null !== $node->type) {
|
||||
$node->type = $this->resolveType($node->type);
|
||||
}
|
||||
$this->resolveAttrGroups($node);
|
||||
} elseif ($node instanceof Stmt\Const_) {
|
||||
foreach ($node->consts as $const) {
|
||||
$this->addNamespacedName($const);
|
||||
}
|
||||
} else if ($node instanceof Stmt\ClassConst) {
|
||||
$this->resolveAttrGroups($node);
|
||||
} elseif ($node instanceof Expr\StaticCall
|
||||
|| $node instanceof Expr\StaticPropertyFetch
|
||||
|| $node instanceof Expr\ClassConstFetch
|
||||
@@ -157,6 +165,7 @@ class NameResolver extends NodeVisitorAbstract
|
||||
private function resolveSignature($node) {
|
||||
foreach ($node->params as $param) {
|
||||
$param->type = $this->resolveType($param->type);
|
||||
$this->resolveAttrGroups($param);
|
||||
}
|
||||
$node->returnType = $this->resolveType($node->returnType);
|
||||
}
|
||||
@@ -225,4 +234,13 @@ class NameResolver extends NodeVisitorAbstract
|
||||
$node->namespacedName = Name::concat(
|
||||
$this->nameContext->getNamespace(), (string) $node->name);
|
||||
}
|
||||
|
||||
protected function resolveAttrGroups(Node $node)
|
||||
{
|
||||
foreach ($node->attrGroups as $attrGroup) {
|
||||
foreach ($attrGroup->attrs as $attr) {
|
||||
$attr->name = $this->resolveClassName($attr->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
52
vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php
vendored
Normal file
52
vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\NodeVisitor;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
|
||||
/**
|
||||
* Visitor that connects a child node to its parent node
|
||||
* as well as its sibling nodes.
|
||||
*
|
||||
* On the child node, the parent node can be accessed through
|
||||
* <code>$node->getAttribute('parent')</code>, the previous
|
||||
* node can be accessed through <code>$node->getAttribute('previous')</code>,
|
||||
* and the next node can be accessed through <code>$node->getAttribute('next')</code>.
|
||||
*/
|
||||
final class NodeConnectingVisitor extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var Node[]
|
||||
*/
|
||||
private $stack = [];
|
||||
|
||||
/**
|
||||
* @var ?Node
|
||||
*/
|
||||
private $previous;
|
||||
|
||||
public function beforeTraverse(array $nodes) {
|
||||
$this->stack = [];
|
||||
$this->previous = null;
|
||||
}
|
||||
|
||||
public function enterNode(Node $node) {
|
||||
if (!empty($this->stack)) {
|
||||
$node->setAttribute('parent', $this->stack[count($this->stack) - 1]);
|
||||
}
|
||||
|
||||
if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) {
|
||||
$node->setAttribute('previous', $this->previous);
|
||||
$this->previous->setAttribute('next', $node);
|
||||
}
|
||||
|
||||
$this->stack[] = $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node) {
|
||||
$this->previous = $node;
|
||||
|
||||
array_pop($this->stack);
|
||||
}
|
||||
}
|
||||
41
vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php
vendored
Normal file
41
vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\NodeVisitor;
|
||||
|
||||
use function array_pop;
|
||||
use function count;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
|
||||
/**
|
||||
* Visitor that connects a child node to its parent node.
|
||||
*
|
||||
* On the child node, the parent node can be accessed through
|
||||
* <code>$node->getAttribute('parent')</code>.
|
||||
*/
|
||||
final class ParentConnectingVisitor extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var Node[]
|
||||
*/
|
||||
private $stack = [];
|
||||
|
||||
public function beforeTraverse(array $nodes)
|
||||
{
|
||||
$this->stack = [];
|
||||
}
|
||||
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
if (!empty($this->stack)) {
|
||||
$node->setAttribute('parent', $this->stack[count($this->stack) - 1]);
|
||||
}
|
||||
|
||||
$this->stack[] = $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
array_pop($this->stack);
|
||||
}
|
||||
}
|
||||
1645
vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php
vendored
1645
vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php
vendored
File diff suppressed because it is too large
Load Diff
3194
vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php
vendored
3194
vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php
vendored
File diff suppressed because it is too large
Load Diff
@@ -6,84 +6,84 @@ namespace PhpParser\Parser;
|
||||
final class Tokens
|
||||
{
|
||||
const YYERRTOK = 256;
|
||||
const T_INCLUDE = 257;
|
||||
const T_INCLUDE_ONCE = 258;
|
||||
const T_EVAL = 259;
|
||||
const T_REQUIRE = 260;
|
||||
const T_REQUIRE_ONCE = 261;
|
||||
const T_LOGICAL_OR = 262;
|
||||
const T_LOGICAL_XOR = 263;
|
||||
const T_LOGICAL_AND = 264;
|
||||
const T_PRINT = 265;
|
||||
const T_YIELD = 266;
|
||||
const T_DOUBLE_ARROW = 267;
|
||||
const T_YIELD_FROM = 268;
|
||||
const T_PLUS_EQUAL = 269;
|
||||
const T_MINUS_EQUAL = 270;
|
||||
const T_MUL_EQUAL = 271;
|
||||
const T_DIV_EQUAL = 272;
|
||||
const T_CONCAT_EQUAL = 273;
|
||||
const T_MOD_EQUAL = 274;
|
||||
const T_AND_EQUAL = 275;
|
||||
const T_OR_EQUAL = 276;
|
||||
const T_XOR_EQUAL = 277;
|
||||
const T_SL_EQUAL = 278;
|
||||
const T_SR_EQUAL = 279;
|
||||
const T_POW_EQUAL = 280;
|
||||
const T_COALESCE_EQUAL = 281;
|
||||
const T_COALESCE = 282;
|
||||
const T_BOOLEAN_OR = 283;
|
||||
const T_BOOLEAN_AND = 284;
|
||||
const T_IS_EQUAL = 285;
|
||||
const T_IS_NOT_EQUAL = 286;
|
||||
const T_IS_IDENTICAL = 287;
|
||||
const T_IS_NOT_IDENTICAL = 288;
|
||||
const T_SPACESHIP = 289;
|
||||
const T_IS_SMALLER_OR_EQUAL = 290;
|
||||
const T_IS_GREATER_OR_EQUAL = 291;
|
||||
const T_SL = 292;
|
||||
const T_SR = 293;
|
||||
const T_INSTANCEOF = 294;
|
||||
const T_INC = 295;
|
||||
const T_DEC = 296;
|
||||
const T_INT_CAST = 297;
|
||||
const T_DOUBLE_CAST = 298;
|
||||
const T_STRING_CAST = 299;
|
||||
const T_ARRAY_CAST = 300;
|
||||
const T_OBJECT_CAST = 301;
|
||||
const T_BOOL_CAST = 302;
|
||||
const T_UNSET_CAST = 303;
|
||||
const T_POW = 304;
|
||||
const T_NEW = 305;
|
||||
const T_CLONE = 306;
|
||||
const T_EXIT = 307;
|
||||
const T_IF = 308;
|
||||
const T_ELSEIF = 309;
|
||||
const T_ELSE = 310;
|
||||
const T_ENDIF = 311;
|
||||
const T_LNUMBER = 312;
|
||||
const T_DNUMBER = 313;
|
||||
const T_STRING = 314;
|
||||
const T_STRING_VARNAME = 315;
|
||||
const T_VARIABLE = 316;
|
||||
const T_NUM_STRING = 317;
|
||||
const T_INLINE_HTML = 318;
|
||||
const T_CHARACTER = 319;
|
||||
const T_BAD_CHARACTER = 320;
|
||||
const T_ENCAPSED_AND_WHITESPACE = 321;
|
||||
const T_CONSTANT_ENCAPSED_STRING = 322;
|
||||
const T_ECHO = 323;
|
||||
const T_DO = 324;
|
||||
const T_WHILE = 325;
|
||||
const T_ENDWHILE = 326;
|
||||
const T_FOR = 327;
|
||||
const T_ENDFOR = 328;
|
||||
const T_FOREACH = 329;
|
||||
const T_ENDFOREACH = 330;
|
||||
const T_DECLARE = 331;
|
||||
const T_ENDDECLARE = 332;
|
||||
const T_AS = 333;
|
||||
const T_SWITCH = 334;
|
||||
const T_THROW = 257;
|
||||
const T_INCLUDE = 258;
|
||||
const T_INCLUDE_ONCE = 259;
|
||||
const T_EVAL = 260;
|
||||
const T_REQUIRE = 261;
|
||||
const T_REQUIRE_ONCE = 262;
|
||||
const T_LOGICAL_OR = 263;
|
||||
const T_LOGICAL_XOR = 264;
|
||||
const T_LOGICAL_AND = 265;
|
||||
const T_PRINT = 266;
|
||||
const T_YIELD = 267;
|
||||
const T_DOUBLE_ARROW = 268;
|
||||
const T_YIELD_FROM = 269;
|
||||
const T_PLUS_EQUAL = 270;
|
||||
const T_MINUS_EQUAL = 271;
|
||||
const T_MUL_EQUAL = 272;
|
||||
const T_DIV_EQUAL = 273;
|
||||
const T_CONCAT_EQUAL = 274;
|
||||
const T_MOD_EQUAL = 275;
|
||||
const T_AND_EQUAL = 276;
|
||||
const T_OR_EQUAL = 277;
|
||||
const T_XOR_EQUAL = 278;
|
||||
const T_SL_EQUAL = 279;
|
||||
const T_SR_EQUAL = 280;
|
||||
const T_POW_EQUAL = 281;
|
||||
const T_COALESCE_EQUAL = 282;
|
||||
const T_COALESCE = 283;
|
||||
const T_BOOLEAN_OR = 284;
|
||||
const T_BOOLEAN_AND = 285;
|
||||
const T_IS_EQUAL = 286;
|
||||
const T_IS_NOT_EQUAL = 287;
|
||||
const T_IS_IDENTICAL = 288;
|
||||
const T_IS_NOT_IDENTICAL = 289;
|
||||
const T_SPACESHIP = 290;
|
||||
const T_IS_SMALLER_OR_EQUAL = 291;
|
||||
const T_IS_GREATER_OR_EQUAL = 292;
|
||||
const T_SL = 293;
|
||||
const T_SR = 294;
|
||||
const T_INSTANCEOF = 295;
|
||||
const T_INC = 296;
|
||||
const T_DEC = 297;
|
||||
const T_INT_CAST = 298;
|
||||
const T_DOUBLE_CAST = 299;
|
||||
const T_STRING_CAST = 300;
|
||||
const T_ARRAY_CAST = 301;
|
||||
const T_OBJECT_CAST = 302;
|
||||
const T_BOOL_CAST = 303;
|
||||
const T_UNSET_CAST = 304;
|
||||
const T_POW = 305;
|
||||
const T_NEW = 306;
|
||||
const T_CLONE = 307;
|
||||
const T_EXIT = 308;
|
||||
const T_IF = 309;
|
||||
const T_ELSEIF = 310;
|
||||
const T_ELSE = 311;
|
||||
const T_ENDIF = 312;
|
||||
const T_LNUMBER = 313;
|
||||
const T_DNUMBER = 314;
|
||||
const T_STRING = 315;
|
||||
const T_STRING_VARNAME = 316;
|
||||
const T_VARIABLE = 317;
|
||||
const T_NUM_STRING = 318;
|
||||
const T_INLINE_HTML = 319;
|
||||
const T_ENCAPSED_AND_WHITESPACE = 320;
|
||||
const T_CONSTANT_ENCAPSED_STRING = 321;
|
||||
const T_ECHO = 322;
|
||||
const T_DO = 323;
|
||||
const T_WHILE = 324;
|
||||
const T_ENDWHILE = 325;
|
||||
const T_FOR = 326;
|
||||
const T_ENDFOR = 327;
|
||||
const T_FOREACH = 328;
|
||||
const T_ENDFOREACH = 329;
|
||||
const T_DECLARE = 330;
|
||||
const T_ENDDECLARE = 331;
|
||||
const T_AS = 332;
|
||||
const T_SWITCH = 333;
|
||||
const T_MATCH = 334;
|
||||
const T_ENDSWITCH = 335;
|
||||
const T_CASE = 336;
|
||||
const T_DEFAULT = 337;
|
||||
@@ -97,27 +97,27 @@ final class Tokens
|
||||
const T_TRY = 345;
|
||||
const T_CATCH = 346;
|
||||
const T_FINALLY = 347;
|
||||
const T_THROW = 348;
|
||||
const T_USE = 349;
|
||||
const T_INSTEADOF = 350;
|
||||
const T_GLOBAL = 351;
|
||||
const T_STATIC = 352;
|
||||
const T_ABSTRACT = 353;
|
||||
const T_FINAL = 354;
|
||||
const T_PRIVATE = 355;
|
||||
const T_PROTECTED = 356;
|
||||
const T_PUBLIC = 357;
|
||||
const T_VAR = 358;
|
||||
const T_UNSET = 359;
|
||||
const T_ISSET = 360;
|
||||
const T_EMPTY = 361;
|
||||
const T_HALT_COMPILER = 362;
|
||||
const T_CLASS = 363;
|
||||
const T_TRAIT = 364;
|
||||
const T_INTERFACE = 365;
|
||||
const T_EXTENDS = 366;
|
||||
const T_IMPLEMENTS = 367;
|
||||
const T_OBJECT_OPERATOR = 368;
|
||||
const T_USE = 348;
|
||||
const T_INSTEADOF = 349;
|
||||
const T_GLOBAL = 350;
|
||||
const T_STATIC = 351;
|
||||
const T_ABSTRACT = 352;
|
||||
const T_FINAL = 353;
|
||||
const T_PRIVATE = 354;
|
||||
const T_PROTECTED = 355;
|
||||
const T_PUBLIC = 356;
|
||||
const T_VAR = 357;
|
||||
const T_UNSET = 358;
|
||||
const T_ISSET = 359;
|
||||
const T_EMPTY = 360;
|
||||
const T_HALT_COMPILER = 361;
|
||||
const T_CLASS = 362;
|
||||
const T_TRAIT = 363;
|
||||
const T_INTERFACE = 364;
|
||||
const T_EXTENDS = 365;
|
||||
const T_IMPLEMENTS = 366;
|
||||
const T_OBJECT_OPERATOR = 367;
|
||||
const T_NULLSAFE_OBJECT_OPERATOR = 368;
|
||||
const T_LIST = 369;
|
||||
const T_ARRAY = 370;
|
||||
const T_CALLABLE = 371;
|
||||
@@ -127,20 +127,18 @@ final class Tokens
|
||||
const T_FUNC_C = 375;
|
||||
const T_LINE = 376;
|
||||
const T_FILE = 377;
|
||||
const T_COMMENT = 378;
|
||||
const T_DOC_COMMENT = 379;
|
||||
const T_OPEN_TAG = 380;
|
||||
const T_OPEN_TAG_WITH_ECHO = 381;
|
||||
const T_CLOSE_TAG = 382;
|
||||
const T_WHITESPACE = 383;
|
||||
const T_START_HEREDOC = 384;
|
||||
const T_END_HEREDOC = 385;
|
||||
const T_DOLLAR_OPEN_CURLY_BRACES = 386;
|
||||
const T_CURLY_OPEN = 387;
|
||||
const T_PAAMAYIM_NEKUDOTAYIM = 388;
|
||||
const T_NAMESPACE = 389;
|
||||
const T_NS_C = 390;
|
||||
const T_DIR = 391;
|
||||
const T_NS_SEPARATOR = 392;
|
||||
const T_ELLIPSIS = 393;
|
||||
const T_START_HEREDOC = 378;
|
||||
const T_END_HEREDOC = 379;
|
||||
const T_DOLLAR_OPEN_CURLY_BRACES = 380;
|
||||
const T_CURLY_OPEN = 381;
|
||||
const T_PAAMAYIM_NEKUDOTAYIM = 382;
|
||||
const T_NAMESPACE = 383;
|
||||
const T_NS_C = 384;
|
||||
const T_DIR = 385;
|
||||
const T_NS_SEPARATOR = 386;
|
||||
const T_ELLIPSIS = 387;
|
||||
const T_NAME_FULLY_QUALIFIED = 388;
|
||||
const T_NAME_QUALIFIED = 389;
|
||||
const T_NAME_RELATIVE = 390;
|
||||
const T_ATTRIBUTE = 391;
|
||||
}
|
||||
|
||||
@@ -648,7 +648,7 @@ abstract class ParserAbstract implements Parser
|
||||
}
|
||||
|
||||
protected function handleBuiltinTypes(Name $name) {
|
||||
$scalarTypes = [
|
||||
$builtinTypes = [
|
||||
'bool' => true,
|
||||
'int' => true,
|
||||
'float' => true,
|
||||
@@ -658,6 +658,7 @@ abstract class ParserAbstract implements Parser
|
||||
'object' => true,
|
||||
'null' => true,
|
||||
'false' => true,
|
||||
'mixed' => true,
|
||||
];
|
||||
|
||||
if (!$name->isUnqualified()) {
|
||||
@@ -665,7 +666,7 @@ abstract class ParserAbstract implements Parser
|
||||
}
|
||||
|
||||
$lowerName = $name->toLowerString();
|
||||
if (!isset($scalarTypes[$lowerName])) {
|
||||
if (!isset($builtinTypes[$lowerName])) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
@@ -897,13 +898,6 @@ abstract class ParserAbstract implements Parser
|
||||
}
|
||||
|
||||
protected function checkNamespace(Namespace_ $node) {
|
||||
if ($node->name && $node->name->isSpecialClassName()) {
|
||||
$this->emitError(new Error(
|
||||
sprintf('Cannot use \'%s\' as namespace name', $node->name),
|
||||
$node->name->getAttributes()
|
||||
));
|
||||
}
|
||||
|
||||
if (null !== $node->stmts) {
|
||||
foreach ($node->stmts as $stmt) {
|
||||
if ($stmt instanceof Namespace_) {
|
||||
|
||||
@@ -18,7 +18,9 @@ class Standard extends PrettyPrinterAbstract
|
||||
// Special nodes
|
||||
|
||||
protected function pParam(Node\Param $node) {
|
||||
return ($node->type ? $this->p($node->type) . ' ' : '')
|
||||
return $this->pAttrGroups($node->attrGroups, true)
|
||||
. $this->pModifiers($node->flags)
|
||||
. ($node->type ? $this->p($node->type) . ' ' : '')
|
||||
. ($node->byRef ? '&' : '')
|
||||
. ($node->variadic ? '...' : '')
|
||||
. $this->p($node->var)
|
||||
@@ -26,7 +28,9 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pArg(Node\Arg $node) {
|
||||
return ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value);
|
||||
return ($node->name ? $node->name->toString() . ': ' : '')
|
||||
. ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '')
|
||||
. $this->p($node->value);
|
||||
}
|
||||
|
||||
protected function pConst(Node\Const_ $node) {
|
||||
@@ -49,6 +53,15 @@ class Standard extends PrettyPrinterAbstract
|
||||
return '$' . $node->name;
|
||||
}
|
||||
|
||||
protected function pAttribute(Node\Attribute $node) {
|
||||
return $this->p($node->name)
|
||||
. ($node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : '');
|
||||
}
|
||||
|
||||
protected function pAttributeGroup(Node\AttributeGroup $node) {
|
||||
return '#[' . $this->pCommaSeparated($node->attrs) . ']';
|
||||
}
|
||||
|
||||
// Names
|
||||
|
||||
protected function pName(Name $node) {
|
||||
@@ -384,7 +397,10 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pExpr_Instanceof(Expr\Instanceof_ $node) {
|
||||
return $this->pInfixOp(Expr\Instanceof_::class, $node->expr, ' instanceof ', $node->class);
|
||||
list($precedence, $associativity) = $this->precedenceMap[Expr\Instanceof_::class];
|
||||
return $this->pPrec($node->expr, $precedence, $associativity, -1)
|
||||
. ' instanceof '
|
||||
. $this->pNewVariable($node->class);
|
||||
}
|
||||
|
||||
// Unary expressions
|
||||
@@ -491,6 +507,11 @@ class Standard extends PrettyPrinterAbstract
|
||||
. '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
}
|
||||
|
||||
protected function pExpr_NullsafeMethodCall(Expr\NullsafeMethodCall $node) {
|
||||
return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name)
|
||||
. '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
}
|
||||
|
||||
protected function pExpr_StaticCall(Expr\StaticCall $node) {
|
||||
return $this->pDereferenceLhs($node->class) . '::'
|
||||
. ($node->name instanceof Expr
|
||||
@@ -569,13 +590,17 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) {
|
||||
return $this->p($node->class) . '::' . $this->p($node->name);
|
||||
return $this->pDereferenceLhs($node->class) . '::' . $this->p($node->name);
|
||||
}
|
||||
|
||||
protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) {
|
||||
return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name);
|
||||
}
|
||||
|
||||
protected function pExpr_NullsafePropertyFetch(Expr\NullsafePropertyFetch $node) {
|
||||
return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name);
|
||||
}
|
||||
|
||||
protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) {
|
||||
return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name);
|
||||
}
|
||||
@@ -585,7 +610,8 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pExpr_Closure(Expr\Closure $node) {
|
||||
return ($node->static ? 'static ' : '')
|
||||
return $this->pAttrGroups($node->attrGroups, true)
|
||||
. ($node->static ? 'static ' : '')
|
||||
. 'function ' . ($node->byRef ? '&' : '')
|
||||
. '(' . $this->pCommaSeparated($node->params) . ')'
|
||||
. (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')' : '')
|
||||
@@ -593,8 +619,21 @@ class Standard extends PrettyPrinterAbstract
|
||||
. ' {' . $this->pStmts($node->stmts) . $this->nl . '}';
|
||||
}
|
||||
|
||||
protected function pExpr_Match(Expr\Match_ $node) {
|
||||
return 'match (' . $this->p($node->cond) . ') {'
|
||||
. $this->pCommaSeparatedMultiline($node->arms, true)
|
||||
. $this->nl
|
||||
. '}';
|
||||
}
|
||||
|
||||
protected function pMatchArm(Node\MatchArm $node) {
|
||||
return ($node->conds ? $this->pCommaSeparated($node->conds) : 'default')
|
||||
. ' => ' . $this->p($node->body);
|
||||
}
|
||||
|
||||
protected function pExpr_ArrowFunction(Expr\ArrowFunction $node) {
|
||||
return ($node->static ? 'static ' : '')
|
||||
return $this->pAttrGroups($node->attrGroups, true)
|
||||
. ($node->static ? 'static ' : '')
|
||||
. 'fn' . ($node->byRef ? '&' : '')
|
||||
. '(' . $this->pCommaSeparated($node->params) . ')'
|
||||
. (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '')
|
||||
@@ -611,7 +650,8 @@ class Standard extends PrettyPrinterAbstract
|
||||
$args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : '';
|
||||
return 'new ' . $this->pClassCommon($node->class, $args);
|
||||
}
|
||||
return 'new ' . $this->p($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
return 'new ' . $this->pNewVariable($node->class)
|
||||
. '(' . $this->pMaybeMultiline($node->args) . ')';
|
||||
}
|
||||
|
||||
protected function pExpr_Clone(Expr\Clone_ $node) {
|
||||
@@ -632,6 +672,10 @@ class Standard extends PrettyPrinterAbstract
|
||||
. (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : '');
|
||||
}
|
||||
|
||||
protected function pExpr_Throw(Expr\Throw_ $node) {
|
||||
return 'throw ' . $this->p($node->expr);
|
||||
}
|
||||
|
||||
protected function pExpr_Yield(Expr\Yield_ $node) {
|
||||
if ($node->value === null) {
|
||||
return 'yield';
|
||||
@@ -677,7 +721,8 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pStmt_Interface(Stmt\Interface_ $node) {
|
||||
return 'interface ' . $node->name
|
||||
return $this->pAttrGroups($node->attrGroups)
|
||||
. 'interface ' . $node->name
|
||||
. (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '')
|
||||
. $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
|
||||
}
|
||||
@@ -687,7 +732,8 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pStmt_Trait(Stmt\Trait_ $node) {
|
||||
return 'trait ' . $node->name
|
||||
return $this->pAttrGroups($node->attrGroups)
|
||||
. 'trait ' . $node->name
|
||||
. $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
|
||||
}
|
||||
|
||||
@@ -712,7 +758,8 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pStmt_Property(Stmt\Property $node) {
|
||||
return (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags))
|
||||
return $this->pAttrGroups($node->attrGroups)
|
||||
. (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags))
|
||||
. ($node->type ? $this->p($node->type) . ' ' : '')
|
||||
. $this->pCommaSeparated($node->props) . ';';
|
||||
}
|
||||
@@ -723,9 +770,10 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pStmt_ClassMethod(Stmt\ClassMethod $node) {
|
||||
return $this->pModifiers($node->flags)
|
||||
return $this->pAttrGroups($node->attrGroups)
|
||||
. $this->pModifiers($node->flags)
|
||||
. 'function ' . ($node->byRef ? '&' : '') . $node->name
|
||||
. '(' . $this->pCommaSeparated($node->params) . ')'
|
||||
. '(' . $this->pMaybeMultiline($node->params) . ')'
|
||||
. (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '')
|
||||
. (null !== $node->stmts
|
||||
? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'
|
||||
@@ -733,12 +781,14 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pStmt_ClassConst(Stmt\ClassConst $node) {
|
||||
return $this->pModifiers($node->flags)
|
||||
return $this->pAttrGroups($node->attrGroups)
|
||||
. $this->pModifiers($node->flags)
|
||||
. 'const ' . $this->pCommaSeparated($node->consts) . ';';
|
||||
}
|
||||
|
||||
protected function pStmt_Function(Stmt\Function_ $node) {
|
||||
return 'function ' . ($node->byRef ? '&' : '') . $node->name
|
||||
return $this->pAttrGroups($node->attrGroups)
|
||||
. 'function ' . ($node->byRef ? '&' : '') . $node->name
|
||||
. '(' . $this->pCommaSeparated($node->params) . ')'
|
||||
. (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '')
|
||||
. $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
|
||||
@@ -817,8 +867,8 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
|
||||
protected function pStmt_Catch(Stmt\Catch_ $node) {
|
||||
return 'catch (' . $this->pImplode($node->types, '|') . ' '
|
||||
. $this->p($node->var)
|
||||
return 'catch (' . $this->pImplode($node->types, '|')
|
||||
. ($node->var !== null ? ' ' . $this->p($node->var) : '')
|
||||
. ') {' . $this->pStmts($node->stmts) . $this->nl . '}';
|
||||
}
|
||||
|
||||
@@ -893,11 +943,12 @@ class Standard extends PrettyPrinterAbstract
|
||||
// Helpers
|
||||
|
||||
protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) {
|
||||
return $this->pModifiers($node->flags)
|
||||
. 'class' . $afterClassToken
|
||||
. (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '')
|
||||
. (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '')
|
||||
. $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
|
||||
return $this->pAttrGroups($node->attrGroups, $node->name === null)
|
||||
. $this->pModifiers($node->flags)
|
||||
. 'class' . $afterClassToken
|
||||
. (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '')
|
||||
. (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '')
|
||||
. $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
|
||||
}
|
||||
|
||||
protected function pObjectProperty($node) {
|
||||
@@ -980,11 +1031,16 @@ class Standard extends PrettyPrinterAbstract
|
||||
}
|
||||
}
|
||||
|
||||
protected function pNewVariable(Node $node) {
|
||||
// TODO: This is not fully accurate.
|
||||
return $this->pDereferenceLhs($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
* @return bool
|
||||
*/
|
||||
private function hasNodeWithComments(array $nodes) {
|
||||
protected function hasNodeWithComments(array $nodes) {
|
||||
foreach ($nodes as $node) {
|
||||
if ($node && $node->getComments()) {
|
||||
return true;
|
||||
@@ -993,11 +1049,21 @@ class Standard extends PrettyPrinterAbstract
|
||||
return false;
|
||||
}
|
||||
|
||||
private function pMaybeMultiline(array $nodes, $trailingComma = false) {
|
||||
protected function pMaybeMultiline(array $nodes, bool $trailingComma = false) {
|
||||
if (!$this->hasNodeWithComments($nodes)) {
|
||||
return $this->pCommaSeparated($nodes);
|
||||
} else {
|
||||
return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl;
|
||||
}
|
||||
}
|
||||
|
||||
protected function pAttrGroups(array $nodes, bool $inline = false): string {
|
||||
$result = '';
|
||||
$sep = $inline ? ' ' : $this->nl;
|
||||
foreach ($nodes as $node) {
|
||||
$result .= $this->p($node) . $sep;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ abstract class PrettyPrinterAbstract
|
||||
BinaryOp\BooleanAnd::class => [120, -1],
|
||||
BinaryOp\BooleanOr::class => [130, -1],
|
||||
BinaryOp\Coalesce::class => [140, 1],
|
||||
Expr\Ternary::class => [150, -1],
|
||||
Expr\Ternary::class => [150, 0],
|
||||
// parser uses %left for assignments, but they really behave as %right
|
||||
Expr\Assign::class => [160, 1],
|
||||
Expr\AssignRef::class => [160, 1],
|
||||
@@ -704,8 +704,10 @@ abstract class PrettyPrinterAbstract
|
||||
|
||||
$mapKey = $parentNodeType . '->' . $subNodeName;
|
||||
$insertStr = $this->listInsertionMap[$mapKey] ?? null;
|
||||
$isStmtList = $subNodeName === 'stmts';
|
||||
|
||||
$beforeFirstKeepOrReplace = true;
|
||||
$skipRemovedNode = false;
|
||||
$delayedAdd = [];
|
||||
$lastElemIndentLevel = $this->indentLevel;
|
||||
|
||||
@@ -715,7 +717,7 @@ abstract class PrettyPrinterAbstract
|
||||
$insertNewline = true;
|
||||
}
|
||||
|
||||
if ($subNodeName === 'stmts' && \count($origNodes) === 1 && \count($nodes) !== 1) {
|
||||
if ($isStmtList && \count($origNodes) === 1 && \count($nodes) !== 1) {
|
||||
$startPos = $origNodes[0]->getStartTokenPos();
|
||||
$endPos = $origNodes[0]->getEndTokenPos();
|
||||
\assert($startPos >= 0 && $endPos >= 0);
|
||||
@@ -754,7 +756,7 @@ abstract class PrettyPrinterAbstract
|
||||
|
||||
$itemStartPos = $origArrItem->getStartTokenPos();
|
||||
$itemEndPos = $origArrItem->getEndTokenPos();
|
||||
\assert($itemStartPos >= 0 && $itemEndPos >= 0);
|
||||
\assert($itemStartPos >= 0 && $itemEndPos >= 0 && $itemStartPos >= $pos);
|
||||
|
||||
$origIndentLevel = $this->indentLevel;
|
||||
$lastElemIndentLevel = $this->origTokens->getIndentationBefore($itemStartPos) + $indentAdjustment;
|
||||
@@ -765,16 +767,25 @@ abstract class PrettyPrinterAbstract
|
||||
$commentStartPos = $origComments ? $origComments[0]->getStartTokenPos() : $itemStartPos;
|
||||
\assert($commentStartPos >= 0);
|
||||
|
||||
$commentsChanged = $comments !== $origComments;
|
||||
if ($commentsChanged) {
|
||||
// Remove old comments
|
||||
$itemStartPos = $commentStartPos;
|
||||
if ($commentStartPos < $pos) {
|
||||
// Comments may be assigned to multiple nodes if they start at the same position.
|
||||
// Make sure we don't try to print them multiple times.
|
||||
$commentStartPos = $itemStartPos;
|
||||
}
|
||||
|
||||
if ($skipRemovedNode) {
|
||||
if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) {
|
||||
// We'd remove the brace of a code block.
|
||||
// TODO: Preserve formatting.
|
||||
$this->setIndentLevel($origIndentLevel);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
$result .= $this->origTokens->getTokenCode(
|
||||
$pos, $commentStartPos, $indentAdjustment);
|
||||
}
|
||||
|
||||
if (!empty($delayedAdd)) {
|
||||
$result .= $this->origTokens->getTokenCode(
|
||||
$pos, $commentStartPos, $indentAdjustment);
|
||||
|
||||
/** @var Node $delayedAddNode */
|
||||
foreach ($delayedAdd as $delayedAddNode) {
|
||||
if ($insertNewline) {
|
||||
@@ -793,19 +804,20 @@ abstract class PrettyPrinterAbstract
|
||||
}
|
||||
}
|
||||
|
||||
$result .= $this->origTokens->getTokenCode(
|
||||
$commentStartPos, $itemStartPos, $indentAdjustment);
|
||||
|
||||
$delayedAdd = [];
|
||||
}
|
||||
|
||||
if ($comments !== $origComments) {
|
||||
if ($comments) {
|
||||
$result .= $this->pComments($comments) . $this->nl;
|
||||
}
|
||||
} else {
|
||||
$result .= $this->origTokens->getTokenCode(
|
||||
$pos, $itemStartPos, $indentAdjustment);
|
||||
$commentStartPos, $itemStartPos, $indentAdjustment);
|
||||
}
|
||||
|
||||
if ($commentsChanged && $comments) {
|
||||
// Add new comments
|
||||
$result .= $this->pComments($comments) . $this->nl;
|
||||
}
|
||||
// If we had to remove anything, we have done so now.
|
||||
$skipRemovedNode = false;
|
||||
} elseif ($diffType === DiffElem::TYPE_ADD) {
|
||||
if (null === $insertStr) {
|
||||
// We don't have insertion information for this list type
|
||||
@@ -839,18 +851,34 @@ abstract class PrettyPrinterAbstract
|
||||
$result .= $insertStr;
|
||||
}
|
||||
} elseif ($diffType === DiffElem::TYPE_REMOVE) {
|
||||
if ($i === 0) {
|
||||
// TODO Handle removal at the start
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$origArrItem instanceof Node) {
|
||||
// We only support removal for nodes
|
||||
return null;
|
||||
}
|
||||
|
||||
$itemStartPos = $origArrItem->getStartTokenPos();
|
||||
$itemEndPos = $origArrItem->getEndTokenPos();
|
||||
\assert($itemEndPos >= 0);
|
||||
\assert($itemStartPos >= 0 && $itemEndPos >= 0);
|
||||
|
||||
// Consider comments part of the node.
|
||||
$origComments = $origArrItem->getComments();
|
||||
if ($origComments) {
|
||||
$itemStartPos = $origComments[0]->getStartTokenPos();
|
||||
}
|
||||
|
||||
if ($i === 0) {
|
||||
// If we're removing from the start, keep the tokens before the node and drop those after it,
|
||||
// instead of the other way around.
|
||||
$result .= $this->origTokens->getTokenCode(
|
||||
$pos, $itemStartPos, $indentAdjustment);
|
||||
$skipRemovedNode = true;
|
||||
} else {
|
||||
if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) {
|
||||
// We'd remove the brace of a code block.
|
||||
// TODO: Preserve formatting.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$pos = $itemEndPos + 1;
|
||||
continue;
|
||||
@@ -869,6 +897,11 @@ abstract class PrettyPrinterAbstract
|
||||
$pos = $itemEndPos + 1;
|
||||
}
|
||||
|
||||
if ($skipRemovedNode) {
|
||||
// TODO: Support removing single node.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!empty($delayedAdd)) {
|
||||
if (!isset($this->emptyListInsertionMap[$mapKey])) {
|
||||
return null;
|
||||
@@ -999,6 +1032,7 @@ abstract class PrettyPrinterAbstract
|
||||
|| $node instanceof Expr\ArrayDimFetch
|
||||
|| $node instanceof Expr\FuncCall
|
||||
|| $node instanceof Expr\MethodCall
|
||||
|| $node instanceof Expr\NullsafeMethodCall
|
||||
|| $node instanceof Expr\StaticCall
|
||||
|| $node instanceof Expr\Array_);
|
||||
}
|
||||
@@ -1015,9 +1049,11 @@ abstract class PrettyPrinterAbstract
|
||||
|| $node instanceof Node\Name
|
||||
|| $node instanceof Expr\ArrayDimFetch
|
||||
|| $node instanceof Expr\PropertyFetch
|
||||
|| $node instanceof Expr\NullsafePropertyFetch
|
||||
|| $node instanceof Expr\StaticPropertyFetch
|
||||
|| $node instanceof Expr\FuncCall
|
||||
|| $node instanceof Expr\MethodCall
|
||||
|| $node instanceof Expr\NullsafeMethodCall
|
||||
|| $node instanceof Expr\StaticCall
|
||||
|| $node instanceof Expr\Array_
|
||||
|| $node instanceof Scalar\String_
|
||||
@@ -1124,7 +1160,7 @@ abstract class PrettyPrinterAbstract
|
||||
Expr\PostDec::class => ['var' => self::FIXUP_PREC_LEFT],
|
||||
Expr\Instanceof_::class => [
|
||||
'expr' => self::FIXUP_PREC_LEFT,
|
||||
'class' => self::FIXUP_PREC_RIGHT,
|
||||
'class' => self::FIXUP_PREC_RIGHT, // TODO: FIXUP_NEW_VARIABLE
|
||||
],
|
||||
Expr\Ternary::class => [
|
||||
'cond' => self::FIXUP_PREC_LEFT,
|
||||
@@ -1134,10 +1170,16 @@ abstract class PrettyPrinterAbstract
|
||||
Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS],
|
||||
Expr\StaticCall::class => ['class' => self::FIXUP_DEREF_LHS],
|
||||
Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS],
|
||||
Expr\ClassConstFetch::class => ['var' => self::FIXUP_DEREF_LHS],
|
||||
Expr\New_::class => ['class' => self::FIXUP_DEREF_LHS], // TODO: FIXUP_NEW_VARIABLE
|
||||
Expr\MethodCall::class => [
|
||||
'var' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_BRACED_NAME,
|
||||
],
|
||||
Expr\NullsafeMethodCall::class => [
|
||||
'var' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_BRACED_NAME,
|
||||
],
|
||||
Expr\StaticPropertyFetch::class => [
|
||||
'class' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_VAR_BRACED_NAME,
|
||||
@@ -1146,6 +1188,10 @@ abstract class PrettyPrinterAbstract
|
||||
'var' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_BRACED_NAME,
|
||||
],
|
||||
Expr\NullsafePropertyFetch::class => [
|
||||
'var' => self::FIXUP_DEREF_LHS,
|
||||
'name' => self::FIXUP_BRACED_NAME,
|
||||
],
|
||||
Scalar\Encapsed::class => [
|
||||
'parts' => self::FIXUP_ENCAPSED,
|
||||
],
|
||||
@@ -1220,6 +1266,7 @@ abstract class PrettyPrinterAbstract
|
||||
'Param->type' => $stripRight,
|
||||
'Param->default' => $stripEquals,
|
||||
'Stmt_Break->num' => $stripBoth,
|
||||
'Stmt_Catch->var' => $stripLeft,
|
||||
'Stmt_ClassMethod->returnType' => $stripColon,
|
||||
'Stmt_Class->extends' => ['left' => \T_EXTENDS],
|
||||
'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS],
|
||||
@@ -1257,6 +1304,7 @@ abstract class PrettyPrinterAbstract
|
||||
'Param->type' => [null, false, null, ' '],
|
||||
'Param->default' => [null, false, ' = ', null],
|
||||
'Stmt_Break->num' => [\T_BREAK, false, ' ', null],
|
||||
'Stmt_Catch->var' => [null, false, ' ', null],
|
||||
'Stmt_ClassMethod->returnType' => [')', false, ' : ', null],
|
||||
'Stmt_Class->extends' => [null, false, ' extends ', null],
|
||||
'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null],
|
||||
@@ -1301,6 +1349,7 @@ abstract class PrettyPrinterAbstract
|
||||
'Expr_Isset->vars' => ', ',
|
||||
'Expr_List->items' => ', ',
|
||||
'Expr_MethodCall->args' => ', ',
|
||||
'Expr_NullsafeMethodCall->args' => ', ',
|
||||
'Expr_New->args' => ', ',
|
||||
'Expr_PrintableNewAnonClass->args' => ', ',
|
||||
'Expr_StaticCall->args' => ', ',
|
||||
@@ -1318,12 +1367,15 @@ abstract class PrettyPrinterAbstract
|
||||
'Stmt_Global->vars' => ', ',
|
||||
'Stmt_GroupUse->uses' => ', ',
|
||||
'Stmt_Interface->extends' => ', ',
|
||||
'Stmt_Match->arms' => ', ',
|
||||
'Stmt_Property->props' => ', ',
|
||||
'Stmt_StaticVar->vars' => ', ',
|
||||
'Stmt_TraitUse->traits' => ', ',
|
||||
'Stmt_TraitUseAdaptation_Precedence->insteadof' => ', ',
|
||||
'Stmt_Unset->vars' => ', ',
|
||||
'Stmt_Use->uses' => ', ',
|
||||
'MatchArm->conds' => ', ',
|
||||
'AttributeGroup->attrs' => ', ',
|
||||
|
||||
// statement lists
|
||||
'Expr_Closure->stmts' => "\n",
|
||||
@@ -1344,6 +1396,17 @@ abstract class PrettyPrinterAbstract
|
||||
'Stmt_Function->stmts' => "\n",
|
||||
'Stmt_If->stmts' => "\n",
|
||||
'Stmt_Namespace->stmts' => "\n",
|
||||
'Stmt_Class->attrGroups' => "\n",
|
||||
'Stmt_Interface->attrGroups' => "\n",
|
||||
'Stmt_Trait->attrGroups' => "\n",
|
||||
'Stmt_Function->attrGroups' => "\n",
|
||||
'Stmt_ClassMethod->attrGroups' => "\n",
|
||||
'Stmt_ClassConst->attrGroups' => "\n",
|
||||
'Stmt_Property->attrGroups' => "\n",
|
||||
'Expr_PrintableNewAnonClass->attrGroups' => ' ',
|
||||
'Expr_Closure->attrGroups' => ' ',
|
||||
'Expr_ArrowFunction->attrGroups' => ' ',
|
||||
'Param->attrGroups' => ' ',
|
||||
'Stmt_Switch->cases' => "\n",
|
||||
'Stmt_TraitUse->adaptations' => "\n",
|
||||
'Stmt_TryCatch->stmts' => "\n",
|
||||
@@ -1366,6 +1429,7 @@ abstract class PrettyPrinterAbstract
|
||||
'Expr_Closure->params' => ['(', '', ''],
|
||||
'Expr_FuncCall->args' => ['(', '', ''],
|
||||
'Expr_MethodCall->args' => ['(', '', ''],
|
||||
'Expr_NullsafeMethodCall->args' => ['(', '', ''],
|
||||
'Expr_New->args' => ['(', '', ''],
|
||||
'Expr_PrintableNewAnonClass->args' => ['(', '', ''],
|
||||
'Expr_PrintableNewAnonClass->implements' => [null, ' implements ', ''],
|
||||
@@ -1413,6 +1477,7 @@ abstract class PrettyPrinterAbstract
|
||||
'Stmt_ClassMethod->flags' => \T_FUNCTION,
|
||||
'Stmt_Class->flags' => \T_CLASS,
|
||||
'Stmt_Property->flags' => \T_VARIABLE,
|
||||
'Param->flags' => \T_VARIABLE,
|
||||
//'Stmt_TraitUseAdaptation_Alias->newModifier' => 0, // TODO
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user