5
5
import 'package:analyzer/dart/ast/ast.dart' ;
6
6
import 'package:analyzer/dart/element/element.dart' ;
7
7
import 'package:analyzer/dart/element/type.dart' ;
8
+ import 'package:analyzer/error/listener.dart' ;
8
9
import 'package:analyzer/src/dart/ast/ast.dart' ;
9
10
import 'package:analyzer/src/dart/element/member.dart' ;
10
11
import 'package:analyzer/src/dart/element/type_algebra.dart' ;
@@ -15,10 +16,13 @@ import 'package:analyzer/src/generated/type_system.dart';
15
16
16
17
class ExtensionMemberResolver {
17
18
final ResolverVisitor _resolver;
19
+
18
20
ExtensionMemberResolver (this ._resolver);
19
21
20
22
DartType get _dynamicType => _typeProvider.dynamicType;
21
23
24
+ ErrorReporter get _errorReporter => _resolver.errorReporter;
25
+
22
26
Scope get _nameScope => _resolver.nameScope;
23
27
24
28
TypeProvider get _typeProvider => _resolver.typeProvider;
@@ -48,7 +52,7 @@ class ExtensionMemberResolver {
48
52
return extension ;
49
53
}
50
54
51
- _resolver.errorReporter .reportErrorForNode (
55
+ _errorReporter .reportErrorForNode (
52
56
CompileTimeErrorCode .AMBIGUOUS_EXTENSION_METHOD_ACCESS ,
53
57
target,
54
58
[
@@ -61,24 +65,51 @@ class ExtensionMemberResolver {
61
65
}
62
66
63
67
void resolveOverride (ExtensionOverride node) {
68
+ var nodeImpl = node as ExtensionOverrideImpl ;
64
69
var element = node.staticElement;
65
70
var typeParameters = element.typeParameters;
66
71
67
- DartType receiverType;
72
+ if (! _isValidContext (node)) {
73
+ _errorReporter.reportErrorForNode (
74
+ CompileTimeErrorCode .EXTENSION_OVERRIDE_WITHOUT_ACCESS ,
75
+ node,
76
+ );
77
+ nodeImpl.staticType = _dynamicType;
78
+ }
79
+
68
80
var arguments = node.argumentList.arguments;
69
- if (arguments.length == 1 ) {
70
- receiverType = arguments[0 ].staticType;
81
+ if (arguments.length != 1 ) {
82
+ _errorReporter.reportErrorForNode (
83
+ CompileTimeErrorCode .INVALID_EXTENSION_ARGUMENT_COUNT ,
84
+ node.argumentList,
85
+ );
86
+ nodeImpl.typeArgumentTypes = _listOfDynamic (typeParameters);
87
+ nodeImpl.extendedType = _dynamicType;
88
+ return ;
71
89
}
72
- // TODO(scheglov) Test when not exactly 1 argument.
73
90
74
- var typeArgumentTypes =
75
- _inferTypeArguments (element, receiverType, node.typeArguments);
91
+ var receiverExpression = arguments[0 ];
92
+ var receiverType = receiverExpression.staticType;
93
+
94
+ var typeArgumentTypes = _inferTypeArguments (
95
+ element,
96
+ receiverType,
97
+ node.typeArguments,
98
+ );
76
99
77
- var nodeImpl = node as ExtensionOverrideImpl ;
78
100
nodeImpl.typeArgumentTypes = typeArgumentTypes;
79
- nodeImpl.extendedType =
80
- Substitution .fromPairs (typeParameters, typeArgumentTypes)
81
- .substituteType (element.extendedType);
101
+ nodeImpl.extendedType = Substitution .fromPairs (
102
+ typeParameters,
103
+ typeArgumentTypes,
104
+ ).substituteType (element.extendedType);
105
+
106
+ if (! _typeSystem.isAssignableTo (receiverType, node.extendedType)) {
107
+ _errorReporter.reportErrorForNode (
108
+ CompileTimeErrorCode .EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE ,
109
+ receiverExpression,
110
+ [receiverType, node.extendedType],
111
+ );
112
+ }
82
113
}
83
114
84
115
/// Return the most specific extension or `null` if no single one can be
@@ -259,7 +290,7 @@ class ExtensionMemberResolver {
259
290
return arguments.map ((a) => a.type).toList ();
260
291
} else {
261
292
// TODO(scheglov) Report an error.
262
- return List . filled (typeParameters.length, _dynamicType );
293
+ return _listOfDynamic (typeParameters);
263
294
}
264
295
} else {
265
296
if (receiverType != null ) {
@@ -275,7 +306,7 @@ class ExtensionMemberResolver {
275
306
);
276
307
return inferrer.infer (typeParameters);
277
308
} else {
278
- return List . filled (typeParameters.length, _dynamicType );
309
+ return _listOfDynamic (typeParameters);
279
310
}
280
311
}
281
312
}
@@ -341,6 +372,22 @@ class ExtensionMemberResolver {
341
372
/// Ask the type system for a subtype check.
342
373
bool _isSubtypeOf (DartType type1, DartType type2) =>
343
374
_typeSystem.isSubtypeOf (type1, type2);
375
+
376
+ List <DartType > _listOfDynamic (List <TypeParameterElement > parameters) {
377
+ return List <DartType >.filled (parameters.length, _dynamicType);
378
+ }
379
+
380
+ /// Return `true` if the extension override [node] is being used as a target
381
+ /// of an operation that might be accessing an instance member.
382
+ static bool _isValidContext (ExtensionOverride node) {
383
+ AstNode parent = node.parent;
384
+ return parent is BinaryExpression && parent.leftOperand == node ||
385
+ parent is FunctionExpressionInvocation && parent.function == node ||
386
+ parent is IndexExpression && parent.target == node ||
387
+ parent is MethodInvocation && parent.target == node ||
388
+ parent is PrefixExpression ||
389
+ parent is PropertyAccess && parent.target == node;
390
+ }
344
391
}
345
392
346
393
class InstantiatedExtension {
0 commit comments