@@ -711,6 +711,12 @@ private function parseAttributeStatement($parentNode) {
711711 if ($ parentNode instanceof ClassMembersNode) {
712712 // Create a class element or a MissingMemberDeclaration
713713 $ statement = $ this ->parseClassElementFn ()($ parentNode );
714+ } elseif ($ parentNode instanceof TraitMembers) {
715+ // Create a trait element or a MissingMemberDeclaration
716+ $ statement = $ this ->parseTraitElementFn ()($ parentNode );
717+ } elseif ($ parentNode instanceof InterfaceMembers) {
718+ // Create an interface element or a MissingMemberDeclaration
719+ $ statement = $ this ->parseInterfaceElementFn ()($ parentNode );
714720 } else {
715721 // Classlikes, anonymous functions, global functions, and arrow functions can have attributes. Global constants cannot.
716722 if (in_array ($ this ->token ->kind , [TokenKind::ClassKeyword, TokenKind::TraitKeyword, TokenKind::InterfaceKeyword, TokenKind::AbstractKeyword, TokenKind::FinalKeyword, TokenKind::FunctionKeyword, TokenKind::FnKeyword], true ) ||
@@ -726,6 +732,8 @@ private function parseAttributeStatement($parentNode) {
726732
727733 if ($ statement instanceof FunctionLike ||
728734 $ statement instanceof ClassDeclaration ||
735+ $ statement instanceof TraitDeclaration ||
736+ $ statement instanceof InterfaceDeclaration ||
729737 $ statement instanceof ClassConstDeclaration ||
730738 $ statement instanceof PropertyDeclaration ||
731739 $ statement instanceof MissingDeclaration ||
@@ -3088,6 +3096,12 @@ private function parseObjectCreationExpression($parentNode) {
30883096 // TODO - add tests for this scenario
30893097 $ oldIsParsingObjectCreationExpression = $ this ->isParsingObjectCreationExpression ;
30903098 $ this ->isParsingObjectCreationExpression = true ;
3099+
3100+ if ($ this ->getCurrentToken ()->kind === TokenKind::AttributeToken) {
3101+ // Attributes such as `new #[MyAttr] class` can only be used with anonymous class declarations.
3102+ // But handle this like $objectCreationExpression->classMembers and leave it up to the applications to detect the invalid combination.
3103+ $ objectCreationExpression ->attributes = $ this ->parseAttributeGroups ($ objectCreationExpression );
3104+ }
30913105 $ objectCreationExpression ->classTypeDesignator =
30923106 $ this ->eatOptional1 (TokenKind::ClassKeyword) ??
30933107 $ this ->parseExpression ($ objectCreationExpression );
@@ -3311,6 +3325,9 @@ private function parseInterfaceElementFn() {
33113325 case TokenKind::FunctionKeyword:
33123326 return $ this ->parseMethodDeclaration ($ parentNode , $ modifiers );
33133327
3328+ case TokenKind::AttributeToken:
3329+ return $ this ->parseAttributeStatement ($ parentNode );
3330+
33143331 default :
33153332 $ missingInterfaceMemberDeclaration = new MissingMemberDeclaration ();
33163333 $ missingInterfaceMemberDeclaration ->parent = $ parentNode ;
@@ -3491,6 +3508,9 @@ private function parseTraitElementFn() {
34913508 case TokenKind::UseKeyword:
34923509 return $ this ->parseTraitUseClause ($ parentNode );
34933510
3511+ case TokenKind::AttributeToken:
3512+ return $ this ->parseAttributeStatement ($ parentNode );
3513+
34943514 default :
34953515 return $ this ->parseRemainingPropertyDeclarationOrMissingMemberDeclaration ($ parentNode , $ modifiers );
34963516 }
0 commit comments