| 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 f76cf73f3abadec5d36778d6537953ee285b7ad2..de346c55c615cdcfb46a5594b5b25840e27791a0 100644
|
| --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| @@ -617,9 +617,11 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| */
|
| @override
|
| Object visitListLiteral(ListLiteral node) {
|
| - DartType staticType = _dynamicType;
|
| TypeArgumentList typeArguments = node.typeArguments;
|
| +
|
| + // If we have explicit arguments, use them
|
| if (typeArguments != null) {
|
| + DartType staticType = _dynamicType;
|
| NodeList<TypeName> arguments = typeArguments.arguments;
|
| if (arguments != null && arguments.length == 1) {
|
| TypeName argumentTypeName = arguments[0];
|
| @@ -628,25 +630,47 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| staticType = argumentType;
|
| }
|
| }
|
| - } else if (_strongMode) {
|
| + _recordStaticType(
|
| + node, _typeProvider.listType.instantiate(<DartType>[staticType]));
|
| + return null;
|
| + }
|
| +
|
| + // If there are no type arguments and we are in strong mode, try to infer
|
| + // some arguments.
|
| + if (_strongMode) {
|
| DartType contextType = InferenceContext.getType(node);
|
| +
|
| + // If we have a type from the context, use it.
|
| if (contextType is InterfaceType &&
|
| contextType.typeArguments.length == 1 &&
|
| contextType.element == _typeProvider.listType.element) {
|
| - staticType = contextType.typeArguments[0];
|
| _resolver.inferenceContext.recordInference(node, contextType);
|
| - } else if (node.elements.isNotEmpty) {
|
| + _recordStaticType(node, contextType);
|
| + return null;
|
| + }
|
| +
|
| + // If we don't have a type from the context, try to infer from the
|
| + // elements
|
| + if (node.elements.isNotEmpty) {
|
| // Infer the list type from the arguments.
|
| - // TODO(jmesserly): record inference here?
|
| - staticType =
|
| + DartType staticType =
|
| node.elements.map((e) => e.staticType).reduce(_leastUpperBound);
|
| if (staticType.isBottom) {
|
| staticType = _dynamicType;
|
| }
|
| + DartType listLiteralType =
|
| + _typeProvider.listType.instantiate(<DartType>[staticType]);
|
| + if (!staticType.isDynamic) {
|
| + _resolver.inferenceContext.recordInference(node, listLiteralType);
|
| + }
|
| + _recordStaticType(node, listLiteralType);
|
| + return null;
|
| }
|
| }
|
| +
|
| + // If we have no type arguments and couldn't infer any, use dynamic.
|
| _recordStaticType(
|
| - node, _typeProvider.listType.instantiate(<DartType>[staticType]));
|
| + node, _typeProvider.listType.instantiate(<DartType>[_dynamicType]));
|
| return null;
|
| }
|
|
|
| @@ -664,10 +688,12 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| */
|
| @override
|
| Object visitMapLiteral(MapLiteral node) {
|
| - DartType staticKeyType = _dynamicType;
|
| - DartType staticValueType = _dynamicType;
|
| TypeArgumentList typeArguments = node.typeArguments;
|
| +
|
| + // If we have type arguments, use them
|
| if (typeArguments != null) {
|
| + DartType staticKeyType = _dynamicType;
|
| + DartType staticValueType = _dynamicType;
|
| NodeList<TypeName> arguments = typeArguments.arguments;
|
| if (arguments != null && arguments.length == 2) {
|
| TypeName entryKeyTypeName = arguments[0];
|
| @@ -681,20 +707,31 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| staticValueType = entryValueType;
|
| }
|
| }
|
| - } else if (_strongMode) {
|
| + _recordStaticType(
|
| + node,
|
| + _typeProvider.mapType
|
| + .instantiate(<DartType>[staticKeyType, staticValueType]));
|
| + return null;
|
| + }
|
| +
|
| + // If we have no explicit type arguments, and we are in strong mode
|
| + // then try to infer type arguments.
|
| + if (_strongMode) {
|
| DartType contextType = InferenceContext.getType(node);
|
| + // If we have a context type, use that for inference.
|
| if (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);
|
| - } else if (node.entries.isNotEmpty) {
|
| - // Infer the list type from the arguments.
|
| - // TODO(jmesserly): record inference here?
|
| - staticKeyType =
|
| + _recordStaticType(node, contextType);
|
| + return null;
|
| + }
|
| +
|
| + // Otherwise, try to infer a type from the keys and values.
|
| + if (node.entries.isNotEmpty) {
|
| + DartType staticKeyType =
|
| node.entries.map((e) => e.key.staticType).reduce(_leastUpperBound);
|
| - staticValueType = node.entries
|
| + DartType staticValueType = node.entries
|
| .map((e) => e.value.staticType)
|
| .reduce(_leastUpperBound);
|
| if (staticKeyType.isBottom) {
|
| @@ -703,12 +740,21 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| if (staticValueType.isBottom) {
|
| staticValueType = _dynamicType;
|
| }
|
| + DartType mapLiteralType = _typeProvider.mapType
|
| + .instantiate(<DartType>[staticKeyType, staticValueType]);
|
| + if (!(staticValueType.isDynamic && staticKeyType.isDynamic)) {
|
| + _resolver.inferenceContext.recordInference(node, mapLiteralType);
|
| + }
|
| + _recordStaticType(node, mapLiteralType);
|
| + return null;
|
| }
|
| }
|
| +
|
| + // If no type arguments and no inference, use dynamic
|
| _recordStaticType(
|
| node,
|
| _typeProvider.mapType
|
| - .instantiate(<DartType>[staticKeyType, staticValueType]));
|
| + .instantiate(<DartType>[_dynamicType, _dynamicType]));
|
| return null;
|
| }
|
|
|
|
|