@@ -295,11 +295,8 @@ private function isListTerminator(int $parseContext) {
295
295
case ParseContext::SourceElements:
296
296
return false ;
297
297
298
- case ParseContext::InterfaceMembers:
299
- case ParseContext::ClassMembers:
298
+ case ParseContext::ClasslikeMembers:
300
299
case ParseContext::BlockStatements:
301
- case ParseContext::TraitMembers:
302
- case ParseContext::EnumMembers:
303
300
return $ tokenKind === TokenKind::CloseBraceToken;
304
301
case ParseContext::SwitchStatementElements:
305
302
return $ tokenKind === TokenKind::CloseBraceToken || $ tokenKind === TokenKind::EndSwitchKeyword;
@@ -345,17 +342,8 @@ private function isValidListElement($context, Token $token) {
345
342
case ParseContext::DeclareStatementElements:
346
343
return $ this ->isStatementStart ($ token );
347
344
348
- case ParseContext::ClassMembers:
349
- return $ this ->isClassMemberDeclarationStart ($ token );
350
-
351
- case ParseContext::TraitMembers:
352
- return $ this ->isTraitMemberDeclarationStart ($ token );
353
-
354
- case ParseContext::EnumMembers:
355
- return $ this ->isEnumMemberDeclarationStart ($ token );
356
-
357
- case ParseContext::InterfaceMembers:
358
- return $ this ->isInterfaceMemberDeclarationStart ($ token );
345
+ case ParseContext::ClasslikeMembers:
346
+ return $ this ->isClasslikeMemberDeclarationStart ($ token );
359
347
360
348
case ParseContext::SwitchStatementElements:
361
349
return
@@ -376,17 +364,8 @@ private function getParseListElementFn($context) {
376
364
case ParseContext::ForeachStatementElements:
377
365
case ParseContext::DeclareStatementElements:
378
366
return $ this ->parseStatementFn ();
379
- case ParseContext::ClassMembers:
380
- return $ this ->parseClassElementFn ();
381
-
382
- case ParseContext::TraitMembers:
383
- return $ this ->parseTraitElementFn ();
384
-
385
- case ParseContext::InterfaceMembers:
386
- return $ this ->parseInterfaceElementFn ();
387
-
388
- case ParseContext::EnumMembers:
389
- return $ this ->parseEnumElementFn ();
367
+ case ParseContext::ClasslikeMembers:
368
+ return $ this ->parseClasslikeElementFn ();
390
369
391
370
case ParseContext::SwitchStatementElements:
392
371
return $ this ->parseCaseOrDefaultStatement ();
@@ -636,15 +615,19 @@ private function parseStatementFn() {
636
615
};
637
616
}
638
617
639
- private function parseClassElementFn () {
618
+ private function parseClasslikeElementFn () {
640
619
return function ($ parentNode ) {
641
620
$ modifiers = $ this ->parseModifiers ();
642
621
643
622
$ token = $ this ->getCurrentToken ();
623
+ // Note that parsing the wrong type of class element in a classlike is a compile-time error, not a parse error.
644
624
switch ($ token ->kind ) {
645
625
case TokenKind::ConstKeyword:
646
626
return $ this ->parseClassConstDeclaration ($ parentNode , $ modifiers );
647
627
628
+ case TokenKind::CaseKeyword:
629
+ return $ this ->parseEnumCaseDeclaration ($ parentNode );
630
+
648
631
case TokenKind::FunctionKeyword:
649
632
return $ this ->parseMethodDeclaration ($ parentNode , $ modifiers );
650
633
@@ -688,14 +671,14 @@ private function parseClassDeclaration($parentNode) : Node {
688
671
$ classNode ->name ->kind = TokenKind::Name;
689
672
$ classNode ->classBaseClause = $ this ->parseClassBaseClause ($ classNode );
690
673
$ classNode ->classInterfaceClause = $ this ->parseClassInterfaceClause ($ classNode );
691
- $ classNode ->classMembers = $ this ->parseClassMembers ($ classNode );
674
+ $ classNode ->classMembers = $ this ->parseClasslikeMembers ($ classNode );
692
675
return $ classNode ;
693
676
}
694
677
695
- private function parseClassMembers ($ parentNode ) : ClassMembersNode {
678
+ private function parseClasslikeMembers ($ parentNode ) : ClassMembersNode {
696
679
$ classMembers = new ClassMembersNode ();
697
680
$ classMembers ->openBrace = $ this ->eat1 (TokenKind::OpenBraceToken);
698
- $ classMembers ->classMemberDeclarations = $ this ->parseList ($ classMembers , ParseContext::ClassMembers );
681
+ $ classMembers ->classMemberDeclarations = $ this ->parseList ($ classMembers , ParseContext::ClasslikeMembers );
699
682
$ classMembers ->closeBrace = $ this ->eat1 (TokenKind::CloseBraceToken);
700
683
$ classMembers ->parent = $ parentNode ;
701
684
return $ classMembers ;
@@ -741,18 +724,9 @@ private function parseAttributeExpression($parentNode) {
741
724
*/
742
725
private function parseAttributeStatement ($ parentNode ) {
743
726
$ attributeGroups = $ this ->parseAttributeGroups (null );
744
- if ($ parentNode instanceof ClassMembersNode) {
727
+ if ($ parentNode instanceof ClassMembersNode || $ parentNode instanceof TraitMembers || $ parentNode instanceof EnumMembers || $ parentNode instanceof InterfaceMembers ) {
745
728
// Create a class element or a MissingMemberDeclaration
746
- $ statement = $ this ->parseClassElementFn ()($ parentNode );
747
- } elseif ($ parentNode instanceof TraitMembers) {
748
- // Create a trait element or a MissingMemberDeclaration
749
- $ statement = $ this ->parseTraitElementFn ()($ parentNode );
750
- } elseif ($ parentNode instanceof EnumMembers) {
751
- // Create a enum element or a MissingMemberDeclaration
752
- $ statement = $ this ->parseEnumElementFn ()($ parentNode );
753
- } elseif ($ parentNode instanceof InterfaceMembers) {
754
- // Create an interface element or a MissingMemberDeclaration
755
- $ statement = $ this ->parseInterfaceElementFn ()($ parentNode );
729
+ $ statement = $ this ->parseClasslikeElementFn ()($ parentNode );
756
730
} else {
757
731
// Classlikes, anonymous functions, global functions, and arrow functions can have attributes. Global constants cannot.
758
732
if (in_array ($ this ->token ->kind , [TokenKind::ClassKeyword, TokenKind::TraitKeyword, TokenKind::InterfaceKeyword, TokenKind::AbstractKeyword, TokenKind::FinalKeyword, TokenKind::FunctionKeyword, TokenKind::FnKeyword, TokenKind::EnumKeyword], true ) ||
@@ -1045,7 +1019,7 @@ private function parseCompoundStatement($parentNode) {
1045
1019
return $ compoundStatement ;
1046
1020
}
1047
1021
1048
- private function isClassMemberDeclarationStart (Token $ token ) {
1022
+ private function isClasslikeMemberDeclarationStart (Token $ token ) {
1049
1023
switch ($ token ->kind ) {
1050
1024
// const-modifier
1051
1025
case TokenKind::ConstKeyword:
@@ -1073,6 +1047,9 @@ private function isClassMemberDeclarationStart(Token $token) {
1073
1047
1074
1048
// attributes
1075
1049
case TokenKind::AttributeToken:
1050
+
1051
+ // enum
1052
+ case TokenKind::CaseKeyword:
1076
1053
return true ;
1077
1054
1078
1055
}
@@ -1417,7 +1394,7 @@ private function parseStringLiteralExpression2($parentNode): StringLiteral {
1417
1394
case TokenKind::DollarOpenBraceToken:
1418
1395
case TokenKind::OpenBraceDollarToken:
1419
1396
$ expression ->children [] = $ this ->eat (TokenKind::DollarOpenBraceToken, TokenKind::OpenBraceDollarToken);
1420
- /**
1397
+ /**
1421
1398
* @phpstan-ignore-next-line "Strict comparison using
1422
1399
* === between 403|404 and 408 will always evaluate to
1423
1400
* false" is wrong because those tokens were eaten above
@@ -3286,7 +3263,7 @@ private function parseObjectCreationExpression($parentNode) {
3286
3263
$ objectCreationExpression ->classInterfaceClause = $ this ->parseClassInterfaceClause ($ objectCreationExpression );
3287
3264
3288
3265
if ($ this ->getCurrentToken ()->kind === TokenKind::OpenBraceToken) {
3289
- $ objectCreationExpression ->classMembers = $ this ->parseClassMembers ($ objectCreationExpression );
3266
+ $ objectCreationExpression ->classMembers = $ this ->parseClasslikeMembers ($ objectCreationExpression );
3290
3267
}
3291
3268
3292
3269
return $ objectCreationExpression ;
@@ -3474,63 +3451,12 @@ private function parseInterfaceDeclaration($parentNode): InterfaceDeclaration {
3474
3451
private function parseInterfaceMembers ($ parentNode ) : InterfaceMembers {
3475
3452
$ interfaceMembers = new InterfaceMembers ();
3476
3453
$ interfaceMembers ->openBrace = $ this ->eat1 (TokenKind::OpenBraceToken);
3477
- $ interfaceMembers ->interfaceMemberDeclarations = $ this ->parseList ($ interfaceMembers , ParseContext::InterfaceMembers );
3454
+ $ interfaceMembers ->interfaceMemberDeclarations = $ this ->parseList ($ interfaceMembers , ParseContext::ClasslikeMembers );
3478
3455
$ interfaceMembers ->closeBrace = $ this ->eat1 (TokenKind::CloseBraceToken);
3479
3456
$ interfaceMembers ->parent = $ parentNode ;
3480
3457
return $ interfaceMembers ;
3481
3458
}
3482
3459
3483
- private function isInterfaceMemberDeclarationStart (Token $ token ) {
3484
- switch ($ token ->kind ) {
3485
- // visibility-modifier
3486
- case TokenKind::PublicKeyword:
3487
- case TokenKind::ProtectedKeyword:
3488
- case TokenKind::PrivateKeyword:
3489
-
3490
- // static-modifier
3491
- case TokenKind::StaticKeyword:
3492
-
3493
- // readonly-modifier
3494
- case TokenKind::ReadonlyKeyword:
3495
-
3496
- // class-modifier
3497
- case TokenKind::AbstractKeyword:
3498
- case TokenKind::FinalKeyword:
3499
-
3500
- case TokenKind::ConstKeyword:
3501
-
3502
- case TokenKind::FunctionKeyword:
3503
-
3504
- case TokenKind::AttributeToken:
3505
- return true ;
3506
- }
3507
- return false ;
3508
- }
3509
-
3510
- private function parseInterfaceElementFn () {
3511
- return function ($ parentNode ) {
3512
- $ modifiers = $ this ->parseModifiers ();
3513
-
3514
- $ token = $ this ->getCurrentToken ();
3515
- switch ($ token ->kind ) {
3516
- case TokenKind::ConstKeyword:
3517
- return $ this ->parseClassConstDeclaration ($ parentNode , $ modifiers );
3518
-
3519
- case TokenKind::FunctionKeyword:
3520
- return $ this ->parseMethodDeclaration ($ parentNode , $ modifiers );
3521
-
3522
- case TokenKind::AttributeToken:
3523
- return $ this ->parseAttributeStatement ($ parentNode );
3524
-
3525
- default :
3526
- $ missingInterfaceMemberDeclaration = new MissingMemberDeclaration ();
3527
- $ missingInterfaceMemberDeclaration ->parent = $ parentNode ;
3528
- $ missingInterfaceMemberDeclaration ->modifiers = $ modifiers ;
3529
- return $ missingInterfaceMemberDeclaration ;
3530
- }
3531
- };
3532
- }
3533
-
3534
3460
private function parseInterfaceBaseClause ($ parentNode ) {
3535
3461
$ interfaceBaseClause = new InterfaceBaseClause ();
3536
3462
$ interfaceBaseClause ->parent = $ parentNode ;
@@ -3657,75 +3583,13 @@ private function parseTraitMembers($parentNode) {
3657
3583
3658
3584
$ traitMembers ->openBrace = $ this ->eat1 (TokenKind::OpenBraceToken);
3659
3585
3660
- $ traitMembers ->traitMemberDeclarations = $ this ->parseList ($ traitMembers , ParseContext::TraitMembers );
3586
+ $ traitMembers ->traitMemberDeclarations = $ this ->parseList ($ traitMembers , ParseContext::ClasslikeMembers );
3661
3587
3662
3588
$ traitMembers ->closeBrace = $ this ->eat1 (TokenKind::CloseBraceToken);
3663
3589
3664
3590
return $ traitMembers ;
3665
3591
}
3666
3592
3667
- private function isTraitMemberDeclarationStart ($ token ) {
3668
- switch ($ token ->kind ) {
3669
- // property-declaration
3670
- case TokenKind::VariableName:
3671
-
3672
- // modifiers
3673
- case TokenKind::PublicKeyword:
3674
- case TokenKind::ProtectedKeyword:
3675
- case TokenKind::PrivateKeyword:
3676
- case TokenKind::VarKeyword:
3677
- case TokenKind::StaticKeyword:
3678
- case TokenKind::AbstractKeyword:
3679
- case TokenKind::FinalKeyword:
3680
- case TokenKind::ReadonlyKeyword:
3681
- case TokenKind::ConstKeyword:
3682
-
3683
- // method-declaration
3684
- case TokenKind::FunctionKeyword:
3685
-
3686
- // trait-use-clauses
3687
- case TokenKind::UseKeyword:
3688
-
3689
- // attributes
3690
- case TokenKind::AttributeToken:
3691
- return true ;
3692
- }
3693
- return false ;
3694
- }
3695
-
3696
- private function parseTraitElementFn () {
3697
- return function ($ parentNode ) {
3698
- $ modifiers = $ this ->parseModifiers ();
3699
-
3700
- $ token = $ this ->getCurrentToken ();
3701
- switch ($ token ->kind ) {
3702
- case TokenKind::ConstKeyword:
3703
- return $ this ->parseClassConstDeclaration ($ parentNode , $ modifiers );
3704
-
3705
- case TokenKind::FunctionKeyword:
3706
- return $ this ->parseMethodDeclaration ($ parentNode , $ modifiers );
3707
-
3708
- case TokenKind::QuestionToken:
3709
- return $ this ->parseRemainingPropertyDeclarationOrMissingMemberDeclaration (
3710
- $ parentNode ,
3711
- $ modifiers ,
3712
- $ this ->eat1 (TokenKind::QuestionToken)
3713
- );
3714
- case TokenKind::VariableName:
3715
- return $ this ->parsePropertyDeclaration ($ parentNode , $ modifiers );
3716
-
3717
- case TokenKind::UseKeyword:
3718
- return $ this ->parseTraitUseClause ($ parentNode );
3719
-
3720
- case TokenKind::AttributeToken:
3721
- return $ this ->parseAttributeStatement ($ parentNode );
3722
-
3723
- default :
3724
- return $ this ->parseRemainingPropertyDeclarationOrMissingMemberDeclaration ($ parentNode , $ modifiers );
3725
- }
3726
- };
3727
- }
3728
-
3729
3593
private function parseEnumDeclaration ($ parentNode ) {
3730
3594
$ enumDeclaration = new EnumDeclaration ();
3731
3595
$ enumDeclaration ->parent = $ parentNode ;
@@ -3765,78 +3629,13 @@ private function parseEnumMembers($parentNode) {
3765
3629
3766
3630
$ enumMembers ->openBrace = $ this ->eat1 (TokenKind::OpenBraceToken);
3767
3631
3768
- $ enumMembers ->enumMemberDeclarations = $ this ->parseList ($ enumMembers , ParseContext::EnumMembers );
3632
+ $ enumMembers ->enumMemberDeclarations = $ this ->parseList ($ enumMembers , ParseContext::ClasslikeMembers );
3769
3633
3770
3634
$ enumMembers ->closeBrace = $ this ->eat1 (TokenKind::CloseBraceToken);
3771
3635
3772
3636
return $ enumMembers ;
3773
3637
}
3774
3638
3775
- private function isEnumMemberDeclarationStart ($ token ) {
3776
- switch ($ token ->kind ) {
3777
- // modifiers
3778
- case TokenKind::PublicKeyword:
3779
- case TokenKind::ProtectedKeyword:
3780
- case TokenKind::PrivateKeyword:
3781
- case TokenKind::StaticKeyword:
3782
- case TokenKind::AbstractKeyword:
3783
- case TokenKind::FinalKeyword:
3784
-
3785
- // method-declaration
3786
- case TokenKind::FunctionKeyword:
3787
-
3788
- // trait-use-clauses (enums can use traits)
3789
- case TokenKind::UseKeyword:
3790
-
3791
- // cases and constants
3792
- case TokenKind::CaseKeyword:
3793
- case TokenKind::ConstKeyword:
3794
-
3795
- // attributes
3796
- case TokenKind::AttributeToken:
3797
- return true ;
3798
- }
3799
- return false ;
3800
- }
3801
-
3802
- private function parseEnumElementFn () {
3803
- return function ($ parentNode ) {
3804
- $ modifiers = $ this ->parseModifiers ();
3805
-
3806
- $ token = $ this ->getCurrentToken ();
3807
- switch ($ token ->kind ) {
3808
- // TODO: CaseKeyword
3809
- case TokenKind::CaseKeyword:
3810
- return $ this ->parseEnumCaseDeclaration ($ parentNode );
3811
-
3812
- case TokenKind::ConstKeyword:
3813
- return $ this ->parseClassConstDeclaration ($ parentNode , $ modifiers );
3814
-
3815
- case TokenKind::FunctionKeyword:
3816
- return $ this ->parseMethodDeclaration ($ parentNode , $ modifiers );
3817
-
3818
- case TokenKind::QuestionToken:
3819
- return $ this ->parseRemainingPropertyDeclarationOrMissingMemberDeclaration (
3820
- $ parentNode ,
3821
- $ modifiers ,
3822
- $ this ->eat1 (TokenKind::QuestionToken)
3823
- );
3824
- case TokenKind::VariableName:
3825
- return $ this ->parsePropertyDeclaration ($ parentNode , $ modifiers );
3826
-
3827
- case TokenKind::UseKeyword:
3828
- return $ this ->parseTraitUseClause ($ parentNode );
3829
-
3830
- case TokenKind::AttributeToken:
3831
- return $ this ->parseAttributeStatement ($ parentNode );
3832
-
3833
- default :
3834
- return $ this ->parseRemainingPropertyDeclarationOrMissingMemberDeclaration ($ parentNode , $ modifiers );
3835
- }
3836
- };
3837
- }
3838
-
3839
-
3840
3639
/**
3841
3640
* @param Node $parentNode
3842
3641
* @param Token[] $modifiers
0 commit comments