Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2037)

Unified Diff: pkg/analyzer/lib/src/task/strong_mode.dart

Issue 1359243003: Infer setter parameter types in strong mode (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/strong_mode_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2db99146898cde14482ece9d4e9880abd07112df..0c53dad08256ede52c81be4c971fb256a8573e4a 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -231,37 +231,6 @@ class InstanceMemberInferrer {
}
/**
- * If the given [accessorElement] represents a non-synthetic instance getter
- * for which no return type was provided, infer the return type of the getter.
- */
- void _inferAccessor(PropertyAccessorElement accessorElement) {
- if (!accessorElement.isSynthetic &&
- accessorElement.isGetter &&
- !accessorElement.isStatic &&
- accessorElement.hasImplicitReturnType) {
- List<ExecutableElement> overriddenGetters = inheritanceManager
- .lookupOverrides(
- accessorElement.enclosingElement, accessorElement.name);
- if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) {
- DartType newType = _computeReturnType(overriddenGetters);
- List<ExecutableElement> overriddenSetters = inheritanceManager
- .lookupOverrides(
- accessorElement.enclosingElement, accessorElement.name + '=');
- PropertyAccessorElement setter = (accessorElement.enclosingElement
- as ClassElement).getSetter(accessorElement.name);
- if (setter != null) {
- overriddenSetters.add(setter);
- }
- if (!_isCompatible(newType, overriddenSetters)) {
- newType = typeProvider.dynamicType;
- }
- setReturnType(accessorElement, newType);
- (accessorElement.variable as FieldElementImpl).type = newType;
- }
- }
- }
-
- /**
* Infer type information for all of the instance members in the given
* [classElement].
*/
@@ -290,8 +259,8 @@ class InstanceMemberInferrer {
// Then infer the types for the members.
//
classElement.fields.forEach(_inferField);
- classElement.accessors.forEach(_inferAccessor);
- classElement.methods.forEach(_inferMethod);
+ classElement.accessors.forEach(_inferExecutable);
+ classElement.methods.forEach(_inferExecutable);
classElement.hasBeenInferred = true;
} finally {
elementsBeingInferred.remove(classElement);
@@ -344,47 +313,82 @@ class InstanceMemberInferrer {
}
/**
- * If the given [methodElement] represents a non-synthetic instance method
- * for which no return type was provided, infer the return type of the method.
+ * If the given [element] represents a non-synthetic instance method,
+ * getter or setter, infer the return type and any parameter type(s) where
+ * they were not provided.
*/
- void _inferMethod(MethodElement methodElement) {
- if (methodElement.isSynthetic || methodElement.isStatic) {
+ void _inferExecutable(ExecutableElement element) {
+ if (element.isSynthetic || element.isStatic) {
return;
}
List<ExecutableElement> overriddenMethods = null;
//
// Infer the return type.
//
- if (methodElement.hasImplicitReturnType) {
+ if (element.hasImplicitReturnType) {
overriddenMethods = inheritanceManager.lookupOverrides(
- methodElement.enclosingElement, methodElement.name);
- if (overriddenMethods.isEmpty || !_onlyMethods(overriddenMethods)) {
+ element.enclosingElement, element.name);
+ if (overriddenMethods.isEmpty ||
+ !_allSameElementKind(element, overriddenMethods)) {
return;
}
- MethodElementImpl element = methodElement as MethodElementImpl;
setReturnType(element, _computeReturnType(overriddenMethods));
+ if (element is PropertyAccessorElement) {
+ _updateSyntheticVariableType(element);
+ }
}
//
// Infer the parameter types.
//
- List<ParameterElement> parameters = methodElement.parameters;
+ List<ParameterElement> parameters = element.parameters;
int length = parameters.length;
for (int i = 0; i < length; ++i) {
ParameterElement parameter = parameters[i];
if (parameter is ParameterElementImpl && parameter.hasImplicitType) {
if (overriddenMethods == null) {
overriddenMethods = inheritanceManager.lookupOverrides(
- methodElement.enclosingElement, methodElement.name);
+ element.enclosingElement, element.name);
}
- if (overriddenMethods.isEmpty || !_onlyMethods(overriddenMethods)) {
+ if (overriddenMethods.isEmpty ||
+ !_allSameElementKind(element, overriddenMethods)) {
return;
}
parameter.type = _computeParameterType(parameter, i, overriddenMethods);
+ if (element is PropertyAccessorElement) {
+ _updateSyntheticVariableType(element);
+ }
}
}
}
/**
+ * 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.
+ */
+ 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;
+ }
+ if (newType != null) {
+ (element.variable as VariableElementImpl).type = newType;
+ }
+ }
+
+ /**
* Infer type information for all of the instance members in the given
* interface [type].
*/
@@ -426,13 +430,9 @@ class InstanceMemberInferrer {
/**
* Return `true` if the list of [elements] contains only methods.
*/
- bool _onlyMethods(List<ExecutableElement> elements) {
- for (ExecutableElement element in elements) {
- if (element is! MethodElement) {
- return false;
- }
- }
- return true;
+ bool _allSameElementKind(
+ ExecutableElement element, List<ExecutableElement> elements) {
+ return elements.every((e) => e.kind == element.kind);
}
}
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/strong_mode_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698