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 <johnniwinther@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
a527b4d9b0
commit
53c69a614e
@@ -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(
|
||||
|
||||
@@ -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 {;
|
||||
|
||||
@@ -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: <testLibrary>::@enum::A::@constructor::new
|
||||
declaredFragment: <testLibraryFragment> v1@11
|
||||
rightBracket: }
|
||||
declaredFragment: <testLibraryFragment> A@5
|
||||
EnumDeclaration
|
||||
augmentKeyword: augment
|
||||
enumKeyword: enum
|
||||
namePart: NameWithTypeParameters
|
||||
typeName: A
|
||||
body: BlockEnumBody
|
||||
leftBracket: {
|
||||
constants
|
||||
EnumConstantDeclaration
|
||||
name: v2
|
||||
constructorElement: <testLibrary>::@enum::A::@constructor::new
|
||||
declaredFragment: <testLibraryFragment> v2@36
|
||||
rightBracket: }
|
||||
declaredFragment: <testLibraryFragment> A@30
|
||||
FunctionDeclaration
|
||||
returnType: NamedType
|
||||
name: void
|
||||
element: <null>
|
||||
type: void
|
||||
name: f
|
||||
functionExpression: FunctionExpression
|
||||
parameters: FormalParameterList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
body: BlockFunctionBody
|
||||
block: Block
|
||||
leftBracket: {
|
||||
statements
|
||||
ExpressionStatement
|
||||
expression: PrefixedIdentifier
|
||||
prefix: SimpleIdentifier
|
||||
token: A
|
||||
element: <testLibrary>::@enum::A
|
||||
staticType: null
|
||||
period: .
|
||||
identifier: SimpleIdentifier
|
||||
token: v2
|
||||
element: <testLibrary>::@enum::A::@getter::v2
|
||||
staticType: A
|
||||
element: <testLibrary>::@enum::A::@getter::v2
|
||||
staticType: A
|
||||
semicolon: ;
|
||||
rightBracket: }
|
||||
declaredFragment: <testLibraryFragment> f@47
|
||||
element: <testLibrary>::@function::f
|
||||
type: void Function()
|
||||
staticType: void Function()
|
||||
declaredFragment: <testLibraryFragment> f@47
|
||||
element: <testLibrary>::@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: <testLibrary>::@enum::A::@constructor::new
|
||||
declaredFragment: <testLibraryFragment> v1@11
|
||||
rightBracket: }
|
||||
declaredFragment: <testLibraryFragment> 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: <testLibraryFragment> values@52
|
||||
element: <testLibrary>::@enum::A::@getter::values#1
|
||||
type: int Function()
|
||||
rightBracket: }
|
||||
declaredFragment: <testLibraryFragment> A@30
|
||||
EnumDeclaration
|
||||
augmentKeyword: augment
|
||||
enumKeyword: enum
|
||||
namePart: NameWithTypeParameters
|
||||
typeName: A
|
||||
body: BlockEnumBody
|
||||
leftBracket: {
|
||||
constants
|
||||
EnumConstantDeclaration
|
||||
name: v2
|
||||
constructorElement: <testLibrary>::@enum::A::@constructor::new
|
||||
declaredFragment: <testLibraryFragment> v2@87
|
||||
rightBracket: }
|
||||
declaredFragment: <testLibraryFragment> A@81
|
||||
FunctionDeclaration
|
||||
returnType: NamedType
|
||||
name: void
|
||||
element: <null>
|
||||
type: void
|
||||
name: f
|
||||
functionExpression: FunctionExpression
|
||||
parameters: FormalParameterList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
body: BlockFunctionBody
|
||||
block: Block
|
||||
leftBracket: {
|
||||
statements
|
||||
ExpressionStatement
|
||||
expression: PrefixedIdentifier
|
||||
prefix: SimpleIdentifier
|
||||
token: A
|
||||
element: <testLibrary>::@enum::A
|
||||
staticType: null
|
||||
period: .
|
||||
identifier: SimpleIdentifier
|
||||
token: values
|
||||
element: <testLibrary>::@enum::A::@getter::values
|
||||
staticType: List<A>
|
||||
element: <testLibrary>::@enum::A::@getter::values
|
||||
staticType: List<A>
|
||||
semicolon: ;
|
||||
rightBracket: }
|
||||
declaredFragment: <testLibraryFragment> f@98
|
||||
element: <testLibrary>::@function::f
|
||||
type: void Function()
|
||||
staticType: void Function()
|
||||
declaredFragment: <testLibraryFragment> f@98
|
||||
element: <testLibrary>::@function::f
|
||||
type: void Function()
|
||||
''');
|
||||
}
|
||||
|
||||
test_constructor_argumentList_contextType() async {
|
||||
var result = await resolveTestCodeWithDiagnostics(r'''
|
||||
enum E {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user