@@ -230,37 +230,6 @@ class InstanceMemberInferrer {
230
230
: matchingParameter.type;
231
231
}
232
232
233
- /**
234
- * If the given [accessorElement] represents a non-synthetic instance getter
235
- * for which no return type was provided, infer the return type of the getter.
236
- */
237
- void _inferAccessor (PropertyAccessorElement accessorElement) {
238
- if (! accessorElement.isSynthetic &&
239
- accessorElement.isGetter &&
240
- ! accessorElement.isStatic &&
241
- accessorElement.hasImplicitReturnType) {
242
- List <ExecutableElement > overriddenGetters = inheritanceManager
243
- .lookupOverrides (
244
- accessorElement.enclosingElement, accessorElement.name);
245
- if (overriddenGetters.isNotEmpty && _onlyGetters (overriddenGetters)) {
246
- DartType newType = _computeReturnType (overriddenGetters);
247
- List <ExecutableElement > overriddenSetters = inheritanceManager
248
- .lookupOverrides (
249
- accessorElement.enclosingElement, accessorElement.name + '=' );
250
- PropertyAccessorElement setter = (accessorElement.enclosingElement
251
- as ClassElement ).getSetter (accessorElement.name);
252
- if (setter != null ) {
253
- overriddenSetters.add (setter);
254
- }
255
- if (! _isCompatible (newType, overriddenSetters)) {
256
- newType = typeProvider.dynamicType;
257
- }
258
- setReturnType (accessorElement, newType);
259
- (accessorElement.variable as FieldElementImpl ).type = newType;
260
- }
261
- }
262
- }
263
-
264
233
/**
265
234
* Infer type information for all of the instance members in the given
266
235
* [classElement] .
@@ -290,8 +259,8 @@ class InstanceMemberInferrer {
290
259
// Then infer the types for the members.
291
260
//
292
261
classElement.fields.forEach (_inferField);
293
- classElement.accessors.forEach (_inferAccessor );
294
- classElement.methods.forEach (_inferMethod );
262
+ classElement.accessors.forEach (_inferExecutable );
263
+ classElement.methods.forEach (_inferExecutable );
295
264
classElement.hasBeenInferred = true ;
296
265
} finally {
297
266
elementsBeingInferred.remove (classElement);
@@ -344,46 +313,81 @@ class InstanceMemberInferrer {
344
313
}
345
314
346
315
/**
347
- * If the given [methodElement] represents a non-synthetic instance method
348
- * for which no return type was provided, infer the return type of the method.
316
+ * If the given [element] represents a non-synthetic instance method,
317
+ * getter or setter, infer the return type and any parameter type(s) where
318
+ * they were not provided.
349
319
*/
350
- void _inferMethod ( MethodElement methodElement ) {
351
- if (methodElement .isSynthetic || methodElement .isStatic) {
320
+ void _inferExecutable ( ExecutableElement element ) {
321
+ if (element .isSynthetic || element .isStatic) {
352
322
return ;
353
323
}
354
324
List <ExecutableElement > overriddenMethods = null ;
355
325
//
356
326
// Infer the return type.
357
327
//
358
- if (methodElement .hasImplicitReturnType) {
328
+ if (element .hasImplicitReturnType) {
359
329
overriddenMethods = inheritanceManager.lookupOverrides (
360
- methodElement.enclosingElement, methodElement.name);
361
- if (overriddenMethods.isEmpty || ! _onlyMethods (overriddenMethods)) {
330
+ element.enclosingElement, element.name);
331
+ if (overriddenMethods.isEmpty ||
332
+ ! _allSameElementKind (element, overriddenMethods)) {
362
333
return ;
363
334
}
364
- MethodElementImpl element = methodElement as MethodElementImpl ;
365
335
setReturnType (element, _computeReturnType (overriddenMethods));
336
+ if (element is PropertyAccessorElement ) {
337
+ _updateSyntheticVariableType (element);
338
+ }
366
339
}
367
340
//
368
341
// Infer the parameter types.
369
342
//
370
- List <ParameterElement > parameters = methodElement .parameters;
343
+ List <ParameterElement > parameters = element .parameters;
371
344
int length = parameters.length;
372
345
for (int i = 0 ; i < length; ++ i) {
373
346
ParameterElement parameter = parameters[i];
374
347
if (parameter is ParameterElementImpl && parameter.hasImplicitType) {
375
348
if (overriddenMethods == null ) {
376
349
overriddenMethods = inheritanceManager.lookupOverrides (
377
- methodElement .enclosingElement, methodElement .name);
350
+ element .enclosingElement, element .name);
378
351
}
379
- if (overriddenMethods.isEmpty || ! _onlyMethods (overriddenMethods)) {
352
+ if (overriddenMethods.isEmpty ||
353
+ ! _allSameElementKind (element, overriddenMethods)) {
380
354
return ;
381
355
}
382
356
parameter.type = _computeParameterType (parameter, i, overriddenMethods);
357
+ if (element is PropertyAccessorElement ) {
358
+ _updateSyntheticVariableType (element);
359
+ }
383
360
}
384
361
}
385
362
}
386
363
364
+ /**
365
+ * If the given [element] is a non-synthetic getter or setter, update its
366
+ * synthetic variable's type to match the getter's return type, or if no
367
+ * corresponding getter exists, use the setter's parameter type.
368
+ *
369
+ * In general, the type of the synthetic variable should not be used, because
370
+ * getters and setters are independent methods. But this logic matches what
371
+ * `TypeResolverVisitor.visitMethodDeclaration` would fill in there.
372
+ */
373
+ void _updateSyntheticVariableType (PropertyAccessorElement element) {
374
+ assert (! element.isSynthetic);
375
+ PropertyAccessorElement getter = element;
376
+ if (element.isSetter) {
377
+ // See if we can find any getter.
378
+ getter = element.correspondingGetter;
379
+ }
380
+ DartType newType;
381
+ if (getter != null ) {
382
+ newType = getter.returnType;
383
+ } else if (element.isSetter && element.parameters.isNotEmpty) {
384
+ newType = element.parameters[0 ].type;
385
+ }
386
+ if (newType != null ) {
387
+ (element.variable as VariableElementImpl ).type = newType;
388
+ }
389
+ }
390
+
387
391
/**
388
392
* Infer type information for all of the instance members in the given
389
393
* interface [type] .
@@ -426,13 +430,9 @@ class InstanceMemberInferrer {
426
430
/**
427
431
* Return `true` if the list of [elements] contains only methods.
428
432
*/
429
- bool _onlyMethods (List <ExecutableElement > elements) {
430
- for (ExecutableElement element in elements) {
431
- if (element is ! MethodElement ) {
432
- return false ;
433
- }
434
- }
435
- return true ;
433
+ bool _allSameElementKind (
434
+ ExecutableElement element, List <ExecutableElement > elements) {
435
+ return elements.every ((e) => e.kind == element.kind);
436
436
}
437
437
}
438
438
0 commit comments