mirror of
https://github.com/nikic/PHP-Parser.git
synced 2025-07-14 02:46:31 +02:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
e612609022 | |||
4fd36b9946 | |||
a1f72690ef | |||
2e2954ccdf | |||
3f718ee2c3 | |||
b9b45dd2bc | |||
a4b43edb03 | |||
3cf61fdd26 | |||
9484baf8f8 | |||
aad0e2896f | |||
624f71fa6f | |||
1bd73cc04c | |||
94d93f27a5 | |||
a167aa2061 | |||
993f29906b | |||
9d44edf85d | |||
aa97a9bb69 | |||
aa72c5d674 | |||
60d025a914 | |||
b2cecec6bc | |||
8012faea54 | |||
f3b19c19ef | |||
78d9985d11 | |||
57b8673ea7 |
.travis.ymlCHANGELOG.mdREADME.md
bin
composer.jsondoc
grammar
lib/PhpParser
Lexer.php
Lexer
Emulative.php
TokenEmulator
Node
Arg.phpConst_.php
Expr
ArrayDimFetch.phpArrayItem.phpArray_.phpArrowFunction.phpAssign.phpAssignOp.phpAssignRef.phpBinaryOp.phpBitwiseNot.phpBooleanNot.phpCast.phpClassConstFetch.phpClone_.phpClosure.phpClosureUse.phpConstFetch.phpEmpty_.phpError.phpErrorSuppress.phpEval_.phpExit_.phpFuncCall.phpInclude_.phpInstanceof_.phpIsset_.phpList_.phpMethodCall.phpNew_.phpPostDec.phpPostInc.phpPreDec.phpPreInc.phpPrint_.phpPropertyFetch.phpShellExec.phpStaticCall.phpStaticPropertyFetch.phpTernary.phpUnaryMinus.phpUnaryPlus.phpVariable.phpYieldFrom.phpYield_.php
Identifier.phpName.phpNullableType.phpParam.phpScalar
Stmt
Break_.phpCase_.phpCatch_.phpClassConst.phpClassMethod.phpClass_.phpConst_.phpContinue_.phpDeclareDeclare.phpDeclare_.phpDo_.phpEcho_.phpElseIf_.phpElse_.phpExpression.phpFinally_.phpFor_.phpForeach_.phpFunction_.phpGlobal_.phpGoto_.phpGroupUse.phpHaltCompiler.phpIf_.phpInlineHTML.phpInterface_.phpLabel.phpNamespace_.phpProperty.phpPropertyProperty.phpReturn_.phpStaticVar.phpStatic_.phpSwitch_.phpThrow_.phpTraitUse.php
TraitUseAdaptation
Trait_.phpTryCatch.phpUnset_.phpUseUse.phpUse_.phpWhile_.phpNodeVisitor
Parser
ParserAbstract.phpPrettyPrinter
PrettyPrinterAbstract.phptest
PhpParser
code
formatPreservation
parser
errorHandling
expr
arrayDef.testarrayDestructuring.testarraySpread.testarrow_function.testassign.testconstant_expr.test
exprStmtMode.testnopPositions.testfetchAndCall
issetAndEmpty.testlistReferences.testlistWithKeys.testuvs
scalar
stmt
prettyPrinter
test_old
@ -16,7 +16,12 @@ php:
|
||||
|
||||
install:
|
||||
- if [ $TRAVIS_PHP_VERSION = '7.0' ]; then composer require satooshi/php-coveralls '~1.0'; fi
|
||||
- composer install --prefer-dist
|
||||
- |
|
||||
if [ $TRAVIS_PHP_VERSION = 'nightly' ]; then
|
||||
composer install --prefer-dist --ignore-platform-reqs;
|
||||
else
|
||||
composer install --prefer-dist;
|
||||
fi
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
|
33
CHANGELOG.md
33
CHANGELOG.md
@ -1,8 +1,39 @@
|
||||
Version 4.2.2-dev
|
||||
Version 4.2.4-dev
|
||||
-----------------
|
||||
|
||||
Nothing yet.
|
||||
|
||||
Version 4.2.3 (2019-08-12)
|
||||
--------------------------
|
||||
|
||||
### Added
|
||||
|
||||
* [PHP 7.4] Add support for numeric literal separators. (#615)
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed resolution of return types for arrow functions. (#613)
|
||||
* Fixed compatibility with PHP 7.4.
|
||||
|
||||
Version 4.2.2 (2019-05-25)
|
||||
--------------------------
|
||||
|
||||
### Added
|
||||
|
||||
* [PHP 7.4] Add support for arrow functions using a new `Expr\ArrowFunction` node. (#602)
|
||||
* [PHP 7.4] Add support for array spreads, using a new `unpack` subnode on `ArrayItem`. (#609)
|
||||
* Added support for inserting into empty list nodes in the formatting preserving pretty printer.
|
||||
|
||||
### Changed
|
||||
|
||||
* `php-parse` will now print messages to stderr, so that stdout only contains the actual result of
|
||||
the operation (such as a JSON dump). (#605)
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed attribute assignment for zero-length nop statements, and a related assertion failure in
|
||||
the formatting-preserving pretty printer. (#589)
|
||||
|
||||
Version 4.2.1 (2019-02-16)
|
||||
--------------------------
|
||||
|
||||
|
@ -3,10 +3,10 @@ PHP Parser
|
||||
|
||||
[](https://travis-ci.org/nikic/PHP-Parser) [](https://coveralls.io/github/nikic/PHP-Parser?branch=master)
|
||||
|
||||
This is a PHP 5.2 to PHP 7.3 parser written in PHP. Its purpose is to simplify static code analysis and
|
||||
This is a PHP 5.2 to PHP 7.4 parser written in PHP. Its purpose is to simplify static code analysis and
|
||||
manipulation.
|
||||
|
||||
[**Documentation for version 4.x**][doc_master] (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 7.3).
|
||||
[**Documentation for version 4.x**][doc_master] (stable; for running on PHP >= 7.0; for parsing PHP 5.2 to PHP 7.4).
|
||||
|
||||
[Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2).
|
||||
|
||||
|
@ -45,14 +45,15 @@ $traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
|
||||
foreach ($files as $file) {
|
||||
if (strpos($file, '<?php') === 0) {
|
||||
$code = $file;
|
||||
echo "====> Code $code\n";
|
||||
fwrite(STDERR, "====> Code $code\n");
|
||||
} else {
|
||||
if (!file_exists($file)) {
|
||||
die("File $file does not exist.\n");
|
||||
fwrite(STDERR, "File $file does not exist.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$code = file_get_contents($file);
|
||||
echo "====> File $file:\n";
|
||||
fwrite(STDERR, "====> File $file:\n");
|
||||
}
|
||||
|
||||
if ($attributes['with-recovery']) {
|
||||
@ -60,7 +61,7 @@ foreach ($files as $file) {
|
||||
$stmts = $parser->parse($code, $errorHandler);
|
||||
foreach ($errorHandler->getErrors() as $error) {
|
||||
$message = formatErrorMessage($error, $code, $attributes['with-column-info']);
|
||||
echo $message . "\n";
|
||||
fwrite(STDERR, $message . "\n");
|
||||
}
|
||||
if (null === $stmts) {
|
||||
continue;
|
||||
@ -70,25 +71,26 @@ foreach ($files as $file) {
|
||||
$stmts = $parser->parse($code);
|
||||
} catch (PhpParser\Error $error) {
|
||||
$message = formatErrorMessage($error, $code, $attributes['with-column-info']);
|
||||
die($message . "\n");
|
||||
fwrite(STDERR, $message . "\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($operations as $operation) {
|
||||
if ('dump' === $operation) {
|
||||
echo "==> Node dump:\n";
|
||||
fwrite(STDERR, "==> Node dump:\n");
|
||||
echo $dumper->dump($stmts, $code), "\n";
|
||||
} elseif ('pretty-print' === $operation) {
|
||||
echo "==> Pretty print:\n";
|
||||
fwrite(STDERR, "==> Pretty print:\n");
|
||||
echo $prettyPrinter->prettyPrintFile($stmts), "\n";
|
||||
} elseif ('json-dump' === $operation) {
|
||||
echo "==> JSON dump:\n";
|
||||
fwrite(STDERR, "==> JSON dump:\n");
|
||||
echo json_encode($stmts, JSON_PRETTY_PRINT), "\n";
|
||||
} elseif ('var-dump' === $operation) {
|
||||
echo "==> var_dump():\n";
|
||||
fwrite(STDERR, "==> var_dump():\n");
|
||||
var_dump($stmts);
|
||||
} elseif ('resolve-names' === $operation) {
|
||||
echo "==> Resolved names.\n";
|
||||
fwrite(STDERR, "==> Resolved names.\n");
|
||||
$stmts = $traverser->traverse($stmts);
|
||||
}
|
||||
}
|
||||
@ -104,9 +106,9 @@ function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) {
|
||||
|
||||
function showHelp($error = '') {
|
||||
if ($error) {
|
||||
echo $error . "\n\n";
|
||||
fwrite(STDERR, $error . "\n\n");
|
||||
}
|
||||
die(<<<OUTPUT
|
||||
fwrite($error ? STDERR : STDOUT, <<<OUTPUT
|
||||
Usage: php-parse [operations] file1.php [file2.php ...]
|
||||
or: php-parse [operations] "<?php code"
|
||||
Turn PHP source code into an abstract syntax tree.
|
||||
@ -131,6 +133,7 @@ Example:
|
||||
|
||||
OUTPUT
|
||||
);
|
||||
exit($error ? 1 : 0);
|
||||
}
|
||||
|
||||
function parseArgs($args) {
|
||||
|
@ -17,7 +17,7 @@
|
||||
"ext-tokenizer": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.5 || ^7.0"
|
||||
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
@ -1,7 +1,7 @@
|
||||
Introduction
|
||||
============
|
||||
|
||||
This project is a PHP 5.2 to PHP 7.3 parser **written in PHP itself**.
|
||||
This project is a PHP 5.2 to PHP 7.4 parser **written in PHP itself**.
|
||||
|
||||
What is this for?
|
||||
-----------------
|
||||
@ -26,11 +26,11 @@ programmatic PHP code analysis are incidentally PHP developers, not C developers
|
||||
What can it parse?
|
||||
------------------
|
||||
|
||||
The parser supports parsing PHP 5.2-7.3.
|
||||
The parser supports parsing PHP 5.2-7.4.
|
||||
|
||||
As the parser is based on the tokens returned by `token_get_all` (which is only able to lex the PHP
|
||||
version it runs on), additionally a wrapper for emulating tokens from newer versions is provided.
|
||||
This allows to parse PHP 7.3 source code running on PHP 7.0, for example. This emulation is somewhat
|
||||
This allows to parse PHP 7.4 source code running on PHP 7.0, for example. This emulation is somewhat
|
||||
hacky and not perfect, but it should work well on any sane code.
|
||||
|
||||
What output does it produce?
|
||||
@ -56,7 +56,7 @@ array(
|
||||
```
|
||||
|
||||
This matches the structure of the code: An echo statement, which takes two strings as expressions,
|
||||
with the values `Hi` and `World!`.
|
||||
with the values `Hi` and `World`.
|
||||
|
||||
You can also see that the AST does not contain any whitespace information (but most comments are saved).
|
||||
So using it for formatting analysis is not possible.
|
||||
|
@ -77,7 +77,7 @@ A parser instance can be reused to parse multiple files.
|
||||
Node dumping
|
||||
------------
|
||||
|
||||
To dump the abstact syntax tree in human readable form, a `NodeDumper` can be used:
|
||||
To dump the abstract syntax tree in human readable form, a `NodeDumper` can be used:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
@ -312,7 +312,7 @@ $extendingClasses = $nodeFinder->find($stmts, function(Node $node) {
|
||||
&& $node->extends !== null;
|
||||
});
|
||||
|
||||
// Find first class occuring in the AST. Returns null if no class exists.
|
||||
// Find first class occurring in the AST. Returns null if no class exists.
|
||||
$class = $nodeFinder->findFirstInstanceOf($stmts, Node\Stmt\Class_::class);
|
||||
|
||||
// Find first class that has name $name
|
||||
|
@ -16,7 +16,7 @@ top_statement_list_ex:
|
||||
|
||||
top_statement_list:
|
||||
top_statement_list_ex
|
||||
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes);
|
||||
{ makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
|
||||
if ($nop !== null) { $1[] = $nop; } $$ = $1; }
|
||||
;
|
||||
|
||||
@ -27,7 +27,7 @@ reserved_non_modifiers:
|
||||
| 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_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
|
||||
;
|
||||
|
||||
semi_reserved:
|
||||
@ -160,7 +160,7 @@ inner_statement_list_ex:
|
||||
|
||||
inner_statement_list:
|
||||
inner_statement_list_ex
|
||||
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes);
|
||||
{ makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
|
||||
if ($nop !== null) { $1[] = $nop; } $$ = $1; }
|
||||
;
|
||||
|
||||
@ -461,7 +461,7 @@ class_statement_list_ex:
|
||||
|
||||
class_statement_list:
|
||||
class_statement_list_ex
|
||||
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes);
|
||||
{ makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
|
||||
if ($nop !== null) { $1[] = $nop; } $$ = $1; }
|
||||
;
|
||||
|
||||
@ -988,6 +988,7 @@ array_pair:
|
||||
| expr { $$ = Expr\ArrayItem[$1, null, false]; }
|
||||
| expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; }
|
||||
| '&' variable { $$ = Expr\ArrayItem[$2, null, true]; }
|
||||
| T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; }
|
||||
;
|
||||
|
||||
encaps_list:
|
||||
|
@ -16,7 +16,7 @@ top_statement_list_ex:
|
||||
|
||||
top_statement_list:
|
||||
top_statement_list_ex
|
||||
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes);
|
||||
{ makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
|
||||
if ($nop !== null) { $1[] = $nop; } $$ = $1; }
|
||||
;
|
||||
|
||||
@ -27,7 +27,7 @@ reserved_non_modifiers:
|
||||
| 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_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
|
||||
;
|
||||
|
||||
semi_reserved:
|
||||
@ -196,7 +196,7 @@ inner_statement_list_ex:
|
||||
|
||||
inner_statement_list:
|
||||
inner_statement_list_ex
|
||||
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes);
|
||||
{ makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
|
||||
if ($nop !== null) { $1[] = $nop; } $$ = $1; }
|
||||
;
|
||||
|
||||
@ -530,7 +530,7 @@ class_statement_list_ex:
|
||||
|
||||
class_statement_list:
|
||||
class_statement_list_ex
|
||||
{ makeNop($nop, $this->lookaheadStartAttributes, $this->endAttributes);
|
||||
{ makeZeroLengthNop($nop, $this->lookaheadStartAttributes);
|
||||
if ($nop !== null) { $1[] = $nop; } $$ = $1; }
|
||||
;
|
||||
|
||||
@ -729,6 +729,12 @@ expr:
|
||||
| T_YIELD expr { $$ = Expr\Yield_[$2, null]; }
|
||||
| T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; }
|
||||
| T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; }
|
||||
|
||||
| T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
|
||||
{ $$ = Expr\ArrowFunction[['static' => false, 'byRef' => $2, 'params' => $4, 'returnType' => $6, 'expr' => $8]]; }
|
||||
| T_STATIC T_FN optional_ref '(' parameter_list ')' optional_return_type T_DOUBLE_ARROW expr
|
||||
{ $$ = Expr\ArrowFunction[['static' => true, 'byRef' => $3, 'params' => $5, 'returnType' => $7, 'expr' => $9]]; }
|
||||
|
||||
| T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type
|
||||
block_or_error
|
||||
{ $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $8]]; }
|
||||
@ -977,6 +983,7 @@ array_pair:
|
||||
| expr { $$ = Expr\ArrayItem[$1, null, false]; }
|
||||
| expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; }
|
||||
| '&' variable { $$ = Expr\ArrayItem[$2, null, true]; }
|
||||
| T_ELLIPSIS expr { $$ = Expr\ArrayItem[$2, null, false, attributes(), true]; }
|
||||
| /* empty */ { $$ = null; }
|
||||
;
|
||||
|
||||
|
@ -13,9 +13,12 @@ $tmpResultFile = __DIR__ . '/tmp_parser.php';
|
||||
$resultDir = __DIR__ . '/../lib/PhpParser/Parser';
|
||||
$tokensResultsFile = $resultDir . '/Tokens.php';
|
||||
|
||||
// check for kmyacc.exe binary in this directory, otherwise fall back to global name
|
||||
$kmyacc = __DIR__ . '/kmyacc.exe';
|
||||
if (!file_exists($kmyacc)) {
|
||||
// check for kmyacc binary in this directory, otherwise fall back to global name
|
||||
if (file_exists(__DIR__ . '/kmyacc.exe')) {
|
||||
$kmyacc = __DIR__ . '/kmyacc.exe';
|
||||
} else if (file_exists(__DIR__ . '/kmyacc')) {
|
||||
$kmyacc = __DIR__ . '/kmyacc';
|
||||
} else {
|
||||
$kmyacc = 'kmyacc';
|
||||
}
|
||||
|
||||
@ -175,6 +178,15 @@ function resolveMacros($code) {
|
||||
. ' else { ' . $args[0] . ' = null; }';
|
||||
}
|
||||
|
||||
if ('makeZeroLengthNop' == $name) {
|
||||
assertArgs(2, $args, $name);
|
||||
|
||||
return '$startAttributes = ' . $args[1] . ';'
|
||||
. ' if (isset($startAttributes[\'comments\']))'
|
||||
. ' { ' . $args[0] . ' = new Stmt\Nop($this->createZeroLengthAttributes($startAttributes)); }'
|
||||
. ' else { ' . $args[0] . ' = null; }';
|
||||
}
|
||||
|
||||
if ('strKind' == $name) {
|
||||
assertArgs(1, $args, $name);
|
||||
|
||||
|
@ -64,6 +64,7 @@
|
||||
%token T_CONTINUE
|
||||
%token T_GOTO
|
||||
%token T_FUNCTION
|
||||
%token T_FN
|
||||
%token T_CONST
|
||||
%token T_RETURN
|
||||
%token T_TRY
|
||||
|
@ -16,7 +16,13 @@ class Lexer
|
||||
protected $tokenMap;
|
||||
protected $dropTokens;
|
||||
|
||||
protected $usedAttributes;
|
||||
private $attributeStartLineUsed;
|
||||
private $attributeEndLineUsed;
|
||||
private $attributeStartTokenPosUsed;
|
||||
private $attributeEndTokenPosUsed;
|
||||
private $attributeStartFilePosUsed;
|
||||
private $attributeEndFilePosUsed;
|
||||
private $attributeCommentsUsed;
|
||||
|
||||
/**
|
||||
* Creates a Lexer.
|
||||
@ -31,18 +37,28 @@ class Lexer
|
||||
// map from internal tokens to PhpParser tokens
|
||||
$this->tokenMap = $this->createTokenMap();
|
||||
|
||||
// Compatibility define for PHP < 7.4
|
||||
if (!defined('T_BAD_CHARACTER')) {
|
||||
\define('T_BAD_CHARACTER', -1);
|
||||
}
|
||||
|
||||
// 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.)
|
||||
$this->dropTokens = array_fill_keys(
|
||||
[\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT], 1
|
||||
[\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1
|
||||
);
|
||||
|
||||
// the usedAttributes member is a map of the used attribute names to a dummy
|
||||
// value (here "true")
|
||||
$options += [
|
||||
'usedAttributes' => ['comments', 'startLine', 'endLine'],
|
||||
];
|
||||
$this->usedAttributes = array_fill_keys($options['usedAttributes'], true);
|
||||
$defaultAttributes = ['comments', 'startLine', 'endLine'];
|
||||
$usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true);
|
||||
|
||||
// Create individual boolean properties to make these checks faster.
|
||||
$this->attributeStartLineUsed = isset($usedAttributes['startLine']);
|
||||
$this->attributeEndLineUsed = isset($usedAttributes['endLine']);
|
||||
$this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']);
|
||||
$this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']);
|
||||
$this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']);
|
||||
$this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']);
|
||||
$this->attributeCommentsUsed = isset($usedAttributes['comments']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,13 +97,9 @@ class Lexer
|
||||
}
|
||||
|
||||
private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) {
|
||||
$tokens = [];
|
||||
for ($i = $start; $i < $end; $i++) {
|
||||
$chr = $this->code[$i];
|
||||
if ($chr === 'b' || $chr === 'B') {
|
||||
// HHVM does not treat b" tokens correctly, so ignore these
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($chr === "\0") {
|
||||
// PHP cuts error message after null byte, so need special case
|
||||
$errorMsg = 'Unexpected null byte';
|
||||
@ -97,6 +109,7 @@ class Lexer
|
||||
);
|
||||
}
|
||||
|
||||
$tokens[] = [\T_BAD_CHARACTER, $chr, $line];
|
||||
$errorHandler->handleError(new Error($errorMsg, [
|
||||
'startLine' => $line,
|
||||
'endLine' => $line,
|
||||
@ -104,6 +117,7 @@ class Lexer
|
||||
'endFilePos' => $i,
|
||||
]));
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,16 +158,29 @@ class Lexer
|
||||
|
||||
$filePos = 0;
|
||||
$line = 1;
|
||||
foreach ($this->tokens as $token) {
|
||||
$numTokens = \count($this->tokens);
|
||||
for ($i = 0; $i < $numTokens; $i++) {
|
||||
$token = $this->tokens[$i];
|
||||
|
||||
// Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token.
|
||||
// In this case we only need to emit an error.
|
||||
if ($token[0] === \T_BAD_CHARACTER) {
|
||||
$this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler);
|
||||
}
|
||||
|
||||
$tokenValue = \is_string($token) ? $token : $token[1];
|
||||
$tokenLen = \strlen($tokenValue);
|
||||
|
||||
if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) {
|
||||
// Something is missing, must be an invalid character
|
||||
$nextFilePos = strpos($this->code, $tokenValue, $filePos);
|
||||
$this->handleInvalidCharacterRange(
|
||||
$badCharTokens = $this->handleInvalidCharacterRange(
|
||||
$filePos, $nextFilePos, $line, $errorHandler);
|
||||
$filePos = (int) $nextFilePos;
|
||||
|
||||
array_splice($this->tokens, $i, 0, $badCharTokens);
|
||||
$numTokens += \count($badCharTokens);
|
||||
$i += \count($badCharTokens);
|
||||
}
|
||||
|
||||
$filePos += $tokenLen;
|
||||
@ -176,8 +203,9 @@ class Lexer
|
||||
$this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line];
|
||||
} else {
|
||||
// Invalid characters at the end of the input
|
||||
$this->handleInvalidCharacterRange(
|
||||
$badCharTokens = $this->handleInvalidCharacterRange(
|
||||
$filePos, \strlen($this->code), $line, $errorHandler);
|
||||
$this->tokens = array_merge($this->tokens, $badCharTokens);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -230,13 +258,13 @@ class Lexer
|
||||
$token = "\0";
|
||||
}
|
||||
|
||||
if (isset($this->usedAttributes['startLine'])) {
|
||||
if ($this->attributeStartLineUsed) {
|
||||
$startAttributes['startLine'] = $this->line;
|
||||
}
|
||||
if (isset($this->usedAttributes['startTokenPos'])) {
|
||||
if ($this->attributeStartTokenPosUsed) {
|
||||
$startAttributes['startTokenPos'] = $this->pos;
|
||||
}
|
||||
if (isset($this->usedAttributes['startFilePos'])) {
|
||||
if ($this->attributeStartFilePosUsed) {
|
||||
$startAttributes['startFilePos'] = $this->filePos;
|
||||
}
|
||||
|
||||
@ -263,7 +291,7 @@ class Lexer
|
||||
$this->filePos += \strlen($value);
|
||||
} else {
|
||||
if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) {
|
||||
if (isset($this->usedAttributes['comments'])) {
|
||||
if ($this->attributeCommentsUsed) {
|
||||
$comment = \T_DOC_COMMENT === $token[0]
|
||||
? new Comment\Doc($token[1], $this->line, $this->filePos, $this->pos)
|
||||
: new Comment($token[1], $this->line, $this->filePos, $this->pos);
|
||||
@ -276,13 +304,13 @@ class Lexer
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($this->usedAttributes['endLine'])) {
|
||||
if ($this->attributeEndLineUsed) {
|
||||
$endAttributes['endLine'] = $this->line;
|
||||
}
|
||||
if (isset($this->usedAttributes['endTokenPos'])) {
|
||||
if ($this->attributeEndTokenPosUsed) {
|
||||
$endAttributes['endTokenPos'] = $this->pos;
|
||||
}
|
||||
if (isset($this->usedAttributes['endFilePos'])) {
|
||||
if ($this->attributeEndFilePosUsed) {
|
||||
$endAttributes['endFilePos'] = $this->filePos - 1;
|
||||
}
|
||||
|
||||
|
@ -4,26 +4,33 @@ namespace PhpParser\Lexer;
|
||||
|
||||
use PhpParser\Error;
|
||||
use PhpParser\ErrorHandler;
|
||||
use PhpParser\Parser;
|
||||
use PhpParser\Lexer;
|
||||
use PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator;
|
||||
use PhpParser\Lexer\TokenEmulator\TokenEmulatorInterface;
|
||||
use PhpParser\Parser\Tokens;
|
||||
|
||||
class Emulative extends \PhpParser\Lexer
|
||||
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-Z_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x
|
||||
REGEX;
|
||||
|
||||
const T_COALESCE_EQUAL = 1007;
|
||||
|
||||
/**
|
||||
* @var mixed[] Patches used to reverse changes introduced in the code
|
||||
*/
|
||||
/** @var mixed[] Patches used to reverse changes introduced in the code */
|
||||
private $patches = [];
|
||||
|
||||
/** @var TokenEmulatorInterface[] */
|
||||
private $tokenEmulators = [];
|
||||
|
||||
/**
|
||||
* @param mixed[] $options
|
||||
*/
|
||||
@ -31,8 +38,12 @@ REGEX;
|
||||
{
|
||||
parent::__construct($options);
|
||||
|
||||
// add emulated tokens here
|
||||
$this->tokenMap[self::T_COALESCE_EQUAL] = Parser\Tokens::T_COALESCE_EQUAL;
|
||||
$this->tokenEmulators[] = new FnTokenEmulator();
|
||||
$this->tokenEmulators[] = new CoaleseEqualTokenEmulator();
|
||||
$this->tokenEmulators[] = new NumericLiteralSeparatorEmulator();
|
||||
|
||||
$this->tokenMap[self::T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL;
|
||||
$this->tokenMap[self::T_FN] = Tokens::T_FN;
|
||||
}
|
||||
|
||||
public function startLexing(string $code, ErrorHandler $errorHandler = null) {
|
||||
@ -49,9 +60,6 @@ REGEX;
|
||||
// 1. emulation of heredoc and nowdoc new syntax
|
||||
$preparedCode = $this->processHeredocNowdoc($code);
|
||||
parent::startLexing($preparedCode, $collector);
|
||||
|
||||
// 2. emulation of ??= token
|
||||
$this->processCoaleseEqual($code);
|
||||
$this->fixupTokens();
|
||||
|
||||
$errors = $collector->getErrors();
|
||||
@ -61,39 +69,11 @@ REGEX;
|
||||
$errorHandler->handleError($error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isCoalesceEqualEmulationNeeded(string $code): bool
|
||||
{
|
||||
// skip version where this works without emulation
|
||||
if (version_compare(\PHP_VERSION, self::PHP_7_4, '>=')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strpos($code, '??=') !== false;
|
||||
}
|
||||
|
||||
private function processCoaleseEqual(string $code)
|
||||
{
|
||||
if ($this->isCoalesceEqualEmulationNeeded($code) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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($this->tokens); $i < $c; ++$i) {
|
||||
if (isset($this->tokens[$i + 1])) {
|
||||
if ($this->tokens[$i][0] === T_COALESCE && $this->tokens[$i + 1] === '=') {
|
||||
array_splice($this->tokens, $i, 2, [
|
||||
[self::T_COALESCE_EQUAL, '??=', $line]
|
||||
]);
|
||||
$c--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (\is_array($this->tokens[$i])) {
|
||||
$line += substr_count($this->tokens[$i][1], "\n");
|
||||
// add token emulation
|
||||
foreach ($this->tokenEmulators as $emulativeToken) {
|
||||
if ($emulativeToken->isEmulationNeeded($code)) {
|
||||
$this->tokens = $emulativeToken->emulate($code, $this->tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,15 +135,13 @@ REGEX;
|
||||
|
||||
private function isEmulationNeeded(string $code): bool
|
||||
{
|
||||
if ($this->isHeredocNowdocEmulationNeeded($code)) {
|
||||
return true;
|
||||
foreach ($this->tokenEmulators as $emulativeToken) {
|
||||
if ($emulativeToken->isEmulationNeeded($code)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isCoalesceEqualEmulationNeeded($code)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return $this->isHeredocNowdocEmulationNeeded($code);
|
||||
}
|
||||
|
||||
private function fixupTokens()
|
||||
|
@ -0,0 +1,41 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class CoaleseEqualTokenEmulator implements TokenEmulatorInterface
|
||||
{
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
{
|
||||
// skip version where this is supported
|
||||
if (version_compare(\PHP_VERSION, Emulative::PHP_7_4, '>=')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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 (isset($tokens[$i + 1])) {
|
||||
if ($tokens[$i][0] === T_COALESCE && $tokens[$i + 1] === '=') {
|
||||
array_splice($tokens, $i, 2, [
|
||||
[Emulative::T_COALESCE_EQUAL, '??=', $line]
|
||||
]);
|
||||
$c--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (\is_array($tokens[$i])) {
|
||||
$line += substr_count($tokens[$i][1], "\n");
|
||||
}
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
}
|
53
lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php
Normal file
53
lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class FnTokenEmulator implements TokenEmulatorInterface
|
||||
{
|
||||
public function isEmulationNeeded(string $code) : bool
|
||||
{
|
||||
// skip version where this is supported
|
||||
if (version_compare(\PHP_VERSION, Emulative::PHP_7_4, '>=')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strpos($code, 'fn') !== 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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Lexer\TokenEmulator;
|
||||
|
||||
use PhpParser\Lexer\Emulative;
|
||||
|
||||
final class NumericLiteralSeparatorEmulator implements TokenEmulatorInterface
|
||||
{
|
||||
const BIN = '(?:0b[01]+(?:_[01]+)*)';
|
||||
const HEX = '(?:0x[0-9a-f]+(?:_[0-9a-f]+)*)';
|
||||
const DEC = '(?:[0-9]+(?:_[0-9]+)*)';
|
||||
const SIMPLE_FLOAT = '(?:' . self::DEC . '\.' . self::DEC . '?|\.' . self::DEC . ')';
|
||||
const EXP = '(?:e[+-]?' . self::DEC . ')';
|
||||
const FLOAT = '(?:' . self::SIMPLE_FLOAT . self::EXP . '?|' . self::DEC . self::EXP . ')';
|
||||
const NUMBER = '~' . self::FLOAT . '|' . self::BIN . '|' . self::HEX . '|' . self::DEC . '~iA';
|
||||
|
||||
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-9a-f]_[0-9a-f]~i', $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
|
||||
$codeOffset = 0;
|
||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
||||
$token = $tokens[$i];
|
||||
$tokenLen = \strlen(\is_array($token) ? $token[1] : $token);
|
||||
|
||||
if ($token[0] !== T_LNUMBER && $token[0] !== T_DNUMBER) {
|
||||
$codeOffset += $tokenLen;
|
||||
continue;
|
||||
}
|
||||
|
||||
$res = preg_match(self::NUMBER, $code, $matches, 0, $codeOffset);
|
||||
assert($res, "No number at number token position");
|
||||
|
||||
$match = $matches[0];
|
||||
$matchLen = \strlen($match);
|
||||
if ($matchLen === $tokenLen) {
|
||||
// Original token already holds the full number.
|
||||
$codeOffset += $tokenLen;
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokenKind = $this->resolveIntegerOrFloatToken($match);
|
||||
$newTokens = [[$tokenKind, $match, $token[2]]];
|
||||
|
||||
$numTokens = 1;
|
||||
$len = $tokenLen;
|
||||
while ($matchLen > $len) {
|
||||
$nextToken = $tokens[$i + $numTokens];
|
||||
$nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken;
|
||||
$nextTokenLen = \strlen($nextTokenText);
|
||||
|
||||
$numTokens++;
|
||||
if ($matchLen < $len + $nextTokenLen) {
|
||||
// Split trailing characters into a partial token.
|
||||
assert(is_array($nextToken), "Partial token should be an array token");
|
||||
$partialText = substr($nextTokenText, $matchLen - $len);
|
||||
$newTokens[] = [$nextToken[0], $partialText, $nextToken[2]];
|
||||
break;
|
||||
}
|
||||
|
||||
$len += $nextTokenLen;
|
||||
}
|
||||
|
||||
array_splice($tokens, $i, $numTokens, $newTokens);
|
||||
$c -= $numTokens - \count($newTokens);
|
||||
$codeOffset += $matchLen;
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
private function resolveIntegerOrFloatToken(string $str): int
|
||||
{
|
||||
$str = str_replace('_', '', $str);
|
||||
|
||||
if (stripos($str, '0b') === 0) {
|
||||
$num = bindec($str);
|
||||
} elseif (stripos($str, '0x') === 0) {
|
||||
$num = hexdec($str);
|
||||
} elseif (stripos($str, '0') === 0 && ctype_digit($str)) {
|
||||
$num = octdec($str);
|
||||
} else {
|
||||
$num = +$str;
|
||||
}
|
||||
|
||||
return is_float($num) ? T_DNUMBER : T_LNUMBER;
|
||||
}
|
||||
}
|
14
lib/PhpParser/Lexer/TokenEmulator/TokenEmulatorInterface.php
Normal file
14
lib/PhpParser/Lexer/TokenEmulator/TokenEmulatorInterface.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?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;
|
||||
}
|
@ -22,7 +22,7 @@ class Arg extends NodeAbstract
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $value, bool $byRef = false, bool $unpack = false, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->value = $value;
|
||||
$this->byRef = $byRef;
|
||||
$this->unpack = $unpack;
|
||||
|
@ -22,7 +22,7 @@ class Const_ extends NodeAbstract
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, Expr $value, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class ArrayDimFetch extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, Expr $dim = null, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->dim = $dim;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ class ArrayItem extends Expr
|
||||
public $value;
|
||||
/** @var bool Whether to assign by reference */
|
||||
public $byRef;
|
||||
/** @var bool Whether to unpack the argument */
|
||||
public $unpack;
|
||||
|
||||
/**
|
||||
* Constructs an array item node.
|
||||
@ -21,17 +23,18 @@ class ArrayItem extends Expr
|
||||
* @param bool $byRef Whether to assign by reference
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $value, Expr $key = null, bool $byRef = false, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
public function __construct(Expr $value, Expr $key = null, bool $byRef = false, array $attributes = [], bool $unpack = false) {
|
||||
$this->attributes = $attributes;
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
$this->byRef = $byRef;
|
||||
$this->unpack = $unpack;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['key', 'value', 'byRef'];
|
||||
return ['key', 'value', 'byRef', 'unpack'];
|
||||
}
|
||||
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_ArrayItem';
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class Array_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $items = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
|
71
lib/PhpParser/Node/Expr/ArrowFunction.php
Normal file
71
lib/PhpParser/Node/Expr/ArrowFunction.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace PhpParser\Node\Expr;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\FunctionLike;
|
||||
|
||||
class ArrowFunction extends Expr implements FunctionLike
|
||||
{
|
||||
/** @var bool */
|
||||
public $static;
|
||||
|
||||
/** @var bool */
|
||||
public $byRef;
|
||||
|
||||
/** @var Node\Param[] */
|
||||
public $params = [];
|
||||
|
||||
/** @var null|Node\Identifier|Node\Name|Node\NullableType */
|
||||
public $returnType;
|
||||
|
||||
/** @var Expr */
|
||||
public $expr;
|
||||
|
||||
/**
|
||||
* @param array $subNodes Array of the following optional subnodes:
|
||||
* 'static' => false : Whether the closure is static
|
||||
* 'byRef' => false : Whether to return by reference
|
||||
* 'params' => array() : Parameters
|
||||
* 'returnType' => null : Return type
|
||||
* 'expr' => Expr : Expression body
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $subNodes = [], array $attributes = []) {
|
||||
$this->attributes = $attributes;
|
||||
$this->static = $subNodes['static'] ?? false;
|
||||
$this->byRef = $subNodes['byRef'] ?? false;
|
||||
$this->params = $subNodes['params'] ?? [];
|
||||
$returnType = $subNodes['returnType'] ?? null;
|
||||
$this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
|
||||
$this->expr = $subNodes['expr'] ?? null;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
return ['static', 'byRef', 'params', 'returnType', 'expr'];
|
||||
}
|
||||
|
||||
public function returnsByRef() : bool {
|
||||
return $this->byRef;
|
||||
}
|
||||
|
||||
public function getParams() : array {
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
public function getReturnType() {
|
||||
return $this->returnType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Node\Stmt\Return_[]
|
||||
*/
|
||||
public function getStmts() : array {
|
||||
return [new Node\Stmt\Return_($this->expr)];
|
||||
}
|
||||
|
||||
public function getType() : string {
|
||||
return 'Expr_ArrowFunction';
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ class Assign extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ abstract class AssignOp extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class AssignRef extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ abstract class BinaryOp extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $left, Expr $right, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->left = $left;
|
||||
$this->right = $right;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class BitwiseNot extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class BooleanNot extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ abstract class Cast extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ class ClassConstFetch extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($class, $name, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->class = $class;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class Clone_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ class Closure extends Expr implements FunctionLike
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $subNodes = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->static = $subNodes['static'] ?? false;
|
||||
$this->byRef = $subNodes['byRef'] ?? false;
|
||||
$this->params = $subNodes['params'] ?? [];
|
||||
|
@ -19,7 +19,7 @@ class ClosureUse extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr\Variable $var, bool $byRef = false, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->byRef = $byRef;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ class ConstFetch extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Name $name, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Empty_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ class Error extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
|
@ -16,7 +16,7 @@ class ErrorSuppress extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Eval_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ class Exit_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr = null, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ class FuncCall extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $args = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->name = $name;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ class Include_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, int $type, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class Instanceof_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, $class, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
$this->class = $class;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class Isset_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $vars, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->vars = $vars;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class List_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $items, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ class MethodCall extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, $name, array $args = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
$this->args = $args;
|
||||
|
@ -20,7 +20,7 @@ class New_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($class, array $args = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->class = $class;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class PostDec extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class PostInc extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class PreDec extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class PreInc extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Print_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ class PropertyFetch extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $var, $name, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->var = $var;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class ShellExec extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $parts, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->parts = $parts;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ class StaticCall extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($class, $name, array $args = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->class = $class;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
$this->args = $args;
|
||||
|
@ -21,7 +21,7 @@ class StaticPropertyFetch extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($class, $name, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->class = $class;
|
||||
$this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ class Ternary extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $cond, $if, Expr $else, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->cond = $cond;
|
||||
$this->if = $if;
|
||||
$this->else = $else;
|
||||
|
@ -16,7 +16,7 @@ class UnaryMinus extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class UnaryPlus extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Variable extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class YieldFrom extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ class Yield_ extends Expr
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Expr $value = null, Expr $key = null, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class Identifier extends NodeAbstract
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(string $name, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,7 @@ use PhpParser\NodeAbstract;
|
||||
|
||||
class Name extends NodeAbstract
|
||||
{
|
||||
/**
|
||||
* @var string[] Parts of the name
|
||||
*/
|
||||
/** @var string[] Parts of the name */
|
||||
public $parts;
|
||||
|
||||
private static $specialClassNames = [
|
||||
@ -24,7 +22,7 @@ class Name extends NodeAbstract
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->parts = self::prepareName($name);
|
||||
}
|
||||
|
||||
@ -237,7 +235,7 @@ class Name extends NodeAbstract
|
||||
'Expected string, array of parts or Name instance'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function getType() : string {
|
||||
return 'Name';
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class NullableType extends NodeAbstract
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($type, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->type = \is_string($type) ? new Identifier($type) : $type;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ class Param extends NodeAbstract
|
||||
$var, Expr $default = null, $type = null,
|
||||
bool $byRef = false, bool $variadic = false, array $attributes = []
|
||||
) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->type = \is_string($type) ? new Identifier($type) : $type;
|
||||
$this->byRef = $byRef;
|
||||
$this->variadic = $variadic;
|
||||
|
@ -16,7 +16,7 @@ class DNumber extends Scalar
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(float $value, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
@ -34,6 +34,8 @@ class DNumber extends Scalar
|
||||
* @return float The parsed number
|
||||
*/
|
||||
public static function parse(string $str) : float {
|
||||
$str = str_replace('_', '', $str);
|
||||
|
||||
// if string contains any of .eE just cast it to float
|
||||
if (false !== strpbrk($str, '.eE')) {
|
||||
return (float) $str;
|
||||
|
@ -17,7 +17,7 @@ class Encapsed extends Scalar
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $parts, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->parts = $parts;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class EncapsedStringPart extends Scalar
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(string $value, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ class LNumber extends Scalar
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(int $value, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
@ -41,6 +41,8 @@ class LNumber extends Scalar
|
||||
* @return LNumber The constructed LNumber, including kind attribute
|
||||
*/
|
||||
public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = false) : LNumber {
|
||||
$str = str_replace('_', '', $str);
|
||||
|
||||
if ('0' !== $str[0] || '0' === $str) {
|
||||
$attributes['kind'] = LNumber::KIND_DEC;
|
||||
return new LNumber((int) $str, $attributes);
|
||||
|
@ -12,7 +12,7 @@ abstract class MagicConst extends Scalar
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
public function getSubNodeNames() : array {
|
||||
|
@ -34,7 +34,7 @@ class String_ extends Scalar
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(string $value, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ class String_ extends Scalar
|
||||
if (isset(self::$replacements[$str])) {
|
||||
return self::$replacements[$str];
|
||||
} elseif ('x' === $str[0] || 'X' === $str[0]) {
|
||||
return chr(hexdec($str));
|
||||
return chr(hexdec(substr($str, 1)));
|
||||
} elseif ('u' === $str[0]) {
|
||||
return self::codePointToUtf8(hexdec($matches[2]));
|
||||
} else {
|
||||
@ -134,7 +134,7 @@ class String_ extends Scalar
|
||||
}
|
||||
throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large');
|
||||
}
|
||||
|
||||
|
||||
public function getType() : string {
|
||||
return 'Scalar_String';
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class Break_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Node\Expr $num = null, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->num = $num;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ class Case_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($cond, array $stmts = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->cond = $cond;
|
||||
$this->stmts = $stmts;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class Catch_ extends Node\Stmt
|
||||
public function __construct(
|
||||
array $types, Expr\Variable $var, array $stmts = [], array $attributes = []
|
||||
) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->types = $types;
|
||||
$this->var = $var;
|
||||
$this->stmts = $stmts;
|
||||
|
@ -19,7 +19,7 @@ class ClassConst extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $consts, int $flags = 0, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->flags = $flags;
|
||||
$this->consts = $consts;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class ClassMethod extends Node\Stmt implements FunctionLike
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $subNodes = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0;
|
||||
$this->byRef = $subNodes['byRef'] ?? false;
|
||||
$this->name = \is_string($name) ? new Node\Identifier($name) : $name;
|
||||
|
@ -35,7 +35,7 @@ class Class_ extends ClassLike
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $subNodes = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0;
|
||||
$this->name = \is_string($name) ? new Node\Identifier($name) : $name;
|
||||
$this->extends = $subNodes['extends'] ?? null;
|
||||
|
@ -16,7 +16,7 @@ class Const_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $consts, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->consts = $consts;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Continue_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Node\Expr $num = null, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->num = $num;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ class DeclareDeclare extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($key, Node\Expr $value, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->key = \is_string($key) ? new Node\Identifier($key) : $key;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class Declare_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $declares, array $stmts = null, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->declares = $declares;
|
||||
$this->stmts = $stmts;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class Do_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->cond = $cond;
|
||||
$this->stmts = $stmts;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class Echo_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $exprs, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->exprs = $exprs;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ class ElseIf_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->cond = $cond;
|
||||
$this->stmts = $stmts;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class Else_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $stmts = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->stmts = $stmts;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ class Expression extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Node\Expr $expr, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Finally_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $stmts = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->stmts = $stmts;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ class For_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $subNodes = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->init = $subNodes['init'] ?? [];
|
||||
$this->cond = $subNodes['cond'] ?? [];
|
||||
$this->loop = $subNodes['loop'] ?? [];
|
||||
|
@ -29,7 +29,7 @@ class Foreach_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->expr = $expr;
|
||||
$this->keyVar = $subNodes['keyVar'] ?? null;
|
||||
$this->byRef = $subNodes['byRef'] ?? false;
|
||||
|
@ -33,7 +33,7 @@ class Function_ extends Node\Stmt implements FunctionLike
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $subNodes = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->byRef = $subNodes['byRef'] ?? false;
|
||||
$this->name = \is_string($name) ? new Node\Identifier($name) : $name;
|
||||
$this->params = $subNodes['params'] ?? [];
|
||||
|
@ -16,7 +16,7 @@ class Global_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(array $vars, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->vars = $vars;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class Goto_ extends Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ class GroupUse extends Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Name $prefix, array $uses, int $type = Use_::TYPE_NORMAL, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->type = $type;
|
||||
$this->prefix = $prefix;
|
||||
$this->uses = $uses;
|
||||
|
@ -16,7 +16,7 @@ class HaltCompiler extends Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(string $remaining, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->remaining = $remaining;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ class If_ extends Node\Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->cond = $cond;
|
||||
$this->stmts = $subNodes['stmts'] ?? [];
|
||||
$this->elseifs = $subNodes['elseifs'] ?? [];
|
||||
|
@ -16,7 +16,7 @@ class InlineHTML extends Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct(string $value, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ class Interface_ extends ClassLike
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $subNodes = [], array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->name = \is_string($name) ? new Node\Identifier($name) : $name;
|
||||
$this->extends = $subNodes['extends'] ?? [];
|
||||
$this->stmts = $subNodes['stmts'] ?? [];
|
||||
|
@ -17,7 +17,7 @@ class Label extends Stmt
|
||||
* @param array $attributes Additional attributes
|
||||
*/
|
||||
public function __construct($name, array $attributes = []) {
|
||||
parent::__construct($attributes);
|
||||
$this->attributes = $attributes;
|
||||
$this->name = \is_string($name) ? new Identifier($name) : $name;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user