From 53c69a614e2c1dfb3e60cd1954926edf5acb99a1 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 26 May 2026 10:39:42 -0700 Subject: [PATCH] Augment. When moving enum 'values' constants from augmentation to the introductory declaration, skip 'values' fragment of the augmentation. This `values` fragment is a purely synthetic construct. Change-Id: I795e6b2a92d8d5809c8107b41522e0d41c7d03bd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/506220 Reviewed-by: Johnni Winther Commit-Queue: Konstantin Shcheglov --- .../lib/src/summary2/element_builder.dart | 21 +- .../test/src/dart/parser/enum_test.dart | 54 + .../test/src/dart/resolution/enum_test.dart | 202 ++++ .../test/src/summary/elements/enum_test.dart | 1076 ++++++++++++++--- 4 files changed, 1206 insertions(+), 147 deletions(-) diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart index 66abea0d134..b71c0c6cdb0 100644 --- a/pkg/analyzer/lib/src/summary2/element_builder.dart +++ b/pkg/analyzer/lib/src/summary2/element_builder.dart @@ -120,9 +120,10 @@ class ElementBuilder { ? lastStaticFragments : lastInstanceFragments; var lastFragment = lastFragments[fragment.name]; + var fragmentToTrack = fragment; switch (fragment) { case FieldFragmentImpl(): - _handleInstanceFieldFragment( + fragmentToTrack = _handleInstanceFieldFragment( instanceElement, lastFragment, fragment, @@ -154,7 +155,7 @@ class ElementBuilder { default: throw UnimplementedError('${fragment.runtimeType}'); } - lastFragments[fragment.name] = fragment; + lastFragments[fragmentToTrack.name] = fragmentToTrack; } // Mark extension type members. @@ -403,7 +404,15 @@ class ElementBuilder { interfaceElement.addConstructor(element); } - void _handleInstanceFieldFragment( + /// Adds [fieldFragment] into the element model for [instanceElement]. + /// + /// The returned fragment is the one that should be tracked as the last + /// fragment with this name in its namespace. Usually this is [fieldFragment]. + /// For a synthetic enum `values` field from an augmentation, the synthetic + /// field itself is discarded after its initializer elements are moved into + /// the introductory `values` field, so the introductory `values` fragment is + /// returned instead. + FieldFragmentImpl _handleInstanceFieldFragment( InstanceElementImpl instanceElement, FragmentImpl? lastFragment, FieldFragmentImpl fieldFragment, @@ -411,7 +420,7 @@ class ElementBuilder { var instanceFragment = fieldFragment.enclosingFragment; // Move elements of `values` from augmentation to the first fragment. - if (fieldFragment.name == 'values' && + if (fieldFragment.isOriginEnumValues && instanceFragment is EnumFragmentImpl && instanceFragment.previousFragment != null) { var implicitsMap = libraryBuilder.implicitEnumNodes; @@ -421,7 +430,7 @@ class ElementBuilder { firstImplicit.valuesInitializer.addElements( augmentationImplicit.valuesInitializer.elements, ); - return; + return firstImplicit.valuesFragment; } instanceFragment.addField(fieldFragment); @@ -519,6 +528,8 @@ class ElementBuilder { setterElement.variable = fieldElement; } } + + return fieldFragment; } void _handleInstanceGetterFragment( diff --git a/pkg/analyzer/test/src/dart/parser/enum_test.dart b/pkg/analyzer/test/src/dart/parser/enum_test.dart index 2722b2b80dc..e4dae3f619c 100644 --- a/pkg/analyzer/test/src/dart/parser/enum_test.dart +++ b/pkg/analyzer/test/src/dart/parser/enum_test.dart @@ -16,6 +16,24 @@ main() { @reflectiveTest class EnumDeclarationParserTest extends ParserDiagnosticsTest { + test_augment_blockBody_empty() { + var parseResult = parseTestCodeWithDiagnostics(r''' +augment enum E {} +'''); + + var node = parseResult.findNode.singleEnumDeclaration; + assertParsedNodeText(node, r''' +EnumDeclaration + augmentKeyword: augment + enumKeyword: enum + namePart: NameWithTypeParameters + typeName: E + body: BlockEnumBody + leftBracket: { + rightBracket: } +'''); + } + test_augment_constant_add() { var parseResult = parseTestCodeWithDiagnostics(r''' augment enum E { @@ -95,6 +113,23 @@ EnumDeclaration '''); } + test_augment_emptyBody() { + var parseResult = parseTestCodeWithDiagnostics(r''' +augment enum E; +'''); + + var node = parseResult.findNode.singleEnumDeclaration; + assertParsedNodeText(node, r''' +EnumDeclaration + augmentKeyword: augment + enumKeyword: enum + namePart: NameWithTypeParameters + typeName: E + body: EmptyEnumBody + semicolon: ; +'''); + } + test_augment_implementsClause() { var parseResult = parseTestCodeWithDiagnostics(r''' augment enum E implements B {} @@ -116,6 +151,25 @@ EnumDeclaration '''); } + test_augment_noConstants_semicolon() { + var parseResult = parseTestCodeWithDiagnostics(r''' +augment enum E {;} +'''); + + var node = parseResult.findNode.singleEnumDeclaration; + assertParsedNodeText(node, r''' +EnumDeclaration + augmentKeyword: augment + enumKeyword: enum + namePart: NameWithTypeParameters + typeName: E + body: BlockEnumBody + leftBracket: { + semicolon: ; + rightBracket: } +'''); + } + test_augment_noConstants_semicolon_method() { var parseResult = parseTestCodeWithDiagnostics(r''' augment enum E {; diff --git a/pkg/analyzer/test/src/dart/resolution/enum_test.dart b/pkg/analyzer/test/src/dart/resolution/enum_test.dart index 6b636135830..582cccb730e 100644 --- a/pkg/analyzer/test/src/dart/resolution/enum_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/enum_test.dart @@ -34,6 +34,208 @@ enum E { '''); } + test_constant_augmentation_add() async { + var result = await resolveTestCodeWithDiagnostics(r''' +enum A { + v1 +} + +augment enum A { + v2 +} + +void f() { + A.v2; +} +'''); + + assertResolvedNodeText(result.unit, r''' +CompilationUnit + declarations + EnumDeclaration + enumKeyword: enum + namePart: NameWithTypeParameters + typeName: A + body: BlockEnumBody + leftBracket: { + constants + EnumConstantDeclaration + name: v1 + constructorElement: ::@enum::A::@constructor::new + declaredFragment: v1@11 + rightBracket: } + declaredFragment: A@5 + EnumDeclaration + augmentKeyword: augment + enumKeyword: enum + namePart: NameWithTypeParameters + typeName: A + body: BlockEnumBody + leftBracket: { + constants + EnumConstantDeclaration + name: v2 + constructorElement: ::@enum::A::@constructor::new + declaredFragment: v2@36 + rightBracket: } + declaredFragment: A@30 + FunctionDeclaration + returnType: NamedType + name: void + element: + type: void + name: f + functionExpression: FunctionExpression + parameters: FormalParameterList + leftParenthesis: ( + rightParenthesis: ) + body: BlockFunctionBody + block: Block + leftBracket: { + statements + ExpressionStatement + expression: PrefixedIdentifier + prefix: SimpleIdentifier + token: A + element: ::@enum::A + staticType: null + period: . + identifier: SimpleIdentifier + token: v2 + element: ::@enum::A::@getter::v2 + staticType: A + element: ::@enum::A::@getter::v2 + staticType: A + semicolon: ; + rightBracket: } + declaredFragment: f@47 + element: ::@function::f + type: void Function() + staticType: void Function() + declaredFragment: f@47 + element: ::@function::f + type: void Function() +'''); + } + + test_constant_augmentation_valuesGetter_recovery() async { + var result = await resolveTestCodeWithDiagnostics(r''' +enum A { + v1 +} + +augment enum A {; + static int get values => 0; +// ^^^^^^ +// [diag.valuesDeclarationInEnum] A member named 'values' can't be declared in an enum. +} + +augment enum A { + v2 +} + +void f() { + A.values; +} +'''); + + assertResolvedNodeText(result.unit, r''' +CompilationUnit + declarations + EnumDeclaration + enumKeyword: enum + namePart: NameWithTypeParameters + typeName: A + body: BlockEnumBody + leftBracket: { + constants + EnumConstantDeclaration + name: v1 + constructorElement: ::@enum::A::@constructor::new + declaredFragment: v1@11 + rightBracket: } + declaredFragment: A@5 + EnumDeclaration + augmentKeyword: augment + enumKeyword: enum + namePart: NameWithTypeParameters + typeName: A + body: BlockEnumBody + leftBracket: { + semicolon: ; + members + MethodDeclaration + modifierKeyword: static + returnType: NamedType + name: int + element: dart:core::@class::int + type: int + propertyKeyword: get + name: values + body: ExpressionFunctionBody + functionDefinition: => + expression: IntegerLiteral + literal: 0 + staticType: int + semicolon: ; + declaredFragment: values@52 + element: ::@enum::A::@getter::values#1 + type: int Function() + rightBracket: } + declaredFragment: A@30 + EnumDeclaration + augmentKeyword: augment + enumKeyword: enum + namePart: NameWithTypeParameters + typeName: A + body: BlockEnumBody + leftBracket: { + constants + EnumConstantDeclaration + name: v2 + constructorElement: ::@enum::A::@constructor::new + declaredFragment: v2@87 + rightBracket: } + declaredFragment: A@81 + FunctionDeclaration + returnType: NamedType + name: void + element: + type: void + name: f + functionExpression: FunctionExpression + parameters: FormalParameterList + leftParenthesis: ( + rightParenthesis: ) + body: BlockFunctionBody + block: Block + leftBracket: { + statements + ExpressionStatement + expression: PrefixedIdentifier + prefix: SimpleIdentifier + token: A + element: ::@enum::A + staticType: null + period: . + identifier: SimpleIdentifier + token: values + element: ::@enum::A::@getter::values + staticType: List + element: ::@enum::A::@getter::values + staticType: List + semicolon: ; + rightBracket: } + declaredFragment: f@98 + element: ::@function::f + type: void Function() + staticType: void Function() + declaredFragment: f@98 + element: ::@function::f + type: void Function() +'''); + } + test_constructor_argumentList_contextType() async { var result = await resolveTestCodeWithDiagnostics(r''' enum E { diff --git a/pkg/analyzer/test/src/summary/elements/enum_test.dart b/pkg/analyzer/test/src/summary/elements/enum_test.dart index 79bd622bfd3..65cb1fa896b 100644 --- a/pkg/analyzer/test/src/summary/elements/enum_test.dart +++ b/pkg/analyzer/test/src/summary/elements/enum_test.dart @@ -129,148 +129,6 @@ library '''); } - test_constant_augmentation_add() async { - var library = await buildLibrary(r''' -enum A { - v1 -} - -augment enum A { - v2 -} -'''); - - checkElementText(library, r''' -library - reference: - fragments - #F0 - element: - enums - #F1 enum A (nameOffset:5) (firstTokenOffset:0) (offset:5) - element: ::@enum::A - nextFragment: #F2 - fields - #F3 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v1 (nameOffset:11) (firstTokenOffset:11) (offset:11) - element: ::@enum::A::@field::v1 - initializer: expression_0 - InstanceCreationExpression - constructorName: ConstructorName - type: NamedType - name: A @-1 - element: ::@enum::A - type: A - element: ::@enum::A::@constructor::new - argumentList: ArgumentList - leftParenthesis: ( @0 - rightParenthesis: ) @0 - staticType: A - inducedGetter: #F4 - #F5 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) - element: ::@enum::A::@field::values - initializer: expression_1 - ListLiteral - leftBracket: [ @0 - elements - SimpleIdentifier - token: v1 @-1 - element: ::@enum::A::@getter::v1 - staticType: A - SimpleIdentifier - token: v2 @-1 - element: ::@enum::A::@getter::v2 - staticType: A - rightBracket: ] @0 - staticType: List - inducedGetter: #F6 - constructors - #F7 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) - element: ::@enum::A::@constructor::new - typeName: A - getters - #F4 isCompleteDeclaration isOriginVariable isStatic v1 (nameOffset:) (firstTokenOffset:) (offset:11) - element: ::@enum::A::@getter::v1 - inducingVariable: #F3 - #F6 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) - element: ::@enum::A::@getter::values - inducingVariable: #F5 - #F2 isAugmentation enum A (nameOffset:30) (firstTokenOffset:17) (offset:30) - element: ::@enum::A - previousFragment: #F1 - fields - #F8 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v2 (nameOffset:36) (firstTokenOffset:36) (offset:36) - element: ::@enum::A::@field::v2 - initializer: expression_2 - InstanceCreationExpression - constructorName: ConstructorName - type: NamedType - name: A @-1 - element: ::@enum::A - type: A - element: ::@enum::A::@constructor::new - argumentList: ArgumentList - leftParenthesis: ( @0 - rightParenthesis: ) @0 - staticType: A - inducedGetter: #F9 - getters - #F9 isCompleteDeclaration isOriginVariable isStatic v2 (nameOffset:) (firstTokenOffset:) (offset:36) - element: ::@enum::A::@getter::v2 - inducingVariable: #F8 - enums - isSimplyBounded enum A - reference: ::@enum::A - firstFragment: #F1 - supertype: Enum - fields - hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v1 - reference: ::@enum::A::@field::v1 - firstFragment: #F3 - type: A - constantInitializer - fragment: #F3 - expression: expression_0 - getter: ::@enum::A::@getter::v1 - isConst isOriginEnumValues isStatic values - reference: ::@enum::A::@field::values - firstFragment: #F5 - type: List - constantInitializer - fragment: #F5 - expression: expression_1 - getter: ::@enum::A::@getter::values - hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v2 - reference: ::@enum::A::@field::v2 - firstFragment: #F8 - type: A - constantInitializer - fragment: #F8 - expression: expression_2 - getter: ::@enum::A::@getter::v2 - constructors - isConst isOriginImplicitDefault new - reference: ::@enum::A::@constructor::new - firstFragment: #F7 - superConstructor: dart:core::@class::Enum::@constructor::new - getters - isOriginVariable isStatic v1 - reference: ::@enum::A::@getter::v1 - firstFragment: #F4 - returnType: A - variable: ::@enum::A::@field::v1 - isOriginVariable isStatic values - reference: ::@enum::A::@getter::values - firstFragment: #F6 - returnType: List - variable: ::@enum::A::@field::values - isOriginVariable isStatic v2 - reference: ::@enum::A::@getter::v2 - firstFragment: #F9 - returnType: A - variable: ::@enum::A::@field::v2 -'''); - } - test_constant_augmentation_add_chain() async { var library = await buildLibrary(r''' enum A { @@ -1196,6 +1054,824 @@ library '''); } + test_constant_augmentation_introductoryHasConstants_augmentationHasConstants() async { + var library = await buildLibrary(r''' +enum A { + v1 +} + +augment enum A { + v2 +} +'''); + + checkElementText(library, r''' +library + reference: + fragments + #F0 + element: + enums + #F1 enum A (nameOffset:5) (firstTokenOffset:0) (offset:5) + element: ::@enum::A + nextFragment: #F2 + fields + #F3 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v1 (nameOffset:11) (firstTokenOffset:11) (offset:11) + element: ::@enum::A::@field::v1 + initializer: expression_0 + InstanceCreationExpression + constructorName: ConstructorName + type: NamedType + name: A @-1 + element: ::@enum::A + type: A + element: ::@enum::A::@constructor::new + argumentList: ArgumentList + leftParenthesis: ( @0 + rightParenthesis: ) @0 + staticType: A + inducedGetter: #F4 + #F5 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::A::@field::values + initializer: expression_1 + ListLiteral + leftBracket: [ @0 + elements + SimpleIdentifier + token: v1 @-1 + element: ::@enum::A::@getter::v1 + staticType: A + SimpleIdentifier + token: v2 @-1 + element: ::@enum::A::@getter::v2 + staticType: A + rightBracket: ] @0 + staticType: List + inducedGetter: #F6 + constructors + #F7 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::A::@constructor::new + typeName: A + getters + #F4 isCompleteDeclaration isOriginVariable isStatic v1 (nameOffset:) (firstTokenOffset:) (offset:11) + element: ::@enum::A::@getter::v1 + inducingVariable: #F3 + #F6 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::A::@getter::values + inducingVariable: #F5 + #F2 isAugmentation enum A (nameOffset:30) (firstTokenOffset:17) (offset:30) + element: ::@enum::A + previousFragment: #F1 + fields + #F8 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v2 (nameOffset:36) (firstTokenOffset:36) (offset:36) + element: ::@enum::A::@field::v2 + initializer: expression_2 + InstanceCreationExpression + constructorName: ConstructorName + type: NamedType + name: A @-1 + element: ::@enum::A + type: A + element: ::@enum::A::@constructor::new + argumentList: ArgumentList + leftParenthesis: ( @0 + rightParenthesis: ) @0 + staticType: A + inducedGetter: #F9 + getters + #F9 isCompleteDeclaration isOriginVariable isStatic v2 (nameOffset:) (firstTokenOffset:) (offset:36) + element: ::@enum::A::@getter::v2 + inducingVariable: #F8 + enums + isSimplyBounded enum A + reference: ::@enum::A + firstFragment: #F1 + supertype: Enum + fields + hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v1 + reference: ::@enum::A::@field::v1 + firstFragment: #F3 + type: A + constantInitializer + fragment: #F3 + expression: expression_0 + getter: ::@enum::A::@getter::v1 + isConst isOriginEnumValues isStatic values + reference: ::@enum::A::@field::values + firstFragment: #F5 + type: List + constantInitializer + fragment: #F5 + expression: expression_1 + getter: ::@enum::A::@getter::values + hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v2 + reference: ::@enum::A::@field::v2 + firstFragment: #F8 + type: A + constantInitializer + fragment: #F8 + expression: expression_2 + getter: ::@enum::A::@getter::v2 + constructors + isConst isOriginImplicitDefault new + reference: ::@enum::A::@constructor::new + firstFragment: #F7 + superConstructor: dart:core::@class::Enum::@constructor::new + getters + isOriginVariable isStatic v1 + reference: ::@enum::A::@getter::v1 + firstFragment: #F4 + returnType: A + variable: ::@enum::A::@field::v1 + isOriginVariable isStatic values + reference: ::@enum::A::@getter::values + firstFragment: #F6 + returnType: List + variable: ::@enum::A::@field::values + isOriginVariable isStatic v2 + reference: ::@enum::A::@getter::v2 + firstFragment: #F9 + returnType: A + variable: ::@enum::A::@field::v2 +'''); + } + + test_constant_augmentation_introductoryHasConstants_augmentationNoConstants_blockBody_empty() async { + var library = await buildLibrary(r''' +enum E { v } + +augment enum E {} +'''); + checkElementText(library, r''' +library + reference: + fragments + #F0 + element: + enums + #F1 enum E (nameOffset:5) (firstTokenOffset:0) (offset:5) + element: ::@enum::E + nextFragment: #F2 + fields + #F3 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v (nameOffset:9) (firstTokenOffset:9) (offset:9) + element: ::@enum::E::@field::v + initializer: expression_0 + InstanceCreationExpression + constructorName: ConstructorName + type: NamedType + name: E @-1 + element: ::@enum::E + type: E + element: ::@enum::E::@constructor::new + argumentList: ArgumentList + leftParenthesis: ( @0 + rightParenthesis: ) @0 + staticType: E + inducedGetter: #F4 + #F5 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@field::values + initializer: expression_1 + ListLiteral + leftBracket: [ @0 + elements + SimpleIdentifier + token: v @-1 + element: ::@enum::E::@getter::v + staticType: E + rightBracket: ] @0 + staticType: List + inducedGetter: #F6 + constructors + #F7 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@constructor::new + typeName: E + getters + #F4 isCompleteDeclaration isOriginVariable isStatic v (nameOffset:) (firstTokenOffset:) (offset:9) + element: ::@enum::E::@getter::v + inducingVariable: #F3 + #F6 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@getter::values + inducingVariable: #F5 + #F2 isAugmentation enum E (nameOffset:27) (firstTokenOffset:14) (offset:27) + element: ::@enum::E + previousFragment: #F1 + enums + isSimplyBounded enum E + reference: ::@enum::E + firstFragment: #F1 + supertype: Enum + fields + hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v + reference: ::@enum::E::@field::v + firstFragment: #F3 + type: E + constantInitializer + fragment: #F3 + expression: expression_0 + getter: ::@enum::E::@getter::v + isConst isOriginEnumValues isStatic values + reference: ::@enum::E::@field::values + firstFragment: #F5 + type: List + constantInitializer + fragment: #F5 + expression: expression_1 + getter: ::@enum::E::@getter::values + constructors + isConst isOriginImplicitDefault new + reference: ::@enum::E::@constructor::new + firstFragment: #F7 + superConstructor: dart:core::@class::Enum::@constructor::new + getters + isOriginVariable isStatic v + reference: ::@enum::E::@getter::v + firstFragment: #F4 + returnType: E + variable: ::@enum::E::@field::v + isOriginVariable isStatic values + reference: ::@enum::E::@getter::values + firstFragment: #F6 + returnType: List + variable: ::@enum::E::@field::values +'''); + } + + test_constant_augmentation_introductoryHasConstants_augmentationNoConstants_blockBody_semicolon() async { + var library = await buildLibrary(r''' +enum E { v } + +augment enum E {;} +'''); + checkElementText(library, r''' +library + reference: + fragments + #F0 + element: + enums + #F1 enum E (nameOffset:5) (firstTokenOffset:0) (offset:5) + element: ::@enum::E + nextFragment: #F2 + fields + #F3 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v (nameOffset:9) (firstTokenOffset:9) (offset:9) + element: ::@enum::E::@field::v + initializer: expression_0 + InstanceCreationExpression + constructorName: ConstructorName + type: NamedType + name: E @-1 + element: ::@enum::E + type: E + element: ::@enum::E::@constructor::new + argumentList: ArgumentList + leftParenthesis: ( @0 + rightParenthesis: ) @0 + staticType: E + inducedGetter: #F4 + #F5 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@field::values + initializer: expression_1 + ListLiteral + leftBracket: [ @0 + elements + SimpleIdentifier + token: v @-1 + element: ::@enum::E::@getter::v + staticType: E + rightBracket: ] @0 + staticType: List + inducedGetter: #F6 + constructors + #F7 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@constructor::new + typeName: E + getters + #F4 isCompleteDeclaration isOriginVariable isStatic v (nameOffset:) (firstTokenOffset:) (offset:9) + element: ::@enum::E::@getter::v + inducingVariable: #F3 + #F6 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@getter::values + inducingVariable: #F5 + #F2 isAugmentation enum E (nameOffset:27) (firstTokenOffset:14) (offset:27) + element: ::@enum::E + previousFragment: #F1 + enums + isSimplyBounded enum E + reference: ::@enum::E + firstFragment: #F1 + supertype: Enum + fields + hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v + reference: ::@enum::E::@field::v + firstFragment: #F3 + type: E + constantInitializer + fragment: #F3 + expression: expression_0 + getter: ::@enum::E::@getter::v + isConst isOriginEnumValues isStatic values + reference: ::@enum::E::@field::values + firstFragment: #F5 + type: List + constantInitializer + fragment: #F5 + expression: expression_1 + getter: ::@enum::E::@getter::values + constructors + isConst isOriginImplicitDefault new + reference: ::@enum::E::@constructor::new + firstFragment: #F7 + superConstructor: dart:core::@class::Enum::@constructor::new + getters + isOriginVariable isStatic v + reference: ::@enum::E::@getter::v + firstFragment: #F4 + returnType: E + variable: ::@enum::E::@field::v + isOriginVariable isStatic values + reference: ::@enum::E::@getter::values + firstFragment: #F6 + returnType: List + variable: ::@enum::E::@field::values +'''); + } + + test_constant_augmentation_introductoryHasConstants_augmentationNoConstants_emptyBody() async { + var library = await buildLibrary(r''' +enum E { v } + +augment enum E; +'''); + checkElementText(library, r''' +library + reference: + fragments + #F0 + element: + enums + #F1 enum E (nameOffset:5) (firstTokenOffset:0) (offset:5) + element: ::@enum::E + nextFragment: #F2 + fields + #F3 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v (nameOffset:9) (firstTokenOffset:9) (offset:9) + element: ::@enum::E::@field::v + initializer: expression_0 + InstanceCreationExpression + constructorName: ConstructorName + type: NamedType + name: E @-1 + element: ::@enum::E + type: E + element: ::@enum::E::@constructor::new + argumentList: ArgumentList + leftParenthesis: ( @0 + rightParenthesis: ) @0 + staticType: E + inducedGetter: #F4 + #F5 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@field::values + initializer: expression_1 + ListLiteral + leftBracket: [ @0 + elements + SimpleIdentifier + token: v @-1 + element: ::@enum::E::@getter::v + staticType: E + rightBracket: ] @0 + staticType: List + inducedGetter: #F6 + constructors + #F7 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@constructor::new + typeName: E + getters + #F4 isCompleteDeclaration isOriginVariable isStatic v (nameOffset:) (firstTokenOffset:) (offset:9) + element: ::@enum::E::@getter::v + inducingVariable: #F3 + #F6 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@getter::values + inducingVariable: #F5 + #F2 isAugmentation enum E (nameOffset:27) (firstTokenOffset:14) (offset:27) + element: ::@enum::E + previousFragment: #F1 + enums + isSimplyBounded enum E + reference: ::@enum::E + firstFragment: #F1 + supertype: Enum + fields + hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v + reference: ::@enum::E::@field::v + firstFragment: #F3 + type: E + constantInitializer + fragment: #F3 + expression: expression_0 + getter: ::@enum::E::@getter::v + isConst isOriginEnumValues isStatic values + reference: ::@enum::E::@field::values + firstFragment: #F5 + type: List + constantInitializer + fragment: #F5 + expression: expression_1 + getter: ::@enum::E::@getter::values + constructors + isConst isOriginImplicitDefault new + reference: ::@enum::E::@constructor::new + firstFragment: #F7 + superConstructor: dart:core::@class::Enum::@constructor::new + getters + isOriginVariable isStatic v + reference: ::@enum::E::@getter::v + firstFragment: #F4 + returnType: E + variable: ::@enum::E::@field::v + isOriginVariable isStatic values + reference: ::@enum::E::@getter::values + firstFragment: #F6 + returnType: List + variable: ::@enum::E::@field::values +'''); + } + + test_constant_augmentation_introductoryNoConstants_augmentationHasConstants() async { + var library = await buildLibrary(r''' +enum E {} + +augment enum E { v } +'''); + checkElementText(library, r''' +library + reference: + fragments + #F0 + element: + enums + #F1 enum E (nameOffset:5) (firstTokenOffset:0) (offset:5) + element: ::@enum::E + nextFragment: #F2 + fields + #F3 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@field::values + initializer: expression_0 + ListLiteral + leftBracket: [ @0 + elements + SimpleIdentifier + token: v @-1 + element: ::@enum::E::@getter::v + staticType: E + rightBracket: ] @0 + staticType: List + inducedGetter: #F4 + constructors + #F5 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@constructor::new + typeName: E + getters + #F4 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@getter::values + inducingVariable: #F3 + #F2 isAugmentation enum E (nameOffset:24) (firstTokenOffset:11) (offset:24) + element: ::@enum::E + previousFragment: #F1 + fields + #F6 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v (nameOffset:28) (firstTokenOffset:28) (offset:28) + element: ::@enum::E::@field::v + initializer: expression_1 + InstanceCreationExpression + constructorName: ConstructorName + type: NamedType + name: E @-1 + element: ::@enum::E + type: E + element: ::@enum::E::@constructor::new + argumentList: ArgumentList + leftParenthesis: ( @0 + rightParenthesis: ) @0 + staticType: E + inducedGetter: #F7 + getters + #F7 isCompleteDeclaration isOriginVariable isStatic v (nameOffset:) (firstTokenOffset:) (offset:28) + element: ::@enum::E::@getter::v + inducingVariable: #F6 + enums + isSimplyBounded enum E + reference: ::@enum::E + firstFragment: #F1 + supertype: Enum + fields + isConst isOriginEnumValues isStatic values + reference: ::@enum::E::@field::values + firstFragment: #F3 + type: List + constantInitializer + fragment: #F3 + expression: expression_0 + getter: ::@enum::E::@getter::values + hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v + reference: ::@enum::E::@field::v + firstFragment: #F6 + type: E + constantInitializer + fragment: #F6 + expression: expression_1 + getter: ::@enum::E::@getter::v + constructors + isConst isOriginImplicitDefault new + reference: ::@enum::E::@constructor::new + firstFragment: #F5 + superConstructor: dart:core::@class::Enum::@constructor::new + getters + isOriginVariable isStatic values + reference: ::@enum::E::@getter::values + firstFragment: #F4 + returnType: List + variable: ::@enum::E::@field::values + isOriginVariable isStatic v + reference: ::@enum::E::@getter::v + firstFragment: #F7 + returnType: E + variable: ::@enum::E::@field::v +'''); + } + + test_constant_augmentation_introductoryNoConstants_augmentationNoConstants() async { + var library = await buildLibrary(r''' +enum E {} + +augment enum E {} +'''); + checkElementText(library, r''' +library + reference: + fragments + #F0 + element: + enums + #F1 enum E (nameOffset:5) (firstTokenOffset:0) (offset:5) + element: ::@enum::E + nextFragment: #F2 + fields + #F3 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@field::values + initializer: expression_0 + ListLiteral + leftBracket: [ @0 + rightBracket: ] @0 + staticType: List + inducedGetter: #F4 + constructors + #F5 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@constructor::new + typeName: E + getters + #F4 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@getter::values + inducingVariable: #F3 + #F2 isAugmentation enum E (nameOffset:24) (firstTokenOffset:11) (offset:24) + element: ::@enum::E + previousFragment: #F1 + enums + isSimplyBounded enum E + reference: ::@enum::E + firstFragment: #F1 + supertype: Enum + fields + isConst isOriginEnumValues isStatic values + reference: ::@enum::E::@field::values + firstFragment: #F3 + type: List + constantInitializer + fragment: #F3 + expression: expression_0 + getter: ::@enum::E::@getter::values + constructors + isConst isOriginImplicitDefault new + reference: ::@enum::E::@constructor::new + firstFragment: #F5 + superConstructor: dart:core::@class::Enum::@constructor::new + getters + isOriginVariable isStatic values + reference: ::@enum::E::@getter::values + firstFragment: #F4 + returnType: List + variable: ::@enum::E::@field::values +'''); + } + + test_constant_augmentation_valuesGetter() async { + var library = await buildLibrary(r''' +enum A { + v1 +} + +augment enum A { + v2 +} + +augment enum A {; + static int get values => 0; +} + +augment enum A { + v3 +} +'''); + checkElementText(library, r''' +library + reference: + fragments + #F0 + element: + enums + #F1 enum A (nameOffset:5) (firstTokenOffset:0) (offset:5) + element: ::@enum::A + nextFragment: #F2 + fields + #F3 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v1 (nameOffset:11) (firstTokenOffset:11) (offset:11) + element: ::@enum::A::@field::v1 + initializer: expression_0 + InstanceCreationExpression + constructorName: ConstructorName + type: NamedType + name: A @-1 + element: ::@enum::A + type: A + element: ::@enum::A::@constructor::new + argumentList: ArgumentList + leftParenthesis: ( @0 + rightParenthesis: ) @0 + staticType: A + inducedGetter: #F4 + #F5 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::A::@field::values + initializer: expression_1 + ListLiteral + leftBracket: [ @0 + elements + SimpleIdentifier + token: v1 @-1 + element: ::@enum::A::@getter::v1 + staticType: A + SimpleIdentifier + token: v2 @-1 + element: ::@enum::A::@getter::v2 + staticType: A + SimpleIdentifier + token: v3 @-1 + element: ::@enum::A::@getter::v3 + staticType: A + rightBracket: ] @0 + staticType: List + inducedGetter: #F6 + constructors + #F7 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::A::@constructor::new + typeName: A + getters + #F4 isCompleteDeclaration isOriginVariable isStatic v1 (nameOffset:) (firstTokenOffset:) (offset:11) + element: ::@enum::A::@getter::v1 + inducingVariable: #F3 + #F6 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::A::@getter::values + inducingVariable: #F5 + #F2 isAugmentation enum A (nameOffset:30) (firstTokenOffset:17) (offset:30) + element: ::@enum::A + previousFragment: #F1 + nextFragment: #F8 + fields + #F9 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v2 (nameOffset:36) (firstTokenOffset:36) (offset:36) + element: ::@enum::A::@field::v2 + initializer: expression_2 + InstanceCreationExpression + constructorName: ConstructorName + type: NamedType + name: A @-1 + element: ::@enum::A + type: A + element: ::@enum::A::@constructor::new + argumentList: ArgumentList + leftParenthesis: ( @0 + rightParenthesis: ) @0 + staticType: A + inducedGetter: #F10 + getters + #F10 isCompleteDeclaration isOriginVariable isStatic v2 (nameOffset:) (firstTokenOffset:) (offset:36) + element: ::@enum::A::@getter::v2 + inducingVariable: #F9 + #F8 isAugmentation enum A (nameOffset:55) (firstTokenOffset:42) (offset:55) + element: ::@enum::A + previousFragment: #F2 + nextFragment: #F11 + fields + #F12 isOriginGetterSetter isStatic values (nameOffset:) (firstTokenOffset:) (offset:55) + element: ::@enum::A::@field::values#1 + getters + #F13 isCompleteDeclaration isOriginDeclaration isStatic values (nameOffset:77) (firstTokenOffset:62) (offset:77) + element: ::@enum::A::@getter::values#1 + #F11 isAugmentation enum A (nameOffset:106) (firstTokenOffset:93) (offset:106) + element: ::@enum::A + previousFragment: #F8 + fields + #F14 hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic v3 (nameOffset:112) (firstTokenOffset:112) (offset:112) + element: ::@enum::A::@field::v3 + initializer: expression_3 + InstanceCreationExpression + constructorName: ConstructorName + type: NamedType + name: A @-1 + element: ::@enum::A + type: A + element: ::@enum::A::@constructor::new + argumentList: ArgumentList + leftParenthesis: ( @0 + rightParenthesis: ) @0 + staticType: A + inducedGetter: #F15 + getters + #F15 isCompleteDeclaration isOriginVariable isStatic v3 (nameOffset:) (firstTokenOffset:) (offset:112) + element: ::@enum::A::@getter::v3 + inducingVariable: #F14 + enums + isSimplyBounded enum A + reference: ::@enum::A + firstFragment: #F1 + supertype: Enum + fields + hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v1 + reference: ::@enum::A::@field::v1 + firstFragment: #F3 + type: A + constantInitializer + fragment: #F3 + expression: expression_0 + getter: ::@enum::A::@getter::v1 + isConst isOriginEnumValues isStatic values + reference: ::@enum::A::@field::values + firstFragment: #F5 + type: List + constantInitializer + fragment: #F5 + expression: expression_1 + getter: ::@enum::A::@getter::values + hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v2 + reference: ::@enum::A::@field::v2 + firstFragment: #F9 + type: A + constantInitializer + fragment: #F9 + expression: expression_2 + getter: ::@enum::A::@getter::v2 + isOriginGetterSetter isStatic values + reference: ::@enum::A::@field::values#1 + firstFragment: #F12 + type: int + getter: ::@enum::A::@getter::values#1 + hasImplicitType hasInitializer isConst isEnumConstant isOriginDeclaration isStatic isTypeInferredFromInitializer v3 + reference: ::@enum::A::@field::v3 + firstFragment: #F14 + type: A + constantInitializer + fragment: #F14 + expression: expression_3 + getter: ::@enum::A::@getter::v3 + constructors + isConst isOriginImplicitDefault new + reference: ::@enum::A::@constructor::new + firstFragment: #F7 + superConstructor: dart:core::@class::Enum::@constructor::new + getters + isOriginVariable isStatic v1 + reference: ::@enum::A::@getter::v1 + firstFragment: #F4 + returnType: A + variable: ::@enum::A::@field::v1 + isOriginVariable isStatic values + reference: ::@enum::A::@getter::values + firstFragment: #F6 + returnType: List + variable: ::@enum::A::@field::values + isOriginVariable isStatic v2 + reference: ::@enum::A::@getter::v2 + firstFragment: #F10 + returnType: A + variable: ::@enum::A::@field::v2 + isOriginDeclaration isStatic values + reference: ::@enum::A::@getter::values#1 + firstFragment: #F13 + returnType: int + variable: ::@enum::A::@field::values#1 + isOriginVariable isStatic v3 + reference: ::@enum::A::@getter::v3 + firstFragment: #F15 + returnType: A + variable: ::@enum::A::@field::v3 +'''); + } + test_constant_documented() async { var library = await buildLibrary(r''' enum E { @@ -10312,6 +10988,64 @@ library '''); } + test_enum_emptyBlockBody() async { + var library = await buildLibrary(r''' +enum E {} +'''); + checkElementText(library, r''' +library + reference: + fragments + #F0 + element: + enums + #F1 enum E (nameOffset:5) (firstTokenOffset:0) (offset:5) + element: ::@enum::E + fields + #F2 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@field::values + initializer: expression_0 + ListLiteral + leftBracket: [ @0 + rightBracket: ] @0 + staticType: List + inducedGetter: #F3 + constructors + #F4 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@constructor::new + typeName: E + getters + #F3 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@getter::values + inducingVariable: #F2 + enums + isSimplyBounded enum E + reference: ::@enum::E + firstFragment: #F1 + supertype: Enum + fields + isConst isOriginEnumValues isStatic values + reference: ::@enum::E::@field::values + firstFragment: #F2 + type: List + constantInitializer + fragment: #F2 + expression: expression_0 + getter: ::@enum::E::@getter::values + constructors + isConst isOriginImplicitDefault new + reference: ::@enum::E::@constructor::new + firstFragment: #F4 + superConstructor: dart:core::@class::Enum::@constructor::new + getters + isOriginVariable isStatic values + reference: ::@enum::E::@getter::values + firstFragment: #F3 + returnType: List + variable: ::@enum::E::@field::values +'''); + } + test_enum_emptyBody() async { var library = await buildLibrary(r''' enum E; @@ -13088,6 +13822,64 @@ library '''); } + test_enum_noConstants_semicolon() async { + var library = await buildLibrary(r''' +enum E {;} +'''); + checkElementText(library, r''' +library + reference: + fragments + #F0 + element: + enums + #F1 enum E (nameOffset:5) (firstTokenOffset:0) (offset:5) + element: ::@enum::E + fields + #F2 isConst isOriginEnumValues isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@field::values + initializer: expression_0 + ListLiteral + leftBracket: [ @0 + rightBracket: ] @0 + staticType: List + inducedGetter: #F3 + constructors + #F4 isConst isOriginImplicitDefault new (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@constructor::new + typeName: E + getters + #F3 isCompleteDeclaration isOriginVariable isStatic values (nameOffset:) (firstTokenOffset:) (offset:5) + element: ::@enum::E::@getter::values + inducingVariable: #F2 + enums + isSimplyBounded enum E + reference: ::@enum::E + firstFragment: #F1 + supertype: Enum + fields + isConst isOriginEnumValues isStatic values + reference: ::@enum::E::@field::values + firstFragment: #F2 + type: List + constantInitializer + fragment: #F2 + expression: expression_0 + getter: ::@enum::E::@getter::values + constructors + isConst isOriginImplicitDefault new + reference: ::@enum::E::@constructor::new + firstFragment: #F4 + superConstructor: dart:core::@class::Enum::@constructor::new + getters + isOriginVariable isStatic values + reference: ::@enum::E::@getter::values + firstFragment: #F3 + returnType: List + variable: ::@enum::E::@field::values +'''); + } + test_enum_typeParameters() async { var library = await buildLibrary(r''' enum E { v }