Skip to content

Commit ba5064f

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Analyzer AST changes for generic metadata
Bug: #44838 Change-Id: I55b8dacc571570568c1b3f101a1a4e1f517f7f6f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182581 Commit-Queue: Paul Berry <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 2f004a2 commit ba5064f

File tree

13 files changed

+153
-26
lines changed

13 files changed

+153
-26
lines changed

pkg/analyzer/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* Added `AnalysisContext.sdkRoot`.
99
* Removed `NullSafetyUnderstandingFlag`.
1010
* Removed `functionTypeAliasElement` from `TypeSystem.instantiateToBounds2`.
11+
* Added `Annotation.typeArguments` in preparation for supporting #44838.
1112

1213
## 0.41.1
1314
* Updated `PackageBuildWorkspace` that supports `package:build` to stop

pkg/analyzer/lib/dart/ast/ast.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,12 @@ abstract class AnnotatedNode implements AstNode {
8888
/// annotation*
8989
///
9090
/// annotation ::=
91-
/// '@' [Identifier] ('.' [SimpleIdentifier])? [ArgumentList]?
91+
/// '@' metadatum
92+
///
93+
/// metadatum ::=
94+
/// [Identifier]
95+
/// | qualifiedName
96+
/// | constructorDesignation argumentPart
9297
///
9398
/// Clients may not extend, implement or mix-in this class.
9499
abstract class Annotation implements AstNode {
@@ -146,6 +151,14 @@ abstract class Annotation implements AstNode {
146151

147152
/// Set the period before the constructor name to the given [token].
148153
set period(Token? token);
154+
155+
/// Returns the type arguments to the constructor being invoked, or `null` if
156+
/// (a) this annotation is not the invocation of a constructor or (b) this
157+
/// annotation does not specify type arguments explicitly.
158+
///
159+
/// Note that type arguments are only valid if [Feature.generic_metadata] is
160+
/// enabled.
161+
TypeArgumentList? get typeArguments;
149162
}
150163

151164
/// A list of arguments in the invocation of an executable element (that is, a

pkg/analyzer/lib/dart/ast/ast_factory.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,16 @@ abstract class AstFactory {
2020
/// [constructorName] can be `null` if the annotation is not referencing a
2121
/// named constructor. The [arguments] can be `null` if the annotation is not
2222
/// referencing a constructor.
23-
Annotation annotation(Token atSign, Identifier name, Token? period,
24-
SimpleIdentifier? constructorName, ArgumentList? arguments);
23+
///
24+
/// Note that type arguments are only valid if [Feature.generic_metadata] is
25+
/// enabled.
26+
Annotation annotation(
27+
{required Token atSign,
28+
required Identifier name,
29+
TypeArgumentList? typeArguments,
30+
Token? period,
31+
SimpleIdentifier? constructorName,
32+
ArgumentList? arguments});
2533

2634
/// Returns a newly created list of arguments. The list of [arguments] can
2735
/// be `null` if there are no arguments.

pkg/analyzer/lib/src/dart/ast/ast.dart

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@ class AnnotationImpl extends AstNodeImpl implements Annotation {
180180
/// the name of the field that is being referenced.
181181
late IdentifierImpl _name;
182182

183+
/// The type arguments to the constructor being invoked, or `null` if (a) this
184+
/// annotation is not the invocation of a constructor or (b) this annotation
185+
/// does not specify type arguments explicitly.
186+
///
187+
/// Note that type arguments are only valid if [Feature.generic_metadata] is
188+
/// enabled.
189+
TypeArgumentListImpl? _typeArguments;
190+
183191
/// The period before the constructor name, or `null` if this annotation is
184192
/// not the invocation of a named constructor.
185193
@override
@@ -206,9 +214,18 @@ class AnnotationImpl extends AstNodeImpl implements Annotation {
206214
/// [constructorName] can be `null` if the annotation is not referencing a
207215
/// named constructor. The [arguments] can be `null` if the annotation is not
208216
/// referencing a constructor.
209-
AnnotationImpl(this.atSign, IdentifierImpl name, this.period,
210-
SimpleIdentifierImpl? constructorName, ArgumentListImpl? arguments) {
217+
///
218+
/// Note that type arguments are only valid if [Feature.generic_metadata] is
219+
/// enabled.
220+
AnnotationImpl(
221+
this.atSign,
222+
IdentifierImpl name,
223+
TypeArgumentListImpl? typeArguments,
224+
this.period,
225+
SimpleIdentifierImpl? constructorName,
226+
ArgumentListImpl? arguments) {
211227
_name = _becomeParentOf(name)!;
228+
_typeArguments = _becomeParentOf(typeArguments);
212229
_constructorName = _becomeParentOf(constructorName);
213230
_arguments = _becomeParentOf(arguments);
214231
}
@@ -228,6 +245,7 @@ class AnnotationImpl extends AstNodeImpl implements Annotation {
228245
Iterable<SyntacticEntity> get childEntities => ChildEntities()
229246
..add(atSign)
230247
..add(_name)
248+
..add(_typeArguments)
231249
..add(period)
232250
..add(_constructorName)
233251
..add(_arguments);
@@ -276,12 +294,22 @@ class AnnotationImpl extends AstNodeImpl implements Annotation {
276294
@override
277295
AstNode get parent => super.parent!;
278296

297+
@override
298+
TypeArgumentList? get typeArguments => _typeArguments;
299+
300+
/// Sets the type arguments to the constructor being invoked to the given
301+
/// [typeArguments].
302+
set typeArguments(TypeArgumentList? typeArguments) {
303+
_typeArguments = _becomeParentOf(typeArguments as TypeArgumentListImpl?);
304+
}
305+
279306
@override
280307
E? accept<E>(AstVisitor<E> visitor) => visitor.visitAnnotation(this);
281308

282309
@override
283310
void visitChildren(AstVisitor visitor) {
284311
_name.accept(visitor);
312+
_typeArguments?.accept(visitor);
285313
_constructorName?.accept(visitor);
286314
_arguments?.accept(visitor);
287315
}

pkg/analyzer/lib/src/dart/ast/ast_factory.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,17 @@ class AstFactoryImpl extends AstFactory {
1717
AdjacentStringsImpl(strings);
1818

1919
@override
20-
Annotation annotation(Token atSign, Identifier name, Token? period,
21-
SimpleIdentifier? constructorName, ArgumentList? arguments) =>
20+
Annotation annotation(
21+
{required Token atSign,
22+
required Identifier name,
23+
TypeArgumentList? typeArguments,
24+
Token? period,
25+
SimpleIdentifier? constructorName,
26+
ArgumentList? arguments}) =>
2227
AnnotationImpl(
2328
atSign,
2429
name as IdentifierImpl,
30+
typeArguments as TypeArgumentListImpl?,
2531
period,
2632
constructorName as SimpleIdentifierImpl?,
2733
arguments as ArgumentListImpl?);

pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class ToSourceVisitor implements AstVisitor<void> {
136136
void visitAnnotation(Annotation node) {
137137
sink.write('@');
138138
safelyVisitNode(node.name);
139+
safelyVisitNode(node.typeArguments);
139140
safelyVisitNodeWithPrefix(".", node.constructorName);
140141
safelyVisitNode(node.arguments);
141142
}

pkg/analyzer/lib/src/dart/ast/utilities.dart

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,12 @@ class AstCloner implements AstVisitor<AstNode> {
113113

114114
@override
115115
Annotation visitAnnotation(Annotation node) => astFactory.annotation(
116-
cloneToken(node.atSign),
117-
cloneNode(node.name),
118-
cloneNullableToken(node.period),
119-
cloneNullableNode(node.constructorName),
120-
cloneNullableNode(node.arguments));
116+
atSign: cloneToken(node.atSign),
117+
name: cloneNode(node.name),
118+
typeArguments: cloneNullableNode(node.typeArguments),
119+
period: cloneNullableToken(node.period),
120+
constructorName: cloneNullableNode(node.constructorName),
121+
arguments: cloneNullableNode(node.arguments));
121122

122123
@override
123124
ArgumentList visitArgumentList(ArgumentList node) => astFactory.argumentList(
@@ -1214,6 +1215,7 @@ class AstComparator implements AstVisitor<bool> {
12141215
Annotation other = _other as Annotation;
12151216
return isEqualTokens(node.atSign, other.atSign) &&
12161217
isEqualNodes(node.name, other.name) &&
1218+
isEqualNodes(node.typeArguments, other.typeArguments) &&
12171219
isEqualTokens(node.period, other.period) &&
12181220
isEqualNodes(node.constructorName, other.constructorName) &&
12191221
isEqualNodes(node.arguments, other.arguments);
@@ -2657,6 +2659,9 @@ class NodeReplacer implements AstVisitor<bool> {
26572659
if (identical(node.arguments, _oldNode)) {
26582660
node.arguments = _newNode as ArgumentList;
26592661
return true;
2662+
} else if (identical(node.typeArguments, _oldNode)) {
2663+
(node as AnnotationImpl).typeArguments = _newNode as TypeArgumentList?;
2664+
return true;
26602665
} else if (identical(node.constructorName, _oldNode)) {
26612666
node.constructorName = _newNode as SimpleIdentifier;
26622667
return true;
@@ -4013,6 +4018,7 @@ class ResolutionCopier implements AstVisitor<bool> {
40134018
if (_and(
40144019
_isEqualTokens(node.atSign, toNode.atSign),
40154020
_isEqualNodes(node.name, toNode.name),
4021+
_isEqualNodes(node.typeArguments, toNode.typeArguments),
40164022
_isEqualTokens(node.period, toNode.period),
40174023
_isEqualNodes(node.constructorName, toNode.constructorName),
40184024
_isEqualNodes(node.arguments, toNode.arguments))) {

pkg/analyzer/lib/src/fasta/ast_builder.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,8 +1833,12 @@ class AstBuilder extends StackListener {
18331833
periodBeforeName != null ? pop() as SimpleIdentifier : null;
18341834
pop(); // Type arguments, not allowed.
18351835
var name = pop() as Identifier;
1836-
push(ast.annotation(atSign, name, periodBeforeName, constructorName,
1837-
invocation?.argumentList));
1836+
push(ast.annotation(
1837+
atSign: atSign,
1838+
name: name,
1839+
period: periodBeforeName,
1840+
constructorName: constructorName,
1841+
arguments: invocation?.argumentList));
18381842
}
18391843

18401844
@override

pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,20 @@ class AstTestFactory {
3131
astFactory.adjacentStrings(strings);
3232

3333
static Annotation annotation(Identifier name) => astFactory.annotation(
34-
TokenFactory.tokenFromType(TokenType.AT), name, null, null, null);
34+
atSign: TokenFactory.tokenFromType(TokenType.AT), name: name);
3535

3636
static Annotation annotation2(Identifier name,
37-
SimpleIdentifier? constructorName, ArgumentList arguments) =>
37+
SimpleIdentifier? constructorName, ArgumentList arguments,
38+
{TypeArgumentList? typeArguments}) =>
3839
astFactory.annotation(
39-
TokenFactory.tokenFromType(TokenType.AT),
40-
name,
41-
constructorName == null
40+
atSign: TokenFactory.tokenFromType(TokenType.AT),
41+
name: name,
42+
typeArguments: typeArguments,
43+
period: constructorName == null
4244
? null
4345
: TokenFactory.tokenFromType(TokenType.PERIOD),
44-
constructorName,
45-
arguments);
46+
constructorName: constructorName,
47+
arguments: arguments);
4648

4749
static ArgumentList argumentList([List<Expression> arguments = const []]) =>
4850
astFactory.argumentList(TokenFactory.tokenFromType(TokenType.OPEN_PAREN),

pkg/analyzer/lib/src/summary2/ast_binary_reader.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,11 @@ class AstBinaryReader {
262262
var constructorName = _readOptionalNode() as SimpleIdentifier?;
263263
var arguments = _readOptionalNode() as ArgumentList?;
264264
return astFactory.annotation(
265-
Tokens.AT,
266-
name,
267-
Tokens.PERIOD,
268-
constructorName,
269-
arguments,
265+
atSign: Tokens.AT,
266+
name: name,
267+
period: Tokens.PERIOD,
268+
constructorName: constructorName,
269+
arguments: arguments,
270270
);
271271
}
272272

pkg/analyzer/test/generated/utilities_test.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,12 @@ class Getter_NodeReplacerTest_test_annotation_3
13721372
SimpleIdentifier? get(Annotation node) => node.constructorName;
13731373
}
13741374

1375+
class Getter_NodeReplacerTest_test_annotation_4
1376+
implements NodeReplacerTest_Getter<Annotation, TypeArgumentList> {
1377+
@override
1378+
TypeArgumentList? get(Annotation node) => node.typeArguments;
1379+
}
1380+
13751381
class Getter_NodeReplacerTest_test_asExpression
13761382
implements NodeReplacerTest_Getter<AsExpression, TypeAnnotation> {
13771383
@override
@@ -2627,6 +2633,18 @@ class NodeReplacerTest {
26272633
_assertReplace(node, Getter_NodeReplacerTest_test_annotation_2());
26282634
}
26292635

2636+
void test_annotation_generic() {
2637+
Annotation node = AstTestFactory.annotation2(
2638+
AstTestFactory.identifier3("C"),
2639+
AstTestFactory.identifier3("c"),
2640+
AstTestFactory.argumentList([AstTestFactory.integer(0)]),
2641+
typeArguments:
2642+
AstTestFactory.typeArgumentList2([AstTestFactory.typeName4('T')]));
2643+
_assertReplace(node, Getter_NodeReplacerTest_test_annotation());
2644+
_assertReplace(node, Getter_NodeReplacerTest_test_annotation_3());
2645+
_assertReplace(node, Getter_NodeReplacerTest_test_annotation_2());
2646+
}
2647+
26302648
void test_argumentList() {
26312649
ArgumentList node =
26322650
AstTestFactory.argumentList([AstTestFactory.integer(0)]);

pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ class ToSourceVisitor2Test {
4141
AstTestFactory.identifier3("c"), AstTestFactory.argumentList()));
4242
}
4343

44+
void test_visitAnnotation_constructor_generic() {
45+
_assertSource(
46+
"@A<T>.c()",
47+
AstTestFactory.annotation2(AstTestFactory.identifier3("A"),
48+
AstTestFactory.identifier3("c"), AstTestFactory.argumentList(),
49+
typeArguments: AstTestFactory.typeArgumentList2(
50+
[AstTestFactory.typeName4('T')])));
51+
}
52+
4453
void test_visitArgumentList() {
4554
_assertSource(
4655
"(a, b)",

pkg/analyzer/test/src/dart/ast/utilities_test.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,37 @@ class ResolutionCopierTest with ElementsTypesMixin {
190190
expect(toNode.element, same(element));
191191
}
192192

193+
void test_visitAnnotation_generic() {
194+
var annotationClassName = "A";
195+
var annotationConstructorName = "named";
196+
var argumentName = "x";
197+
var fromNode = AstTestFactory.annotation2(
198+
AstTestFactory.identifier3(annotationClassName),
199+
AstTestFactory.identifier3(annotationConstructorName),
200+
AstTestFactory.argumentList(
201+
[AstTestFactory.identifier3(argumentName)])) as AnnotationImpl;
202+
var elementA = ElementFactory.classElement2(annotationClassName, ['T']);
203+
var element = ElementFactory.constructorElement(
204+
elementA, annotationConstructorName, true, [typeProvider.dynamicType]);
205+
fromNode.element = element;
206+
var typeArgumentName = 'U';
207+
var elementU = ElementFactory.classElement2(typeArgumentName);
208+
fromNode.typeArguments =
209+
AstTestFactory.typeArgumentList2([AstTestFactory.typeName(elementU)]);
210+
var toNode = AstTestFactory.annotation2(
211+
AstTestFactory.identifier3(annotationClassName),
212+
AstTestFactory.identifier3(annotationConstructorName),
213+
AstTestFactory.argumentList(
214+
[AstTestFactory.identifier3(argumentName)])) as AnnotationImpl;
215+
toNode.typeArguments = AstTestFactory.typeArgumentList2(
216+
[AstTestFactory.typeName4(typeArgumentName)]);
217+
ResolutionCopier.copyResolutionData(fromNode, toNode);
218+
expect(toNode.element, same(element));
219+
expect(
220+
(toNode.typeArguments!.arguments.single as TypeName).name.staticElement,
221+
same(elementU));
222+
}
223+
193224
void test_visitAsExpression() {
194225
AsExpression fromNode = AstTestFactory.asExpression(
195226
AstTestFactory.identifier3("x"), AstTestFactory.typeName4("A"));

0 commit comments

Comments
 (0)