3
3
// BSD-style license that can be found in the LICENSE file.
4
4
5
5
import 'package:analyzer/dart/ast/ast.dart' ;
6
+ import 'package:analyzer/dart/ast/syntactic_entity.dart' ;
6
7
import 'package:analyzer/dart/element/element.dart' ;
7
8
import 'package:analyzer/dart/element/nullability_suffix.dart' ;
8
9
import 'package:analyzer/dart/element/type.dart' ;
@@ -12,7 +13,6 @@ import 'package:analyzer/src/dart/ast/ast_factory.dart';
12
13
import 'package:analyzer/src/dart/ast/extensions.dart' ;
13
14
import 'package:analyzer/src/dart/ast/utilities.dart' ;
14
15
import 'package:analyzer/src/dart/element/type.dart' ;
15
- import 'package:analyzer/src/dart/resolver/resolution_result.dart' ;
16
16
import 'package:analyzer/src/error/codes.dart' ;
17
17
import 'package:analyzer/src/generated/resolver.dart' ;
18
18
@@ -83,35 +83,46 @@ class FunctionReferenceResolver {
83
83
if (function is PrefixedIdentifierImpl ) {
84
84
var prefixElement =
85
85
_resolver.nameScope.lookup (function.prefix.name).getter;
86
+ function.prefix.staticElement = prefixElement;
86
87
if (prefixElement is PrefixElement ) {
87
- _resolveReceiverPrefix (node, prefixElement, function);
88
- return ;
88
+ var functionName = function.identifier.name;
89
+ var functionElement = prefixElement.scope.lookup (functionName).getter;
90
+ if (functionElement == null ) {
91
+ _errorReporter.reportErrorForNode (
92
+ CompileTimeErrorCode .UNDEFINED_PREFIXED_NAME ,
93
+ function.identifier,
94
+ [function.identifier.name, function.prefix.name],
95
+ );
96
+ function.staticType = DynamicTypeImpl .instance;
97
+ node.staticType = DynamicTypeImpl .instance;
98
+ return ;
99
+ } else {
100
+ functionElement = _resolver.toLegacyElement (functionElement);
101
+ _resolveReceiverPrefix (
102
+ node, prefixElement, function, functionElement);
103
+ return ;
104
+ }
105
+ } else if (prefixElement is VariableElement ) {
106
+ function.prefix.staticType = prefixElement.type;
107
+ } else if (prefixElement is PropertyAccessorElement ) {
108
+ function.prefix.staticType = prefixElement.returnType;
89
109
}
90
110
91
- ResolutionResult resolveTypeProperty (DartType prefixType) {
92
- return _resolver.typePropertyResolver.resolve (
93
- receiver: function.prefix,
94
- receiverType: prefixType,
95
- name: function.identifier.name,
96
- propertyErrorEntity: function.identifier,
97
- nameErrorEntity: function,
98
- );
99
- }
111
+ var methodElement = _resolveTypeProperty (
112
+ receiver: function.prefix,
113
+ receiverElement: prefixElement,
114
+ name: function.identifier,
115
+ nameErrorEntity: function,
116
+ );
100
117
101
- function.prefix.staticElement = prefixElement;
102
- ExecutableElement ? methodElement;
103
- if (prefixElement is VariableElement ) {
104
- var prefixType = prefixElement.type;
105
- function.prefix.staticType = prefixType;
106
- methodElement = resolveTypeProperty (prefixType).getter;
107
- } else if (prefixElement is PropertyAccessorElement ) {
108
- var prefixType = prefixElement.returnType;
109
- function.prefix.staticType = prefixType;
110
- methodElement = resolveTypeProperty (prefixType).getter;
111
- }
112
118
if (methodElement is MethodElement ) {
113
- _resolveFunctionReferenceMethod (
114
- node: node, function: function, element: methodElement);
119
+ function.identifier.staticElement = methodElement;
120
+ function.staticType = methodElement.type;
121
+ _resolve (
122
+ node: node,
123
+ name: function.identifier.name,
124
+ rawType: methodElement.type,
125
+ );
115
126
return ;
116
127
}
117
128
@@ -143,11 +154,39 @@ class FunctionReferenceResolver {
143
154
node.staticType = DynamicTypeImpl .instance;
144
155
return ;
145
156
}
157
+ } else if (target is PrefixedIdentifierImpl ) {
158
+ var prefixElement =
159
+ _resolver.nameScope.lookup (target.prefix.name).getter;
160
+ if (prefixElement is PrefixElement ) {
161
+ var prefixName = target.identifier.name;
162
+ var targetElement = prefixElement.scope.lookup (prefixName).getter;
163
+
164
+ var methodElement = _resolveTypeProperty (
165
+ receiver: target,
166
+ receiverElement: targetElement,
167
+ name: function.propertyName,
168
+ nameErrorEntity: function,
169
+ );
170
+
171
+ if (methodElement == null ) {
172
+ // TODO(srawlins): Can we get here?
173
+ node.staticType = DynamicTypeImpl .instance;
174
+ return ;
175
+ } else {
176
+ _resolveReceiverPrefix (node, prefixElement, target, methodElement);
177
+ return ;
178
+ }
179
+ } else {
180
+ // TODO(srawlins): Can we get here?
181
+ node.staticType = DynamicTypeImpl .instance;
182
+ return ;
183
+ }
146
184
} else {
147
- // TODO(srawlins): Can we get here? PrefixedIdentifier?
185
+ // TODO(srawlins): Can we get here?
148
186
node.staticType = DynamicTypeImpl .instance;
149
187
return ;
150
188
}
189
+
151
190
var propertyElement = _resolver.typePropertyResolver
152
191
.resolve (
153
192
receiver: function.realTarget,
@@ -238,55 +277,14 @@ class FunctionReferenceResolver {
238
277
_resolveTypeLiteral (node: node, instantiatedType: type, name: name);
239
278
}
240
279
241
- void _resolveFunctionReferenceMethod ({
242
- required FunctionReferenceImpl node,
243
- required PrefixedIdentifier function,
244
- required MethodElement element,
245
- }) {
246
- function.accept (_resolver);
247
- var receiver = function.prefix;
248
- var receiverType = receiver.staticType;
249
- if (receiverType == null ) {
250
- // TODO(srawlins): Handle this situation; see
251
- // `test_staticMethod_explicitReceiver` test case.
252
- node.staticType = DynamicTypeImpl .instance;
253
- return ;
254
- }
255
- var nameNode = function.identifier;
256
- var name = nameNode.name;
257
- var result = _resolver.typePropertyResolver.resolve (
258
- receiver: receiver,
259
- receiverType: receiverType,
260
- name: name,
261
- propertyErrorEntity: nameNode,
262
- nameErrorEntity: nameNode,
263
- );
264
-
265
- var target = result.getter;
266
- if (target != null ) {
267
- // TODO(srawlins): Set static type on `nameNode`?
268
-
269
- _resolve (node: node, name: name, rawType: element.type);
270
- return ;
271
- }
272
-
273
- // TODO(srawlins): Report unresolved identifier.
274
- node.function.accept (_resolver);
275
- node.staticType = DynamicTypeImpl .instance;
276
- }
277
-
278
280
void _resolveReceiverPrefix (
279
281
FunctionReferenceImpl node,
280
282
PrefixElement prefixElement,
281
283
PrefixedIdentifier prefix,
284
+ Element element,
282
285
) {
283
286
// TODO(srawlins): Handle `loadLibrary`, as in `p.loadLibrary<int>;`.
284
287
285
- var nameNode = prefix.identifier;
286
- var name = nameNode.name;
287
- var element = prefixElement.scope.lookup (name).getter;
288
- element = _resolver.toLegacyElement (element);
289
-
290
288
if (element is MultiplyDefinedElement ) {
291
289
MultiplyDefinedElement multiply = element;
292
290
element = multiply.conflictingElements[0 ];
@@ -310,7 +308,6 @@ class FunctionReferenceResolver {
310
308
return ;
311
309
} else if (element is TypeAliasElement ) {
312
310
prefix.accept (_resolver);
313
- (nameNode as SimpleIdentifierImpl ).staticElement = element;
314
311
_resolveTypeAlias (node: node, element: element, typeAlias: prefix);
315
312
return ;
316
313
}
@@ -326,10 +323,26 @@ class FunctionReferenceResolver {
326
323
327
324
// TODO(srawlins): Report undefined prefixed identifier.
328
325
329
- node.function.accept (_resolver);
330
326
node.staticType = DynamicTypeImpl .instance;
331
327
}
332
328
329
+ /// Returns the element that represents the property named [propertyName] on
330
+ /// [classElement] .
331
+ ExecutableElement ? _resolveStaticElement (
332
+ ClassElement classElement, SimpleIdentifier propertyName) {
333
+ String name = propertyName.name;
334
+ ExecutableElement ? element;
335
+ if (propertyName.inSetterContext ()) {
336
+ element = classElement.getSetter (name);
337
+ }
338
+ element ?? = classElement.getGetter (name);
339
+ element ?? = classElement.getMethod (name);
340
+ if (element != null && element.isAccessibleIn (_resolver.definingLibrary)) {
341
+ return element;
342
+ }
343
+ return null ;
344
+ }
345
+
333
346
void _resolveTypeAlias ({
334
347
required FunctionReferenceImpl node,
335
348
required TypeAliasElement element,
@@ -358,4 +371,53 @@ class FunctionReferenceResolver {
358
371
typeLiteral.staticType = _typeType;
359
372
NodeReplacer .replace (node, typeLiteral);
360
373
}
374
+
375
+ /// Resolves [name] as a property on [receiver] (with element
376
+ /// [receiverElement] ).
377
+ ///
378
+ /// Returns `null` if [receiverElement] is `null` , a [TypeParameterElement] ,
379
+ /// or a [TypeAliasElement] for a non-interface type.
380
+ ExecutableElement ? _resolveTypeProperty ({
381
+ required Expression receiver,
382
+ required Element ? receiverElement,
383
+ required SimpleIdentifier name,
384
+ required SyntacticEntity nameErrorEntity,
385
+ }) {
386
+ if (receiverElement == null ) {
387
+ return null ;
388
+ }
389
+ if (receiverElement is TypeParameterElement ) {
390
+ return null ;
391
+ }
392
+ if (receiverElement is ClassElement ) {
393
+ return _resolveStaticElement (receiverElement, name);
394
+ } else if (receiverElement is TypeAliasElement ) {
395
+ var aliasedType = receiverElement.aliasedType;
396
+ if (aliasedType is InterfaceType ) {
397
+ return _resolveStaticElement (aliasedType.element, name);
398
+ } else {
399
+ return null ;
400
+ }
401
+ }
402
+
403
+ DartType receiverType;
404
+ if (receiverElement is VariableElement ) {
405
+ receiverType = receiverElement.type;
406
+ } else if (receiverElement is PropertyAccessorElement ) {
407
+ receiverType = receiverElement.returnType;
408
+ } else {
409
+ assert (false ,
410
+ 'Unexpected receiverElement type: ${receiverElement .runtimeType }' );
411
+ return null ;
412
+ }
413
+ return _resolver.typePropertyResolver
414
+ .resolve (
415
+ receiver: receiver,
416
+ receiverType: receiverType,
417
+ name: name.name,
418
+ propertyErrorEntity: name,
419
+ nameErrorEntity: nameErrorEntity,
420
+ )
421
+ .getter;
422
+ }
361
423
}
0 commit comments