Skip to content

Commit e673c19

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Resolve annotations via type aliases.
Change-Id: I6d22e06775d31856fc85a350892efe15208832f5 Bug: #44838 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193743 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent d0ee565 commit e673c19

File tree

5 files changed

+1013
-47
lines changed

5 files changed

+1013
-47
lines changed

pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart

Lines changed: 131 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import 'package:analyzer/src/dart/constant/utilities.dart';
1414
import 'package:analyzer/src/dart/element/element.dart';
1515
import 'package:analyzer/src/dart/element/member.dart';
1616
import 'package:analyzer/src/dart/element/type.dart';
17+
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
1718
import 'package:analyzer/src/error/codes.dart';
1819
import 'package:analyzer/src/generated/resolver.dart';
1920

@@ -46,6 +47,38 @@ class AnnotationResolver {
4647
}
4748
}
4849

50+
void _classConstructorInvocation(
51+
AnnotationImpl node,
52+
ClassElement classElement,
53+
SimpleIdentifierImpl? constructorName,
54+
ArgumentList argumentList,
55+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
56+
) {
57+
ConstructorElement? constructorElement;
58+
if (constructorName != null) {
59+
constructorElement = classElement.getNamedConstructor(
60+
constructorName.name,
61+
);
62+
} else {
63+
constructorElement = classElement.unnamedConstructor;
64+
}
65+
66+
_constructorInvocation(
67+
node,
68+
constructorName,
69+
classElement.typeParameters,
70+
constructorElement,
71+
argumentList,
72+
(typeArguments) {
73+
return classElement.instantiate(
74+
typeArguments: typeArguments,
75+
nullabilitySuffix: _resolver.noneOrStarSuffix,
76+
);
77+
},
78+
whyNotPromotedList,
79+
);
80+
}
81+
4982
void _classGetter(
5083
AnnotationImpl node,
5184
ClassElement classElement,
@@ -80,20 +113,13 @@ class AnnotationResolver {
80113

81114
void _constructorInvocation(
82115
AnnotationImpl node,
83-
ClassElement classElement,
84116
SimpleIdentifierImpl? constructorName,
117+
List<TypeParameterElement> typeParameters,
118+
ConstructorElement? constructorElement,
85119
ArgumentList argumentList,
120+
InterfaceType Function(List<DartType> typeArguments) instantiateElement,
86121
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
87122
) {
88-
ConstructorElement? constructorElement;
89-
if (constructorName != null) {
90-
constructorElement = classElement.getNamedConstructor(
91-
constructorName.name,
92-
);
93-
} else {
94-
constructorElement = classElement.unnamedConstructor;
95-
}
96-
97123
constructorElement = _resolver.toLegacyElement(constructorElement);
98124
constructorName?.staticElement = constructorElement;
99125
node.element = constructorElement;
@@ -108,8 +134,6 @@ class AnnotationResolver {
108134
return;
109135
}
110136

111-
var typeParameters = classElement.typeParameters;
112-
113137
// If no type parameters, the elements are correct.
114138
if (typeParameters.isEmpty) {
115139
_resolveConstructorInvocationArguments(node);
@@ -123,10 +147,7 @@ class AnnotationResolver {
123147
List<DartType> typeArguments,
124148
ConstructorElement constructorElement,
125149
) {
126-
var type = classElement.instantiate(
127-
typeArguments: typeArguments,
128-
nullabilitySuffix: _resolver.noneOrStarSuffix,
129-
);
150+
var type = instantiateElement(typeArguments);
130151
constructorElement = ConstructorMember.from(constructorElement, type);
131152
constructorName?.staticElement = constructorElement;
132153
node.element = constructorElement;
@@ -166,8 +187,11 @@ class AnnotationResolver {
166187
_resolver.visitArgumentList(argumentList,
167188
whyNotPromotedList: whyNotPromotedList);
168189

169-
var constructorRawType = _resolver.typeAnalyzer
170-
.constructorToGenericFunctionType(constructorElement);
190+
var elementToInfer = ConstructorElementToInfer(
191+
typeParameters,
192+
constructorElement,
193+
);
194+
var constructorRawType = elementToInfer.asType;
171195

172196
var inferred = _resolver.inferenceHelper.inferGenericInvoke(
173197
node, constructorRawType, typeArgumentList, argumentList, node,
@@ -264,7 +288,7 @@ class AnnotationResolver {
264288
// Class(args) or Class.CONST
265289
if (element1 is ClassElement) {
266290
if (argumentList != null) {
267-
_constructorInvocation(
291+
_classConstructorInvocation(
268292
node, element1, name2, argumentList, whyNotPromotedList);
269293
} else {
270294
_classGetter(node, element1, name2, whyNotPromotedList);
@@ -286,7 +310,7 @@ class AnnotationResolver {
286310
// prefix.Class(args) or prefix.Class.CONST
287311
if (element2 is ClassElement) {
288312
if (argumentList != null) {
289-
_constructorInvocation(
313+
_classConstructorInvocation(
290314
node, element2, name3, argumentList, whyNotPromotedList);
291315
} else {
292316
_classGetter(node, element2, name3, whyNotPromotedList);
@@ -303,6 +327,19 @@ class AnnotationResolver {
303327
_propertyAccessorElement(node, name2, element2, whyNotPromotedList);
304328
return;
305329
}
330+
331+
// prefix.TypeAlias(args) or prefix.TypeAlias.CONST
332+
if (element2 is TypeAliasElement) {
333+
var aliasedType = element2.aliasedType;
334+
var argumentList = node.arguments;
335+
if (aliasedType is InterfaceType && argumentList != null) {
336+
_typeAliasConstructorInvocation(node, element2, name3, aliasedType,
337+
argumentList, whyNotPromotedList);
338+
} else {
339+
_typeAliasGetter(node, element2, name3, whyNotPromotedList);
340+
}
341+
return;
342+
}
306343
// undefined
307344
if (element2 == null) {
308345
_errorReporter.reportErrorForNode(
@@ -322,6 +359,19 @@ class AnnotationResolver {
322359
return;
323360
}
324361

362+
// TypeAlias(args) or TypeAlias.CONST
363+
if (element1 is TypeAliasElement) {
364+
var aliasedType = element1.aliasedType;
365+
var argumentList = node.arguments;
366+
if (aliasedType is InterfaceType && argumentList != null) {
367+
_typeAliasConstructorInvocation(node, element1, name2, aliasedType,
368+
argumentList, whyNotPromotedList);
369+
} else {
370+
_typeAliasGetter(node, element1, name2, whyNotPromotedList);
371+
}
372+
return;
373+
}
374+
325375
// TODO(scheglov) Must be const.
326376
if (element1 is VariableElement) {
327377
return;
@@ -393,6 +443,67 @@ class AnnotationResolver {
393443
}
394444
}
395445

446+
void _typeAliasConstructorInvocation(
447+
AnnotationImpl node,
448+
TypeAliasElement typeAliasElement,
449+
SimpleIdentifierImpl? constructorName,
450+
InterfaceType aliasedType,
451+
ArgumentList argumentList,
452+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
453+
) {
454+
var constructorElement = aliasedType.lookUpConstructor(
455+
constructorName?.name,
456+
_definingLibrary,
457+
);
458+
459+
_constructorInvocation(
460+
node,
461+
constructorName,
462+
typeAliasElement.typeParameters,
463+
constructorElement,
464+
argumentList,
465+
(typeArguments) {
466+
return typeAliasElement.instantiate(
467+
typeArguments: typeArguments,
468+
nullabilitySuffix: _resolver.noneOrStarSuffix,
469+
) as InterfaceType;
470+
},
471+
whyNotPromotedList,
472+
);
473+
}
474+
475+
void _typeAliasGetter(
476+
AnnotationImpl node,
477+
TypeAliasElement typeAliasElement,
478+
SimpleIdentifierImpl? getterName,
479+
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
480+
) {
481+
ExecutableElement? getter;
482+
var aliasedType = typeAliasElement.aliasedType;
483+
if (aliasedType is InterfaceType) {
484+
var classElement = aliasedType.element;
485+
if (getterName != null) {
486+
getter = classElement.getGetter(getterName.name);
487+
getter = _resolver.toLegacyElement(getter);
488+
}
489+
}
490+
491+
getterName?.staticElement = getter;
492+
node.element = getter;
493+
494+
if (getterName != null && getter is PropertyAccessorElement) {
495+
_propertyAccessorElement(node, getterName, getter, whyNotPromotedList);
496+
_resolveAnnotationElementGetter(node, getter);
497+
} else if (getter is! ConstructorElement) {
498+
_errorReporter.reportErrorForNode(
499+
CompileTimeErrorCode.INVALID_ANNOTATION,
500+
node,
501+
);
502+
}
503+
504+
_visitArguments(node, whyNotPromotedList);
505+
}
506+
396507
void _visitArguments(AnnotationImpl node,
397508
List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
398509
var arguments = node.arguments;

pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ class ConstructorElementToInfer {
4040

4141
ConstructorElementToInfer(this.typeParameters, this.element);
4242

43+
/// Return the equivalent generic function type that we could use to
44+
/// forward to the constructor, or for a non-generic type simply returns
45+
/// the constructor type.
46+
///
47+
/// For example given the type `class C<T> { C(T arg); }`, the generic
48+
/// function type is `<T>(T) -> C<T>`.
4349
FunctionType get asType {
4450
return FunctionTypeImpl(
4551
typeFormals: typeParameters,

pkg/analyzer/lib/src/generated/static_type_analyzer.dart

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,10 @@
44

55
import 'package:analyzer/dart/ast/ast.dart';
66
import 'package:analyzer/dart/ast/visitor.dart';
7-
import 'package:analyzer/dart/element/element.dart';
8-
import 'package:analyzer/dart/element/nullability_suffix.dart';
97
import 'package:analyzer/dart/element/type.dart';
108
import 'package:analyzer/src/dart/ast/ast.dart';
119
import 'package:analyzer/src/dart/ast/extensions.dart';
1210
import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
13-
import 'package:analyzer/src/dart/element/type.dart';
1411
import 'package:analyzer/src/dart/element/type_provider.dart';
1512
import 'package:analyzer/src/dart/element/type_system.dart';
1613
import 'package:analyzer/src/generated/migration.dart';
@@ -48,28 +45,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<void> {
4845
_dynamicType = _typeProvider.dynamicType;
4946
}
5047

51-
/// Given a constructor for a generic type, returns the equivalent generic
52-
/// function type that we could use to forward to the constructor, or for a
53-
/// non-generic type simply returns the constructor type.
54-
///
55-
/// For example given the type `class C<T> { C(T arg); }`, the generic function
56-
/// type is `<T>(T) -> C<T>`.
57-
FunctionType constructorToGenericFunctionType(
58-
ConstructorElement constructor) {
59-
var classElement = constructor.enclosingElement;
60-
var typeParameters = classElement.typeParameters;
61-
if (typeParameters.isEmpty) {
62-
return constructor.type;
63-
}
64-
65-
return FunctionTypeImpl(
66-
typeFormals: typeParameters,
67-
parameters: constructor.parameters,
68-
returnType: constructor.returnType,
69-
nullabilitySuffix: NullabilitySuffix.star,
70-
);
71-
}
72-
7348
/// Record that the static type of the given node is the given type.
7449
///
7550
/// @param expression the node whose type is to be recorded

pkg/analyzer/lib/src/test_utilities/find_element.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class FindElement extends _FindElementBase {
149149
return result!;
150150
}
151151

152+
@override
152153
ParameterElement parameter(String name) {
153154
ParameterElement? result;
154155

@@ -527,6 +528,28 @@ abstract class _FindElementBase {
527528
throw StateError('Not found: $name');
528529
}
529530

531+
ParameterElement parameter(String name) {
532+
ParameterElement? result;
533+
534+
for (var class_ in unitElement.types) {
535+
for (var constructor in class_.constructors) {
536+
for (var parameter in constructor.parameters) {
537+
if (parameter.name == name) {
538+
if (result != null) {
539+
throw StateError('Not unique: $name');
540+
}
541+
result = parameter;
542+
}
543+
}
544+
}
545+
}
546+
547+
if (result != null) {
548+
return result;
549+
}
550+
throw StateError('Not found: $name');
551+
}
552+
530553
PropertyAccessorElement setter(String name, {String? of}) {
531554
PropertyAccessorElement? result;
532555

0 commit comments

Comments
 (0)