Begin adding summary support for `for` elements.
Change-Id: Icdcfba5caaac34375b65c838dabc97e9b9201ee9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97120
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index a2e6994..3f6a387 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -520,6 +520,15 @@
rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
body: body);
+ static ForElement forElement(
+ ForLoopParts forLoopParts, CollectionElement body) =>
+ astFactory.forElement(
+ forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
+ leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
+ forLoopParts: forLoopParts,
+ rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
+ body: body);
+
static FormalParameterList formalParameterList(
[List<FormalParameter> parameters]) =>
astFactory.formalParameterList(
@@ -529,6 +538,17 @@
null,
TokenFactory.tokenFromType(TokenType.CLOSE_PAREN));
+ static ForPartsWithExpression forPartsWithExpression(
+ Expression initialization,
+ Expression condition,
+ List<Expression> updaters) =>
+ astFactory.forPartsWithExpression(
+ initialization: initialization,
+ leftSeparator: TokenFactory.tokenFromType(TokenType.SEMICOLON),
+ condition: condition,
+ rightSeparator: TokenFactory.tokenFromType(TokenType.SEMICOLON),
+ updaters: updaters);
+
@Deprecated('Use forStatement2')
static ForStatement2 forStatement(Expression initialization,
Expression condition, List<Expression> updaters, Statement body) =>
diff --git a/pkg/analyzer/lib/src/summary/expr_builder.dart b/pkg/analyzer/lib/src/summary/expr_builder.dart
index 960e342..bb2ccb2 100644
--- a/pkg/analyzer/lib/src/summary/expr_builder.dart
+++ b/pkg/analyzer/lib/src/summary/expr_builder.dart
@@ -42,7 +42,7 @@
// The stack of values. Note that they are usually [Expression]s, but may be
// any [CollectionElement] to support map/set/list literals.
- final List<CollectionElement> stack = <CollectionElement>[];
+ final List<AstNode> stack = <AstNode>[];
final List<UnlinkedExecutable> localFunctions;
@@ -329,6 +329,15 @@
case UnlinkedExprOperation.ifElseElement:
_pushIfElement(true);
break;
+ case UnlinkedExprOperation.forParts:
+ _pushForParts();
+ break;
+ case UnlinkedExprOperation.forElement:
+ _pushForElement();
+ break;
+ case UnlinkedExprOperation.pushEmptyExpression:
+ _push(null);
+ break;
case UnlinkedExprOperation.cascadeSectionBegin:
case UnlinkedExprOperation.cascadeSectionEnd:
case UnlinkedExprOperation.pushLocalFunctionReference:
@@ -629,9 +638,12 @@
Expression _pop() => stack.removeLast() as Expression;
- CollectionElement _popCollectionElement() => stack.removeLast();
+ CollectionElement _popCollectionElement() =>
+ stack.removeLast() as CollectionElement;
- void _push(CollectionElement expr) {
+ AstNode _popNode() => stack.removeLast();
+
+ void _push(Expression expr) {
stack.add(expr);
}
@@ -656,11 +668,34 @@
_push(AstTestFactory.propertyAccess(target, propertyNode));
}
+ void _pushForElement() {
+ var body = _popCollectionElement();
+ var forLoopParts = _popNode() as ForLoopParts;
+ _pushCollectionElement(AstTestFactory.forElement(forLoopParts, body));
+ }
+
+ void _pushForParts() {
+ var updaterCount = _uc.ints[intPtr++];
+ var updaters = <Expression>[];
+ for (int i = 0; i < updaterCount; i++) {
+ updaters.insert(0, _pop());
+ }
+ Expression condition = _pop();
+ AstNode initialization = _popNode();
+ if (initialization is Expression || initialization == null) {
+ _pushNode(AstTestFactory.forPartsWithExpression(
+ initialization, condition, updaters));
+ } else {
+ throw UnimplementedError('TODO(paulberry)');
+ }
+ }
+
void _pushIfElement(bool hasElse) {
CollectionElement elseElement = hasElse ? _popCollectionElement() : null;
CollectionElement thenElement = _popCollectionElement();
Expression condition = _pop();
- _push(AstTestFactory.ifElement(condition, thenElement, elseElement));
+ _pushCollectionElement(
+ AstTestFactory.ifElement(condition, thenElement, elseElement));
}
void _pushInstanceCreation() {
@@ -868,6 +903,10 @@
_pushCollectionElement(AstTestFactory.mapLiteralEntry2(key, value));
}
+ void _pushNode(AstNode node) {
+ stack.add(node);
+ }
+
void _pushPrefix(TokenType operator) {
Expression operand = _pop();
_push(AstTestFactory.prefixExpression(operator, operand));
@@ -938,7 +977,7 @@
void _pushSpread(TokenType operator) {
Expression operand = _pop();
- _push(AstTestFactory.spreadElement(operator, operand));
+ _pushCollectionElement(AstTestFactory.spreadElement(operator, operand));
}
List<Expression> _removeTopExpressions(int count) {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 6cd172f..ca4f27a 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -991,7 +991,20 @@
/// other two are collection elements. Push an "if" element having the given
/// condition, with the two collection elements as its "then" and "else"
/// clauses, respectively.
- ifElseElement
+ ifElseElement,
+
+ /// Pop the top n+2 values from the stack, where n is obtained from
+ /// [UnlinkedExpr.ints]. The first two are the initialization and condition
+ /// of the for-loop; the remainder are the updaters.
+ forParts,
+
+ /// Pop the top 2 values from the stack. The first is the for loop parts.
+ /// The second is the body.
+ forElement,
+
+ /// Push the empty expression (used for missing initializers and conditions in
+ /// `for` loops)
+ pushEmptyExpression
}
/// Enum used to indicate the kind of a parameter.
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index c9e84f8..5a5bede 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -3887,6 +3887,19 @@
/// condition, with the two collection elements as its "then" and "else"
/// clauses, respectively.
ifElseElement,
+
+ /// Pop the top n+2 values from the stack, where n is obtained from
+ /// [UnlinkedExpr.ints]. The first two are the initialization and condition
+ /// of the for-loop; the remainder are the updaters.
+ forParts,
+
+ /// Pop the top 2 values from the stack. The first is the for loop parts.
+ /// The second is the body.
+ forElement,
+
+ /// Push the empty expression (used for missing initializers and conditions in
+ /// `for` loops)
+ pushEmptyExpression,
}
/// Unlinked summary information about an import declaration.
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index d38b602..8bb9b33 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -1906,6 +1906,7 @@
case UnlinkedExprOperation.makeUntypedMap:
case UnlinkedExprOperation.makeUntypedSet:
case UnlinkedExprOperation.makeUntypedSetOrMap:
+ case UnlinkedExprOperation.forParts:
intPtr++;
break;
case UnlinkedExprOperation.assignToRef:
@@ -5206,6 +5207,7 @@
case UnlinkedExprOperation.makeUntypedMap:
case UnlinkedExprOperation.makeUntypedSet:
case UnlinkedExprOperation.makeUntypedSetOrMap:
+ case UnlinkedExprOperation.forParts:
intPtr++;
break;
case UnlinkedExprOperation.makeTypedList:
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index f367937..ab5a11b 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -293,8 +293,10 @@
}
/// Serialize the given [expr] expression into this serializer state.
- void _serialize(Expression expr) {
- if (expr is IntegerLiteral) {
+ void _serialize(Expression expr, {bool emptyExpressionPermitted: false}) {
+ if (emptyExpressionPermitted && expr == null) {
+ operations.add(UnlinkedExprOperation.pushEmptyExpression);
+ } else if (expr is IntegerLiteral) {
int value = expr.value ?? 0;
if (value >= 0) {
_pushInt(value);
@@ -558,9 +560,28 @@
_serializeCollectionElement(elseElement);
operations.add(UnlinkedExprOperation.ifElseElement);
}
+ } else if (element is ForElement) {
+ var parts = element.forLoopParts;
+ if (parts is ForParts) {
+ if (parts is ForPartsWithExpression) {
+ _serialize(parts.initialization, emptyExpressionPermitted: true);
+ } else {
+ // See https://github.com/dart-lang/sdk/issues/35569
+ throw StateError('TODO(paulberry)');
+ }
+ _serialize(parts.condition, emptyExpressionPermitted: true);
+ for (var updater in parts.updaters) {
+ _serialize(updater);
+ }
+ operations.add(UnlinkedExprOperation.forParts);
+ ints.add(parts.updaters.length);
+ } else {
+ // See https://github.com/dart-lang/sdk/issues/35569
+ throw new StateError('TODO(paulberry)');
+ }
+ _serializeCollectionElement(element.body);
+ operations.add(UnlinkedExprOperation.forElement);
} else {
- // TODO(paulberry): Implement serialization for spread and control flow
- // elements.
throw new StateError('Unsupported CollectionElement: $element');
}
}
diff --git a/pkg/analyzer/test/src/summary/expr_builder_test.dart b/pkg/analyzer/test/src/summary/expr_builder_test.dart
index 67a8ae9..46a6306 100644
--- a/pkg/analyzer/test/src/summary/expr_builder_test.dart
+++ b/pkg/analyzer/test/src/summary/expr_builder_test.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -293,6 +294,51 @@
checkSimpleExpression('0 <= 1');
}
+ void test_list_for() {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var sourceText = '[for (i = 0; i < 10; i++) i]';
+ // Resynthesis inserts synthetic "const" tokens; work around that.
+ var expectedText = 'const $sourceText';
+ checkSimpleExpression(sourceText,
+ expectedText: expectedText, extraDeclarations: 'int i;');
+ }
+
+ void test_list_for_empty_condition() {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var sourceText = '[for (i = 0;; i++) i]';
+ // Resynthesis inserts synthetic "const" tokens; work around that.
+ var expectedText = 'const $sourceText';
+ checkSimpleExpression(sourceText,
+ expectedText: expectedText, extraDeclarations: 'int i;');
+ }
+
+ void test_list_for_empty_initializer() {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var sourceText = '[for (; i < 10; i++) i]';
+ // Resynthesis inserts synthetic "const" tokens; work around that.
+ var expectedText = 'const $sourceText';
+ checkSimpleExpression(sourceText,
+ expectedText: expectedText, extraDeclarations: 'int i;');
+ }
+
+ void test_list_for_two_updaters() {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var sourceText = '[for (i = 0; i < 10; i++, j++) i]';
+ // Resynthesis inserts synthetic "const" tokens; work around that.
+ var expectedText = 'const $sourceText';
+ checkSimpleExpression(sourceText,
+ expectedText: expectedText, extraDeclarations: 'int i; int j;');
+ }
+
+ void test_list_for_zero_updaters() {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var sourceText = '[for (i = 0; i < 10;) i]';
+ // Resynthesis inserts synthetic "const" tokens; work around that.
+ var expectedText = 'const $sourceText';
+ checkSimpleExpression(sourceText,
+ expectedText: expectedText, extraDeclarations: 'int i;');
+ }
+
void test_makeSymbol() {
checkSimpleExpression('#foo');
}
@@ -313,6 +359,15 @@
checkSimpleExpression('const {0 : false}');
}
+ void test_map_for() {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var sourceText = '{1 : 2, for (i = 0; i < 10; i++) i : i}';
+ // Resynthesis inserts synthetic "const" tokens; work around that.
+ var expectedText = 'const $sourceText';
+ checkSimpleExpression(sourceText,
+ expectedText: expectedText, extraDeclarations: 'int i;');
+ }
+
void test_modulo() {
checkSimpleExpression('0 % 1');
}
@@ -462,6 +517,15 @@
checkSimpleExpression('true');
}
+ void test_set_for() {
+ experimentStatus = ExperimentStatus(control_flow_collections: true);
+ var sourceText = '{1, for (i = 0; i < 10; i++) i}';
+ // Resynthesis inserts synthetic "const" tokens; work around that.
+ var expectedText = 'const $sourceText';
+ checkSimpleExpression(sourceText,
+ expectedText: expectedText, extraDeclarations: 'int i;');
+ }
+
void test_subtract() {
checkSimpleExpression('0 - 1');
}
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index e5a4dfb..51ecb6a 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -7650,6 +7650,205 @@
forTypeInferenceOnly: true);
}
+ test_expr_list_for() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('int i; var v = [for (i = 0; i < 10; i++) i];');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '[for (i = 0; i < 10; i++) i]',
+ isValidConst: false,
+ operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.less,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.forParts,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.forElement,
+ UnlinkedExprOperation.makeUntypedList
+ ],
+ assignmentOperators: [
+ UnlinkedExprAssignOperator.assign,
+ UnlinkedExprAssignOperator.postfixIncrement
+ ],
+ ints: [
+ 0,
+ 10,
+ 1,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor)
+ ]);
+ }
+
+ test_expr_list_for_empty_condition() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('int i; var v = [for (i = 0;; i++) i];');
+ assertUnlinkedConst(variable.initializer.bodyExpr, '[for (i = 0;; i++) i]',
+ isValidConst: false,
+ operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.pushEmptyExpression,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.forParts,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.forElement,
+ UnlinkedExprOperation.makeUntypedList
+ ],
+ assignmentOperators: [
+ UnlinkedExprAssignOperator.assign,
+ UnlinkedExprAssignOperator.postfixIncrement
+ ],
+ ints: [
+ 0,
+ 1,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor)
+ ]);
+ }
+
+ test_expr_list_for_empty_initializer() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('int i; var v = [for (; i < 10; i++) i];');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '[for (; i < 10; i++) i]',
+ isValidConst: false,
+ operators: [
+ UnlinkedExprOperation.pushEmptyExpression,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.less,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.forParts,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.forElement,
+ UnlinkedExprOperation.makeUntypedList
+ ],
+ assignmentOperators: [
+ UnlinkedExprAssignOperator.postfixIncrement
+ ],
+ ints: [
+ 10,
+ 1,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor)
+ ]);
+ }
+
+ test_expr_list_for_two_updaters() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable = serializeVariableText(
+ 'int i; int j; var v = [for (i = 0; i < 10; i++, j++) i];');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '[for (i = 0; i < 10; i++, j++) i]',
+ isValidConst: false,
+ operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.less,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.forParts,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.forElement,
+ UnlinkedExprOperation.makeUntypedList
+ ],
+ assignmentOperators: [
+ UnlinkedExprAssignOperator.assign,
+ UnlinkedExprAssignOperator.postfixIncrement,
+ UnlinkedExprAssignOperator.postfixIncrement
+ ],
+ ints: [
+ 0,
+ 10,
+ 2,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'j',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor)
+ ]);
+ }
+
+ test_expr_list_for_zero_updaters() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable =
+ serializeVariableText('int i; var v = [for (i = 0; i < 10;) i];');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '[for (i = 0; i < 10;) i]',
+ isValidConst: false,
+ operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.less,
+ UnlinkedExprOperation.forParts,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.forElement,
+ UnlinkedExprOperation.makeUntypedList
+ ],
+ assignmentOperators: [
+ UnlinkedExprAssignOperator.assign
+ ],
+ ints: [
+ 0,
+ 10,
+ 0,
+ 1
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor)
+ ]);
+ }
+
test_expr_makeTypedList() {
UnlinkedVariable variable =
serializeVariableText('var v = <int>[11, 22, 33];');
@@ -7742,6 +7941,101 @@
forTypeInferenceOnly: true);
}
+ test_expr_map_for() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable = serializeVariableText(
+ 'int i; var v = {1: 2, for (i = 0; i < 10; i++) i: i};');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '{1: 2, for (i = 0; i < 10; i++) i: i}',
+ isValidConst: false,
+ operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeMapLiteralEntry,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.less,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.forParts,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.makeMapLiteralEntry,
+ UnlinkedExprOperation.forElement,
+ UnlinkedExprOperation.makeUntypedSetOrMap
+ ],
+ assignmentOperators: [
+ UnlinkedExprAssignOperator.assign,
+ UnlinkedExprAssignOperator.postfixIncrement
+ ],
+ ints: [
+ 1,
+ 2,
+ 0,
+ 10,
+ 1,
+ 2
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor)
+ ]);
+ }
+
+ test_expr_set_for() {
+ experimentStatus = ExperimentStatus(
+ control_flow_collections: true, spread_collections: true);
+ UnlinkedVariable variable = serializeVariableText(
+ 'int i; var v = {1, for (i = 0; i < 10; i++) i};');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr, '{1, for (i = 0; i < 10; i++) i}',
+ isValidConst: false,
+ operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.less,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.forParts,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.forElement,
+ UnlinkedExprOperation.makeUntypedSetOrMap
+ ],
+ assignmentOperators: [
+ UnlinkedExprAssignOperator.assign,
+ UnlinkedExprAssignOperator.postfixIncrement
+ ],
+ ints: [
+ 1,
+ 0,
+ 10,
+ 1,
+ 2
+ ],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'i',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor)
+ ]);
+ }
+
test_expr_super() {
UnlinkedVariable variable = serializeVariableText('''
final v = super;