Index: pkg/analyzer/lib/src/task/strong_mode.dart |
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart |
index c3716adcc0b22c848270f28947239856ce1523e3..46b84e026c8f8437cc558a0d52a142e3429ea918 100644 |
--- a/pkg/analyzer/lib/src/task/strong_mode.dart |
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart |
@@ -6,8 +6,11 @@ library analyzer.src.task.strong_mode; |
import 'dart:collection'; |
+import 'package:analyzer/dart/element/element.dart'; |
+import 'package:analyzer/dart/element/type.dart'; |
+import 'package:analyzer/src/dart/element/element.dart'; |
+import 'package:analyzer/src/dart/element/type.dart'; |
import 'package:analyzer/src/generated/ast.dart'; |
-import 'package:analyzer/src/generated/element.dart'; |
import 'package:analyzer/src/generated/resolver.dart' |
show TypeProvider, InheritanceManager; |
import 'package:analyzer/src/generated/type_system.dart'; |
@@ -137,6 +140,14 @@ class InstanceMemberInferrer { |
} |
/** |
+ * Return `true` if the list of [elements] contains only methods. |
+ */ |
+ bool _allSameElementKind( |
+ ExecutableElement element, List<ExecutableElement> elements) { |
+ return elements.every((e) => e.kind == element.kind); |
+ } |
+ |
+ /** |
* Compute the best type for the [parameter] at the given [index] that must be |
* compatible with the types of the corresponding parameters of the given |
* [overriddenMethods]. |
@@ -213,7 +224,7 @@ class InstanceMemberInferrer { |
matchingParameter = methodParameters.lastWhere( |
(ParameterElement methodParameter) => |
methodParameter.parameterKind == ParameterKind.NAMED && |
- methodParameter.name == parameter.name, |
+ methodParameter.name == parameter.name, |
orElse: () => null); |
} else { |
// |
@@ -278,51 +289,10 @@ class InstanceMemberInferrer { |
} |
} |
- /** |
- * If the given [fieldElement] represents a non-synthetic instance field for |
- * which no type was provided, infer the type of the field. |
- */ |
- void _inferField(FieldElement fieldElement) { |
- if (!fieldElement.isSynthetic && |
- !fieldElement.isStatic && |
- fieldElement.hasImplicitType) { |
- // |
- // First look for overridden getters with the same name as the field. |
- // |
- List<ExecutableElement> overriddenGetters = inheritanceManager |
- .lookupOverrides(fieldElement.enclosingElement, fieldElement.name); |
- DartType newType = null; |
- if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) { |
- newType = _computeReturnType(overriddenGetters); |
- List<ExecutableElement> overriddenSetters = inheritanceManager |
- .lookupOverrides( |
- fieldElement.enclosingElement, fieldElement.name + '='); |
- if (!_isCompatible(newType, overriddenSetters)) { |
- newType = null; |
- } |
- } |
- // |
- // If there is no overridden getter or if the overridden getter's type is |
- // dynamic, then we can infer the type from the initialization expression |
- // without breaking subtype rules. We could potentially infer a consistent |
- // return type even if the overridden getter's type was not dynamic, but |
- // choose not to for simplicity. The field is required to be final to |
- // prevent choosing a type that is inconsistent with assignments we cannot |
- // analyze. |
- // |
- if (newType == null || newType.isDynamic) { |
- if (fieldElement.initializer != null && |
- (fieldElement.isFinal || overriddenGetters.isEmpty)) { |
- newType = fieldElement.initializer.returnType; |
- } |
- } |
- if (newType == null || newType.isBottom) { |
- newType = typeProvider.dynamicType; |
- } |
- (fieldElement as FieldElementImpl).type = newType; |
- setReturnType(fieldElement.getter, newType); |
- if (!fieldElement.isFinal && !fieldElement.isConst) { |
- setParameterType(fieldElement.setter, newType); |
+ void _inferConstructorFieldFormals(ConstructorElement element) { |
+ for (ParameterElement p in element.parameters) { |
+ if (p is FieldFormalParameterElement) { |
+ _inferFieldFormalParameter(p); |
} |
} |
} |
@@ -377,29 +347,58 @@ class InstanceMemberInferrer { |
} |
/** |
- * If the given [element] is a non-synthetic getter or setter, update its |
- * synthetic variable's type to match the getter's return type, or if no |
- * corresponding getter exists, use the setter's parameter type. |
- * |
- * In general, the type of the synthetic variable should not be used, because |
- * getters and setters are independent methods. But this logic matches what |
- * `TypeResolverVisitor.visitMethodDeclaration` would fill in there. |
+ * If the given [fieldElement] represents a non-synthetic instance field for |
+ * which no type was provided, infer the type of the field. |
*/ |
- void _updateSyntheticVariableType(PropertyAccessorElement element) { |
- assert(!element.isSynthetic); |
- PropertyAccessorElement getter = element; |
- if (element.isSetter) { |
- // See if we can find any getter. |
- getter = element.correspondingGetter; |
- } |
- DartType newType; |
- if (getter != null) { |
- newType = getter.returnType; |
- } else if (element.isSetter && element.parameters.isNotEmpty) { |
- newType = element.parameters[0].type; |
+ void _inferField(FieldElement fieldElement) { |
+ if (!fieldElement.isSynthetic && |
+ !fieldElement.isStatic && |
+ fieldElement.hasImplicitType) { |
+ // |
+ // First look for overridden getters with the same name as the field. |
+ // |
+ List<ExecutableElement> overriddenGetters = inheritanceManager |
+ .lookupOverrides(fieldElement.enclosingElement, fieldElement.name); |
+ DartType newType = null; |
+ if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) { |
+ newType = _computeReturnType(overriddenGetters); |
+ List<ExecutableElement> overriddenSetters = |
+ inheritanceManager.lookupOverrides( |
+ fieldElement.enclosingElement, fieldElement.name + '='); |
+ if (!_isCompatible(newType, overriddenSetters)) { |
+ newType = null; |
+ } |
+ } |
+ // |
+ // If there is no overridden getter or if the overridden getter's type is |
+ // dynamic, then we can infer the type from the initialization expression |
+ // without breaking subtype rules. We could potentially infer a consistent |
+ // return type even if the overridden getter's type was not dynamic, but |
+ // choose not to for simplicity. The field is required to be final to |
+ // prevent choosing a type that is inconsistent with assignments we cannot |
+ // analyze. |
+ // |
+ if (newType == null || newType.isDynamic) { |
+ if (fieldElement.initializer != null && |
+ (fieldElement.isFinal || overriddenGetters.isEmpty)) { |
+ newType = fieldElement.initializer.returnType; |
+ } |
+ } |
+ if (newType == null || newType.isBottom) { |
+ newType = typeProvider.dynamicType; |
+ } |
+ (fieldElement as FieldElementImpl).type = newType; |
+ setReturnType(fieldElement.getter, newType); |
+ if (!fieldElement.isFinal && !fieldElement.isConst) { |
+ setParameterType(fieldElement.setter, newType); |
+ } |
} |
- if (newType != null) { |
- (element.variable as VariableElementImpl).type = newType; |
+ } |
+ |
+ void _inferFieldFormalParameter(FieldFormalParameterElement element) { |
+ FieldElement field = element.field; |
+ if (field != null && element.hasImplicitType) { |
+ (element as FieldFormalParameterElementImpl).type = field.type; |
} |
} |
@@ -443,25 +442,29 @@ class InstanceMemberInferrer { |
} |
/** |
- * Return `true` if the list of [elements] contains only methods. |
+ * If the given [element] is a non-synthetic getter or setter, update its |
+ * synthetic variable's type to match the getter's return type, or if no |
+ * corresponding getter exists, use the setter's parameter type. |
+ * |
+ * In general, the type of the synthetic variable should not be used, because |
+ * getters and setters are independent methods. But this logic matches what |
+ * `TypeResolverVisitor.visitMethodDeclaration` would fill in there. |
*/ |
- bool _allSameElementKind( |
- ExecutableElement element, List<ExecutableElement> elements) { |
- return elements.every((e) => e.kind == element.kind); |
- } |
- |
- void _inferConstructorFieldFormals(ConstructorElement element) { |
- for (ParameterElement p in element.parameters) { |
- if (p is FieldFormalParameterElement) { |
- _inferFieldFormalParameter(p); |
- } |
+ void _updateSyntheticVariableType(PropertyAccessorElement element) { |
+ assert(!element.isSynthetic); |
+ PropertyAccessorElement getter = element; |
+ if (element.isSetter) { |
+ // See if we can find any getter. |
+ getter = element.correspondingGetter; |
} |
- } |
- |
- void _inferFieldFormalParameter(FieldFormalParameterElement element) { |
- FieldElement field = element.field; |
- if (field != null && element.hasImplicitType) { |
- (element as FieldFormalParameterElementImpl).type = field.type; |
+ DartType newType; |
+ if (getter != null) { |
+ newType = getter.returnType; |
+ } else if (element.isSetter && element.parameters.isNotEmpty) { |
+ newType = element.parameters[0].type; |
+ } |
+ if (newType != null) { |
+ (element.variable as VariableElementImpl).type = newType; |
} |
} |
} |