Start supporting resolution of the code-as-ui constructs
Change-Id: I8fba9bfcac2339b113de6bc2954821585e7b8ab4
Reviewed-on: https://dart-review.googlesource.com/c/91240
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index db1514c..767e9dd 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2616,6 +2616,64 @@
}
@override
+ bool visitForStatement2(ForStatement2 node) {
+ bool outerBreakValue = _enclosingBlockContainsBreak;
+ _enclosingBlockContainsBreak = false;
+ ForLoopParts parts = node.forLoopParts;
+ try {
+ if (parts is ForEachParts) {
+ bool iterableExits = _nodeExits(parts.iterable);
+ // Discard whether the for-each body exits; since the for-each iterable
+ // may be empty, execution may never enter the body, so it doesn't matter
+ // if it exits or not. We still must visit the body, to accurately
+ // manage `_enclosingBlockBreaksLabel`.
+ _nodeExits(node.body);
+ return iterableExits;
+ }
+ VariableDeclarationList variables;
+ Expression initialization;
+ Expression condition;
+ NodeList<Expression> updaters;
+ if (parts is ForPartsWithDeclarations) {
+ variables = parts.variables;
+ condition = parts.condition;
+ updaters = parts.updaters;
+ } else if (parts is ForPartsWithExpression) {
+ initialization = parts.initialization;
+ condition = parts.condition;
+ updaters = parts.updaters;
+ }
+ if (variables != null &&
+ _visitVariableDeclarations(variables.variables)) {
+ return true;
+ }
+ if (initialization != null && _nodeExits(initialization)) {
+ return true;
+ }
+ if (condition != null && _nodeExits(condition)) {
+ return true;
+ }
+ if (_visitExpressions(updaters)) {
+ return true;
+ }
+ bool blockReturns = _nodeExits(node.body);
+ // TODO(jwren) Do we want to take all constant expressions into account?
+ // If for(; true; ) (or for(;;)), and the body doesn't return or the body
+ // doesn't have a break, then return true.
+ bool implicitOrExplictTrue =
+ condition == null || (condition is BooleanLiteral && condition.value);
+ if (implicitOrExplictTrue) {
+ if (blockReturns || !_enclosingBlockContainsBreak) {
+ return true;
+ }
+ }
+ return false;
+ } finally {
+ _enclosingBlockContainsBreak = outerBreakValue;
+ }
+ }
+
+ @override
bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
false;
@@ -4970,6 +5028,22 @@
}
@override
+ void visitForStatement2(ForStatement2 node) {
+ _overrideManager.enterScope();
+ try {
+ super.visitForStatement2(node);
+ } finally {
+ _overrideManager.exitScope();
+ }
+ }
+
+ @override
+ void visitForStatement2InScope(ForStatement2 node) {
+ throw new UnsupportedError('Implement this');
+ visitStatementInScope(node.body);
+ }
+
+ @override
void visitForStatementInScope(ForStatement node) {
node.variables?.accept(this);
node.initialization?.accept(this);
@@ -4982,8 +5056,6 @@
} finally {
_overrideManager.exitScope();
}
- // TODO(brianwilkerson) If the loop can only be exited because the condition
- // is false, then propagateFalseState(condition);
}
@override
@@ -5191,6 +5263,29 @@
}
@override
+ void visitListLiteral2(ListLiteral2 node) {
+ InterfaceType listT;
+
+ if (node.typeArguments != null) {
+ var targs = node.typeArguments.arguments.map((t) => t.type).toList();
+ if (targs.length == 1 && !targs[0].isDynamic) {
+ listT = typeProvider.listType.instantiate([targs[0]]);
+ }
+ } else {
+ listT = typeAnalyzer.inferListType2(node, downwards: true);
+ }
+ if (listT != null) {
+ for (CollectionElement element in node.elements) {
+ _pushCollectionTypesDown(element, listT);
+ }
+ InferenceContext.setType(node, listT);
+ } else {
+ InferenceContext.clearType(node);
+ }
+ super.visitListLiteral2(node);
+ }
+
+ @override
void visitMapLiteral(MapLiteral node) {
InterfaceType mapT;
if (node.typeArguments != null) {
@@ -5225,6 +5320,54 @@
}
@override
+ void visitMapLiteral2(MapLiteral2 node) {
+ InterfaceType mapT;
+ if (node.typeArguments != null) {
+ var targs = node.typeArguments.arguments.map((t) => t.type).toList();
+ if (targs.length == 2 && targs.any((t) => !t.isDynamic)) {
+ mapT = typeProvider.mapType.instantiate([targs[0], targs[1]]);
+ }
+ } else {
+ mapT = typeAnalyzer.inferMapType2(node, downwards: true);
+ if (mapT != null &&
+ node.typeArguments == null &&
+ node.entries.isEmpty &&
+ typeSystem.isAssignableTo(typeProvider.iterableObjectType, mapT) &&
+ !typeSystem.isAssignableTo(typeProvider.mapObjectObjectType, mapT)) {
+ // The node is really an empty set literal with no type arguments, so
+ // don't try to visit the replaced map literal.
+ return;
+ }
+ }
+ if (mapT != null) {
+ DartType kType = mapT.typeArguments[0];
+ DartType vType = mapT.typeArguments[1];
+
+ void pushTypesDown(MapElement element) {
+ if (element is MapForElement) {
+ pushTypesDown(element.body);
+ } else if (element is MapIfElement) {
+ pushTypesDown(element.thenElement);
+ pushTypesDown(element.elseElement);
+ } else if (element is MapLiteralEntry) {
+ InferenceContext.setType(element.key, kType);
+ InferenceContext.setType(element.value, vType);
+ } else if (element is SpreadElement) {
+ InferenceContext.setType(element.expression, mapT);
+ }
+ }
+
+ for (MapElement element in node.entries) {
+ pushTypesDown(element);
+ }
+ InferenceContext.setType(node, mapT);
+ } else {
+ InferenceContext.clearType(node);
+ }
+ super.visitMapLiteral2(node);
+ }
+
+ @override
void visitMethodDeclaration(MethodDeclaration node) {
ExecutableElement outerFunction = _enclosingFunction;
FunctionBody outerFunctionBody = _currentFunctionBody;
@@ -5385,6 +5528,32 @@
}
@override
+ void visitSetLiteral2(SetLiteral2 node) {
+ InterfaceType setT;
+
+ TypeArgumentList typeArguments = node.typeArguments;
+ if (typeArguments != null) {
+ if (typeArguments.length == 1) {
+ DartType elementType = typeArguments.arguments[0].type;
+ if (!elementType.isDynamic) {
+ setT = typeProvider.setType.instantiate([elementType]);
+ }
+ }
+ } else {
+ setT = typeAnalyzer.inferSetType2(node, downwards: true);
+ }
+ if (setT != null) {
+ for (CollectionElement element in node.elements) {
+ _pushCollectionTypesDown(element, setT);
+ }
+ InferenceContext.setType(node, setT);
+ } else {
+ InferenceContext.clearType(node);
+ }
+ super.visitSetLiteral2(node);
+ }
+
+ @override
void visitShowCombinator(ShowCombinator node) {}
@override
@@ -5950,6 +6119,20 @@
}
}
+ void _pushCollectionTypesDown(
+ CollectionElement element, ParameterizedType collectionType) {
+ if (element is CollectionForElement) {
+ _pushCollectionTypesDown(element.body, collectionType);
+ } else if (element is CollectionIfElement) {
+ _pushCollectionTypesDown(element.thenElement, collectionType);
+ _pushCollectionTypesDown(element.elseElement, collectionType);
+ } else if (element is Expression) {
+ InferenceContext.setType(element, collectionType.typeArguments[0]);
+ } else if (element is SpreadElement) {
+ InferenceContext.setType(element.expression, collectionType);
+ }
+ }
+
/// Given an [argumentList] and the [parameters] related to the element that
/// will be invoked using those arguments, compute the list of parameters that
/// correspond to the list of arguments.
@@ -6397,6 +6580,30 @@
}
}
+ @override
+ void visitForStatement2(ForStatement2 node) {
+ Scope outerNameScope = nameScope;
+ ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
+ try {
+ nameScope = new EnclosedScope(nameScope);
+ _implicitLabelScope = _implicitLabelScope.nest(node);
+ visitForStatement2InScope(node);
+ } finally {
+ nameScope = outerNameScope;
+ _implicitLabelScope = outerImplicitScope;
+ }
+ }
+
+ /// Visit the given [node] after it's scope has been created. This replaces
+ /// the normal call to the inherited visit method so that ResolverVisitor can
+ /// intervene when type propagation is enabled.
+ void visitForStatement2InScope(ForStatement2 node) {
+ // TODO(brianwilkerson) Investigate the possibility of removing the
+ // visit...InScope methods now that type propagation is no longer done.
+ node.forLoopParts?.accept(this);
+ visitStatementInScope(node.body);
+ }
+
/// Visit the given statement after it's scope has been created. This replaces
/// the normal call to the inherited visit method so that ResolverVisitor can
/// intervene when type propagation is enabled.
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 88f8f3b..b55d885 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -182,6 +182,40 @@
return inferred;
}
+ DartType inferListType2(ListLiteral2 node, {bool downwards: false}) {
+ DartType contextType = InferenceContext.getContext(node);
+
+ var ts = _typeSystem as Dart2TypeSystem;
+ List<DartType> elementTypes;
+ List<ParameterElement> parameters;
+
+ if (downwards) {
+ if (contextType == null) {
+ return null;
+ }
+ elementTypes = [];
+ parameters = [];
+ } else {
+ // Also use upwards information to infer the type.
+ elementTypes = node.elements
+ .map((element) => _computeElementType(element))
+ .where((t) => t != null)
+ .toList();
+ TypeParameterType listTypeParam =
+ _typeProvider.listType.typeParameters[0].type;
+ ParameterElementImpl syntheticParamElement =
+ new ParameterElementImpl.synthetic(
+ 'element', listTypeParam, ParameterKind.POSITIONAL);
+ parameters = new List.filled(elementTypes.length, syntheticParamElement);
+ }
+ InterfaceType inferred = ts.inferGenericFunctionOrType<InterfaceType>(
+ _typeProvider.listType, parameters, elementTypes, contextType,
+ downwards: downwards,
+ errorReporter: _resolver.errorReporter,
+ errorNode: node);
+ return inferred;
+ }
+
ParameterizedType inferMapType(MapLiteral node, {bool downwards: false}) {
DartType contextType = InferenceContext.getContext(node);
if (contextType != null && _experimentStatus.set_literals) {
@@ -247,6 +281,73 @@
return inferred;
}
+ ParameterizedType inferMapType2(MapLiteral2 node, {bool downwards: false}) {
+ DartType contextType = InferenceContext.getContext(node);
+ if (contextType != null && _experimentStatus.set_literals) {
+ DartType unwrap(DartType type) {
+ if (type is InterfaceType &&
+ type.isDartAsyncFutureOr &&
+ type.typeArguments.length == 1) {
+ return unwrap(type.typeArguments[0]);
+ }
+ return type;
+ }
+
+ DartType unwrappedContextType = unwrap(contextType);
+ if (node.typeArguments == null &&
+ node.entries.isEmpty &&
+ _typeSystem.isAssignableTo(
+ _typeProvider.iterableObjectType, unwrappedContextType) &&
+ !_typeSystem.isAssignableTo(
+ _typeProvider.mapObjectObjectType, unwrappedContextType)) {
+ // The node is really an empty set literal with no type arguments.
+ // Rewrite the AST and infer the type of the set as appropriate.
+ SetLiteral setLiteral = new AstFactoryImpl().setLiteral(
+ node.constKeyword, null, node.leftBracket, null, node.rightBracket);
+ InferenceContext.setType(setLiteral, contextType);
+ NodeReplacer.replace(node, setLiteral);
+ DartType type = inferSetType(setLiteral, downwards: downwards);
+ setLiteral.staticType = type;
+ return type;
+ }
+ }
+ List<DartType> elementTypes;
+ List<ParameterElement> parameters;
+ if (downwards) {
+ if (contextType == null) {
+ return null;
+ }
+ elementTypes = [];
+ parameters = [];
+ } else {
+ var keyTypes = node.entries
+ .map((entry) => _computeKeyType(entry))
+ .where((t) => t != null);
+ var valueTypes = node.entries
+ .map((entry) => _computeValueType(entry))
+ .where((t) => t != null);
+ var keyTypeParam = _typeProvider.mapType.typeParameters[0].type;
+ var valueTypeParam = _typeProvider.mapType.typeParameters[1].type;
+ var syntheticKeyParameter = new ParameterElementImpl.synthetic(
+ 'key', keyTypeParam, ParameterKind.POSITIONAL);
+ var syntheticValueParameter = new ParameterElementImpl.synthetic(
+ 'value', valueTypeParam, ParameterKind.POSITIONAL);
+ parameters = new List.filled(keyTypes.length, syntheticKeyParameter,
+ growable: true)
+ ..addAll(new List.filled(valueTypes.length, syntheticValueParameter));
+ elementTypes = new List<DartType>.from(keyTypes)..addAll(valueTypes);
+ }
+
+ // Use both downwards and upwards information to infer the type.
+ var ts = _typeSystem as Dart2TypeSystem;
+ ParameterizedType inferred = ts.inferGenericFunctionOrType(
+ _typeProvider.mapType, parameters, elementTypes, contextType,
+ downwards: downwards,
+ errorReporter: _resolver.errorReporter,
+ errorNode: node);
+ return inferred;
+ }
+
DartType inferSetType(SetLiteral node, {bool downwards: false}) {
DartType contextType = InferenceContext.getContext(node);
@@ -280,6 +381,41 @@
return inferred;
}
+ DartType inferSetType2(SetLiteral2 node, {bool downwards: false}) {
+ DartType contextType = InferenceContext.getContext(node);
+
+ var ts = _typeSystem as Dart2TypeSystem;
+ List<DartType> elementTypes;
+ List<ParameterElement> parameters;
+
+ if (downwards) {
+ if (contextType == null) {
+ return null;
+ }
+
+ elementTypes = [];
+ parameters = [];
+ } else {
+ // Also use upwards information to infer the type.
+ elementTypes = node.elements
+ .map((element) => _computeElementType(element))
+ .where((t) => t != null)
+ .toList();
+ TypeParameterType setTypeParam =
+ _typeProvider.setType.typeParameters[0].type;
+ ParameterElementImpl syntheticParamElement =
+ new ParameterElementImpl.synthetic(
+ 'element', setTypeParam, ParameterKind.POSITIONAL);
+ parameters = new List.filled(elementTypes.length, syntheticParamElement);
+ }
+ DartType inferred = ts.inferGenericFunctionOrType<InterfaceType>(
+ _typeProvider.setType, parameters, elementTypes, contextType,
+ downwards: downwards,
+ errorReporter: _resolver.errorReporter,
+ errorNode: node);
+ return inferred;
+ }
+
/**
* The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
* `String`.</blockquote>
@@ -694,6 +830,45 @@
_recordStaticType(node, listDynamicType);
}
+ @override
+ void visitListLiteral2(ListLiteral2 node) {
+ TypeArgumentList typeArguments = node.typeArguments;
+
+ // If we have explicit arguments, use them
+ if (typeArguments != null) {
+ DartType staticType = _dynamicType;
+ NodeList<TypeAnnotation> arguments = typeArguments.arguments;
+ if (arguments != null && arguments.length == 1) {
+ DartType argumentType = _getType(arguments[0]);
+ if (argumentType != null) {
+ staticType = argumentType;
+ }
+ }
+ _recordStaticType(
+ node, _typeProvider.listType.instantiate(<DartType>[staticType]));
+ return;
+ }
+
+ DartType listDynamicType =
+ _typeProvider.listType.instantiate(<DartType>[_dynamicType]);
+
+ // If there are no type arguments, try to infer some arguments.
+ DartType inferred = inferListType2(node);
+
+ if (inferred != listDynamicType) {
+ // TODO(jmesserly): this results in an "inferred" message even when we
+ // in fact had an error above, because it will still attempt to return
+ // a type. Perhaps we should record inference from TypeSystem if
+ // everything was successful?
+ _resolver.inferenceContext.recordInference(node, inferred);
+ _recordStaticType(node, inferred);
+ return;
+ }
+
+ // If we have no type arguments and couldn't infer any, use dynamic.
+ _recordStaticType(node, listDynamicType);
+ }
+
/**
* The Dart Language Specification, 12.7: <blockquote>The static type of a map literal of the form
* <i><b>const</b> <K, V> {k<sub>1</sub>:e<sub>1</sub>, …,
@@ -752,6 +927,52 @@
_recordStaticType(node, mapDynamicType);
}
+ @override
+ void visitMapLiteral2(MapLiteral2 node) {
+ TypeArgumentList typeArguments = node.typeArguments;
+
+ // If we have type arguments, use them
+ if (typeArguments != null) {
+ DartType staticKeyType = _dynamicType;
+ DartType staticValueType = _dynamicType;
+ NodeList<TypeAnnotation> arguments = typeArguments.arguments;
+ if (arguments != null && arguments.length == 2) {
+ DartType entryKeyType = _getType(arguments[0]);
+ if (entryKeyType != null) {
+ staticKeyType = entryKeyType;
+ }
+ DartType entryValueType = _getType(arguments[1]);
+ if (entryValueType != null) {
+ staticValueType = entryValueType;
+ }
+ }
+ _recordStaticType(
+ node,
+ _typeProvider.mapType
+ .instantiate(<DartType>[staticKeyType, staticValueType]));
+ return;
+ }
+
+ DartType mapDynamicType = _typeProvider.mapType
+ .instantiate(<DartType>[_dynamicType, _dynamicType]);
+
+ // If we have no explicit type arguments, try to infer type arguments.
+ ParameterizedType inferred = inferMapType2(node);
+
+ if (inferred != mapDynamicType) {
+ // TODO(jmesserly): this results in an "inferred" message even when we
+ // in fact had an error above, because it will still attempt to return
+ // a type. Perhaps we should record inference from TypeSystem if
+ // everything was successful?
+ _resolver.inferenceContext.recordInference(node, inferred);
+ _recordStaticType(node, inferred);
+ return;
+ }
+
+ // If no type arguments and no inference, use dynamic
+ _recordStaticType(node, mapDynamicType);
+ }
+
/**
* The Dart Language Specification, 12.15.1: <blockquote>An ordinary method invocation <i>i</i>
* has the form <i>o.m(a<sub>1</sub>, …, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>,
@@ -1038,6 +1259,45 @@
_recordStaticType(node, setDynamicType);
}
+ @override
+ void visitSetLiteral2(SetLiteral2 node) {
+ TypeArgumentList typeArguments = node.typeArguments;
+
+ // If we have type arguments, use them
+ if (typeArguments != null) {
+ DartType elementType = _dynamicType;
+ NodeList<TypeAnnotation> arguments = typeArguments.arguments;
+ if (arguments != null && arguments.length == 1) {
+ DartType type = _getType(arguments[0]);
+ if (type != null) {
+ elementType = type;
+ }
+ }
+ _recordStaticType(
+ node, _typeProvider.setType.instantiate(<DartType>[elementType]));
+ return;
+ }
+
+ DartType setDynamicType =
+ _typeProvider.setType.instantiate(<DartType>[_dynamicType]);
+
+ // If we have no explicit type arguments, try to infer type arguments.
+ ParameterizedType inferred = inferSetType2(node);
+
+ if (inferred != setDynamicType) {
+ // TODO(jmesserly): this results in an "inferred" message even when we
+ // in fact had an error above, because it will still attempt to return
+ // a type. Perhaps we should record inference from TypeSystem if
+ // everything was successful?
+ _resolver.inferenceContext.recordInference(node, inferred);
+ _recordStaticType(node, inferred);
+ return;
+ }
+
+ // If no type arguments and no inference, use dynamic
+ _recordStaticType(node, setDynamicType);
+ }
+
/**
* The Dart Language Specification, 12.30: <blockquote>Evaluation of an identifier expression
* <i>e</i> of the form <i>id</i> proceeds as follows:
@@ -1246,6 +1506,30 @@
return _dynamicType;
}
+ DartType _computeElementType(CollectionElement element) {
+ if (element is CollectionForElement) {
+ return _computeElementType(element.body);
+ } else if (element is CollectionIfElement) {
+ DartType thenType = _computeElementType(element.thenElement);
+ if (element.elseElement == null) {
+ return thenType;
+ }
+ DartType elseType = _computeElementType(element.elseElement);
+ return _typeSystem.leastUpperBound(thenType, elseType);
+ } else if (element is Expression) {
+ return element.staticType;
+ } else if (element is SpreadElement) {
+ DartType collectionType = element.expression.staticType;
+ if (collectionType is ParameterizedType) {
+ List<DartType> typeArguments = collectionType.typeArguments;
+ if (typeArguments.length == 1) {
+ return typeArguments[0];
+ }
+ }
+ }
+ return null;
+ }
+
/**
* Compute the return type of the method or function represented by the given
* type that is being invoked.
@@ -1261,6 +1545,30 @@
return _dynamicType;
}
+ DartType _computeKeyType(MapElement element) {
+ if (element is MapForElement) {
+ return _computeKeyType(element.body);
+ } else if (element is MapIfElement) {
+ DartType thenType = _computeKeyType(element.thenElement);
+ if (element.elseElement == null) {
+ return thenType;
+ }
+ DartType elseType = _computeKeyType(element.elseElement);
+ return _typeSystem.leastUpperBound(thenType, elseType);
+ } else if (element is MapLiteralEntry) {
+ return element.key.staticType;
+ } else if (element is SpreadElement) {
+ DartType collectionType = element.expression.staticType;
+ if (collectionType is ParameterizedType) {
+ List<DartType> typeArguments = collectionType.typeArguments;
+ if (typeArguments.length == 2) {
+ return typeArguments[0];
+ }
+ }
+ }
+ return null;
+ }
+
/**
* Given a function body and its return type, compute the return type of
* the entire function, taking into account whether the function body
@@ -1327,6 +1635,30 @@
return returnType.type;
}
+ DartType _computeValueType(MapElement element) {
+ if (element is MapForElement) {
+ return _computeValueType(element.body);
+ } else if (element is MapIfElement) {
+ DartType thenType = _computeValueType(element.thenElement);
+ if (element.elseElement == null) {
+ return thenType;
+ }
+ DartType elseType = _computeValueType(element.elseElement);
+ return _typeSystem.leastUpperBound(thenType, elseType);
+ } else if (element is MapLiteralEntry) {
+ return element.value.staticType;
+ } else if (element is SpreadElement) {
+ DartType collectionType = element.expression.staticType;
+ if (collectionType is ParameterizedType) {
+ List<DartType> typeArguments = collectionType.typeArguments;
+ if (typeArguments.length == 2) {
+ return typeArguments[1];
+ }
+ }
+ }
+ return null;
+ }
+
DartType _findIteratedType(DartType type, DartType targetType) {
// TODO(vsm): Use leafp's matchType here?
// Set by _find if match is found
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 8ba4f84..088deb95 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -934,8 +934,8 @@
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
// The expected type ought to be `List<int>`, but type inference isn't yet
// implemented.
- expect(result.type,
- typeProvider.listType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
}
@@ -944,10 +944,8 @@
const c = [1, if (1 < 0) 2 else 3, 4];
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.listType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
expect(result.toListValue().map((e) => e.toIntValue()), [1, 3, 4]);
}
@@ -956,10 +954,8 @@
const c = [1, if (1 < 0) 2, 3];
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.listType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
expect(result.toListValue().map((e) => e.toIntValue()), [1, 3]);
}
@@ -968,10 +964,8 @@
const c = [1, if (1 > 0) 2 else 3, 4];
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.listType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 4]);
}
@@ -980,10 +974,8 @@
const c = [1, if (1 > 0) 2, 3];
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.listType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
}
@@ -992,10 +984,8 @@
const c = [1, ...[2, 3], 4];
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.listType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.listType.instantiate([typeProvider.intType]));
expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3, 4]);
}
@@ -1006,12 +996,10 @@
const c = {'a' : 1, if (1 > 0) if (2 > 1) {'b' : 2}, 'c' : 3};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
expect(
result.type,
typeProvider.mapType
- .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]));
+ .instantiate([typeProvider.intType, typeProvider.intType]));
Map<DartObject, DartObject> value = result.toMapValue();
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'b', 'c']));
@@ -1023,12 +1011,10 @@
const c = {'a' : 1, if (1 < 0) 'b' : 2 else 'c' : 3, 'd' : 4};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
expect(
result.type,
typeProvider.mapType
- .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]));
+ .instantiate([typeProvider.stringType, typeProvider.intType]));
Map<DartObject, DartObject> value = result.toMapValue();
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'c', 'd']));
@@ -1040,12 +1026,10 @@
const c = {'a' : 1, if (1 < 0) 'b' : 2, 'c' : 3};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
expect(
result.type,
typeProvider.mapType
- .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]));
+ .instantiate([typeProvider.stringType, typeProvider.intType]));
Map<DartObject, DartObject> value = result.toMapValue();
expect(
value.keys.map((e) => e.toStringValue()), unorderedEquals(['a', 'c']));
@@ -1057,12 +1041,10 @@
const c = {'a' : 1, if (1 > 0) 'b' : 2 else 'c' : 3, 'd' : 4};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
expect(
result.type,
typeProvider.mapType
- .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]));
+ .instantiate([typeProvider.stringType, typeProvider.intType]));
Map<DartObject, DartObject> value = result.toMapValue();
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'b', 'd']));
@@ -1074,12 +1056,10 @@
const c = {'a' : 1, if (1 > 0) 'b' : 2, 'c' : 3};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
expect(
result.type,
typeProvider.mapType
- .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]));
+ .instantiate([typeProvider.stringType, typeProvider.intType]));
Map<DartObject, DartObject> value = result.toMapValue();
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'b', 'c']));
@@ -1091,12 +1071,10 @@
const c = {'a' : 1, ...{'b' : 2, 'c' : 3}, 'd' : 4};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `Map<String, int>`, but type inference
- // isn't yet implemented.
expect(
result.type,
typeProvider.mapType
- .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]));
+ .instantiate([typeProvider.stringType, typeProvider.intType]));
Map<DartObject, DartObject> value = result.toMapValue();
expect(value.keys.map((e) => e.toStringValue()),
unorderedEquals(['a', 'b', 'c', 'd']));
@@ -1111,10 +1089,8 @@
const c = {1, if (1 > 0) if (2 > 1) 2, 3};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.setType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
}
@@ -1123,10 +1099,8 @@
const c = {1, if (1 < 0) 2 else 3, 4};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.setType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3, 4]);
}
@@ -1135,10 +1109,8 @@
const c = {1, if (1 < 0) 2, 3};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.setType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3]);
}
@@ -1147,10 +1119,8 @@
const c = {1, if (1 > 0) 2 else 3, 4};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.setType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 4]);
}
@@ -1159,10 +1129,8 @@
const c = {1, if (1 > 0) 2, 3};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `List<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.setType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
}
@@ -1171,10 +1139,8 @@
const c = {1, ...{2, 3}, 4};
''');
DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
- // The expected type ought to be `Set<int>`, but type inference isn't yet
- // implemented.
- expect(result.type,
- typeProvider.setType.instantiate([typeProvider.dynamicType]));
+ expect(
+ result.type, typeProvider.setType.instantiate([typeProvider.intType]));
expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3, 4]);
}
}