@@ -3051,6 +3051,10 @@ class Parser {
30513051 /// typeWithParameters
30523052 /// : typeIdentifier typeParameters?
30533053 /// ;
3054+ /// classBody
3055+ /// : '{' (metadata memberDeclaration)* '}'
3056+ /// | ';'
3057+ /// ;
30543058 /// ```
30553059 Token parseClass (
30563060 Token token,
@@ -3066,16 +3070,28 @@ class Parser {
30663070 /* forExtensionType = */ false ,
30673071 );
30683072 token = parseClassHeaderOpt (token, beginToken, classKeyword);
3069- if (! token.next! .isA (TokenType .OPEN_CURLY_BRACKET )) {
3070- // Recovery
3071- token = parseClassHeaderRecovery (start, beginToken, classKeyword);
3072- ensureBlock (token, BlockKind .classDeclaration);
3073+ if (token.next! .isA (TokenType .SEMICOLON )) {
3074+ Token semicolonToken = token = token.next! ;
3075+ if (! _isDeclaringConstructorsFeatureEnabled) {
3076+ reportExperimentNotEnabled (
3077+ ExperimentalFlag .declaringConstructors,
3078+ semicolonToken,
3079+ semicolonToken,
3080+ );
3081+ }
3082+ listener.handleNoClassBody (semicolonToken);
3083+ } else {
3084+ if (! token.next! .isA (TokenType .OPEN_CURLY_BRACKET )) {
3085+ // Recovery
3086+ token = parseClassHeaderRecovery (start, beginToken, classKeyword);
3087+ ensureBlock (token, BlockKind .classDeclaration);
3088+ }
3089+ token = parseClassOrMixinOrExtensionBody (
3090+ token,
3091+ DeclarationKind .Class ,
3092+ className,
3093+ );
30733094 }
3074- token = parseClassOrMixinOrExtensionBody (
3075- token,
3076- DeclarationKind .Class ,
3077- className,
3078- );
30793095 listener.endClassDeclaration (beginToken, token);
30803096 return token;
30813097 }
@@ -3751,19 +3767,31 @@ class Parser {
37513767 );
37523768 Token start = token;
37533769 token = parseClassOrMixinOrEnumImplementsOpt (token);
3754- if (! token.next! .isA (TokenType .OPEN_CURLY_BRACKET )) {
3755- // TODO(johnniwinther): Reuse logic from [parseClassHeaderRecovery] to
3756- // handle `extends`, `with` and out-of-order/duplicate clauses.
3757- token = parseExtensionTypeHeaderRecovery (start, extensionKeyword);
3770+ if (token.next! .isA (TokenType .SEMICOLON )) {
3771+ Token semicolonToken = token = token.next! ;
3772+ if (! _isDeclaringConstructorsFeatureEnabled) {
3773+ reportExperimentNotEnabled (
3774+ ExperimentalFlag .declaringConstructors,
3775+ semicolonToken,
3776+ semicolonToken,
3777+ );
3778+ }
3779+ listener.handleNoExtensionTypeBody (semicolonToken);
3780+ } else {
3781+ if (! token.next! .isA (TokenType .OPEN_CURLY_BRACKET )) {
3782+ // TODO(johnniwinther): Reuse logic from [parseClassHeaderRecovery] to
3783+ // handle `extends`, `with` and out-of-order/duplicate clauses.
3784+ token = parseExtensionTypeHeaderRecovery (start, extensionKeyword);
37583785
3759- // Recovery
3760- ensureBlock (token, BlockKind .extensionTypeDeclaration);
3786+ // Recovery
3787+ ensureBlock (token, BlockKind .extensionTypeDeclaration);
3788+ }
3789+ token = parseClassOrMixinOrExtensionBody (
3790+ token,
3791+ DeclarationKind .ExtensionType ,
3792+ name.lexeme,
3793+ );
37613794 }
3762- token = parseClassOrMixinOrExtensionBody (
3763- token,
3764- DeclarationKind .ExtensionType ,
3765- name.lexeme,
3766- );
37673795 listener.endExtensionTypeDeclaration (
37683796 beginToken,
37693797 augmentToken,
0 commit comments