Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/Node/Expression/ObjectCreationExpression.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

namespace Microsoft\PhpParser\Node\Expression;

use Microsoft\PhpParser\Node\AttributeGroup;
use Microsoft\PhpParser\Node\ClassBaseClause;
use Microsoft\PhpParser\Node\ClassInterfaceClause;
use Microsoft\PhpParser\Node\ClassMembersNode;
Expand All @@ -19,6 +20,9 @@ class ObjectCreationExpression extends Expression {
/** @var Token */
public $newKeword;

/** @var AttributeGroup[]|null optional attributes of an anonymous class. */
public $attributes;

/** @var QualifiedName|Variable|Token */
public $classTypeDesignator;

Expand All @@ -41,7 +45,8 @@ class ObjectCreationExpression extends Expression {
public $classMembers;

const CHILD_NAMES = [
'newKeword', // TODO
'newKeword',
'attributes',
'classTypeDesignator',
'openParen',
'argumentExpressionList',
Expand Down
5 changes: 5 additions & 0 deletions src/Node/Statement/InterfaceDeclaration.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Microsoft\PhpParser\ClassLike;
use Microsoft\PhpParser\NamespacedNameInterface;
use Microsoft\PhpParser\NamespacedNameTrait;
use Microsoft\PhpParser\Node\AttributeGroup;
use Microsoft\PhpParser\Node\InterfaceBaseClause;
use Microsoft\PhpParser\Node\InterfaceMembers;
use Microsoft\PhpParser\Node\StatementNode;
Expand All @@ -17,6 +18,9 @@
class InterfaceDeclaration extends StatementNode implements NamespacedNameInterface, ClassLike {
use NamespacedNameTrait;

/** @var AttributeGroup[]|null */
public $attributes;

/** @var Token */
public $interfaceKeyword;

Expand All @@ -30,6 +34,7 @@ class InterfaceDeclaration extends StatementNode implements NamespacedNameInterf
public $interfaceMembers;

const CHILD_NAMES = [
'attributes',
'interfaceKeyword',
'name',
'interfaceBaseClause',
Expand Down
5 changes: 5 additions & 0 deletions src/Node/Statement/TraitDeclaration.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
use Microsoft\PhpParser\ClassLike;
use Microsoft\PhpParser\NamespacedNameInterface;
use Microsoft\PhpParser\NamespacedNameTrait;
use Microsoft\PhpParser\Node\AttributeGroup;
use Microsoft\PhpParser\Node\StatementNode;
use Microsoft\PhpParser\Node\TraitMembers;
use Microsoft\PhpParser\Token;

class TraitDeclaration extends StatementNode implements NamespacedNameInterface, ClassLike {
use NamespacedNameTrait;

/** @var AttributeGroup[]|null */
public $attributes;

/** @var Token */
public $traitKeyword;

Expand All @@ -26,6 +30,7 @@ class TraitDeclaration extends StatementNode implements NamespacedNameInterface,
public $traitMembers;

const CHILD_NAMES = [
'attributes',
'traitKeyword',
'name',
'traitMembers'
Expand Down
20 changes: 20 additions & 0 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,12 @@ private function parseAttributeStatement($parentNode) {
if ($parentNode instanceof ClassMembersNode) {
// Create a class element or a MissingMemberDeclaration
$statement = $this->parseClassElementFn()($parentNode);
} elseif ($parentNode instanceof TraitMembers) {
// Create a trait element or a MissingMemberDeclaration
$statement = $this->parseTraitElementFn()($parentNode);
} elseif ($parentNode instanceof InterfaceMembers) {
// Create an interface element or a MissingMemberDeclaration
$statement = $this->parseInterfaceElementFn()($parentNode);
} else {
// Classlikes, anonymous functions, global functions, and arrow functions can have attributes. Global constants cannot.
if (in_array($this->token->kind, [TokenKind::ClassKeyword, TokenKind::TraitKeyword, TokenKind::InterfaceKeyword, TokenKind::AbstractKeyword, TokenKind::FinalKeyword, TokenKind::FunctionKeyword, TokenKind::FnKeyword], true) ||
Expand All @@ -726,6 +732,8 @@ private function parseAttributeStatement($parentNode) {

if ($statement instanceof FunctionLike ||
$statement instanceof ClassDeclaration ||
$statement instanceof TraitDeclaration ||
$statement instanceof InterfaceDeclaration ||
$statement instanceof ClassConstDeclaration ||
$statement instanceof PropertyDeclaration ||
$statement instanceof MissingDeclaration ||
Expand Down Expand Up @@ -3088,6 +3096,12 @@ private function parseObjectCreationExpression($parentNode) {
// TODO - add tests for this scenario
$oldIsParsingObjectCreationExpression = $this->isParsingObjectCreationExpression;
$this->isParsingObjectCreationExpression = true;

if ($this->getCurrentToken()->kind === TokenKind::AttributeToken) {
// Attributes such as `new #[MyAttr] class` can only be used with anonymous class declarations.
// But handle this like $objectCreationExpression->classMembers and leave it up to the applications to detect the invalid combination.
$objectCreationExpression->attributes = $this->parseAttributeGroups($objectCreationExpression);
}
$objectCreationExpression->classTypeDesignator =
$this->eatOptional1(TokenKind::ClassKeyword) ??
$this->parseExpression($objectCreationExpression);
Expand Down Expand Up @@ -3311,6 +3325,9 @@ private function parseInterfaceElementFn() {
case TokenKind::FunctionKeyword:
return $this->parseMethodDeclaration($parentNode, $modifiers);

case TokenKind::AttributeToken:
return $this->parseAttributeStatement($parentNode);

default:
$missingInterfaceMemberDeclaration = new MissingMemberDeclaration();
$missingInterfaceMemberDeclaration->parent = $parentNode;
Expand Down Expand Up @@ -3491,6 +3508,9 @@ private function parseTraitElementFn() {
case TokenKind::UseKeyword:
return $this->parseTraitUseClause($parentNode);

case TokenKind::AttributeToken:
return $this->parseAttributeStatement($parentNode);

default:
return $this->parseRemainingPropertyDeclarationOrMissingMemberDeclaration($parentNode, $modifiers);
}
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/callExpression14.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"QualifiedName": {
"globalSpecifier": null,
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration1.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration10.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration11.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration12.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration13.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration14.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration15.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration16.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration2.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration3.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration4.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration5.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration7.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration8.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/interfaceDeclaration9.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
{
"InterfaceDeclaration": {
"attributes": null,
"interfaceKeyword": {
"kind": "InterfaceKeyword",
"textLength": 9
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/listExpression9.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"QualifiedName": {
"globalSpecifier": null,
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression1.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"QualifiedName": {
"globalSpecifier": null,
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression10.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"kind": "ClassKeyword",
"textLength": 5
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression11.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"kind": "ClassKeyword",
"textLength": 5
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression12.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"kind": "ClassKeyword",
"textLength": 5
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression13.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"QualifiedName": {
"globalSpecifier": null,
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression14.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"QualifiedName": {
"globalSpecifier": null,
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression15.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"ScopedPropertyAccessExpression": {
"scopeResolutionQualifier": {
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression16.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"QualifiedName": {
"globalSpecifier": null,
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression17.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"QualifiedName": {
"globalSpecifier": null,
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression18.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"ScopedPropertyAccessExpression": {
"scopeResolutionQualifier": {
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression19.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"ParenthesizedExpression": {
"openParen": {
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression2.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"QualifiedName": {
"globalSpecifier": null,
Expand Down
3 changes: 3 additions & 0 deletions tests/cases/parser/objectCreationExpression20.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"ParenthesizedExpression": {
"openParen": {
Expand All @@ -31,6 +32,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"ParenthesizedExpression": {
"openParen": {
Expand All @@ -43,6 +45,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"QualifiedName": {
"globalSpecifier": null,
Expand Down
1 change: 1 addition & 0 deletions tests/cases/parser/objectCreationExpression3.php.tree
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"kind": "NewKeyword",
"textLength": 3
},
"attributes": null,
"classTypeDesignator": {
"Variable": {
"dollar": null,
Expand Down
Loading