From 2a489397631cbf4ad865b32fe0d834c6f7edda34 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Sun, 26 Jul 2020 15:56:36 -0400 Subject: [PATCH 1/5] [WIP] v1.0.0 proposal Drop support for byRefToken in ArgumentExpression - it's a syntax error in php 7.0+ and is prohibited in php 5.4+. Convert the foo and otherFooList to fooList for union types in catch name lists, parameters, properties, and return union types. Remove ThrowStatement in favor of ThrowExpression for php 8.0. Remove EchoExpression in favor of EchoStatement - echo cannot be used as an expression. Remove statement from NamedLabelStatement - it's always null since a named label is a single statement by itself. TODO: Consistently support MissingToken in a single-element list in cases where a non-empty list is required, such as after `?` in types (php 8.0 union types forbid combining `?` with multiple types) TODO: Check for any regressions in diagnostics TODO: Validate that this can be used with real projects --- README.md | 42 ++-- composer.json | 4 +- src/Node/CatchClause.php | 17 +- .../AnonymousFunctionCreationExpression.php | 3 +- src/Node/Expression/ArgumentExpression.php | 6 +- .../ArrowFunctionCreationExpression.php | 3 +- src/Node/FunctionReturnType.php | 7 +- src/Node/MethodDeclaration.php | 3 +- src/Node/Parameter.php | 13 +- src/Node/PropertyDeclaration.php | 15 +- src/Node/Statement/DeclareStatement.php | 12 +- .../EchoStatement.php} | 17 +- src/Node/Statement/FunctionDeclaration.php | 3 +- src/Node/Statement/NamedLabelStatement.php | 6 - src/Node/Statement/ThrowStatement.php | 27 --- src/Node/TraitSelectOrAliasClause.php | 21 +- src/Parser.php | 115 +++------ tests/CallbackTestListener.php | 29 +-- tests/LexicalGrammarTest.php | 4 +- tests/ParserGrammarTest.php | 6 +- .../InlineHtmlInControlStructures.php.tree | 34 ++- .../abstractMethodDeclaration1.php.tree | 3 +- .../abstractMethodDeclaration2.php.tree | 3 +- .../abstractMethodDeclaration3.php.tree | 3 +- .../abstractMethodDeclaration4.php.tree | 3 +- .../abstractMethodDeclaration5.php.tree | 13 +- .../abstractMethodDeclaration6.php.tree | 13 +- .../abstractMethodDeclaration7.php.tree | 3 +- ...nymousFunctionCreationExpression1.php.tree | 43 ++-- ...ymousFunctionCreationExpression10.php.tree | 13 +- ...ymousFunctionCreationExpression11.php.tree | 3 +- ...nymousFunctionCreationExpression2.php.tree | 3 +- ...nymousFunctionCreationExpression3.php.tree | 3 +- ...nymousFunctionCreationExpression4.php.tree | 3 +- ...nymousFunctionCreationExpression5.php.tree | 3 +- ...nymousFunctionCreationExpression6.php.tree | 3 +- ...nymousFunctionCreationExpression7.php.tree | 3 +- .../binaryAssignmentExpressions6.php.tree | 1 - tests/cases/parser/callExpression10.php.tree | 3 - tests/cases/parser/callExpression12.php.tree | 1 - tests/cases/parser/callExpression15.php.tree | 1 - tests/cases/parser/callExpression16.php | 4 + tests/cases/parser/callExpression16.php.diag | 20 ++ tests/cases/parser/callExpression16.php.tree | 85 +++++++ tests/cases/parser/callExpression2.php.tree | 1 - tests/cases/parser/callExpression3.php.tree | 1 - tests/cases/parser/callExpression4.php.tree | 2 - tests/cases/parser/callExpression5.php.tree | 2 - tests/cases/parser/callExpression6.php.tree | 2 - tests/cases/parser/callExpression7.php.tree | 1 - tests/cases/parser/callExpression8.php.tree | 1 - tests/cases/parser/callExpression9.php.tree | 1 - .../parser/classConstDeclaration9.php.tree | 62 +++-- tests/cases/parser/classMethods1.php.tree | 3 +- tests/cases/parser/classMethods3.php.tree | 9 +- tests/cases/parser/classMethods4.php.tree | 19 +- tests/cases/parser/classMethods5.php.tree | 6 +- .../parser/conditionalExpressions2.php.tree | 1 - .../parser/conditionalExpressions3.php.tree | 1 - .../parser/conditionalExpressions4.php.tree | 2 - .../parser/constructorDeclaration1.php.tree | 3 +- tests/cases/parser/declareStatement1.php.tree | 35 +-- .../cases/parser/declareStatement10.php.tree | 35 +-- .../cases/parser/declareStatement11.php.tree | 35 +-- .../cases/parser/declareStatement12.php.diag | 12 - .../cases/parser/declareStatement12.php.tree | 23 +- .../cases/parser/declareStatement13.php.tree | 35 +-- .../cases/parser/declareStatement14.php.tree | 34 +-- .../cases/parser/declareStatement15.php.tree | 34 +-- .../cases/parser/declareStatement16.php.tree | 35 +-- tests/cases/parser/declareStatement2.php.tree | 35 +-- tests/cases/parser/declareStatement3.php.tree | 35 +-- tests/cases/parser/declareStatement4.php.tree | 35 +-- tests/cases/parser/declareStatement5.php.tree | 35 +-- tests/cases/parser/declareStatement6.php.tree | 35 +-- tests/cases/parser/declareStatement7.php.tree | 37 +-- tests/cases/parser/declareStatement8.php.tree | 35 +-- tests/cases/parser/declareStatement9.php.tree | 37 +-- tests/cases/parser/echoExpression1.php.tree | 62 +++-- tests/cases/parser/echoExpression2.php.tree | 36 ++- tests/cases/parser/echoExpression3.php.tree | 14 +- tests/cases/parser/echoExpression4.php.tree | 36 ++- tests/cases/parser/echoExpression5.php.tree | 90 ++++--- tests/cases/parser/echoExpression6.php.tree | 94 ++++---- tests/cases/parser/echoExpression7.php.tree | 36 ++- tests/cases/parser/echoExpression8.php.tree | 40 ++-- tests/cases/parser/echoExpression9.php.tree | 70 +++--- tests/cases/parser/functions1.php.tree | 3 +- tests/cases/parser/functions10.php.tree | 9 +- tests/cases/parser/functions11.php.tree | 27 ++- tests/cases/parser/functions12.php.tree | 27 ++- tests/cases/parser/functions13.php.tree | 27 ++- tests/cases/parser/functions14.php.tree | 30 +-- tests/cases/parser/functions15.php.tree | 30 +-- tests/cases/parser/functions16.php.tree | 6 +- tests/cases/parser/functions17.php.tree | 47 ++-- tests/cases/parser/functions18.php.tree | 47 ++-- tests/cases/parser/functions2.php.tree | 13 +- tests/cases/parser/functions3.php.tree | 47 ++-- tests/cases/parser/functions4.php.tree | 3 +- tests/cases/parser/functions5.php.tree | 3 +- tests/cases/parser/functions6.php.tree | 9 +- tests/cases/parser/functions7.php.tree | 9 +- tests/cases/parser/functions8.php.tree | 9 +- tests/cases/parser/functions9.php.tree | 9 +- .../parser/interfaceDeclaration10.php.tree | 19 +- .../parser/interfaceDeclaration11.php.tree | 6 +- .../parser/interfaceDeclaration12.php.tree | 6 +- .../parser/interfaceDeclaration13.php.tree | 3 +- .../parser/interfaceDeclaration14.php.tree | 3 +- .../parser/interfaceDeclaration7.php.tree | 3 +- .../parser/interfaceDeclaration8.php.tree | 9 +- .../parser/interfaceDeclaration9.php.tree | 9 +- tests/cases/parser/lhsVariable1.php.tree | 74 +++--- tests/cases/parser/lhsVariable2.php.tree | 72 +++--- tests/cases/parser/lhsVariable3.php.tree | 74 +++--- tests/cases/parser/lhsVariable4.php.tree | 72 +++--- tests/cases/parser/lhsVariable5.php.tree | 82 +++---- .../cases/parser/multipleInlineHtml.php.tree | 60 ++--- tests/cases/parser/namedArgument.php.tree | 113 +++++---- tests/cases/parser/namedArgument2.php.tree | 224 +++++++++--------- tests/cases/parser/namedArgument3.php.tree | 4 - .../parser/namedLabelStatement1.php.tree | 3 +- .../parser/namedLabelStatement4.php.tree | 6 +- .../parser/namedLabelStatement5.php.tree | 6 +- .../parser/namedLabelStatement6.php.tree | 43 ++-- .../parser/namedLabelStatement7.php.tree | 3 +- .../parser/namedLabelStatement8.php.tree | 43 ++-- .../namespaced_call_in_arg_list.php.tree | 2 - tests/cases/parser/namespaces2.php.tree | 27 ++- tests/cases/parser/namespaces3.php.tree | 21 +- tests/cases/parser/namespaces4.php.tree | 43 ++-- tests/cases/parser/namespaces5.php.tree | 53 +++-- .../parser/objectCreationExpression7.php.tree | 3 +- .../parser/objectCreationExpression8.php.tree | 5 +- .../cases/parser/parameterPromotion1.php.tree | 22 +- .../cases/parser/parameterPromotion2.php.tree | 9 +- .../cases/parser/programStructure10.php.tree | 40 ++-- .../cases/parser/programStructure11.php.tree | 40 ++-- .../cases/parser/programStructure22.php.tree | 34 ++- .../cases/parser/programStructure29.php.tree | 40 ++-- .../cases/parser/programStructure31.php.tree | 40 ++-- .../cases/parser/programStructure34.php.tree | 58 +++-- .../cases/parser/programStructure35.php.tree | 64 +++-- .../cases/parser/programStructure36.php.tree | 80 +++---- .../cases/parser/programStructure37.php.tree | 34 ++- .../cases/parser/programStructure38.php.tree | 36 ++- tests/cases/parser/programStructure5.php.tree | 16 +- tests/cases/parser/programStructure6.php.tree | 125 +++++----- .../parser/propertyDeclaration1.php.tree | 3 +- .../parser/propertyDeclaration2.php.tree | 3 +- .../parser/propertyDeclaration3.php.tree | 3 +- .../parser/propertyDeclaration4.php.tree | 3 +- .../parser/propertyDeclaration5.php.tree | 3 +- .../scopedPropertyAccessExpression14.php.tree | 90 ++++--- .../scopedPropertyAccessExpression15.php.tree | 112 +++++---- .../scopedPropertyAccessExpression22.php.tree | 5 +- tests/cases/parser/staticReturnType1.php.tree | 13 +- tests/cases/parser/staticReturnType2.php.tree | 3 +- tests/cases/parser/stringLiteral14.php.tree | 1 - tests/cases/parser/stringLiteral15.php.tree | 1 - tests/cases/parser/switchStatement6.php.tree | 3 +- tests/cases/parser/throwStatement2.php.tree | 20 +- tests/cases/parser/throwStatement3.php.tree | 24 +- tests/cases/parser/throwStatement4.php.tree | 20 +- tests/cases/parser/throwStatement5.php.tree | 24 +- tests/cases/parser/throwStatement6.php.tree | 161 +++++++------ tests/cases/parser/traits10.php.tree | 5 +- tests/cases/parser/traits12.php.tree | 28 ++- tests/cases/parser/traits13.php.tree | 23 +- tests/cases/parser/traits14.php.tree | 39 +-- tests/cases/parser/traits15.php.tree | 23 +- tests/cases/parser/traits16.php.tree | 23 +- tests/cases/parser/traits17.php.tree | 23 +- tests/cases/parser/traits19.php.tree | 5 +- tests/cases/parser/traits20.php.tree | 5 +- tests/cases/parser/traits21.php.tree | 10 +- tests/cases/parser/traits22.php.tree | 28 ++- tests/cases/parser/traits24.php.tree | 54 +++-- tests/cases/parser/traits25.php.diag | 9 +- tests/cases/parser/traits25.php.tree | 7 +- tests/cases/parser/traits9.php.tree | 5 +- tests/cases/parser/tryStatement1.php.tree | 21 +- tests/cases/parser/tryStatement10.php.diag | 9 +- tests/cases/parser/tryStatement10.php.tree | 7 +- tests/cases/parser/tryStatement11.php.tree | 38 +-- tests/cases/parser/tryStatement12.php.tree | 70 +++--- tests/cases/parser/tryStatement13.php.diag | 6 + tests/cases/parser/tryStatement13.php.tree | 7 +- tests/cases/parser/tryStatement4.php.diag | 9 +- tests/cases/parser/tryStatement4.php.tree | 7 +- tests/cases/parser/tryStatement5.php.diag | 6 + tests/cases/parser/tryStatement5.php.tree | 7 +- tests/cases/parser/tryStatement6.php.diag | 6 + tests/cases/parser/tryStatement6.php.tree | 7 +- tests/cases/parser/tryStatement8.php.diag | 6 + tests/cases/parser/tryStatement8.php.tree | 7 +- tests/cases/parser/tryStatement9.php.tree | 21 +- tests/cases/parser/typedProperties.php.tree | 120 ++++++---- .../typedPropertiesInvalidElsewhere.php.tree | 3 +- .../typedPropertiesInvalidElsewhere2.php.tree | 3 +- .../parser/typedPropertiesNoType.php.tree | 3 +- .../parser/typedPropertiesSimple.php.tree | 13 +- .../cases/parser/unionTypeParameter1.php.tree | 13 +- .../cases/parser/unionTypeParameter2.php.tree | 45 ++-- .../cases/parser/unionTypeParameter3.php.tree | 3 +- tests/cases/parser/unionTypeProperty.php.tree | 36 +-- .../cases/parser/unionTypeProperty2.php.tree | 13 +- tests/cases/parser/unionTypeReturn1.php.tree | 42 ++-- tests/cases/parser/unionTypeReturn2.php.tree | 36 +-- tests/cases/parser/whileStatement3.php.tree | 6 +- tests/cases/parser/yieldExpression10.php.tree | 3 +- .../parser/yieldExpression10_from.php.tree | 3 +- tests/cases/parser/yieldExpression11.php.tree | 3 +- .../parser/yieldExpression11_from.php.tree | 3 +- tests/cases/parser/yieldExpression12.php.tree | 3 +- .../parser/yieldExpression12_from.php.tree | 3 +- tests/cases/parser/yieldExpression13.php.tree | 3 +- .../parser/yieldExpression13_from.php.tree | 3 +- tests/cases/parser/yieldExpression14.php.tree | 3 +- .../parser/yieldExpression14_from.php.tree | 3 +- tests/cases/parser/yieldExpression15.php.tree | 3 +- .../parser/yieldExpression15_from.php.tree | 3 +- tests/cases/parser/yieldExpression16.php.tree | 3 +- .../parser/yieldExpression16_from.php.tree | 3 +- tests/cases/parser/yieldExpression17.php.tree | 3 +- .../parser/yieldExpression17_from.php.tree | 3 +- tests/cases/parser/yieldExpression18.php.tree | 6 +- tests/cases/parser/yieldExpression19.php.tree | 6 +- tests/cases/parser/yieldExpression2.php.tree | 3 +- .../parser/yieldExpression2_from.php.tree | 3 +- tests/cases/parser/yieldExpression3.php.tree | 3 +- .../parser/yieldExpression3_from.php.tree | 3 +- tests/cases/parser/yieldExpression4.php.tree | 3 +- .../parser/yieldExpression4_from.php.tree | 3 +- tests/cases/parser/yieldExpression5.php.tree | 3 +- .../parser/yieldExpression5_from.php.tree | 3 +- tests/cases/parser/yieldExpression6.php.tree | 3 +- .../parser/yieldExpression6_from.php.tree | 3 +- tests/cases/parser/yieldExpression7.php.tree | 3 +- .../parser/yieldExpression7_from.php.tree | 3 +- tests/cases/parser/yieldExpression8.php.tree | 3 +- .../parser/yieldExpression8_from.php.tree | 3 +- tests/cases/parser/yieldExpression9.php.tree | 3 +- .../parser/yieldExpression9_from.php.tree | 3 +- tests/cases/parser74/arrowFunction.php.tree | 62 +++-- .../parser74/arrowFunctionFallback.php.tree | 121 +++++----- .../parser74/arrowFunctionTypes.php.tree | 170 ++++++------- .../parser74/arrowFunctionUnionTypes.php.tree | 193 +++++++-------- tests/cases/parser74/throwStatement1.php.tree | 3 +- 250 files changed, 2913 insertions(+), 2954 deletions(-) rename src/Node/{Expression/EchoExpression.php => Statement/EchoStatement.php} (65%) delete mode 100644 src/Node/Statement/ThrowStatement.php create mode 100644 tests/cases/parser/callExpression16.php create mode 100644 tests/cases/parser/callExpression16.php.diag create mode 100644 tests/cases/parser/callExpression16.php.tree diff --git a/README.md b/README.md index cf658853..ddb1df50 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,15 @@ [![Build Status](https://travis-ci.org/Microsoft/tolerant-php-parser.svg?branch=master)](https://travis-ci.org/Microsoft/tolerant-php-parser) This is an early-stage PHP parser designed, from the beginning, for IDE usage scenarios (see [Design Goals](#design-goals) for more details). There is -still a ton of work to be done, so at this point, this repo mostly serves as +still a ton of work to be done, so at this point, this repo mostly serves as an experiment and the start of a conversation. ![image](https://cloud.githubusercontent.com/assets/762848/19023070/4ab01c92-889a-11e6-9bb5-ec1a6816aba2.png) +This is the v1 branch, which changes data structures to support syntax added after the initial release for php 7.0. + ## Get Started -After you've [configured your machine](docs/GettingStarted.md), you can use the parser to generate and work +After you've [configured your machine](docs/GettingStarted.md), you can use the parser to generate and work with the Abstract Syntax Tree (AST) via a friendly API. ```php getDescendantNodes() as $descendant) { // All Nodes link back to their parents, so it's easy to navigate the tree. $grandParent = $descendant->getParent()->getParent(); var_dump($grandParent->getNodeKindName()); - + // The AST is fully-representative, and round-trippable to the original source. // This enables consumers to build reliable formatting and refactoring tools. var_dump($grandParent->getLeadingCommentAndWhitespaceText()); } - + // In addition to retrieving all children or descendants of a Node, // Nodes expose properties specific to the Node type. if ($descendant instanceof Node\Expression\EchoExpression) { $echoKeywordStartPosition = $descendant->echoKeyword->getStartPosition(); - // To cut down on memory consumption, positions are represented as a single integer + // To cut down on memory consumption, positions are represented as a single integer // index into the document, but their line and character positions are easily retrieved. $lineCharacterPosition = PositionUtilities::getLineCharacterPositionFromPosition( $echoKeywordStartPosition, @@ -59,15 +61,15 @@ foreach ($astNode->getDescendantNodes() as $descendant) { } ``` -> Note: [the API](docs/ApiDocumentation.md) is not yet finalized, so please file issues let us know what functionality you want exposed, +> Note: [the API](docs/ApiDocumentation.md) is not yet finalized, so please file issues let us know what functionality you want exposed, and we'll see what we can do! Also please file any bugs with unexpected behavior in the parse tree. We're still in our early stages, and any feedback you have is much appreciated :smiley:. ## Design Goals * Error tolerant design - in IDE scenarios, code is, by definition, incomplete. In the case that invalid code is entered, the -parser should still be able to recover and produce a valid + complete tree, as well as relevant diagnostics. +parser should still be able to recover and produce a valid + complete tree, as well as relevant diagnostics. * Fast and lightweight (should be able to parse several MB of source code per second, - to leave room for other features). + to leave room for other features). * Memory-efficient data structures * Allow for incremental parsing in the future * Adheres to [PHP language spec](https://github.com/php/php-langspec), @@ -83,34 +85,34 @@ so each language server operation should be < 50 ms to leave room for all the confusing, really fast, so readability and debug-ability is high priority. * Testable - the parser should produce provably valid parse trees. We achieve this by defining and continuously testing a set of invariants about the tree. -* Friendly and descriptive API to make it easy for others to build on. +* Friendly and descriptive API to make it easy for others to build on. * Written in PHP - make it as easy as possible for the PHP community to consume and contribute. ## Current Status and Approach To ensure a sufficient level of correctness at every step of the way, the parser is being developed using the following incremental approach: -* [x] **Phase 1:** Write lexer that does not support PHP grammar, but supports EOF +* [x] **Phase 1:** Write lexer that does not support PHP grammar, but supports EOF and Unknown tokens. Write tests for all invariants. * [x] **Phase 2:** Support PHP lexical grammar, lots of tests -* [x] **Phase 3:** Write a parser that does not support PHP grammar, but produces tree of +* [x] **Phase 3:** Write a parser that does not support PHP grammar, but produces tree of Error Nodes. Write tests for all invariants. * [x] **Phase 4:** Support PHP syntactic grammar, lots of tests * [ ] **Phase 5 (in progress :running:):** Real-world validation and optimization * [ ] _**Correctness:**_ validate that there are no errors produced on sample codebases, benchmark against other parsers (investigate any instance of disagreement), fuzz-testing * [ ] _**Performance:**_ profile, benchmark against large PHP applications -* [ ] **Phase 6:** Finalize API to make it as easy as possible for people to consume. +* [ ] **Phase 6:** Finalize API to make it as easy as possible for people to consume. ### Additional notes A few of the PHP grammatical constructs (namely yield-expression, and template strings) are not yet supported and there are also other miscellaneous bugs. However, because the parser is error-tolerant, these errors are handled gracefully, and the resulting tree is otherwise complete. To get a more holistic sense for -where we are, you can run the "validation" test suite (see [Contributing Guidelines](Contributing.md) for more info +where we are, you can run the "validation" test suite (see [Contributing Guidelines](Contributing.md) for more info on running tests). Or simply, take a look at the current [validation test results](https://travis-ci.org/Microsoft/tolerant-php-parser). -Even though we haven't yet begun the performance optimization stage, we have seen promising results so far, -and have plenty more room for improvement. See [How It Works](docs/HowItWorks.md) for details on our current -approach, and run the [Performance Tests](Contributing.md#running-performance-tests) on your +Even though we haven't yet begun the performance optimization stage, we have seen promising results so far, +and have plenty more room for improvement. See [How It Works](docs/HowItWorks.md) for details on our current +approach, and run the [Performance Tests](Contributing.md#running-performance-tests) on your own machine to see for yourself. ## Learn more @@ -119,7 +121,7 @@ own machine to see for yourself. **:book: [Documentation](docs/GettingStarted.md#getting-started)** - learn how to reference the parser from your project, and how to perform operations on the AST to answer questions about your code. -**:eyes: [Syntax Visualizer Tool](syntax-visualizer/client#php-parser-syntax-visualizer-tool)** - get a more tangible feel for the AST. Get creative - see if you can break it! +**:eyes: [Syntax Visualizer Tool](syntax-visualizer/client#php-parser-syntax-visualizer-tool)** - get a more tangible feel for the AST. Get creative - see if you can break it! **:chart_with_upwards_trend: [Current Status and Approach](#current-status-and-approach)** - how much of the grammar is supported? Performance? Memory? API stability? @@ -131,10 +133,10 @@ operations on the AST to answer questions about your code. * [Validation Strategy](docs/HowItWorks.md#validation-strategy) **:sparkling_heart: [Contribute!](Contributing.md)** - learn how to get involved, check out some pointers to educational commits that'll -help you ramp up on the codebase (even if you've never worked on a parser before), +help you ramp up on the codebase (even if you've never worked on a parser before), and recommended workflows that make it easier to iterate. --- -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/composer.json b/composer.json index 471f798e..21e67653 100644 --- a/composer.json +++ b/composer.json @@ -3,10 +3,10 @@ "description": "Tolerant PHP-to-AST parser designed for IDE usage scenarios", "type": "library", "require": { - "php": ">=7.0" + "php": ">=7.2" }, "require-dev": { - "phpunit/phpunit": "^6.4|^7.5.20" + "phpunit/phpunit": "^7.5.20" }, "license": "MIT", "authors": [ diff --git a/src/Node/CatchClause.php b/src/Node/CatchClause.php index 2784d116..33a6e9e8 100644 --- a/src/Node/CatchClause.php +++ b/src/Node/CatchClause.php @@ -7,6 +7,8 @@ namespace Microsoft\PhpParser\Node; use Microsoft\PhpParser\Node; +use Microsoft\PhpParser\Node\DelimitedList\QualifiedNameList; +use Microsoft\PhpParser\MissingToken; use Microsoft\PhpParser\Token; class CatchClause extends Node { @@ -14,16 +16,8 @@ class CatchClause extends Node { public $catch; /** @var Token */ public $openParen; - /** @var QualifiedName */ - public $qualifiedName; - /** - * @var QualifiedName[]|Token[] Remaining tokens and qualified names in the catch clause - * (e.g. `catch (FirstException|SecondException $x)` would contain - * the representation of `|SecondException`) - * - * TODO: In the next backwards incompatible release, replace qualifiedName with qualifiedNameList? - */ - public $otherQualifiedNameList; + /** @var QualifiedNameList[]|MissingToken */ + public $qualifiedNameList; /** @var Token|null */ public $variableName; /** @var Token */ @@ -34,8 +28,7 @@ class CatchClause extends Node { const CHILD_NAMES = [ 'catch', 'openParen', - 'qualifiedName', - 'otherQualifiedNameList', + 'qualifiedNameList', 'variableName', 'closeParen', 'compoundStatement' diff --git a/src/Node/Expression/AnonymousFunctionCreationExpression.php b/src/Node/Expression/AnonymousFunctionCreationExpression.php index a723d116..40abdb5b 100644 --- a/src/Node/Expression/AnonymousFunctionCreationExpression.php +++ b/src/Node/Expression/AnonymousFunctionCreationExpression.php @@ -38,8 +38,7 @@ class AnonymousFunctionCreationExpression extends Expression implements Function // FunctionReturnType 'colonToken', 'questionToken', - 'returnType', - 'otherReturnTypes', + 'returnTypeList', // FunctionBody 'compoundStatementOrSemicolon' diff --git a/src/Node/Expression/ArgumentExpression.php b/src/Node/Expression/ArgumentExpression.php index ac1596ac..881a5c0d 100644 --- a/src/Node/Expression/ArgumentExpression.php +++ b/src/Node/Expression/ArgumentExpression.php @@ -10,15 +10,12 @@ use Microsoft\PhpParser\Token; class ArgumentExpression extends Expression { - /** @var Token|null for php named arguments. If this is set, byRefToken and dotDotDotToken will not be set. */ + /** @var Token|null for php named arguments. If this is set, dotDotDotToken will not be set. */ public $name; /** @var Token|null */ public $colonToken; - /** @var Token|null */ - public $byRefToken; // TODO removed in newer versions of PHP. Also only accept variable, not expression if byRef - /** @var Token|null */ public $dotDotDotToken; @@ -28,7 +25,6 @@ class ArgumentExpression extends Expression { const CHILD_NAMES = [ 'name', 'colonToken', - 'byRefToken', 'dotDotDotToken', 'expression' ]; diff --git a/src/Node/Expression/ArrowFunctionCreationExpression.php b/src/Node/Expression/ArrowFunctionCreationExpression.php index 8f93de00..96673692 100644 --- a/src/Node/Expression/ArrowFunctionCreationExpression.php +++ b/src/Node/Expression/ArrowFunctionCreationExpression.php @@ -40,8 +40,7 @@ class ArrowFunctionCreationExpression extends Expression implements FunctionLike // FunctionReturnType 'colonToken', 'questionToken', - 'returnType', - 'otherReturnTypes', + 'returnTypeList', // body 'arrowToken', diff --git a/src/Node/FunctionReturnType.php b/src/Node/FunctionReturnType.php index 8f836773..1429234e 100644 --- a/src/Node/FunctionReturnType.php +++ b/src/Node/FunctionReturnType.php @@ -11,10 +11,9 @@ trait FunctionReturnType { /** @var Token */ public $colonToken; + // TODO: This may be the wrong choice if ?type can ever be mixed with other types in union types /** @var Token|null */ public $questionToken; - /** @var Token|QualifiedName */ - public $returnType; - /** @var DelimitedList\QualifiedNameList|null TODO: Merge with returnType in a future backwards incompatible release */ - public $otherReturnTypes; + /** @var DelimitedList\QualifiedNameList|null */ + public $returnTypeList; } diff --git a/src/Node/MethodDeclaration.php b/src/Node/MethodDeclaration.php index a674e930..49cf1822 100644 --- a/src/Node/MethodDeclaration.php +++ b/src/Node/MethodDeclaration.php @@ -34,8 +34,7 @@ class MethodDeclaration extends Node implements FunctionLike, ModifiedTypeInterf // FunctionReturnType 'colonToken', 'questionToken', - 'returnType', - 'otherReturnTypes', + 'returnTypeList', // FunctionBody 'compoundStatementOrSemicolon' diff --git a/src/Node/Parameter.php b/src/Node/Parameter.php index 24571638..f8294b31 100644 --- a/src/Node/Parameter.php +++ b/src/Node/Parameter.php @@ -6,6 +6,7 @@ namespace Microsoft\PhpParser\Node; +use Microsoft\PhpParser\MissingToken; use Microsoft\PhpParser\Node; use Microsoft\PhpParser\Token; @@ -16,13 +17,8 @@ class Parameter extends Node { public $visibilityToken; /** @var Token|null */ public $questionToken; - /** @var QualifiedName|Token|null */ - public $typeDeclaration; - /** - * @var DelimitedList\QualifiedNameList a list of other types, to support php 8 union types while remaining backwards compatible. - * TODO: Merge with typeDeclaration in a future backwards incompatible release. - */ - public $otherTypeDeclarations; + /** @var DelimitedList\QualifiedNameList|MissingToken|null */ + public $typeDeclarationList; /** @var Token|null */ public $byRefToken; /** @var Token|null */ @@ -38,8 +34,7 @@ class Parameter extends Node { 'attributes', 'visibilityToken', 'questionToken', - 'typeDeclaration', - 'otherTypeDeclarations', + 'typeDeclarationList', 'byRefToken', 'dotDotDotToken', 'variableName', diff --git a/src/Node/PropertyDeclaration.php b/src/Node/PropertyDeclaration.php index 603d4955..1995aed5 100644 --- a/src/Node/PropertyDeclaration.php +++ b/src/Node/PropertyDeclaration.php @@ -6,9 +6,11 @@ namespace Microsoft\PhpParser\Node; +use Microsoft\PhpParser\MissingToken; use Microsoft\PhpParser\ModifiedTypeInterface; use Microsoft\PhpParser\ModifiedTypeTrait; use Microsoft\PhpParser\Node; +use Microsoft\PhpParser\Node\DelimitedList\QualifiedNameList; use Microsoft\PhpParser\Token; class PropertyDeclaration extends Node implements ModifiedTypeInterface { @@ -20,14 +22,8 @@ class PropertyDeclaration extends Node implements ModifiedTypeInterface { /** @var Token|null question token for PHP 7.4 type declaration */ public $questionToken; - /** @var QualifiedName|Token|null */ - public $typeDeclaration; - - /** - * @var DelimitedList\QualifiedNameList|null - * TODO: Unify with typeDeclaration in a future backwards incompatible release - */ - public $otherTypeDeclarations; + /** @var QualifiedNameList|MissingToken|null */ + public $typeDeclarationList; /** @var DelimitedList\ExpressionList */ public $propertyElements; @@ -39,8 +35,7 @@ class PropertyDeclaration extends Node implements ModifiedTypeInterface { 'attributes', 'modifiers', 'questionToken', - 'typeDeclaration', - 'otherTypeDeclarations', + 'typeDeclarationList', 'propertyElements', 'semicolon' ]; diff --git a/src/Node/Statement/DeclareStatement.php b/src/Node/Statement/DeclareStatement.php index fcf39715..d9b6155e 100644 --- a/src/Node/Statement/DeclareStatement.php +++ b/src/Node/Statement/DeclareStatement.php @@ -6,7 +6,7 @@ namespace Microsoft\PhpParser\Node\Statement; -use Microsoft\PhpParser\Node; +use Microsoft\PhpParser\MissingToken; use Microsoft\PhpParser\Node\DelimitedList; use Microsoft\PhpParser\Node\StatementNode; use Microsoft\PhpParser\Token; @@ -16,10 +16,9 @@ class DeclareStatement extends StatementNode { public $declareKeyword; /** @var Token */ public $openParen; - /** @var Node */ - public $declareDirective; - /** @var DelimitedList\DeclareDirectiveList|null TODO: Merge with $declareDirective in a future backwards incompatible release. */ - public $otherDeclareDirectives; + // TODO Maybe create a delimited list with a missing token instead? Probably more consistent. + /** @var DelimitedList\DeclareDirectiveList|MissingToken */ + public $declareDirectiveList; /** @var Token */ public $closeParen; /** @var Token|null */ @@ -34,8 +33,7 @@ class DeclareStatement extends StatementNode { const CHILD_NAMES = [ 'declareKeyword', 'openParen', - 'declareDirective', - 'otherDeclareDirectives', + 'declareDirectiveList', 'closeParen', 'colon', 'statements', diff --git a/src/Node/Expression/EchoExpression.php b/src/Node/Statement/EchoStatement.php similarity index 65% rename from src/Node/Expression/EchoExpression.php rename to src/Node/Statement/EchoStatement.php index d8ea286e..5cfc1067 100644 --- a/src/Node/Expression/EchoExpression.php +++ b/src/Node/Statement/EchoStatement.php @@ -4,20 +4,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -namespace Microsoft\PhpParser\Node\Expression; +namespace Microsoft\PhpParser\Node\Statement; -use Microsoft\PhpParser\Node\Expression; +use Microsoft\PhpParser\Node\StatementNode; use Microsoft\PhpParser\Node\DelimitedList\ExpressionList; use Microsoft\PhpParser\Token; /** - * This represents either a literal echo expression (`echo expr`) + * This represents either a literal echo statement (`echo expr`) * or a short echo tag (`visibilityToken = $this->eatOptional([TokenKind::PublicKeyword, TokenKind::ProtectedKeyword, TokenKind::PrivateKeyword]); $parameter->questionToken = $this->eatOptional1(TokenKind::QuestionToken); - $typeDeclarationList = $this->tryParseParameterTypeDeclarationList($parameter); - if ($typeDeclarationList) { - $parameter->typeDeclaration = array_shift($typeDeclarationList->children); - $parameter->typeDeclaration->parent = $parameter; - if ($typeDeclarationList->children) { - $parameter->otherTypeDeclarations = $typeDeclarationList; - } + $parameter->typeDeclarationList = $this->tryParseParameterTypeDeclarationList($parameter); + if ($parameter->questionToken && !$parameter->typeDeclarationList) { + // TODO ParameterType? + $parameter->typeDeclarationList = new MissingToken(TokenKind::PropertyType, $this->token->fullStart); } $parameter->byRefToken = $this->eatOptional1(TokenKind::AmpersandToken); // TODO add post-parse rule that prevents assignment @@ -858,15 +854,10 @@ private function parseParameterFn() { private function parseAndSetReturnTypeDeclarationList($parentNode) { $returnTypeList = $this->parseReturnTypeDeclarationList($parentNode); if (!$returnTypeList) { - $parentNode->returnType = new MissingToken(TokenKind::ReturnType, $this->token->fullStart); + $parentNode->returnTypeList = new MissingToken(TokenKind::ReturnType, $this->token->fullStart); return; } - $returnType = array_shift($returnTypeList->children); - $parentNode->returnType = $returnType; - $returnType->parent = $parentNode; - if ($returnTypeList->children) { - $parentNode->otherReturnTypes = $returnTypeList; - } + $parentNode->returnTypeList = $returnTypeList; } /** @@ -2410,17 +2401,17 @@ private function parseReturnStatement($parentNode) { return $returnStatement; } + /** @return ExpressionStatement */ private function parseThrowStatement($parentNode) { - $throwStatement = new ThrowStatement(); + $throwStatement = new ExpressionStatement(); + $throwStatement->expression = $this->parseThrowExpression($throwStatement); $throwStatement->parent = $parentNode; - $throwStatement->throwKeyword = $this->eat1(TokenKind::ThrowKeyword); - // TODO error for failures to parse expressions when not optional - $throwStatement->expression = $this->parseExpression($throwStatement); $throwStatement->semicolon = $this->eatSemicolonOrAbortStatement(); return $throwStatement; } + /** @return ThrowExpression */ private function parseThrowExpression($parentNode) { $throwExpression = new ThrowExpression(); $throwExpression->parent = $parentNode; @@ -2454,9 +2445,7 @@ private function parseCatchClause($parentNode) { $catchClause->parent = $parentNode; $catchClause->catch = $this->eat1(TokenKind::CatchKeyword); $catchClause->openParen = $this->eat1(TokenKind::OpenParenToken); - $qualifiedNameList = $this->parseQualifiedNameCatchList($catchClause)->children ?? []; - $catchClause->qualifiedName = $qualifiedNameList[0] ?? null; // TODO generate missing token or error if null - $catchClause->otherQualifiedNameList = array_slice($qualifiedNameList, 1); // TODO: Generate error if the name list has missing tokens + $catchClause->qualifiedNameList = $this->parseQualifiedNameCatchList($catchClause) ?? new MissingToken(TokenKind::QualifiedName, $this->token->fullStart); // TODO generate missing token or error if null $catchClause->variableName = $this->eatOptional1(TokenKind::VariableName); $catchClause->closeParen = $this->eat1(TokenKind::CloseParenToken); $catchClause->compoundStatement = $this->parseCompoundStatement($catchClause); @@ -2501,27 +2490,7 @@ private function parseDeclareStatement($parentNode) { private function parseAndSetDeclareDirectiveList($parentNode) { $declareDirectiveList = $this->parseDeclareDirectiveList($parentNode); - if (!$declareDirectiveList) { - $declareDirective = new DeclareDirective(); - $declareDirective->parent = $parentNode; - - $declareDirective->name = new MissingToken(TokenKind::Name, $this->token->fullStart); - $declareDirective->equals = new MissingToken(TokenKind::EqualsToken, $this->token->fullStart); - // TODO: This is matching the first token in $this::parseDeclareDirectiveFn. - // Probably best to emit a more general "literal error". - $declareDirective->literal = new MissingToken(TokenKind::FloatingLiteralToken, $this->token->fullStart); - - $parentNode->declareDirective = $declareDirective; - return; - } - - $declareDirective = array_shift($declareDirectiveList->children); - $parentNode->declareDirective = $declareDirective; - $declareDirective->parent = $parentNode; - - if ($declareDirectiveList->children) { - $parentNode->otherDeclareDirectives = $declareDirectiveList; - } + $parentNode->declareDirectiveList = $declareDirectiveList ?? new MissingToken(TokenKind::Name, $this->token->fullStart); } /** @@ -2645,27 +2614,22 @@ private function parseScriptInclusionExpression($parentNode) { return $scriptInclusionExpression; } + /** @return EchoStatement */ private function parseEchoStatement($parentNode) { - $expressionStatement = new ExpressionStatement(); - - // TODO: Could flatten into EchoStatement instead? - $echoExpression = new EchoExpression(); - $echoExpression->parent = $expressionStatement; - $echoExpression->echoKeyword = $this->eat1(TokenKind::EchoKeyword); - $echoExpression->expressions = - $this->parseExpressionList($echoExpression); - - $expressionStatement->parent = $parentNode; - $expressionStatement->expression = $echoExpression; - $expressionStatement->semicolon = $this->eatSemicolonOrAbortStatement(); - - return $expressionStatement; + $echoStatement = new EchoStatement(); + $echoStatement->parent = $parentNode; + $echoStatement->echoKeyword = $this->eat1(TokenKind::EchoKeyword); + $echoStatement->expressions = + $this->parseExpressionList($echoStatement); + $echoStatement->semicolon = $this->eatSemicolonOrAbortStatement(); + return $echoStatement; } + /** @return ExpressionStatement */ private function parseUnsetStatement($parentNode) { $expressionStatement = new ExpressionStatement(); - // TODO: Could flatten into UnsetStatement instead? + // FIXME: flatten into UnsetStatement instead? $unsetExpression = $this->parseUnsetIntrinsicExpression($expressionStatement); $expressionStatement->parent = $parentNode; @@ -3003,7 +2967,6 @@ private function parseArgumentExpressionFn() { $argumentExpression->name = $name; $argumentExpression->colonToken = $this->eat1(TokenKind::ColonToken); } else { - $argumentExpression->byRefToken = $this->eatOptional1(TokenKind::AmpersandToken); $argumentExpression->dotDotDotToken = $this->eatOptional1(TokenKind::DotDotDotToken); } $argumentExpression->expression = $this->parseExpression($argumentExpression); @@ -3261,18 +3224,9 @@ private function parsePropertyDeclaration($parentNode, $modifiers, $questionToke $propertyDeclaration->modifiers = $modifiers; $propertyDeclaration->questionToken = $questionToken; if ($typeDeclarationList) { - /** $typeDeclarationList is a Node or a Token (e.g. IntKeyword) */ - $typeDeclaration = \array_shift($typeDeclarationList->children); - $propertyDeclaration->typeDeclaration = $typeDeclaration; - if ($typeDeclaration instanceof Node) { - $typeDeclaration->parent = $propertyDeclaration; - } - if ($typeDeclarationList->children) { - $propertyDeclaration->otherTypeDeclarations = $typeDeclarationList; - $typeDeclarationList->parent = $propertyDeclaration; - } + $propertyDeclaration->typeDeclarationList = $typeDeclarationList; } elseif ($questionToken) { - $propertyDeclaration->typeDeclaration = new MissingToken(TokenKind::PropertyType, $this->token->fullStart); + $propertyDeclaration->typeDeclarationList = new MissingToken(TokenKind::PropertyType, $this->token->fullStart); } $propertyDeclaration->propertyElements = $this->parseExpressionList($propertyDeclaration); $propertyDeclaration->semicolon = $this->eat1(TokenKind::SemicolonToken); @@ -3713,15 +3667,10 @@ private function parseTraitSelectOrAliasClauseFn() { $traitSelectAndAliasClause->modifiers = $this->parseModifiers(); // TODO accept all modifiers, verify later if ($traitSelectAndAliasClause->asOrInsteadOfKeyword->kind === TokenKind::InsteadOfKeyword) { - // https://github.com/Microsoft/tolerant-php-parser/issues/190 - // TODO: In the next backwards incompatible release, convert targetName to a list? - $interfaceNameList = $this->parseQualifiedNameList($traitSelectAndAliasClause)->children ?? []; - $traitSelectAndAliasClause->targetName = $interfaceNameList[0] ?? new MissingToken(TokenKind::BarToken, $this->token->fullStart); - $traitSelectAndAliasClause->remainingTargetNames = array_slice($interfaceNameList, 1); + $traitSelectAndAliasClause->targetNameList = $this->parseQualifiedNameList($traitSelectAndAliasClause); } else { - $traitSelectAndAliasClause->targetName = + $traitSelectAndAliasClause->targetNameList = $this->parseQualifiedNameOrScopedPropertyAccessExpression($traitSelectAndAliasClause); - $traitSelectAndAliasClause->remainingTargetNames = []; } // TODO errors for insteadof/as @@ -4033,14 +3982,10 @@ private function parseInlineHtml($parentNode) { // This is the easiest way to represent `scriptSectionStartTag->kind ?? null) === TokenKind::ScriptSectionStartWithEchoTag) { - $echoStatement = new ExpressionStatement(); - - $echoExpression = new EchoExpression(); - $expressionList = $this->parseExpressionList($echoExpression) ?? (new MissingToken(TokenKind::Expression, $this->token->fullStart)); - $echoExpression->expressions = $expressionList; - $echoExpression->parent = $echoStatement; + $echoStatement = new EchoStatement(); + $expressionList = $this->parseExpressionList($echoStatement) ?? (new MissingToken(TokenKind::Expression, $this->token->fullStart)); + $echoStatement->expressions = $expressionList; - $echoStatement->expression = $echoExpression; $echoStatement->semicolon = $this->eatSemicolonOrAbortStatement(); $echoStatement->parent = $inlineHtml; // Deliberately leave echoKeyword as null instead of MissingToken diff --git a/tests/CallbackTestListener.php b/tests/CallbackTestListener.php index a980fc8a..fb585749 100644 --- a/tests/CallbackTestListener.php +++ b/tests/CallbackTestListener.php @@ -9,28 +9,13 @@ use PHPUnit\Framework\TestListenerDefaultImplementation; use PHPUnit\Framework\AssertionFailedError; -if (PHP_VERSION_ID >= 70100) { - // PHPUnit 7 requires a return type of void, which is impossible in php 7.0 - class CallbackTestListener implements TestListener { - private $cb; - public function __construct(Closure $cb) { - $this->cb = $cb; - } - use TestListenerDefaultImplementation; - // php 7.1 does not support param type widening. - function addFailure(Test $test, AssertionFailedError $e, float $time): void { - ($this->cb)($test); - } +class CallbackTestListener implements TestListener { + private $cb; + public function __construct(Closure $cb) { + $this->cb = $cb; } -} else { - class CallbackTestListener implements TestListener { - private $cb; - public function __construct(Closure $cb) { - $this->cb = $cb; - } - use TestListenerDefaultImplementation; - function addFailure(Test $test, AssertionFailedError $e, $time) { - ($this->cb)($test); - } + use TestListenerDefaultImplementation; + function addFailure(Test $test, AssertionFailedError $e, float $time): void { + ($this->cb)($test); } } diff --git a/tests/LexicalGrammarTest.php b/tests/LexicalGrammarTest.php index 0f70ddb6..1b3f4966 100644 --- a/tests/LexicalGrammarTest.php +++ b/tests/LexicalGrammarTest.php @@ -18,7 +18,7 @@ class LexicalGrammarTest extends TestCase { public function run(TestResult $result = null) : TestResult { if (!isset($GLOBALS["GIT_CHECKOUT_LEXER"])) { $GLOBALS["GIT_CHECKOUT_LEXER"] = true; - exec("git -C " . dirname(self::FILE_PATTERN) . " checkout *.php.tokens"); + // exec("git -C " . dirname(self::FILE_PATTERN) . " checkout *.php.tokens"); } $result->addListener(new CallbackTestListener(function (Test $test) { @@ -39,7 +39,7 @@ public function testOutputTokenClassificationAndLength($testCaseFile, $expectedT $fileContents = file_get_contents($testCaseFile); if (!file_exists($expectedTokensFile)) { file_put_contents($expectedTokensFile, $fileContents); - exec("git add " . $expectedTokensFile); + // exec("git add " . $expectedTokensFile); } $expectedTokens = str_replace("\r\n", "\n", file_get_contents($expectedTokensFile)); diff --git a/tests/ParserGrammarTest.php b/tests/ParserGrammarTest.php index a514ae1e..a7663b9f 100644 --- a/tests/ParserGrammarTest.php +++ b/tests/ParserGrammarTest.php @@ -18,7 +18,7 @@ class ParserGrammarTest extends TestCase { public function run(TestResult $result = null) : TestResult { if (!isset($GLOBALS["GIT_CHECKOUT_PARSER"])) { $GLOBALS["GIT_CHECKOUT_PARSER"] = true; - exec("git -C " . dirname(self::FILE_PATTERN) . " checkout *.php.tree *.php.diag"); + // exec("git -C " . dirname(self::FILE_PATTERN) . " checkout *.php.tree *.php.diag"); } $result->addListener(new CallbackTestListener(function (Test $test) { @@ -44,12 +44,12 @@ public function testOutputTreeClassificationAndLength($testCaseFile, $expectedTo $fileContents = file_get_contents($testCaseFile); if (!file_exists($expectedTokensFile)) { file_put_contents($expectedTokensFile, $fileContents); - exec("git add " . $expectedTokensFile); + // exec("git add " . $expectedTokensFile); } if (!file_exists($expectedDiagnosticsFile)) { file_put_contents($expectedDiagnosticsFile, $fileContents); - exec("git add " . $expectedDiagnosticsFile); + // exec("git add " . $expectedDiagnosticsFile); } $parser = new \Microsoft\PhpParser\Parser(); diff --git a/tests/cases/parser/InlineHtmlInControlStructures.php.tree b/tests/cases/parser/InlineHtmlInControlStructures.php.tree index 0d102096..33cd49bf 100644 --- a/tests/cases/parser/InlineHtmlInControlStructures.php.tree +++ b/tests/cases/parser/InlineHtmlInControlStructures.php.tree @@ -52,26 +52,22 @@ } }, { - "ExpressionStatement": { - "expression": { - "EchoExpression": { - "echoKeyword": null, - "expressions": { - "ExpressionList": { - "children": [ - { - "StringLiteral": { - "startQuote": null, - "children": { - "kind": "StringLiteralToken", - "textLength": 3 - }, - "endQuote": null - } - } - ] + "EchoStatement": { + "echoKeyword": null, + "expressions": { + "ExpressionList": { + "children": [ + { + "StringLiteral": { + "startQuote": null, + "children": { + "kind": "StringLiteralToken", + "textLength": 3 + }, + "endQuote": null + } } - } + ] } }, "semicolon": null diff --git a/tests/cases/parser/abstractMethodDeclaration1.php.tree b/tests/cases/parser/abstractMethodDeclaration1.php.tree index 1a03253c..2313ff32 100644 --- a/tests/cases/parser/abstractMethodDeclaration1.php.tree +++ b/tests/cases/parser/abstractMethodDeclaration1.php.tree @@ -68,8 +68,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/abstractMethodDeclaration2.php.tree b/tests/cases/parser/abstractMethodDeclaration2.php.tree index 42f78cdd..47b5dd25 100644 --- a/tests/cases/parser/abstractMethodDeclaration2.php.tree +++ b/tests/cases/parser/abstractMethodDeclaration2.php.tree @@ -65,8 +65,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/abstractMethodDeclaration3.php.tree b/tests/cases/parser/abstractMethodDeclaration3.php.tree index 4e988a77..02f623cf 100644 --- a/tests/cases/parser/abstractMethodDeclaration3.php.tree +++ b/tests/cases/parser/abstractMethodDeclaration3.php.tree @@ -68,8 +68,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/abstractMethodDeclaration4.php.tree b/tests/cases/parser/abstractMethodDeclaration4.php.tree index ad401f6f..376655fd 100644 --- a/tests/cases/parser/abstractMethodDeclaration4.php.tree +++ b/tests/cases/parser/abstractMethodDeclaration4.php.tree @@ -34,8 +34,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/abstractMethodDeclaration5.php.tree b/tests/cases/parser/abstractMethodDeclaration5.php.tree index 651b6ab7..b1b87ed6 100644 --- a/tests/cases/parser/abstractMethodDeclaration5.php.tree +++ b/tests/cases/parser/abstractMethodDeclaration5.php.tree @@ -67,11 +67,16 @@ "textLength": 1 }, "questionToken": null, - "returnType": { - "kind": "BoolReservedWord", - "textLength": 4 + "returnTypeList": { + "QualifiedNameList": { + "children": [ + { + "kind": "BoolReservedWord", + "textLength": 4 + } + ] + } }, - "otherReturnTypes": null, "compoundStatementOrSemicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/abstractMethodDeclaration6.php.tree b/tests/cases/parser/abstractMethodDeclaration6.php.tree index ea1a6962..01703411 100644 --- a/tests/cases/parser/abstractMethodDeclaration6.php.tree +++ b/tests/cases/parser/abstractMethodDeclaration6.php.tree @@ -72,11 +72,16 @@ "textLength": 1 }, "questionToken": null, - "returnType": { - "kind": "BoolReservedWord", - "textLength": 4 + "returnTypeList": { + "QualifiedNameList": { + "children": [ + { + "kind": "BoolReservedWord", + "textLength": 4 + } + ] + } }, - "otherReturnTypes": null, "compoundStatementOrSemicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/abstractMethodDeclaration7.php.tree b/tests/cases/parser/abstractMethodDeclaration7.php.tree index 3f8d4186..ba3509c2 100644 --- a/tests/cases/parser/abstractMethodDeclaration7.php.tree +++ b/tests/cases/parser/abstractMethodDeclaration7.php.tree @@ -64,8 +64,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/anonymousFunctionCreationExpression1.php.tree b/tests/cases/parser/anonymousFunctionCreationExpression1.php.tree index aa2fea01..88e7e76d 100644 --- a/tests/cases/parser/anonymousFunctionCreationExpression1.php.tree +++ b/tests/cases/parser/anonymousFunctionCreationExpression1.php.tree @@ -41,8 +41,7 @@ "anonymousFunctionUseClause": null, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { @@ -51,29 +50,25 @@ }, "statements": [ { - "ExpressionStatement": { - "expression": { - "EchoExpression": { - "echoKeyword": { - "kind": "EchoKeyword", - "textLength": 4 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "StringLiteral": { - "startQuote": null, - "children": { - "kind": "StringLiteralToken", - "textLength": 7 - }, - "endQuote": null - } - } - ] + "EchoStatement": { + "echoKeyword": { + "kind": "EchoKeyword", + "textLength": 4 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "StringLiteral": { + "startQuote": null, + "children": { + "kind": "StringLiteralToken", + "textLength": 7 + }, + "endQuote": null + } } - } + ] } }, "semicolon": { diff --git a/tests/cases/parser/anonymousFunctionCreationExpression10.php.tree b/tests/cases/parser/anonymousFunctionCreationExpression10.php.tree index 126a2a88..7c19f03e 100644 --- a/tests/cases/parser/anonymousFunctionCreationExpression10.php.tree +++ b/tests/cases/parser/anonymousFunctionCreationExpression10.php.tree @@ -84,11 +84,16 @@ "textLength": 1 }, "questionToken": null, - "returnType": { - "kind": "VoidReservedWord", - "textLength": 4 + "returnTypeList": { + "QualifiedNameList": { + "children": [ + { + "kind": "VoidReservedWord", + "textLength": 4 + } + ] + } }, - "otherReturnTypes": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/anonymousFunctionCreationExpression11.php.tree b/tests/cases/parser/anonymousFunctionCreationExpression11.php.tree index 08021e1b..fa8e19ca 100644 --- a/tests/cases/parser/anonymousFunctionCreationExpression11.php.tree +++ b/tests/cases/parser/anonymousFunctionCreationExpression11.php.tree @@ -55,8 +55,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/anonymousFunctionCreationExpression2.php.tree b/tests/cases/parser/anonymousFunctionCreationExpression2.php.tree index e69b922f..3a8cb5ec 100644 --- a/tests/cases/parser/anonymousFunctionCreationExpression2.php.tree +++ b/tests/cases/parser/anonymousFunctionCreationExpression2.php.tree @@ -38,8 +38,7 @@ "anonymousFunctionUseClause": null, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/anonymousFunctionCreationExpression3.php.tree b/tests/cases/parser/anonymousFunctionCreationExpression3.php.tree index c67ae972..189ced83 100644 --- a/tests/cases/parser/anonymousFunctionCreationExpression3.php.tree +++ b/tests/cases/parser/anonymousFunctionCreationExpression3.php.tree @@ -35,8 +35,7 @@ "anonymousFunctionUseClause": null, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/anonymousFunctionCreationExpression4.php.tree b/tests/cases/parser/anonymousFunctionCreationExpression4.php.tree index 24f67a7b..e66ea4b0 100644 --- a/tests/cases/parser/anonymousFunctionCreationExpression4.php.tree +++ b/tests/cases/parser/anonymousFunctionCreationExpression4.php.tree @@ -42,8 +42,7 @@ "anonymousFunctionUseClause": null, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/anonymousFunctionCreationExpression5.php.tree b/tests/cases/parser/anonymousFunctionCreationExpression5.php.tree index e08e3c56..8a8e6f41 100644 --- a/tests/cases/parser/anonymousFunctionCreationExpression5.php.tree +++ b/tests/cases/parser/anonymousFunctionCreationExpression5.php.tree @@ -55,8 +55,7 @@ "anonymousFunctionUseClause": null, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/anonymousFunctionCreationExpression6.php.tree b/tests/cases/parser/anonymousFunctionCreationExpression6.php.tree index 6dd40366..71d50f86 100644 --- a/tests/cases/parser/anonymousFunctionCreationExpression6.php.tree +++ b/tests/cases/parser/anonymousFunctionCreationExpression6.php.tree @@ -55,8 +55,7 @@ "anonymousFunctionUseClause": null, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/anonymousFunctionCreationExpression7.php.tree b/tests/cases/parser/anonymousFunctionCreationExpression7.php.tree index 136ee3e9..35a56bfd 100644 --- a/tests/cases/parser/anonymousFunctionCreationExpression7.php.tree +++ b/tests/cases/parser/anonymousFunctionCreationExpression7.php.tree @@ -94,8 +94,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser/binaryAssignmentExpressions6.php.tree b/tests/cases/parser/binaryAssignmentExpressions6.php.tree index 7a7a4a10..e65aedd7 100644 --- a/tests/cases/parser/binaryAssignmentExpressions6.php.tree +++ b/tests/cases/parser/binaryAssignmentExpressions6.php.tree @@ -38,7 +38,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "UnaryOpExpression": { diff --git a/tests/cases/parser/callExpression10.php.tree b/tests/cases/parser/callExpression10.php.tree index c77c7d88..196ea2a2 100644 --- a/tests/cases/parser/callExpression10.php.tree +++ b/tests/cases/parser/callExpression10.php.tree @@ -38,7 +38,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "ReservedWord": { @@ -58,7 +57,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "ReservedWord": { @@ -78,7 +76,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "ReservedWord": { diff --git a/tests/cases/parser/callExpression12.php.tree b/tests/cases/parser/callExpression12.php.tree index 3ea4b2eb..245292a1 100644 --- a/tests/cases/parser/callExpression12.php.tree +++ b/tests/cases/parser/callExpression12.php.tree @@ -38,7 +38,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "MemberAccessExpression": { diff --git a/tests/cases/parser/callExpression15.php.tree b/tests/cases/parser/callExpression15.php.tree index 4d83e934..288fd690 100644 --- a/tests/cases/parser/callExpression15.php.tree +++ b/tests/cases/parser/callExpression15.php.tree @@ -73,7 +73,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "NumericLiteral": { diff --git a/tests/cases/parser/callExpression16.php b/tests/cases/parser/callExpression16.php new file mode 100644 index 00000000..97c1677b --- /dev/null +++ b/tests/cases/parser/callExpression16.php @@ -0,0 +1,4 @@ + Date: Mon, 14 Dec 2020 22:07:17 -0500 Subject: [PATCH 2/5] v0.1.0: Raise minimum php version, change some AST representations Raise the minimum php version from 7.0 to 7.2. Depend on phpunit 8 for local development Unify method names for Node and Token to getFullStartPosition and getStartPosition (Consistently end public API methods with Position). Avoid the need for callers to check if an object is a Node/Token before calling a method. Convert UnsetIntrinsicExpression to UnsetStatement - it can only be used as a statement. Unify previously split up lists into a single list in some AST node properties (initially done that way for backward compatibility) Clean up unnecessary special case for throw - This continues to be parsed as an ExpressionStatement with the same precedence Rename throwStatement to throwExpression in test file names. --- .travis.yml | 18 +-- composer.json | 2 +- docs/ApiDocumentation.md | 12 +- src/FilePositionMap.php | 31 +--- src/Node.php | 34 ++--- src/Node/MissingMemberDeclaration.php | 8 +- src/Node/QualifiedName.php | 2 +- .../Statement/BreakOrContinueStatement.php | 7 +- .../UnsetStatement.php} | 10 +- src/Parser.php | 57 ++------ src/Token.php | 2 +- tests/LexicalGrammarTest.php | 4 +- tests/ParserGrammarTest.php | 6 +- tests/api/NodeApiTest.php | 2 +- ...rowStatement1.php => throwExpression1.php} | 0 ...nt1.php.diag => throwExpression1.php.diag} | 0 ...nt1.php.tree => throwExpression1.php.tree} | 24 ++-- ...rowStatement2.php => throwExpression2.php} | 0 ...nt2.php.diag => throwExpression2.php.diag} | 0 ...nt2.php.tree => throwExpression2.php.tree} | 0 ...rowStatement3.php => throwExpression3.php} | 0 ...nt3.php.diag => throwExpression3.php.diag} | 0 ...nt3.php.tree => throwExpression3.php.tree} | 0 ...rowStatement4.php => throwExpression4.php} | 0 ...nt4.php.diag => throwExpression4.php.diag} | 0 ...nt4.php.tree => throwExpression4.php.tree} | 0 ...rowStatement5.php => throwExpression5.php} | 0 ...nt5.php.diag => throwExpression5.php.diag} | 0 ...nt5.php.tree => throwExpression5.php.tree} | 0 ...rowStatement6.php => throwExpression6.php} | 0 ...nt6.php.diag => throwExpression6.php.diag} | 0 ...nt6.php.tree => throwExpression6.php.tree} | 0 ...rowStatement7.php => throwExpression7.php} | 0 ...nt7.php.diag => throwExpression7.php.diag} | 0 ...nt7.php.tree => throwExpression7.php.tree} | 0 .../typedPropertiesInvalidElsewhere.php.tree | 15 +- .../typedPropertiesInvalidElsewhere2.php.tree | 5 +- .../cases/parser/unionTypeProperty2.php.tree | 10 +- .../parser/unsetIntrinsicExpression1.php.tree | 78 +++++----- .../unsetIntrinsicExpression10.php.tree | 32 ++--- .../unsetIntrinsicExpression11.php.tree | 78 +++++----- .../unsetIntrinsicExpression12.php.tree | 52 ++++--- .../parser/unsetIntrinsicExpression2.php.tree | 52 ++++--- .../parser/unsetIntrinsicExpression3.php.tree | 34 ++--- .../parser/unsetIntrinsicExpression4.php.tree | 78 +++++----- .../parser/unsetIntrinsicExpression5.php.tree | 106 +++++++------- .../parser/unsetIntrinsicExpression6.php.tree | 88 ++++++------ .../parser/unsetIntrinsicExpression7.php.tree | 52 ++++--- .../parser/unsetIntrinsicExpression8.php.tree | 56 ++++---- .../parser/unsetIntrinsicExpression9.php.tree | 30 ++-- .../parser74/arrowFunctionUnionTypes.php.tree | 6 +- tests/cases/parser80/attributes1.php.tree | 3 +- tests/cases/parser80/attributes10.php.tree | 3 +- tests/cases/parser80/attributes12.php.tree | 3 +- tests/cases/parser80/attributes15.php.tree | 1 - tests/cases/parser80/attributes16.php.tree | 3 +- tests/cases/parser80/attributes17.php.tree | 3 +- tests/cases/parser80/attributes18.php.tree | 6 +- tests/cases/parser80/attributes2.php.tree | 1 - tests/cases/parser80/attributes3.php.tree | 3 +- tests/cases/parser80/attributes4.php.tree | 4 +- tests/cases/parser80/attributes5.php.tree | 6 +- tests/cases/parser80/attributes7.php.tree | 3 +- tests/cases/parser80/attributes8.php.tree | 3 +- tests/cases/parser80/attributes9.php.tree | 3 +- .../cases/parser80/matchExpression5.php.tree | 136 +++++++++--------- tests/cases/parser80/mixedType1.php.tree | 26 ++-- .../parser80/nullsafe_operator2.php.tree | 1 - tests/cases/parser81/enums2.php.tree | 6 +- tests/cases/parser81/enums4.php.tree | 3 +- 70 files changed, 542 insertions(+), 666 deletions(-) rename src/Node/{Expression/UnsetIntrinsicExpression.php => Statement/UnsetStatement.php} (81%) rename tests/cases/parser/{throwStatement1.php => throwExpression1.php} (100%) rename tests/cases/parser/{throwStatement1.php.diag => throwExpression1.php.diag} (100%) rename tests/cases/parser/{throwStatement1.php.tree => throwExpression1.php.tree} (55%) rename tests/cases/parser/{throwStatement2.php => throwExpression2.php} (100%) rename tests/cases/parser/{throwStatement2.php.diag => throwExpression2.php.diag} (100%) rename tests/cases/parser/{throwStatement2.php.tree => throwExpression2.php.tree} (100%) rename tests/cases/parser/{throwStatement3.php => throwExpression3.php} (100%) rename tests/cases/parser/{throwStatement3.php.diag => throwExpression3.php.diag} (100%) rename tests/cases/parser/{throwStatement3.php.tree => throwExpression3.php.tree} (100%) rename tests/cases/parser/{throwStatement4.php => throwExpression4.php} (100%) rename tests/cases/parser/{throwStatement4.php.diag => throwExpression4.php.diag} (100%) rename tests/cases/parser/{throwStatement4.php.tree => throwExpression4.php.tree} (100%) rename tests/cases/parser/{throwStatement5.php => throwExpression5.php} (100%) rename tests/cases/parser/{throwStatement5.php.diag => throwExpression5.php.diag} (100%) rename tests/cases/parser/{throwStatement5.php.tree => throwExpression5.php.tree} (100%) rename tests/cases/parser/{throwStatement6.php => throwExpression6.php} (100%) rename tests/cases/parser/{throwStatement6.php.diag => throwExpression6.php.diag} (100%) rename tests/cases/parser/{throwStatement6.php.tree => throwExpression6.php.tree} (100%) rename tests/cases/parser/{throwStatement7.php => throwExpression7.php} (100%) rename tests/cases/parser/{throwStatement7.php.diag => throwExpression7.php.diag} (100%) rename tests/cases/parser/{throwStatement7.php.tree => throwExpression7.php.tree} (100%) diff --git a/.travis.yml b/.travis.yml index 6d15865e..030b50a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,10 @@ language: php php: - - 7.0 - - 7.1 - - 7.2 - - 7.3 - - 7.4 - # Should be changed to 8.0 once travis officially provides that label. - - nightly + - '7.2' + - '7.3' + - '7.4' + - '8.0' env: - VALIDATION=false @@ -30,12 +27,7 @@ cache: before_script: - if [[ $STATIC_ANALYSIS = true ]]; then composer require phpstan/phpstan --no-update; fi - - | - if php -r 'exit(PHP_MAJOR_VERSION < 8 ? 0 : 1);'; - then composer install - else - composer install --ignore-platform-reqs - fi + - composer install - set -e # Stop on first error. - phpenv config-rm xdebug.ini || true - if find . -name "*.php" -path "./src/*" -path "./experiments/*" -path "./tools/*" -path "./syntax-visualizer/server/src/*" -exec php -l {} 2>&1 \; | grep "syntax error, unexpected"; then exit 1; fi diff --git a/composer.json b/composer.json index 21e67653..91df816a 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "php": ">=7.2" }, "require-dev": { - "phpunit/phpunit": "^7.5.20" + "phpunit/phpunit": "^8.5.15" }, "license": "MIT", "authors": [ diff --git a/docs/ApiDocumentation.md b/docs/ApiDocumentation.md index 58ce4604..adbee29f 100644 --- a/docs/ApiDocumentation.md +++ b/docs/ApiDocumentation.md @@ -10,15 +10,15 @@ ```php public function getNodeKindName ( ) : string ``` -### Node::getStart +### Node::getStartPosition Gets start position of Node, not including leading comments and whitespace. ```php -public function getStart ( ) : int +public function getStartPosition ( ) : int ``` -### Node::getFullStart +### Node::getFullStartPosition Gets start position of Node, including leading comments and whitespace ```php -public function getFullStart ( ) : int +public function getFullStartPosition ( ) : int ``` ### Node::getParent Gets parent of current node (returns null if has no parent) @@ -198,11 +198,11 @@ public function getFullText ( string & $document ) : string ```php public function getStartPosition ( ) ``` -### Token::getFullStart +### Token::getFullStartPosition > TODO: add doc comment ```php -public function getFullStart ( ) +public function getFullStartPosition ( ) ``` ### Token::getWidth > TODO: add doc comment diff --git a/src/FilePositionMap.php b/src/FilePositionMap.php index 1cb056bc..c6c9f479 100644 --- a/src/FilePositionMap.php +++ b/src/FilePositionMap.php @@ -34,33 +34,11 @@ public function __construct(string $file_contents) { $this->lineForCurrentOffset = 1; } - /** - * @param Node $node the node to get the start line for. - * TODO deprecate and merge this and getTokenStartLine into getStartLine - * if https://github.com/Microsoft/tolerant-php-parser/issues/166 is fixed, - * (i.e. if there is a consistent way to get the start offset) - */ - public function getNodeStartLine(Node $node) : int { - return $this->getLineNumberForOffset($node->getStart()); - } - - /** - * @param Token $token the token to get the start line for. - */ - public function getTokenStartLine(Token $token) : int { - return $this->getLineNumberForOffset($token->start); - } - /** * @param Node|Token $node */ public function getStartLine($node) : int { - if ($node instanceof Token) { - $offset = $node->start; - } else { - $offset = $node->getStart(); - } - return $this->getLineNumberForOffset($offset); + return $this->getLineNumberForOffset($node->getStartPosition()); } /** @@ -68,12 +46,7 @@ public function getStartLine($node) : int { * Similar to getStartLine but includes the column */ public function getStartLineCharacterPositionForOffset($node) : LineCharacterPosition { - if ($node instanceof Token) { - $offset = $node->start; - } else { - $offset = $node->getStart(); - } - return $this->getLineCharacterPositionForOffset($offset); + return $this->getLineCharacterPositionForOffset($node->getStartPosition()); } /** @param Node|Token $node */ diff --git a/src/Node.php b/src/Node.php index 4b87d417..66b8f99d 100644 --- a/src/Node.php +++ b/src/Node.php @@ -31,10 +31,10 @@ public function getNodeKindName() : string { * @return int * @throws \Exception */ - public function getStart() : int { + public function getStartPosition() : int { $child = $this->getChildNodesAndTokens()->current(); if ($child instanceof Node) { - return $child->getStart(); + return $child->getStartPosition(); } elseif ($child instanceof Token) { return $child->start; } @@ -46,7 +46,7 @@ public function getStart() : int { * @return int * @throws \Exception */ - public function getFullStart() : int { + public function getFullStartPosition() : int { foreach($this::CHILD_NAMES as $name) { if (($child = $this->$name) !== null) { @@ -59,7 +59,7 @@ public function getFullStart() : int { } if ($child instanceof Node) { - return $child->getFullStart(); + return $child->getFullStartPosition(); } if ($child instanceof Token) { @@ -330,7 +330,7 @@ public function getChildNames() { * @return int */ public function getWidth() : int { - $first = $this->getStart(); + $first = $this->getStartPosition(); $last = $this->getEndPosition(); return $last - $first; @@ -342,7 +342,7 @@ public function getWidth() : int { * @return int */ public function getFullWidth() : int { - $first = $this->getFullStart(); + $first = $this->getFullStartPosition(); $last = $this->getEndPosition(); return $last - $first; @@ -353,7 +353,7 @@ public function getFullWidth() : int { * @return string */ public function getText() : string { - $start = $this->getStart(); + $start = $this->getStartPosition(); $end = $this->getEndPosition(); $fileContents = $this->getFileContents(); @@ -365,7 +365,7 @@ public function getText() : string { * @return string */ public function getFullText() : string { - $start = $this->getFullStart(); + $start = $this->getFullStartPosition(); $end = $this->getEndPosition(); $fileContents = $this->getFileContents(); @@ -463,7 +463,7 @@ public function getDescendantNodeAtPosition(int $pos) { * @return bool */ private function containsPosition(int $pos): bool { - return $this->getStart() <= $pos && $pos <= $this->getEndPosition(); + return $this->getStartPosition() <= $pos && $pos <= $this->getEndPosition(); } /** @@ -476,7 +476,7 @@ private function containsPosition(int $pos): bool { public function getDocCommentText() { $leadingTriviaText = $this->getLeadingCommentAndWhitespaceText(); $leadingTriviaTokens = PhpTokenizer::getTokensArrayFromContent( - $leadingTriviaText, ParseContext::SourceElements, $this->getFullStart(), false + $leadingTriviaText, ParseContext::SourceElements, $this->getFullStartPosition(), false ); for ($i = \count($leadingTriviaTokens) - 1; $i >= 0; $i--) { $token = $leadingTriviaTokens[$i]; @@ -509,13 +509,13 @@ public function getImportTablesForCurrentScope() { $topLevelNamespaceStatements = $namespaceDefinition->compoundStatementOrSemicolon instanceof Token ? $namespaceDefinition->parent->statementList // we need to start from the namespace definition. : $namespaceDefinition->compoundStatementOrSemicolon->statements; - $namespaceFullStart = $namespaceDefinition->getFullStart(); + $namespaceFullStart = $namespaceDefinition->getFullStartPosition(); } else { $topLevelNamespaceStatements = $this->getRoot()->statementList; $namespaceFullStart = 0; } - $nodeFullStart = $this->getFullStart(); + $nodeFullStart = $this->getFullStartPosition(); // TODO optimize performance // Currently we rebuild the import tables on every call (and therefore every name resolution operation) @@ -535,10 +535,10 @@ public function getImportTablesForCurrentScope() { $contents = $this->getFileContents(); foreach ($topLevelNamespaceStatements as $useDeclaration) { - if ($useDeclaration->getFullStart() <= $namespaceFullStart) { + if ($useDeclaration->getFullStartPosition() <= $namespaceFullStart) { continue; } - if ($useDeclaration->getFullStart() > $nodeFullStart) { + if ($useDeclaration->getFullStartPosition() > $nodeFullStart) { break; } elseif (!($useDeclaration instanceof NamespaceUseDeclaration)) { continue; @@ -609,11 +609,11 @@ public function getNamespaceDefinition() { throw new \Exception("Invalid tree - SourceFileNode must always exist at root of tree."); } - $fullStart = $this->getFullStart(); + $fullStart = $this->getFullStartPosition(); $lastNamespaceDefinition = null; if ($namespaceDefinition instanceof SourceFileNode) { foreach ($namespaceDefinition->getChildNodes() as $childNode) { - if ($childNode instanceof NamespaceDefinition && $childNode->getFullStart() < $fullStart) { + if ($childNode instanceof NamespaceDefinition && $childNode->getFullStartPosition() < $fullStart) { $lastNamespaceDefinition = $childNode; } } @@ -662,7 +662,7 @@ public function getPreviousSibling() { * Add the alias and resolved name to the corresponding namespace, function, or const import table. * If the alias already exists, it will get replaced by the most recent using. * - * TODO - worth throwing an error here in stead? + * TODO - worth throwing an error here instead? */ private function addToImportTable($alias, $functionOrConst, $namespaceNameParts, $contents, & $namespaceImportTable, & $functionImportTable, & $constImportTable):array { diff --git a/src/Node/MissingMemberDeclaration.php b/src/Node/MissingMemberDeclaration.php index 6eca7333..c3043ca5 100644 --- a/src/Node/MissingMemberDeclaration.php +++ b/src/Node/MissingMemberDeclaration.php @@ -20,17 +20,13 @@ class MissingMemberDeclaration extends Node implements ModifiedTypeInterface { /** @var Token|null needed along with typeDeclaration for what looked like typed property declarations but was missing VariableName */ public $questionToken; - /** @var QualifiedName|Token|null */ - public $typeDeclaration; - /** @var DelimitedList\QualifiedNameList|null */ - public $otherTypeDeclarations; + public $typeDeclarationList; const CHILD_NAMES = [ 'attributes', 'modifiers', 'questionToken', - 'typeDeclaration', - 'otherTypeDeclarations', + 'typeDeclarationList', ]; } diff --git a/src/Node/QualifiedName.php b/src/Node/QualifiedName.php index 47663037..2eb08953 100644 --- a/src/Node/QualifiedName.php +++ b/src/Node/QualifiedName.php @@ -81,7 +81,7 @@ public function isUnqualifiedName() : bool { */ public function getResolvedName($namespaceDefinition = null) { // Name resolution not applicable to constructs that define symbol names or aliases. - if (($this->parent instanceof Node\Statement\NamespaceDefinition && $this->parent->name->getStart() === $this->getStart()) || + if (($this->parent instanceof Node\Statement\NamespaceDefinition && $this->parent->name->getStartPosition() === $this->getStartPosition()) || $this->parent instanceof Node\Statement\NamespaceUseDeclaration || $this->parent instanceof Node\NamespaceUseClause || $this->parent instanceof Node\NamespaceUseGroupClause || diff --git a/src/Node/Statement/BreakOrContinueStatement.php b/src/Node/Statement/BreakOrContinueStatement.php index e0ed83e1..442a2a87 100644 --- a/src/Node/Statement/BreakOrContinueStatement.php +++ b/src/Node/Statement/BreakOrContinueStatement.php @@ -60,12 +60,7 @@ public function getDiagnosticForNode() { } } - if ($breakoutLevel instanceof Token) { - $start = $breakoutLevel->getStartPosition(); - } - else { - $start = $breakoutLevel->getStart(); - } + $start = $breakoutLevel->getStartPosition(); $end = $breakoutLevel->getEndPosition(); return new Diagnostic( diff --git a/src/Node/Expression/UnsetIntrinsicExpression.php b/src/Node/Statement/UnsetStatement.php similarity index 81% rename from src/Node/Expression/UnsetIntrinsicExpression.php rename to src/Node/Statement/UnsetStatement.php index 4017f651..447e3cad 100644 --- a/src/Node/Expression/UnsetIntrinsicExpression.php +++ b/src/Node/Statement/UnsetStatement.php @@ -4,13 +4,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -namespace Microsoft\PhpParser\Node\Expression; +namespace Microsoft\PhpParser\Node\Statement; use Microsoft\PhpParser\Node\DelimitedList; use Microsoft\PhpParser\Node\Expression; use Microsoft\PhpParser\Token; -class UnsetIntrinsicExpression extends Expression { +class UnsetStatement extends Expression { /** @var Token */ public $unsetKeyword; @@ -24,10 +24,14 @@ class UnsetIntrinsicExpression extends Expression { /** @var Token */ public $closeParen; + /** @var Token */ + public $semicolon; + const CHILD_NAMES = [ 'unsetKeyword', 'openParen', 'expressions', - 'closeParen' + 'closeParen', + 'semicolon', ]; } diff --git a/src/Parser.php b/src/Parser.php index afd8188b..158ac490 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -50,7 +50,6 @@ ThrowExpression, UnaryExpression, UnaryOpExpression, - UnsetIntrinsicExpression, Variable, YieldExpression }; @@ -106,6 +105,7 @@ SwitchStatementNode, TraitDeclaration, TryStatement, + UnsetStatement, WhileStatement }; use Microsoft\PhpParser\Node\TraitMembers; @@ -533,8 +533,6 @@ private function parseStatementFn() { return $this->parseBreakOrContinueStatement($parentNode); case TokenKind::ReturnKeyword: // return-statement return $this->parseReturnStatement($parentNode); - case TokenKind::ThrowKeyword: // throw-statement - return $this->parseThrowStatement($parentNode); // try-statement case TokenKind::TryKeyword: @@ -2401,16 +2399,6 @@ private function parseReturnStatement($parentNode) { return $returnStatement; } - /** @return ExpressionStatement */ - private function parseThrowStatement($parentNode) { - $throwStatement = new ExpressionStatement(); - $throwStatement->expression = $this->parseThrowExpression($throwStatement); - $throwStatement->parent = $parentNode; - $throwStatement->semicolon = $this->eatSemicolonOrAbortStatement(); - - return $throwStatement; - } - /** @return ThrowExpression */ private function parseThrowExpression($parentNode) { $throwExpression = new ThrowExpression(); @@ -2625,20 +2613,6 @@ private function parseEchoStatement($parentNode) { return $echoStatement; } - /** @return ExpressionStatement */ - private function parseUnsetStatement($parentNode) { - $expressionStatement = new ExpressionStatement(); - - // FIXME: flatten into UnsetStatement instead? - $unsetExpression = $this->parseUnsetIntrinsicExpression($expressionStatement); - - $expressionStatement->parent = $parentNode; - $expressionStatement->expression = $unsetExpression; - $expressionStatement->semicolon = $this->eatSemicolonOrAbortStatement(); - - return $expressionStatement; - } - private function parseListIntrinsicExpression($parentNode) { $listExpression = new ListIntrinsicExpression(); $listExpression->parent = $parentNode; @@ -2703,16 +2677,16 @@ private function parseExpressionList($parentExpression) { ); } - private function parseUnsetIntrinsicExpression($parentNode) { - $unsetExpression = new UnsetIntrinsicExpression(); - $unsetExpression->parent = $parentNode; - - $unsetExpression->unsetKeyword = $this->eat1(TokenKind::UnsetKeyword); - $unsetExpression->openParen = $this->eat1(TokenKind::OpenParenToken); - $unsetExpression->expressions = $this->parseExpressionList($unsetExpression); - $unsetExpression->closeParen = $this->eat1(TokenKind::CloseParenToken); + private function parseUnsetStatement($parentNode) { + $unsetStatement = new UnsetStatement(); + $unsetStatement->parent = $parentNode; - return $unsetExpression; + $unsetStatement->unsetKeyword = $this->eat1(TokenKind::UnsetKeyword); + $unsetStatement->openParen = $this->eat1(TokenKind::OpenParenToken); + $unsetStatement->expressions = $this->parseExpressionList($unsetStatement); + $unsetStatement->closeParen = $this->eat1(TokenKind::CloseParenToken); + $unsetStatement->semicolon = $this->eatSemicolonOrAbortStatement(); + return $unsetStatement; } private function parseArrayCreationExpression($parentNode) { @@ -3225,6 +3199,7 @@ private function parsePropertyDeclaration($parentNode, $modifiers, $questionToke $propertyDeclaration->questionToken = $questionToken; if ($typeDeclarationList) { $propertyDeclaration->typeDeclarationList = $typeDeclarationList; + $typeDeclarationList->parent = $propertyDeclaration; } elseif ($questionToken) { $propertyDeclaration->typeDeclarationList = new MissingToken(TokenKind::PropertyType, $this->token->fullStart); } @@ -3618,14 +3593,10 @@ private function makeMissingMemberDeclaration($parentNode, $modifiers, $question $missingTraitMemberDeclaration->modifiers = $modifiers; $missingTraitMemberDeclaration->questionToken = $questionToken; if ($typeDeclarationList) { - $missingTraitMemberDeclaration->typeDeclaration = \array_shift($typeDeclarationList->children); - $missingTraitMemberDeclaration->typeDeclaration->parent = $missingTraitMemberDeclaration; - if ($typeDeclarationList->children) { - $missingTraitMemberDeclaration->otherTypeDeclarations = $typeDeclarationList; - $typeDeclarationList->parent = $missingTraitMemberDeclaration; - } + $missingTraitMemberDeclaration->typeDeclarationList = $typeDeclarationList; + $missingTraitMemberDeclaration->typeDeclarationList->parent = $missingTraitMemberDeclaration; } elseif ($questionToken) { - $missingTraitMemberDeclaration->typeDeclaration = new MissingToken(TokenKind::PropertyType, $this->token->fullStart); + $missingTraitMemberDeclaration->typeDeclarationList = new MissingToken(TokenKind::PropertyType, $this->token->fullStart); } return $missingTraitMemberDeclaration; } diff --git a/src/Token.php b/src/Token.php index f746e8a2..f4966cf3 100644 --- a/src/Token.php +++ b/src/Token.php @@ -61,7 +61,7 @@ public function getStartPosition() { /** * @return int */ - public function getFullStart() { + public function getFullStartPosition() { return $this->fullStart; } diff --git a/tests/LexicalGrammarTest.php b/tests/LexicalGrammarTest.php index 1b3f4966..0f70ddb6 100644 --- a/tests/LexicalGrammarTest.php +++ b/tests/LexicalGrammarTest.php @@ -18,7 +18,7 @@ class LexicalGrammarTest extends TestCase { public function run(TestResult $result = null) : TestResult { if (!isset($GLOBALS["GIT_CHECKOUT_LEXER"])) { $GLOBALS["GIT_CHECKOUT_LEXER"] = true; - // exec("git -C " . dirname(self::FILE_PATTERN) . " checkout *.php.tokens"); + exec("git -C " . dirname(self::FILE_PATTERN) . " checkout *.php.tokens"); } $result->addListener(new CallbackTestListener(function (Test $test) { @@ -39,7 +39,7 @@ public function testOutputTokenClassificationAndLength($testCaseFile, $expectedT $fileContents = file_get_contents($testCaseFile); if (!file_exists($expectedTokensFile)) { file_put_contents($expectedTokensFile, $fileContents); - // exec("git add " . $expectedTokensFile); + exec("git add " . $expectedTokensFile); } $expectedTokens = str_replace("\r\n", "\n", file_get_contents($expectedTokensFile)); diff --git a/tests/ParserGrammarTest.php b/tests/ParserGrammarTest.php index a7663b9f..a514ae1e 100644 --- a/tests/ParserGrammarTest.php +++ b/tests/ParserGrammarTest.php @@ -18,7 +18,7 @@ class ParserGrammarTest extends TestCase { public function run(TestResult $result = null) : TestResult { if (!isset($GLOBALS["GIT_CHECKOUT_PARSER"])) { $GLOBALS["GIT_CHECKOUT_PARSER"] = true; - // exec("git -C " . dirname(self::FILE_PATTERN) . " checkout *.php.tree *.php.diag"); + exec("git -C " . dirname(self::FILE_PATTERN) . " checkout *.php.tree *.php.diag"); } $result->addListener(new CallbackTestListener(function (Test $test) { @@ -44,12 +44,12 @@ public function testOutputTreeClassificationAndLength($testCaseFile, $expectedTo $fileContents = file_get_contents($testCaseFile); if (!file_exists($expectedTokensFile)) { file_put_contents($expectedTokensFile, $fileContents); - // exec("git add " . $expectedTokensFile); + exec("git add " . $expectedTokensFile); } if (!file_exists($expectedDiagnosticsFile)) { file_put_contents($expectedDiagnosticsFile, $fileContents); - // exec("git add " . $expectedDiagnosticsFile); + exec("git add " . $expectedDiagnosticsFile); } $parser = new \Microsoft\PhpParser\Parser(); diff --git a/tests/api/NodeApiTest.php b/tests/api/NodeApiTest.php index 426005f3..67436a59 100644 --- a/tests/api/NodeApiTest.php +++ b/tests/api/NodeApiTest.php @@ -25,7 +25,7 @@ function a () { public static $sourceFileNode; - public static function setUpBeforeClass() { + public static function setUpBeforeClass(): void { $parser = new Parser(); self::$sourceFileNode = $parser->parseSourceFile(self::FILE_CONTENTS); parent::setUpBeforeClass(); diff --git a/tests/cases/parser/throwStatement1.php b/tests/cases/parser/throwExpression1.php similarity index 100% rename from tests/cases/parser/throwStatement1.php rename to tests/cases/parser/throwExpression1.php diff --git a/tests/cases/parser/throwStatement1.php.diag b/tests/cases/parser/throwExpression1.php.diag similarity index 100% rename from tests/cases/parser/throwStatement1.php.diag rename to tests/cases/parser/throwExpression1.php.diag diff --git a/tests/cases/parser/throwStatement1.php.tree b/tests/cases/parser/throwExpression1.php.tree similarity index 55% rename from tests/cases/parser/throwStatement1.php.tree rename to tests/cases/parser/throwExpression1.php.tree index 39889744..70372917 100644 --- a/tests/cases/parser/throwStatement1.php.tree +++ b/tests/cases/parser/throwExpression1.php.tree @@ -12,17 +12,21 @@ } }, { - "ThrowStatement": { - "throwKeyword": { - "kind": "ThrowKeyword", - "textLength": 5 - }, + "ExpressionStatement": { "expression": { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 2 + "ThrowExpression": { + "throwKeyword": { + "kind": "ThrowKeyword", + "textLength": 5 + }, + "expression": { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 2 + } + } } } }, diff --git a/tests/cases/parser/throwStatement2.php b/tests/cases/parser/throwExpression2.php similarity index 100% rename from tests/cases/parser/throwStatement2.php rename to tests/cases/parser/throwExpression2.php diff --git a/tests/cases/parser/throwStatement2.php.diag b/tests/cases/parser/throwExpression2.php.diag similarity index 100% rename from tests/cases/parser/throwStatement2.php.diag rename to tests/cases/parser/throwExpression2.php.diag diff --git a/tests/cases/parser/throwStatement2.php.tree b/tests/cases/parser/throwExpression2.php.tree similarity index 100% rename from tests/cases/parser/throwStatement2.php.tree rename to tests/cases/parser/throwExpression2.php.tree diff --git a/tests/cases/parser/throwStatement3.php b/tests/cases/parser/throwExpression3.php similarity index 100% rename from tests/cases/parser/throwStatement3.php rename to tests/cases/parser/throwExpression3.php diff --git a/tests/cases/parser/throwStatement3.php.diag b/tests/cases/parser/throwExpression3.php.diag similarity index 100% rename from tests/cases/parser/throwStatement3.php.diag rename to tests/cases/parser/throwExpression3.php.diag diff --git a/tests/cases/parser/throwStatement3.php.tree b/tests/cases/parser/throwExpression3.php.tree similarity index 100% rename from tests/cases/parser/throwStatement3.php.tree rename to tests/cases/parser/throwExpression3.php.tree diff --git a/tests/cases/parser/throwStatement4.php b/tests/cases/parser/throwExpression4.php similarity index 100% rename from tests/cases/parser/throwStatement4.php rename to tests/cases/parser/throwExpression4.php diff --git a/tests/cases/parser/throwStatement4.php.diag b/tests/cases/parser/throwExpression4.php.diag similarity index 100% rename from tests/cases/parser/throwStatement4.php.diag rename to tests/cases/parser/throwExpression4.php.diag diff --git a/tests/cases/parser/throwStatement4.php.tree b/tests/cases/parser/throwExpression4.php.tree similarity index 100% rename from tests/cases/parser/throwStatement4.php.tree rename to tests/cases/parser/throwExpression4.php.tree diff --git a/tests/cases/parser/throwStatement5.php b/tests/cases/parser/throwExpression5.php similarity index 100% rename from tests/cases/parser/throwStatement5.php rename to tests/cases/parser/throwExpression5.php diff --git a/tests/cases/parser/throwStatement5.php.diag b/tests/cases/parser/throwExpression5.php.diag similarity index 100% rename from tests/cases/parser/throwStatement5.php.diag rename to tests/cases/parser/throwExpression5.php.diag diff --git a/tests/cases/parser/throwStatement5.php.tree b/tests/cases/parser/throwExpression5.php.tree similarity index 100% rename from tests/cases/parser/throwStatement5.php.tree rename to tests/cases/parser/throwExpression5.php.tree diff --git a/tests/cases/parser/throwStatement6.php b/tests/cases/parser/throwExpression6.php similarity index 100% rename from tests/cases/parser/throwStatement6.php rename to tests/cases/parser/throwExpression6.php diff --git a/tests/cases/parser/throwStatement6.php.diag b/tests/cases/parser/throwExpression6.php.diag similarity index 100% rename from tests/cases/parser/throwStatement6.php.diag rename to tests/cases/parser/throwExpression6.php.diag diff --git a/tests/cases/parser/throwStatement6.php.tree b/tests/cases/parser/throwExpression6.php.tree similarity index 100% rename from tests/cases/parser/throwStatement6.php.tree rename to tests/cases/parser/throwExpression6.php.tree diff --git a/tests/cases/parser/throwStatement7.php b/tests/cases/parser/throwExpression7.php similarity index 100% rename from tests/cases/parser/throwStatement7.php rename to tests/cases/parser/throwExpression7.php diff --git a/tests/cases/parser/throwStatement7.php.diag b/tests/cases/parser/throwExpression7.php.diag similarity index 100% rename from tests/cases/parser/throwStatement7.php.diag rename to tests/cases/parser/throwExpression7.php.diag diff --git a/tests/cases/parser/throwStatement7.php.tree b/tests/cases/parser/throwExpression7.php.tree similarity index 100% rename from tests/cases/parser/throwStatement7.php.tree rename to tests/cases/parser/throwExpression7.php.tree diff --git a/tests/cases/parser/typedPropertiesInvalidElsewhere.php.tree b/tests/cases/parser/typedPropertiesInvalidElsewhere.php.tree index 294ce63a..8870d357 100644 --- a/tests/cases/parser/typedPropertiesInvalidElsewhere.php.tree +++ b/tests/cases/parser/typedPropertiesInvalidElsewhere.php.tree @@ -42,11 +42,16 @@ } ], "questionToken": null, - "typeDeclaration": { - "kind": "IntReservedWord", - "textLength": 3 - }, - "otherTypeDeclarations": null + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "IntReservedWord", + "textLength": 3 + } + ] + } + } } }, { diff --git a/tests/cases/parser/typedPropertiesInvalidElsewhere2.php.tree b/tests/cases/parser/typedPropertiesInvalidElsewhere2.php.tree index af7b2e09..acd0a956 100644 --- a/tests/cases/parser/typedPropertiesInvalidElsewhere2.php.tree +++ b/tests/cases/parser/typedPropertiesInvalidElsewhere2.php.tree @@ -49,12 +49,11 @@ "kind": "QuestionToken", "textLength": 1 }, - "typeDeclaration": { + "typeDeclarationList": { "error": "MissingToken", "kind": "PropertyType", "textLength": 0 - }, - "otherTypeDeclarations": null + } } }, { diff --git a/tests/cases/parser/unionTypeProperty2.php.tree b/tests/cases/parser/unionTypeProperty2.php.tree index eb295b8c..91135623 100644 --- a/tests/cases/parser/unionTypeProperty2.php.tree +++ b/tests/cases/parser/unionTypeProperty2.php.tree @@ -42,13 +42,13 @@ } ], "questionToken": null, - "typeDeclaration": { - "kind": "IntReservedWord", - "textLength": 3 - }, - "otherTypeDeclarations": { + "typeDeclarationList": { "QualifiedNameList": { "children": [ + { + "kind": "IntReservedWord", + "textLength": 3 + }, { "kind": "BarToken", "textLength": 1 diff --git a/tests/cases/parser/unsetIntrinsicExpression1.php.tree b/tests/cases/parser/unsetIntrinsicExpression1.php.tree index 6169e6b0..2fb82c3a 100644 --- a/tests/cases/parser/unsetIntrinsicExpression1.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression1.php.tree @@ -12,51 +12,47 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 2 - } - } - }, - { - "kind": "CommaToken", - "textLength": 1 - }, - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 2 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 2 } - ] + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 2 + } + } } - }, - "closeParen": { - "kind": "CloseParenToken", - "textLength": 1 - } + ] } }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/unsetIntrinsicExpression10.php.tree b/tests/cases/parser/unsetIntrinsicExpression10.php.tree index 7c451113..7e411f20 100644 --- a/tests/cases/parser/unsetIntrinsicExpression10.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression10.php.tree @@ -12,24 +12,20 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": null, - "closeParen": { - "error": "MissingToken", - "kind": "CloseParenToken", - "textLength": 0 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": null, + "closeParen": { + "error": "MissingToken", + "kind": "CloseParenToken", + "textLength": 0 }, "semicolon": { "error": "MissingToken", diff --git a/tests/cases/parser/unsetIntrinsicExpression11.php.tree b/tests/cases/parser/unsetIntrinsicExpression11.php.tree index f4b1e006..f83738bd 100644 --- a/tests/cases/parser/unsetIntrinsicExpression11.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression11.php.tree @@ -12,51 +12,47 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 2 - } - } - }, - { - "kind": "CommaToken", - "textLength": 1 - }, - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 2 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 2 } - ] + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 2 + } + } } - }, - "closeParen": { - "kind": "CloseParenToken", - "textLength": 1 - } + ] } }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, "semicolon": { "error": "MissingToken", "kind": "SemicolonToken", diff --git a/tests/cases/parser/unsetIntrinsicExpression12.php.tree b/tests/cases/parser/unsetIntrinsicExpression12.php.tree index cd6e9b82..ed42a36e 100644 --- a/tests/cases/parser/unsetIntrinsicExpression12.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression12.php.tree @@ -42,38 +42,34 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 2 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 2 } - ] + } } - }, - "closeParen": { - "kind": "CloseParenToken", - "textLength": 1 - } + ] } }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/unsetIntrinsicExpression2.php.tree b/tests/cases/parser/unsetIntrinsicExpression2.php.tree index e8caaca0..efcd2120 100644 --- a/tests/cases/parser/unsetIntrinsicExpression2.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression2.php.tree @@ -12,38 +12,34 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 2 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 2 } - ] + } } - }, - "closeParen": { - "kind": "CloseParenToken", - "textLength": 1 - } + ] } }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/unsetIntrinsicExpression3.php.tree b/tests/cases/parser/unsetIntrinsicExpression3.php.tree index 93b5903a..64e4673b 100644 --- a/tests/cases/parser/unsetIntrinsicExpression3.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression3.php.tree @@ -12,25 +12,21 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "error": "MissingToken", - "kind": "OpenParenToken", - "textLength": 0 - }, - "expressions": null, - "closeParen": { - "error": "MissingToken", - "kind": "CloseParenToken", - "textLength": 0 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "error": "MissingToken", + "kind": "OpenParenToken", + "textLength": 0 + }, + "expressions": null, + "closeParen": { + "error": "MissingToken", + "kind": "CloseParenToken", + "textLength": 0 }, "semicolon": { "kind": "SemicolonToken", diff --git a/tests/cases/parser/unsetIntrinsicExpression4.php.tree b/tests/cases/parser/unsetIntrinsicExpression4.php.tree index 6bfe08a1..e3640ac2 100644 --- a/tests/cases/parser/unsetIntrinsicExpression4.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression4.php.tree @@ -12,51 +12,47 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 3 - } - } - }, - { - "kind": "CommaToken", - "textLength": 1 - }, - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 6 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 3 } - ] + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 6 + } + } } - }, - "closeParen": { - "kind": "CloseParenToken", - "textLength": 1 - } + ] } }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/unsetIntrinsicExpression5.php.tree b/tests/cases/parser/unsetIntrinsicExpression5.php.tree index 0ad953b1..a066983a 100644 --- a/tests/cases/parser/unsetIntrinsicExpression5.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression5.php.tree @@ -12,65 +12,61 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 3 - } - } - }, - { - "kind": "CommaToken", - "textLength": 1 - }, - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 6 - } - } - }, - { - "kind": "CommaToken", - "textLength": 1 - }, - { - "StringLiteral": { - "startQuote": null, - "children": { - "kind": "StringLiteralToken", - "textLength": 2 - }, - "endQuote": null - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 3 + } + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 6 } - ] + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "StringLiteral": { + "startQuote": null, + "children": { + "kind": "StringLiteralToken", + "textLength": 2 + }, + "endQuote": null + } } - }, - "closeParen": { - "kind": "CloseParenToken", - "textLength": 1 - } + ] } }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/unsetIntrinsicExpression6.php.tree b/tests/cases/parser/unsetIntrinsicExpression6.php.tree index 26663f76..6182a6b9 100644 --- a/tests/cases/parser/unsetIntrinsicExpression6.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression6.php.tree @@ -12,56 +12,52 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 3 - } - } - }, - { - "kind": "CommaToken", - "textLength": 1 - }, - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 6 - } - } - }, - { - "kind": "CommaToken", - "textLength": 1 + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 3 + } + } + }, + { + "kind": "CommaToken", + "textLength": 1 + }, + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 6 } - ] + } + }, + { + "kind": "CommaToken", + "textLength": 1 } - }, - "closeParen": { - "error": "MissingToken", - "kind": "CloseParenToken", - "textLength": 0 - } + ] } }, + "closeParen": { + "error": "MissingToken", + "kind": "CloseParenToken", + "textLength": 0 + }, "semicolon": { "error": "MissingToken", "kind": "SemicolonToken", diff --git a/tests/cases/parser/unsetIntrinsicExpression7.php.tree b/tests/cases/parser/unsetIntrinsicExpression7.php.tree index bdb3ea1a..c80364f5 100644 --- a/tests/cases/parser/unsetIntrinsicExpression7.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression7.php.tree @@ -12,38 +12,34 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 3 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 3 } - ] + } } - }, - "closeParen": { - "kind": "CloseParenToken", - "textLength": 1 - } + ] } }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/unsetIntrinsicExpression8.php.tree b/tests/cases/parser/unsetIntrinsicExpression8.php.tree index 14b2a985..bbfac601 100644 --- a/tests/cases/parser/unsetIntrinsicExpression8.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression8.php.tree @@ -12,40 +12,36 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "error": "MissingToken", - "kind": "OpenParenToken", - "textLength": 0 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "Variable": { - "dollar": null, - "name": { - "kind": "VariableName", - "textLength": 2 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "error": "MissingToken", + "kind": "OpenParenToken", + "textLength": 0 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "Variable": { + "dollar": null, + "name": { + "kind": "VariableName", + "textLength": 2 } - ] + } } - }, - "closeParen": { - "error": "MissingToken", - "kind": "CloseParenToken", - "textLength": 0 - } + ] } }, + "closeParen": { + "error": "MissingToken", + "kind": "CloseParenToken", + "textLength": 0 + }, "semicolon": { "kind": "SemicolonToken", "textLength": 1 diff --git a/tests/cases/parser/unsetIntrinsicExpression9.php.tree b/tests/cases/parser/unsetIntrinsicExpression9.php.tree index d8226c2e..821143b2 100644 --- a/tests/cases/parser/unsetIntrinsicExpression9.php.tree +++ b/tests/cases/parser/unsetIntrinsicExpression9.php.tree @@ -12,23 +12,19 @@ } }, { - "ExpressionStatement": { - "expression": { - "UnsetIntrinsicExpression": { - "unsetKeyword": { - "kind": "UnsetKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expressions": null, - "closeParen": { - "kind": "CloseParenToken", - "textLength": 1 - } - } + "UnsetStatement": { + "unsetKeyword": { + "kind": "UnsetKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expressions": null, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 }, "semicolon": { "kind": "SemicolonToken", diff --git a/tests/cases/parser74/arrowFunctionUnionTypes.php.tree b/tests/cases/parser74/arrowFunctionUnionTypes.php.tree index 72d5987f..c528910d 100644 --- a/tests/cases/parser74/arrowFunctionUnionTypes.php.tree +++ b/tests/cases/parser74/arrowFunctionUnionTypes.php.tree @@ -249,7 +249,7 @@ "QualifiedNameList": { "children": [ { - "kind": "IterableKeyword", + "kind": "IterableReservedWord", "textLength": 8 }, { @@ -406,7 +406,7 @@ "QualifiedNameList": { "children": [ { - "kind": "IterableKeyword", + "kind": "IterableReservedWord", "textLength": 8 }, { @@ -611,4 +611,4 @@ "textLength": 0 } } -} +} \ No newline at end of file diff --git a/tests/cases/parser80/attributes1.php.tree b/tests/cases/parser80/attributes1.php.tree index 04d1d7cb..87d39519 100644 --- a/tests/cases/parser80/attributes1.php.tree +++ b/tests/cases/parser80/attributes1.php.tree @@ -72,8 +72,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser80/attributes10.php.tree b/tests/cases/parser80/attributes10.php.tree index 45a0072c..5bed5717 100644 --- a/tests/cases/parser80/attributes10.php.tree +++ b/tests/cases/parser80/attributes10.php.tree @@ -116,8 +116,7 @@ "anonymousFunctionUseClause": null, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser80/attributes12.php.tree b/tests/cases/parser80/attributes12.php.tree index f610c41e..ced10a83 100644 --- a/tests/cases/parser80/attributes12.php.tree +++ b/tests/cases/parser80/attributes12.php.tree @@ -34,8 +34,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser80/attributes15.php.tree b/tests/cases/parser80/attributes15.php.tree index b5234ffc..5b10ecc3 100644 --- a/tests/cases/parser80/attributes15.php.tree +++ b/tests/cases/parser80/attributes15.php.tree @@ -85,7 +85,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "NumericLiteral": { diff --git a/tests/cases/parser80/attributes16.php.tree b/tests/cases/parser80/attributes16.php.tree index 5cf79aa0..5ff8067c 100644 --- a/tests/cases/parser80/attributes16.php.tree +++ b/tests/cases/parser80/attributes16.php.tree @@ -55,8 +55,7 @@ ], "modifiers": [], "questionToken": null, - "typeDeclaration": null, - "otherTypeDeclarations": null + "typeDeclarationList": null } } ], diff --git a/tests/cases/parser80/attributes17.php.tree b/tests/cases/parser80/attributes17.php.tree index 43656514..4a9827fd 100644 --- a/tests/cases/parser80/attributes17.php.tree +++ b/tests/cases/parser80/attributes17.php.tree @@ -56,8 +56,7 @@ ], "modifiers": [], "questionToken": null, - "typeDeclaration": null, - "otherTypeDeclarations": null + "typeDeclarationList": null } } ], diff --git a/tests/cases/parser80/attributes18.php.tree b/tests/cases/parser80/attributes18.php.tree index 2403179a..30973cc1 100644 --- a/tests/cases/parser80/attributes18.php.tree +++ b/tests/cases/parser80/attributes18.php.tree @@ -55,8 +55,7 @@ ], "visibilityToken": null, "questionToken": null, - "typeDeclaration": null, - "otherTypeDeclarations": null, + "typeDeclarationList": null, "byRefToken": null, "dotDotDotToken": null, "variableName": { @@ -78,8 +77,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "arrowToken": { "error": "MissingToken", "kind": "DoubleArrowToken", diff --git a/tests/cases/parser80/attributes2.php.tree b/tests/cases/parser80/attributes2.php.tree index 23d232d9..c221870b 100644 --- a/tests/cases/parser80/attributes2.php.tree +++ b/tests/cases/parser80/attributes2.php.tree @@ -48,7 +48,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "StringLiteral": { diff --git a/tests/cases/parser80/attributes3.php.tree b/tests/cases/parser80/attributes3.php.tree index b4c40293..dc7bf080 100644 --- a/tests/cases/parser80/attributes3.php.tree +++ b/tests/cases/parser80/attributes3.php.tree @@ -120,8 +120,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser80/attributes4.php.tree b/tests/cases/parser80/attributes4.php.tree index 5ef7d6ca..fe26f1e6 100644 --- a/tests/cases/parser80/attributes4.php.tree +++ b/tests/cases/parser80/attributes4.php.tree @@ -91,8 +91,7 @@ } ], "questionToken": null, - "typeDeclaration": null, - "otherTypeDeclarations": null, + "typeDeclarationList": null, "propertyElements": { "ExpressionList": { "children": [ @@ -188,7 +187,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "BinaryExpression": { diff --git a/tests/cases/parser80/attributes5.php.tree b/tests/cases/parser80/attributes5.php.tree index 567350d7..f5f564a9 100644 --- a/tests/cases/parser80/attributes5.php.tree +++ b/tests/cases/parser80/attributes5.php.tree @@ -73,8 +73,7 @@ ], "visibilityToken": null, "questionToken": null, - "typeDeclaration": null, - "otherTypeDeclarations": null, + "typeDeclarationList": null, "byRefToken": null, "dotDotDotToken": null, "variableName": { @@ -98,8 +97,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser80/attributes7.php.tree b/tests/cases/parser80/attributes7.php.tree index db91c8c0..80f68ec1 100644 --- a/tests/cases/parser80/attributes7.php.tree +++ b/tests/cases/parser80/attributes7.php.tree @@ -73,8 +73,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser80/attributes8.php.tree b/tests/cases/parser80/attributes8.php.tree index 5b8e1749..88bcd8c8 100644 --- a/tests/cases/parser80/attributes8.php.tree +++ b/tests/cases/parser80/attributes8.php.tree @@ -78,8 +78,7 @@ ], "modifiers": [], "questionToken": null, - "typeDeclaration": null, - "otherTypeDeclarations": null + "typeDeclarationList": null } } ], diff --git a/tests/cases/parser80/attributes9.php.tree b/tests/cases/parser80/attributes9.php.tree index 316f36d3..fc832504 100644 --- a/tests/cases/parser80/attributes9.php.tree +++ b/tests/cases/parser80/attributes9.php.tree @@ -98,8 +98,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "arrowToken": { "kind": "DoubleArrowToken", "textLength": 2 diff --git a/tests/cases/parser80/matchExpression5.php.tree b/tests/cases/parser80/matchExpression5.php.tree index d13154b9..b1ca4a0a 100644 --- a/tests/cases/parser80/matchExpression5.php.tree +++ b/tests/cases/parser80/matchExpression5.php.tree @@ -12,83 +12,79 @@ } }, { - "ExpressionStatement": { - "expression": { - "EchoExpression": { - "echoKeyword": { - "kind": "EchoKeyword", - "textLength": 4 - }, - "expressions": { - "ExpressionList": { - "children": [ - { - "MatchExpression": { - "matchToken": { - "kind": "MatchKeyword", - "textLength": 5 - }, - "openParen": { - "kind": "OpenParenToken", - "textLength": 1 - }, - "expression": { - "error": "MissingToken", - "kind": "Expression", - "textLength": 0 - }, - "closeParen": { - "kind": "CloseParenToken", - "textLength": 1 - }, - "openBrace": { - "kind": "OpenBraceToken", - "textLength": 1 - }, - "arms": { - "MatchExpressionArmList": { - "children": [ - { - "MatchArm": { - "conditionList": { - "MatchArmConditionList": { - "children": [ - { - "StringLiteral": { - "startQuote": null, - "children": { - "kind": "StringLiteralToken", - "textLength": 7 - }, - "endQuote": null - } - } - ] + "EchoStatement": { + "echoKeyword": { + "kind": "EchoKeyword", + "textLength": 4 + }, + "expressions": { + "ExpressionList": { + "children": [ + { + "MatchExpression": { + "matchToken": { + "kind": "MatchKeyword", + "textLength": 5 + }, + "openParen": { + "kind": "OpenParenToken", + "textLength": 1 + }, + "expression": { + "error": "MissingToken", + "kind": "Expression", + "textLength": 0 + }, + "closeParen": { + "kind": "CloseParenToken", + "textLength": 1 + }, + "openBrace": { + "kind": "OpenBraceToken", + "textLength": 1 + }, + "arms": { + "MatchExpressionArmList": { + "children": [ + { + "MatchArm": { + "conditionList": { + "MatchArmConditionList": { + "children": [ + { + "StringLiteral": { + "startQuote": null, + "children": { + "kind": "StringLiteralToken", + "textLength": 7 + }, + "endQuote": null + } } - }, - "arrowToken": { - "kind": "DoubleArrowToken", - "textLength": 2 - }, - "body": { - "error": "MissingToken", - "kind": "Expression", - "textLength": 0 - } + ] } + }, + "arrowToken": { + "kind": "DoubleArrowToken", + "textLength": 2 + }, + "body": { + "error": "MissingToken", + "kind": "Expression", + "textLength": 0 } - ] + } } - }, - "closeBrace": { - "kind": "CloseBraceToken", - "textLength": 1 - } + ] } + }, + "closeBrace": { + "kind": "CloseBraceToken", + "textLength": 1 } - ] + } } - } + ] } }, "semicolon": { diff --git a/tests/cases/parser80/mixedType1.php.tree b/tests/cases/parser80/mixedType1.php.tree index 7107817e..a7371b85 100644 --- a/tests/cases/parser80/mixedType1.php.tree +++ b/tests/cases/parser80/mixedType1.php.tree @@ -35,11 +35,16 @@ "attributes": null, "visibilityToken": null, "questionToken": null, - "typeDeclaration": { - "kind": "MixedReservedWord", - "textLength": 5 + "typeDeclarationList": { + "QualifiedNameList": { + "children": [ + { + "kind": "MixedReservedWord", + "textLength": 5 + } + ] + } }, - "otherTypeDeclarations": null, "byRefToken": null, "dotDotDotToken": null, "variableName": { @@ -62,11 +67,16 @@ "textLength": 1 }, "questionToken": null, - "returnType": { - "kind": "MixedReservedWord", - "textLength": 5 + "returnTypeList": { + "QualifiedNameList": { + "children": [ + { + "kind": "MixedReservedWord", + "textLength": 5 + } + ] + } }, - "otherReturnTypes": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser80/nullsafe_operator2.php.tree b/tests/cases/parser80/nullsafe_operator2.php.tree index f824ba54..5175d37a 100644 --- a/tests/cases/parser80/nullsafe_operator2.php.tree +++ b/tests/cases/parser80/nullsafe_operator2.php.tree @@ -47,7 +47,6 @@ "ArgumentExpression": { "name": null, "colonToken": null, - "byRefToken": null, "dotDotDotToken": null, "expression": { "NumericLiteral": { diff --git a/tests/cases/parser81/enums2.php.tree b/tests/cases/parser81/enums2.php.tree index 3cf4b7a5..acb453dd 100644 --- a/tests/cases/parser81/enums2.php.tree +++ b/tests/cases/parser81/enums2.php.tree @@ -106,8 +106,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { @@ -164,8 +163,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { diff --git a/tests/cases/parser81/enums4.php.tree b/tests/cases/parser81/enums4.php.tree index 93190467..682e41eb 100644 --- a/tests/cases/parser81/enums4.php.tree +++ b/tests/cases/parser81/enums4.php.tree @@ -97,8 +97,7 @@ }, "colonToken": null, "questionToken": null, - "returnType": null, - "otherReturnTypes": null, + "returnTypeList": null, "compoundStatementOrSemicolon": { "CompoundStatementNode": { "openBrace": { From 0b40640ac3f56c13c0217ac00380bcbb3adcf2a4 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Thu, 29 Apr 2021 17:19:15 -0400 Subject: [PATCH 3/5] Refactor to use getStartPosition --- README.md | 2 +- src/Node.php | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index ddb1df50..60a18364 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ an experiment and the start of a conversation. ![image](https://cloud.githubusercontent.com/assets/762848/19023070/4ab01c92-889a-11e6-9bb5-ec1a6816aba2.png) -This is the v1 branch, which changes data structures to support syntax added after the initial release for php 7.0. +This is the v0.1 branch, which changes data structures to support syntax added after the initial 0.0.x release line. ## Get Started After you've [configured your machine](docs/GettingStarted.md), you can use the parser to generate and work diff --git a/src/Node.php b/src/Node.php index 66b8f99d..35402f07 100644 --- a/src/Node.php +++ b/src/Node.php @@ -32,13 +32,7 @@ public function getNodeKindName() : string { * @throws \Exception */ public function getStartPosition() : int { - $child = $this->getChildNodesAndTokens()->current(); - if ($child instanceof Node) { - return $child->getStartPosition(); - } elseif ($child instanceof Token) { - return $child->start; - } - throw new \Exception("Unknown type in AST"); + return $this->getChildNodesAndTokens()->current()->getStartPosition(); } /** @@ -58,15 +52,7 @@ public function getFullStartPosition() : int { $child = $child[0]; } - if ($child instanceof Node) { - return $child->getFullStartPosition(); - } - - if ($child instanceof Token) { - return $child->fullStart; - } - - throw new \Exception("Unknown type in AST: " . \gettype($child)); + return $child->getFullStartPosition(); } }; From 5df29efbf9caeee1a6f8aa5474e64a428b8f6ad4 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Thu, 29 Apr 2021 17:29:06 -0400 Subject: [PATCH 4/5] Convert array()/list() to short array `[]` with phpcbf (Using short arrays for array destructuring requires php 7.1) --- src/Node.php | 12 ++++++------ src/Node/QualifiedName.php | 2 +- src/Parser.php | 14 +++++++------- src/PhpTokenizer.php | 2 +- src/TokenStringMaps.php | 8 ++++---- tests/LexerInvariantsTest.php | 6 +++--- tests/LexicalGrammarTest.php | 4 ++-- tests/ParserFrameworkValidationTests.php | 2 +- tests/ParserGrammarTest.php | 4 ++-- tests/ParserInvariantsTest.php | 6 +++--- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Node.php b/src/Node.php index 35402f07..c0aa2475 100644 --- a/src/Node.php +++ b/src/Node.php @@ -373,7 +373,7 @@ public function getLeadingCommentAndWhitespaceText() : string { } protected function getChildrenKvPairs() { - $result = array(); + $result = []; foreach ($this::CHILD_NAMES as $name) { $result[$name] = $this->$name; } @@ -657,20 +657,20 @@ private function addToImportTable($alias, $functionOrConst, $namespaceNameParts, // namespaces are case-insensitive // $alias = \strtolower($alias); $namespaceImportTable[$alias] = ResolvedName::buildName($namespaceNameParts, $contents); - return array($namespaceImportTable, $functionImportTable, $constImportTable); + return [$namespaceImportTable, $functionImportTable, $constImportTable]; } elseif ($functionOrConst->kind === TokenKind::FunctionKeyword) { // functions are case-insensitive // $alias = \strtolower($alias); $functionImportTable[$alias] = ResolvedName::buildName($namespaceNameParts, $contents); - return array($namespaceImportTable, $functionImportTable, $constImportTable); + return [$namespaceImportTable, $functionImportTable, $constImportTable]; } elseif ($functionOrConst->kind === TokenKind::ConstKeyword) { // constants are case-sensitive $constImportTable[$alias] = ResolvedName::buildName($namespaceNameParts, $contents); - return array($namespaceImportTable, $functionImportTable, $constImportTable); + return [$namespaceImportTable, $functionImportTable, $constImportTable]; } - return array($namespaceImportTable, $functionImportTable, $constImportTable); + return [$namespaceImportTable, $functionImportTable, $constImportTable]; } - return array($namespaceImportTable, $functionImportTable, $constImportTable); + return [$namespaceImportTable, $functionImportTable, $constImportTable]; } /** diff --git a/src/Node/QualifiedName.php b/src/Node/QualifiedName.php index 2eb08953..6955dc0e 100644 --- a/src/Node/QualifiedName.php +++ b/src/Node/QualifiedName.php @@ -110,7 +110,7 @@ public function getResolvedName($namespaceDefinition = null) { return $this->getNamespacedName(); } - list($namespaceImportTable, $functionImportTable, $constImportTable) = $this->getImportTablesForCurrentScope(); + [$namespaceImportTable, $functionImportTable, $constImportTable] = $this->getImportTablesForCurrentScope(); // QUALIFIED NAMES // - first segment of the name is translated according to the current class/namespace import table. diff --git a/src/Parser.php b/src/Parser.php index 158ac490..2139ee1a 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -179,7 +179,7 @@ public function parseSourceFile(string $fileContents, string $uri = null) : Sour $this->sourceFile = $sourceFile; $sourceFile->fileContents = $fileContents; $sourceFile->uri = $uri; - $sourceFile->statementList = array(); + $sourceFile->statementList = []; if ($this->getCurrentToken()->kind !== TokenKind::EndOfFileToken) { $inlineHTML = $this->parseInlineHtml($sourceFile); $sourceFile->statementList[] = $inlineHTML; @@ -221,7 +221,7 @@ private function parseList($parentNode, int $listParseContext) { $this->currentParseContext |= 1 << $listParseContext; $parseListElementFn = $this->getParseListElementFn($listParseContext); - $nodeArray = array(); + $nodeArray = []; while (!$this->isListTerminator($listParseContext)) { if ($this->isValidListElement($listParseContext, $this->getCurrentToken())) { $element = $parseListElementFn($parentNode); @@ -1293,7 +1293,7 @@ private function parseStringLiteralExpression2($parentNode) { $expression = new StringLiteral(); $expression->parent = $parentNode; $expression->startQuote = $this->eat(TokenKind::SingleQuoteToken, TokenKind::DoubleQuoteToken, TokenKind::HeredocStart, TokenKind::BacktickToken); - $expression->children = array(); + $expression->children = []; while (true) { switch ($this->getCurrentToken()->kind) { @@ -1449,7 +1449,7 @@ private function isModifier($token) { } private function parseModifiers() { - $modifiers = array(); + $modifiers = []; $token = $this->getCurrentToken(); while ($this->isModifier($token)) { $modifiers[] = $token; @@ -1963,12 +1963,12 @@ private function parseUnaryExpressionOrHigher($parentNode) { private function parseBinaryExpressionOrHigher($precedence, $parentNode) { $leftOperand = $this->parseUnaryExpressionOrHigher($parentNode); - list($prevNewPrecedence, $prevAssociativity) = self::UNKNOWN_PRECEDENCE_AND_ASSOCIATIVITY; + [$prevNewPrecedence, $prevAssociativity] = self::UNKNOWN_PRECEDENCE_AND_ASSOCIATIVITY; while (true) { $token = $this->getCurrentToken(); - list($newPrecedence, $associativity) = $this->getBinaryOperatorPrecedenceAndAssociativity($token); + [$newPrecedence, $associativity] = $this->getBinaryOperatorPrecedenceAndAssociativity($token); // Expressions using operators w/o associativity (equality, relational, instanceof) // cannot reference identical expression types within one of their operands. @@ -2416,7 +2416,7 @@ private function parseTryStatement($parentNode) { $tryStatement->tryKeyword = $this->eat1(TokenKind::TryKeyword); $tryStatement->compoundStatement = $this->parseCompoundStatement($tryStatement); // TODO verifiy this is only compound - $tryStatement->catchClauses = array(); // TODO - should be some standard for empty arrays vs. null? + $tryStatement->catchClauses = []; // TODO - should be some standard for empty arrays vs. null? while ($this->checkToken(TokenKind::CatchKeyword)) { $tryStatement->catchClauses[] = $this->parseCatchClause($tryStatement); } diff --git a/src/PhpTokenizer.php b/src/PhpTokenizer.php index e951bad6..95faed3e 100644 --- a/src/PhpTokenizer.php +++ b/src/PhpTokenizer.php @@ -82,7 +82,7 @@ public static function getTokensArrayFromContent( $tokens = static::tokenGetAll($content, $parseContext); - $arr = array(); + $arr = []; $fullStart = $start = $pos = $initialPos; if ($parseContext !== null) { // If needed, skip over the prefix we added for token_get_all and remove those tokens. diff --git a/src/TokenStringMaps.php b/src/TokenStringMaps.php index 441b33c3..6c1ab835 100644 --- a/src/TokenStringMaps.php +++ b/src/TokenStringMaps.php @@ -9,7 +9,7 @@ use Microsoft\PhpParser\TokenKind; class TokenStringMaps { - const KEYWORDS = array( + const KEYWORDS = [ "abstract" => TokenKind::AbstractKeyword, "and" => TokenKind::AndKeyword, "array" => TokenKind::ArrayKeyword, @@ -82,7 +82,7 @@ class TokenStringMaps { // TODO soft reserved words? - ); + ]; const RESERVED_WORDS = [ // http://php.net/manual/en/reserved.constants.php @@ -109,7 +109,7 @@ class TokenStringMaps { "mixed" => TokenKind::MixedReservedWord, ]; - const OPERATORS_AND_PUNCTUATORS = array( + const OPERATORS_AND_PUNCTUATORS = [ "[" => TokenKind::OpenBracketToken, "]" => TokenKind::CloseBracketToken, "(" => TokenKind::OpenParenToken, @@ -182,7 +182,7 @@ class TokenStringMaps { "?>\r" => TokenKind::ScriptSectionEndTag, // TODO, technically not an operator "@" => TokenKind::AtSymbolToken, // TODO not in spec "`" => TokenKind::BacktickToken - ); + ]; // TODO add new tokens } diff --git a/tests/LexerInvariantsTest.php b/tests/LexerInvariantsTest.php index ffd6bc43..1d721c93 100644 --- a/tests/LexerInvariantsTest.php +++ b/tests/LexerInvariantsTest.php @@ -10,13 +10,13 @@ use Microsoft\PhpParser\TokenKind; class LexerInvariantsTest extends TestCase { - const FILENAMES = array( + const FILENAMES = [ __dir__ . "/cases/testfile.php", __dir__ . "/cases/commentsFile.php" - ); + ]; public static function tokensArrayProvider() { - $fileToTokensMap = array(); + $fileToTokensMap = []; foreach (self::FILENAMES as $filename) { $lexer = \Microsoft\PhpParser\TokenStreamProviderFactory::GetTokenStreamProvider(file_get_contents($filename)); $fileToTokensMap[basename($filename)] = [$filename, $lexer->getTokensArray()]; diff --git a/tests/LexicalGrammarTest.php b/tests/LexicalGrammarTest.php index 0f70ddb6..6598dce0 100644 --- a/tests/LexicalGrammarTest.php +++ b/tests/LexicalGrammarTest.php @@ -57,7 +57,7 @@ public function lexicalProvider() { $skipped = json_decode(file_get_contents(__DIR__ . "/skipped.json")); - $testProviderArray = array(); + $testProviderArray = []; foreach ($testCases as $testCase) { if (in_array(basename($testCase), $skipped)) { continue; @@ -90,7 +90,7 @@ public function testSpecTokenClassificationAndLength($testCaseFile, $expectedTok public function lexicalSpecProvider() { $testCases = glob(__dir__ . "/cases/php-langspec/**/*.php"); - $testProviderArray = array(); + $testProviderArray = []; foreach ($testCases as $testCase) { $testProviderArray[basename($testCase)] = [$testCase, $testCase . ".tree"]; } diff --git a/tests/ParserFrameworkValidationTests.php b/tests/ParserFrameworkValidationTests.php index d73efc84..74ca07a2 100644 --- a/tests/ParserFrameworkValidationTests.php +++ b/tests/ParserFrameworkValidationTests.php @@ -12,7 +12,7 @@ public function frameworkErrorProvider() { $totalSize = 0; $frameworks = glob(__DIR__ . "/../validation/frameworks/*", GLOB_ONLYDIR); - $testProviderArray = array(); + $testProviderArray = []; foreach ($frameworks as $frameworkDir) { $frameworkName = basename($frameworkDir); $iterator = new RecursiveDirectoryIterator(__DIR__ . "/../validation/frameworks/" . $frameworkName); diff --git a/tests/ParserGrammarTest.php b/tests/ParserGrammarTest.php index a514ae1e..1bdd9645 100644 --- a/tests/ParserGrammarTest.php +++ b/tests/ParserGrammarTest.php @@ -88,7 +88,7 @@ public function treeProvider() { $testCases = glob(self::FILE_PATTERN . ".php"); $skipped = json_decode(file_get_contents(__DIR__ . "/skipped.json")); - $testProviderArray = array(); + $testProviderArray = []; foreach ($testCases as $testCase) { if (in_array(basename($testCase), $skipped)) { continue; @@ -124,7 +124,7 @@ public function outTreeProvider() { $testCases = glob(__DIR__ . "/cases/php-langspec/**/*.php"); $skipped = json_decode(file_get_contents(__DIR__ . "/skipped.json")); - $testProviderArray = array(); + $testProviderArray = []; foreach ($testCases as $case) { if (in_array(basename($case), $skipped)) { continue; diff --git a/tests/ParserInvariantsTest.php b/tests/ParserInvariantsTest.php index e66b1a9f..54b49e0d 100644 --- a/tests/ParserInvariantsTest.php +++ b/tests/ParserInvariantsTest.php @@ -13,7 +13,7 @@ class ParserInvariantsTest extends LexerInvariantsTest { const FILENAME_PATTERN = __dir__ . "/cases/{parser,parser74,}/*.php"; public static function sourceFileNodeProvider() { - $testFiles = array(); + $testFiles = []; $testCases = glob(self::FILENAME_PATTERN, GLOB_BRACE); foreach ($testCases as $filename) { @@ -24,13 +24,13 @@ public static function sourceFileNodeProvider() { } public static function tokensArrayProvider() { - $testFiles = array(); + $testFiles = []; $testCases = glob(self::FILENAME_PATTERN, GLOB_BRACE); foreach ($testCases as $filename) { $parser = new \Microsoft\PhpParser\Parser(); $sourceFileNode = $parser->parseSourceFile(file_get_contents($filename)); - $tokensArray = array(); + $tokensArray = []; foreach ($sourceFileNode->getDescendantNodesAndTokens() as $child) { if ($child instanceof \Microsoft\PhpParser\Token) { $tokensArray[] = $child; From 56f2603a0d9a82f82f573197be42a965c1310821 Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Thu, 3 Jun 2021 20:08:05 -0400 Subject: [PATCH 5/5] Support php 8.1 --- src/MissingToken.php | 3 +++ src/Node.php | 2 ++ src/SkippedToken.php | 3 +++ src/Token.php | 3 +++ 4 files changed, 11 insertions(+) diff --git a/src/MissingToken.php b/src/MissingToken.php index be3e6e04..177b46be 100644 --- a/src/MissingToken.php +++ b/src/MissingToken.php @@ -6,11 +6,14 @@ namespace Microsoft\PhpParser; +use ReturnTypeWillChange; + class MissingToken extends Token { public function __construct(int $kind, int $fullStart) { parent::__construct($kind, $fullStart, $fullStart, 0); } + #[ReturnTypeWillChange] public function jsonSerialize() { return array_merge( ["error" => $this->getTokenKindNameFromValue(TokenKind::MissingToken)], diff --git a/src/Node.php b/src/Node.php index c0aa2475..2eb6ebdc 100644 --- a/src/Node.php +++ b/src/Node.php @@ -11,6 +11,7 @@ use Microsoft\PhpParser\Node\SourceFileNode; use Microsoft\PhpParser\Node\Statement\NamespaceDefinition; use Microsoft\PhpParser\Node\Statement\NamespaceUseDeclaration; +use ReturnTypeWillChange; abstract class Node implements \JsonSerializable { const CHILD_NAMES = []; @@ -380,6 +381,7 @@ protected function getChildrenKvPairs() { return $result; } + #[ReturnTypeWillChange] public function jsonSerialize() { $kindName = $this->getNodeKindName(); return ["$kindName" => $this->getChildrenKvPairs()]; diff --git a/src/SkippedToken.php b/src/SkippedToken.php index 4c3174d2..34594db4 100644 --- a/src/SkippedToken.php +++ b/src/SkippedToken.php @@ -6,11 +6,14 @@ namespace Microsoft\PhpParser; +use ReturnTypeWillChange; + class SkippedToken extends Token { public function __construct(Token $token) { parent::__construct($token->kind, $token->fullStart, $token->start, $token->length); } + #[ReturnTypeWillChange] public function jsonSerialize() { return array_merge( ["error" => $this->getTokenKindNameFromValue(TokenKind::SkippedToken)], diff --git a/src/Token.php b/src/Token.php index f4966cf3..6c9daf74 100644 --- a/src/Token.php +++ b/src/Token.php @@ -6,6 +6,8 @@ namespace Microsoft\PhpParser; +use ReturnTypeWillChange; + use function substr; class Token implements \JsonSerializable { @@ -110,6 +112,7 @@ public static function getTokenKindNameFromValue($kind) { return $mapToKindName[$kind] ?? $kind; } + #[ReturnTypeWillChange] public function jsonSerialize() { $kindName = $this->getTokenKindNameFromValue($this->kind);