Chromium Code Reviews| Index: pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
| diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
| index 434354903790154e98f2afdf7f0300d598a8b176..75dccdf42fdee60426c9d44eaa98cc0961a66b6b 100644 |
| --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
| +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart |
| @@ -13,6 +13,7 @@ import 'element.dart'; |
| import 'java_engine.dart'; |
| import 'resolver.dart'; |
| import 'scanner.dart' as sc; |
| +import 'utilities_dart.dart'; |
| /** |
| * Instances of the class `StaticTypeAnalyzer` perform two type-related tasks. First, they |
| @@ -92,6 +93,78 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
| _strongMode = _resolver.definingLibrary.context.analysisOptions.strongMode; |
| } |
| + /** Given a constructor name [node] and a type [type], record an inferred type |
| + * for the constructor if in strong mode. This is used to fill in any |
| + * inferred type parameters found by the resolver. |
| + */ |
| + Object inferConstructorName(ConstructorName node, InterfaceType type) { |
|
Jennifer Messerly
2015/11/23 22:11:58
oh funny, I read this the first time as "infer con
|
| + if (_strongMode) { |
| + node.type.type = type; |
| + _resolver.inferenceContext.recordInference(node.parent, type); |
| + } |
| + } |
| + |
| + /** Given a formal parameter list and a function type use the function type |
| + * to infer types for any of the parameters which have implicit (missing) |
| + * types. Only infers types in strong mode. Returns true if inference |
| + * has occurred. |
| + */ |
| + bool inferFormalParameterList( |
| + FormalParameterList node, DartType functionType) { |
| + bool inferred = false; |
| + if (_strongMode && node != null && functionType is FunctionType) { |
| + DartType inferType(ParameterElementImpl p, DartType inferredType) { |
| + if (p.hasImplicitType && |
| + (p.type == null || p.type.isDynamic) && |
|
Jennifer Messerly
2015/11/23 22:11:58
aside: this might be worth a TODO. Ideally we can
Leaf
2015/11/24 19:32:12
Not sure what the TODO would be to do? The extra
Jennifer Messerly
2015/11/24 20:10:58
Ah, makes sense. Maybe worth a comment. I was conf
Leaf
2015/12/01 21:49:11
Done.
|
| + !inferredType.isDynamic) { |
| + p.type = inferredType; |
| + inferred = true; |
| + } |
| + } |
| + |
| + List<ParameterElement> parameters = node.parameterElements; |
| + |
| + { |
| + List<DartType> normalParameterTypes = functionType.normalParameterTypes; |
| + int normalCount = normalParameterTypes.length; |
| + Iterable<ParameterElement> required = parameters |
| + .where((p) => p.parameterKind == ParameterKind.REQUIRED) |
| + .take(normalCount); |
| + int index = 0; |
| + for (ParameterElementImpl p in required) { |
| + inferType(p, normalParameterTypes[index++]); |
| + } |
| + } |
| + |
| + { |
| + List<DartType> optionalParameterTypes = |
| + functionType.optionalParameterTypes; |
| + int optionalCount = optionalParameterTypes.length; |
| + Iterable<ParameterElement> optional = parameters |
| + .where((p) => p.parameterKind == ParameterKind.POSITIONAL) |
| + .take(optionalCount); |
| + int index = 0; |
| + for (ParameterElementImpl p in optional) { |
| + inferType(p, optionalParameterTypes[index++]); |
| + } |
| + } |
| + |
| + { |
| + Map<String, DartType> namedParameterTypes = |
| + functionType.namedParameterTypes; |
| + Iterable<ParameterElement> named = |
| + parameters.where((p) => p.parameterKind == ParameterKind.NAMED); |
| + for (ParameterElementImpl p in named) { |
| + if (!namedParameterTypes.containsKey(p.name)) { |
| + continue; |
| + } |
| + inferType(p, namedParameterTypes[p.name]); |
| + } |
| + } |
| + } |
| + return inferred; |
| + } |
| + |
| /** |
| * The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is |
| * `String`.</blockquote> |
| @@ -381,8 +454,20 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
| } |
| ExecutableElementImpl functionElement = |
| node.element as ExecutableElementImpl; |
| - functionElement.returnType = |
| - _computeStaticReturnTypeOfFunctionExpression(node); |
| + DartType computedType = _computeStaticReturnTypeOfFunctionExpression(node); |
| + if (_strongMode) { |
| + DartType functionType = InferenceContext.get(node); |
| + // TODO(leafp) handle async et al |
|
Jennifer Messerly
2015/11/23 22:11:58
for now should we skip if isGenerator or isAsync?
Leaf
2015/12/01 21:49:11
Actually, nothing to do here for those cases, remo
|
| + if (functionType is FunctionType) { |
| + DartType returnType = functionType.returnType; |
| + if ((computedType.isDynamic || computedType.isBottom) && |
| + !(returnType.isDynamic || returnType.isBottom)) { |
| + computedType = functionType.returnType; |
| + _resolver.inferenceContext.recordInference(node, functionType); |
| + } |
| + } |
| + } |
| + functionElement.returnType = computedType; |
| _recordPropagatedTypeOfFunction(functionElement, node.body); |
| _recordStaticType(node, node.element.type); |
| return null; |
| @@ -522,6 +607,15 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
| staticType = argumentType; |
| } |
| } |
| + } else { |
| + DartType contextType = InferenceContext.get(node); |
| + if (_strongMode && |
| + contextType is InterfaceType && |
| + contextType.typeArguments.length == 1 && |
| + contextType.element == _typeProvider.listType.element) { |
| + staticType = contextType.typeArguments[0]; |
| + _resolver.inferenceContext.recordInference(node, contextType); |
| + } |
| } |
| _recordStaticType( |
| node, _typeProvider.listType.substitute4(<DartType>[staticType])); |
| @@ -559,6 +653,16 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
| staticValueType = entryValueType; |
| } |
| } |
| + } else { |
| + DartType contextType = InferenceContext.get(node); |
| + if (_strongMode && |
| + contextType is InterfaceType && |
| + contextType.typeArguments.length == 2 && |
| + contextType.element == _typeProvider.mapType.element) { |
| + staticKeyType = contextType.typeArguments[0] ?? staticKeyType; |
| + staticValueType = contextType.typeArguments[1] ?? staticValueType; |
| + _resolver.inferenceContext.recordInference(node, contextType); |
| + } |
| } |
| _recordStaticType( |
| node, |
| @@ -1679,6 +1783,25 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
| } |
| /** |
| + * Given a local variable declaration and its initializer, attempt to infer |
| + * a type for the local variable declaration based on the initializer. |
| + * Inference is only done if an explicit type is not present, and if |
| + * inferring a type improves the type. |
| + */ |
| + void _inferLocalVariableType( |
| + VariableDeclaration node, Expression initializer) { |
| + if (initializer != null && |
| + (node.parent as VariableDeclarationList).type == null && |
| + (node.element is LocalVariableElementImpl) && |
| + (initializer.staticType != null) && |
| + (!initializer.staticType.isBottom)) { |
| + LocalVariableElementImpl element = node.element; |
| + element.type = initializer.staticType; |
| + node.name.staticType = initializer.staticType; |
| + } |
| + } |
| + |
| + /** |
| * Given a method invocation [node], attempt to infer a better |
| * type for the result. |
| */ |
| @@ -1766,25 +1889,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> { |
| } |
| /** |
| - * Given a local variable declaration and its initializer, attempt to infer |
| - * a type for the local variable declaration based on the initializer. |
| - * Inference is only done if an explicit type is not present, and if |
| - * inferring a type improves the type. |
| - */ |
| - void _inferLocalVariableType( |
| - VariableDeclaration node, Expression initializer) { |
| - if (initializer != null && |
| - (node.parent as VariableDeclarationList).type == null && |
| - (node.element is LocalVariableElementImpl) && |
| - (initializer.staticType != null) && |
| - (!initializer.staticType.isBottom)) { |
| - LocalVariableElementImpl element = node.element; |
| - element.type = initializer.staticType; |
| - node.name.staticType = initializer.staticType; |
| - } |
| - } |
| - |
| - /** |
| * Given a property access [node] with static type [nodeType], |
| * and [id] is the property name being accessed, infer a type for the |
| * access itself and its constituent components if the access is to one of the |