Update parser to support simple if/else control flow in literal lists, sets, and maps
Change-Id: I740beea833ed1ad76582ad5232549bd204981808
Reviewed-on: https://dart-review.googlesource.com/c/90901
Commit-Queue: Dan Rubel <danrubel@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index 88972ed..a6c75c5 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -1230,7 +1230,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'if');
}
- @failingTest
test_KEYWORD_if_map() async {
addTestFile('''
f(a, b) {
@@ -1241,7 +1240,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'if');
}
- @failingTest
test_KEYWORD_if_set() async {
addTestFile('''
f(a, b) {
@@ -1252,7 +1250,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'if');
}
- @failingTest
test_KEYWORD_ifElse_list() async {
addTestFile('''
f(a, b) {
@@ -1264,7 +1261,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'else');
}
- @failingTest
test_KEYWORD_ifElse_map() async {
addTestFile('''
f(a, b) {
@@ -1276,7 +1272,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'else');
}
- @failingTest
test_KEYWORD_ifElse_set() async {
addTestFile('''
f(a, b) {
diff --git a/pkg/analysis_server/test/analysis/notification_highlights_test.dart b/pkg/analysis_server/test/analysis/notification_highlights_test.dart
index 7d0fba2..9e1b109 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights_test.dart
@@ -1079,7 +1079,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'if');
}
- @failingTest
test_KEYWORD_if_map() async {
addTestFile('''
f(a, b) {
@@ -1090,7 +1089,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'if');
}
- @failingTest
test_KEYWORD_if_set() async {
addTestFile('''
f(a, b) {
@@ -1101,7 +1099,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'if');
}
- @failingTest
test_KEYWORD_ifElse_list() async {
addTestFile('''
f(a, b) {
@@ -1113,7 +1110,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'else');
}
- @failingTest
test_KEYWORD_ifElse_map() async {
addTestFile('''
f(a, b) {
@@ -1125,7 +1121,6 @@
assertHasRegion(HighlightRegionType.KEYWORD, 'else');
}
- @failingTest
test_KEYWORD_ifElse_set() async {
addTestFile('''
f(a, b) {
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index d2e66e4..31b8756 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -282,19 +282,40 @@
}
@override
+ void handleElseControlFlow(Token elseToken) {
+ push(elseToken);
+ }
+
+ @override
void endIfControlFlow(Token token) {
- CollectionElement thenElement = pop();
+ var thenElement = pop();
ParenthesizedExpression condition = pop();
Token ifToken = pop();
+ pushIfControlFlowInfo(ifToken, condition, thenElement, null, null);
+ }
+
+ @override
+ void endIfElseControlFlow(Token token) {
+ var elseElement = pop();
+ Token elseToken = pop();
+ var thenElement = pop();
+ ParenthesizedExpression condition = pop();
+ Token ifToken = pop();
+ pushIfControlFlowInfo(
+ ifToken, condition, thenElement, elseToken, elseElement);
+ }
+
+ void pushIfControlFlowInfo(Token ifToken, ParenthesizedExpression condition,
+ var thenElement, Token elseToken, var elseElement) {
if (enableControlFlowCollections) {
- push(ast.collectionIfElement(
- ifKeyword: ifToken,
- leftParenthesis: condition.leftParenthesis,
- condition: condition.expression,
- rightParenthesis: condition.rightParenthesis,
- thenElement: thenElement,
- elseKeyword: null,
- elseElement: null));
+ push(new _ControlFlowInfo(
+ ifToken,
+ condition.leftParenthesis,
+ condition.expression,
+ condition.rightParenthesis,
+ thenElement,
+ elseToken,
+ elseElement));
} else {
handleRecoverableError(
templateUnexpectedToken.withArguments(ifToken), ifToken, ifToken);
@@ -894,7 +915,13 @@
debugEvent("LiteralList");
if (enableControlFlowCollections || enableSpreadCollections) {
- List<CollectionElement> elements = popTypedList(count);
+ List<CollectionElement> elements = <CollectionElement>[];
+ popTypedList(count)?.forEach((element) {
+ elements.add(element is _EntryInfo
+ ? element.asCollectionElement(ast)
+ : element as CollectionElement);
+ });
+
TypeArgumentList typeArguments = pop();
push(ast.listLiteral2(
constKeyword: constKeyword,
@@ -968,8 +995,13 @@
debugEvent("LiteralSet");
if (enableControlFlowCollections || enableSpreadCollections) {
- List<CollectionElement> elements =
- popTypedList(count) ?? <CollectionElement>[];
+ List<CollectionElement> elements = <CollectionElement>[];
+ popTypedList(count)?.forEach((element) {
+ elements.add(element is _EntryInfo
+ ? element.asCollectionElement(ast)
+ : element as CollectionElement);
+ });
+
TypeArgumentList typeArguments = pop();
push(ast.setLiteral2(
constKeyword: constKeyword,
@@ -996,9 +1028,9 @@
if (enableControlFlowCollections || enableSpreadCollections) {
List<MapElement> entries = <MapElement>[];
popTypedList(count)?.forEach((entry) {
- if (entry is MapElement) {
- entries.add(entry);
- }
+ entries.add(entry is _EntryInfo
+ ? entry.asMapElement(ast)
+ : entry as MapElement);
});
TypeArgumentList typeArguments = pop();
@@ -3122,3 +3154,58 @@
_ConstructorNameWithInvalidTypeArgs(this.name, this.invalidTypeArgs);
}
+
+abstract class _EntryInfo {
+ CollectionElement asCollectionElement(AstFactory ast);
+ MapElement asMapElement(AstFactory ast);
+}
+
+class _ControlFlowInfo implements _EntryInfo {
+ final Token ifToken;
+ final Token leftParenthesis;
+ final Expression conditionExpression;
+ final Token rightParenthesis;
+ final thenElement;
+ final Token elseToken;
+ final elseElement;
+
+ _ControlFlowInfo(
+ this.ifToken,
+ this.leftParenthesis,
+ this.conditionExpression,
+ this.rightParenthesis,
+ this.thenElement,
+ this.elseToken,
+ this.elseElement);
+
+ @override
+ CollectionElement asCollectionElement(AstFactory ast) =>
+ ast.collectionIfElement(
+ ifKeyword: ifToken,
+ leftParenthesis: leftParenthesis,
+ condition: conditionExpression,
+ rightParenthesis: rightParenthesis,
+ thenElement: thenElement is _EntryInfo
+ ? thenElement.asCollectionElement(ast)
+ : thenElement as CollectionElement,
+ elseKeyword: elseToken,
+ elseElement: elseElement is _EntryInfo
+ ? elseElement.asCollectionElement(ast)
+ : elseElement as CollectionElement,
+ );
+
+ @override
+ MapElement asMapElement(AstFactory ast) => ast.mapIfElement(
+ ifKeyword: ifToken,
+ leftParenthesis: leftParenthesis,
+ condition: conditionExpression,
+ rightParenthesis: rightParenthesis,
+ thenElement: thenElement is _EntryInfo
+ ? thenElement.asMapElement(ast)
+ : thenElement as MapElement,
+ elseKeyword: elseToken,
+ elseElement: elseElement is _EntryInfo
+ ? elseElement.asMapElement(ast)
+ : elseElement as MapElement,
+ );
+}
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index c558376..5a2a061 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -801,6 +801,12 @@
}
@override
+ void endIfElseControlFlow(Token token) {
+ end('IfControlFlow');
+ super.endIfElseControlFlow(token);
+ }
+
+ @override
void endIfStatement(Token ifToken, Token elseToken) {
end('IfStatement');
super.endIfStatement(ifToken, elseToken);
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 5829f98..1c07949 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -151,6 +151,22 @@
expect(condition.value, isTrue);
IntegerLiteral thenElement = second.thenElement;
expect(thenElement.value, 2);
+ expect(second.elseElement, isNull);
+ }
+
+ void test_listLiteral_ifElse() {
+ ListLiteral2 list = parseCollectionLiteral('[1, if (true) 2 else 5]');
+ expect(list.elements, hasLength(2));
+ IntegerLiteral first = list.elements[0];
+ expect(first.value, 1);
+
+ CollectionIfElement second = list.elements[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ IntegerLiteral thenElement = second.thenElement;
+ expect(thenElement.value, 2);
+ IntegerLiteral elseElement = second.elseElement;
+ expect(elseElement.value, 5);
}
void test_listLiteral_ifSpread() {
@@ -164,6 +180,23 @@
expect(condition.value, isTrue);
SpreadElement thenElement = second.thenElement;
expect(thenElement.spreadOperator.lexeme, '...');
+ expect(second.elseElement, isNull);
+ }
+
+ void test_listLiteral_ifElseSpread() {
+ ListLiteral2 list =
+ parseCollectionLiteral('[1, if (true) ...[2] else ...?[5]]');
+ expect(list.elements, hasLength(2));
+ IntegerLiteral first = list.elements[0];
+ expect(first.value, 1);
+
+ CollectionIfElement second = list.elements[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ SpreadElement thenElement = second.thenElement;
+ expect(thenElement.spreadOperator.lexeme, '...');
+ SpreadElement elseElement = second.elseElement;
+ expect(elseElement.spreadOperator.lexeme, '...?');
}
void test_listLiteral_spread() {
@@ -190,6 +223,77 @@
expect(spreadExpression.elements, hasLength(1));
}
+ void test_mapLiteral_if() {
+ MapLiteral2 map = parseCollectionLiteral('{1:1, if (true) 2:4}');
+ expect(map.entries, hasLength(2));
+ MapLiteralEntry first = map.entries[0];
+ IntegerLiteral firstValue = first.value;
+ expect(firstValue.value, 1);
+
+ MapIfElement second = map.entries[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ MapLiteralEntry thenElement = second.thenElement;
+ IntegerLiteral thenElementValue = thenElement.value;
+ expect(thenElementValue.value, 4);
+ expect(second.elseElement, isNull);
+ }
+
+ void test_mapLiteral_ifElse() {
+ MapLiteral2 map = parseCollectionLiteral('{1:1, if (true) 2:4 else 5:6}');
+ expect(map.entries, hasLength(2));
+ MapLiteralEntry first = map.entries[0];
+ IntegerLiteral firstValue = first.value;
+ expect(firstValue.value, 1);
+
+ MapIfElement second = map.entries[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ MapLiteralEntry thenElement = second.thenElement;
+ IntegerLiteral thenElementValue = thenElement.value;
+ expect(thenElementValue.value, 4);
+ MapLiteralEntry elseElement = second.elseElement;
+ IntegerLiteral elseElementValue = elseElement.value;
+ expect(elseElementValue.value, 6);
+ }
+
+ void test_mapLiteral_ifSpread() {
+ MapLiteral2 map = parseCollectionLiteral('{1:1, if (true) ...{2:4}}');
+ expect(map.entries, hasLength(2));
+ MapLiteralEntry first = map.entries[0];
+ IntegerLiteral firstValue = first.value;
+ expect(firstValue.value, 1);
+
+ MapIfElement second = map.entries[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ SpreadElement thenElement = second.thenElement;
+ expect(thenElement.spreadOperator.lexeme, '...');
+ expect(second.elseElement, isNull);
+ }
+
+ void test_mapLiteral_ifElseSpread() {
+ MapLiteral2 map =
+ parseCollectionLiteral('{1:7, if (true) ...{2:4} else ...?{5:6}}');
+ expect(map.entries, hasLength(2));
+ MapLiteralEntry first = map.entries[0];
+ IntegerLiteral firstValue = first.value;
+ expect(firstValue.value, 7);
+
+ MapIfElement second = map.entries[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ SpreadElement thenElement = second.thenElement;
+ expect(thenElement.spreadOperator.lexeme, '...');
+ SpreadElement elseElement = second.elseElement;
+ expect(elseElement.spreadOperator.lexeme, '...?');
+ MapLiteral2 elseElementExpression = elseElement.expression;
+ expect(elseElementExpression.entries, hasLength(1));
+ MapLiteralEntry entry = elseElementExpression.entries[0];
+ IntegerLiteral entryValue = entry.value;
+ expect(entryValue.value, 6);
+ }
+
void test_mapLiteral_spread() {
MapLiteral2 map = parseCollectionLiteral('{1: 2, ...{3: 4}}');
expect(map.constKeyword, isNull);
@@ -262,6 +366,69 @@
expect(spreadExpression.entries, hasLength(1));
}
+ void test_setLiteral_if() {
+ SetLiteral2 setLiteral = parseCollectionLiteral('{1, if (true) 2}');
+ expect(setLiteral.elements, hasLength(2));
+ IntegerLiteral first = setLiteral.elements[0];
+ expect(first.value, 1);
+
+ CollectionIfElement second = setLiteral.elements[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ IntegerLiteral thenElement = second.thenElement;
+ expect(thenElement.value, 2);
+ expect(second.elseElement, isNull);
+ }
+
+ void test_setLiteral_ifElse() {
+ SetLiteral2 setLiteral = parseCollectionLiteral('{1, if (true) 2 else 5}');
+ expect(setLiteral.elements, hasLength(2));
+ IntegerLiteral first = setLiteral.elements[0];
+ expect(first.value, 1);
+
+ CollectionIfElement second = setLiteral.elements[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ IntegerLiteral thenElement = second.thenElement;
+ expect(thenElement.value, 2);
+ IntegerLiteral elseElement = second.elseElement;
+ expect(elseElement.value, 5);
+ }
+
+ void test_setLiteral_ifSpread() {
+ SetLiteral2 setLiteral = parseCollectionLiteral('{1, if (true) ...[2]}');
+ expect(setLiteral.elements, hasLength(2));
+ IntegerLiteral first = setLiteral.elements[0];
+ expect(first.value, 1);
+
+ CollectionIfElement second = setLiteral.elements[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ SpreadElement thenElement = second.thenElement;
+ expect(thenElement.spreadOperator.lexeme, '...');
+ expect(second.elseElement, isNull);
+ }
+
+ void test_setLiteral_ifElseSpread() {
+ SetLiteral2 setLiteral =
+ parseCollectionLiteral('{1, if (true) ...{2} else ...?[5]}');
+ expect(setLiteral.elements, hasLength(2));
+ IntegerLiteral first = setLiteral.elements[0];
+ expect(first.value, 1);
+
+ CollectionIfElement second = setLiteral.elements[1];
+ BooleanLiteral condition = second.condition;
+ expect(condition.value, isTrue);
+ SpreadElement thenElement = second.thenElement;
+ expect(thenElement.spreadOperator.lexeme, '...');
+ SetLiteral2 theExpression = thenElement.expression;
+ expect(theExpression.elements, hasLength(1));
+ SpreadElement elseElement = second.elseElement;
+ expect(elseElement.spreadOperator.lexeme, '...?');
+ ListLiteral2 elseExpression = elseElement.expression;
+ expect(elseExpression.elements, hasLength(1));
+ }
+
void test_setLiteral_spread2() {
SetLiteral2 set = parseCollectionLiteral('{3, ...[4]}');
expect(set.constKeyword, isNull);
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 21f1eff..ace876e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -3528,6 +3528,19 @@
}
@override
+ void endIfElseControlFlow(Token token) {
+ debugEvent("IfElseControlFlow");
+ // TODO(danrubel) implement control flow support
+ pop(); // else entry
+ var entry = pop(); // then entry
+ pop(); // parenthesized expression
+ Token ifToken = pop();
+ push(entry); // push the entry back on the stack and drop the rest
+ handleRecoverableError(
+ fasta.templateUnexpectedToken.withArguments(ifToken), ifToken, ifToken);
+ }
+
+ @override
void handleSpreadExpression(Token spreadToken) {
debugEvent("SpreadExpression");
// TODO(danrubel) implement spread expression support
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index 3292dd8..b909283 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -646,6 +646,11 @@
}
@override
+ void endIfElseControlFlow(Token token) {
+ listener?.endIfElseControlFlow(token);
+ }
+
+ @override
void endIfStatement(Token ifToken, Token elseToken) {
listener?.endIfStatement(ifToken, elseToken);
}
@@ -981,6 +986,11 @@
}
@override
+ void handleElseControlFlow(Token elseToken) {
+ listener?.handleElseControlFlow(elseToken);
+ }
+
+ @override
void handleEmptyStatement(Token token) {
listener?.handleEmptyStatement(token);
}
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 101e349..0345607 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -1077,6 +1077,10 @@
/// Called before parsing an `if` control flow list, set, or map entry.
void beginIfControlFlow(Token ifToken) {}
+ /// Called before parsing the `else` portion of an `if` control flow list,
+ /// set, or map entry.
+ void handleElseControlFlow(Token elseToken) {}
+
/// Called after parsing an `if` control flow list, set, or map entry.
/// Substructures:
/// - if conditional expression
@@ -1085,6 +1089,15 @@
logEvent("IfControlFlow");
}
+ /// Called after parsing an if-else control flow list, set, or map entry.
+ /// Substructures:
+ /// - if conditional expression
+ /// - then expression
+ /// - else expression
+ void endIfElseControlFlow(Token token) {
+ logEvent("IfElseControlFlow");
+ }
+
/// Called after parsing a list, set, or map entry that starts with
/// one of the spread collection tokens `...` or `...?`. Substructures:
/// - expression
diff --git a/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
index b9bc2a4..5f200e9 100644
--- a/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
@@ -70,7 +70,9 @@
@override
LiteralEntryInfo computeNext(Token token) {
- // TODO(danrubel): handle `else'
+ if (optional('else', token.next)) {
+ return const IfElse();
+ }
return const IfComplete();
}
}
@@ -82,11 +84,55 @@
@override
LiteralEntryInfo computeNext(Token token) {
- // TODO(danrubel): handle `else'
+ if (optional('else', token.next)) {
+ return const IfElse();
+ }
return const IfComplete();
}
}
+/// A step for parsing the `else` portion of an `if` control flow.
+class IfElse extends LiteralEntryInfo {
+ const IfElse() : super(false);
+
+ @override
+ Token parse(Token token, Parser parser) {
+ Token elseToken = token.next;
+ assert(optional('else', elseToken));
+ parser.listener.handleElseControlFlow(elseToken);
+ return elseToken;
+ }
+
+ @override
+ LiteralEntryInfo computeNext(Token token) {
+ assert(optional('else', token));
+ Token next = token.next;
+ if (optional('...', next) || optional('...?', next)) {
+ return const ElseSpread();
+ }
+ // TODO(danrubel): nested control flow structures
+ return const ElseEntry();
+ }
+}
+
+class ElseSpread extends SpreadOperator {
+ const ElseSpread();
+
+ @override
+ LiteralEntryInfo computeNext(Token token) {
+ return const IfElseComplete();
+ }
+}
+
+class ElseEntry extends LiteralEntryInfo {
+ const ElseEntry() : super(true);
+
+ @override
+ LiteralEntryInfo computeNext(Token token) {
+ return const IfElseComplete();
+ }
+}
+
class IfComplete extends LiteralEntryInfo {
const IfComplete() : super(false);
@@ -97,6 +143,16 @@
}
}
+class IfElseComplete extends LiteralEntryInfo {
+ const IfElseComplete() : super(false);
+
+ @override
+ Token parse(Token token, Parser parser) {
+ parser.listener.endIfElseControlFlow(token);
+ return token;
+ }
+}
+
/// The first step when processing a spread entry.
class SpreadOperator extends LiteralEntryInfo {
const SpreadOperator() : super(false);
diff --git a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
index b87ff91..f300037 100644
--- a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
@@ -383,6 +383,12 @@
}
@override
+ void endIfElseControlFlow(Token token) {
+ // TODO(danrubel) add support for if control flow collection entries
+ // but for now this is ignored and an error reported in the body builder.
+ }
+
+ @override
void handleSpreadExpression(Token spreadToken) {
// TODO(danrubel) add support for spread collections
// but for now this is ignored and an error reported in the body builder.
diff --git a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart b/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
index a087fe3..380347f 100644
--- a/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/literal_entry_info_test.dart
@@ -71,6 +71,21 @@
);
}
+ test_ifElse() {
+ parseEntry(
+ 'before if (true) 2 else 5',
+ [
+ 'beginIfControlFlow if',
+ 'handleLiteralBool true',
+ 'handleParenthesizedCondition (',
+ 'handleLiteralInt 2',
+ 'handleElseControlFlow else',
+ 'handleLiteralInt 5',
+ 'endIfElseControlFlow 5',
+ ],
+ );
+ }
+
test_ifSpreadQ() {
parseEntry(
'before if (true) ...?[2]',
@@ -87,6 +102,29 @@
);
}
+ test_ifElseSpreadQ() {
+ parseEntry(
+ 'before if (true) ...?[2] else ... const {5}',
+ [
+ 'beginIfControlFlow if',
+ 'handleLiteralBool true',
+ 'handleParenthesizedCondition (',
+ 'handleNoTypeArguments [',
+ 'handleLiteralInt 2',
+ 'handleLiteralList 1, [, null, ]',
+ 'handleSpreadExpression ...?',
+ 'handleElseControlFlow else',
+ 'beginConstLiteral {',
+ 'handleNoTypeArguments {',
+ 'handleLiteralInt 5',
+ 'handleLiteralSet 1, {, const, }',
+ 'endConstLiteral ',
+ 'handleSpreadExpression ...',
+ 'endIfElseControlFlow }',
+ ],
+ );
+ }
+
test_intLiteral() {
parseEntry('before 1', [
'handleLiteralInt 1',
@@ -302,6 +340,16 @@
}
@override
+ void endIfElseControlFlow(Token token) {
+ calls.add('endIfElseControlFlow $token');
+ }
+
+ @override
+ void handleElseControlFlow(Token elseToken) {
+ calls.add('handleElseControlFlow $elseToken');
+ }
+
+ @override
void handleIdentifier(Token token, IdentifierContext context) {
calls.add('handleIdentifier $token $context');
}
@@ -336,6 +384,12 @@
}
@override
+ void handleLiteralSet(
+ int count, Token beginToken, Token constKeyword, Token token) {
+ calls.add('handleLiteralSet $count, $beginToken, $constKeyword, $token');
+ }
+
+ @override
void handleNoArguments(Token token) {
calls.add('handleNoArguments $token');
}