Skip to content

Commit 56b6844

Browse files
lrhnCommit Queue
authored andcommitted
Parse ?. as ?+. in element.
Bug: https://dartbug.com//language/4477 Change-Id: If68b21a2b22ed65dde09c03dab8a3f4721a2fa34 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/442480 Commit-Queue: Lasse Nielsen <[email protected]> Reviewed-by: Jens Johansen <[email protected]>
1 parent e96b02a commit 56b6844

15 files changed

+1854
-61
lines changed

pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart

Lines changed: 78 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7867,7 +7867,7 @@ class Parser {
78677867
///
78687868
/// ```
78697869
/// listLiteral:
7870-
/// 'const'? typeArguments? '[' (expressionList ','?)? ']'
7870+
/// 'const'? typeArguments? '[' (elementList ','?)? ']'
78717871
/// ;
78727872
/// ```
78737873
///
@@ -7900,12 +7900,13 @@ class Parser {
79007900
break;
79017901
}
79027902
int ifCount = 0;
7903-
LiteralEntryInfo? info = computeLiteralEntry(token);
7903+
LiteralEntryInfo? info = _computeLiteralEntry(token);
79047904
while (info != null) {
7905+
next = token.next!;
79057906
if (info.hasEntry) {
7906-
if (token.next!.isA(TokenType.QUESTION)) {
7907-
Token nullAwareToken = token.next!;
7908-
token = token.next!;
7907+
if (next.isA(TokenType.QUESTION)) {
7908+
Token nullAwareToken = next;
7909+
token = next;
79097910
token = parseExpression(token);
79107911
listener.handleNullAwareElement(nullAwareToken);
79117912
} else {
@@ -7915,7 +7916,7 @@ class Parser {
79157916
token = info.parse(token, this);
79167917
}
79177918
ifCount += info.ifConditionDelta;
7918-
info = info.computeNext(token);
7919+
info = _nextLiteralEntry(info, token);
79197920
}
79207921
next = token.next!;
79217922
++count;
@@ -7983,7 +7984,7 @@ class Parser {
79837984

79847985
while (true) {
79857986
int ifCount = 0;
7986-
LiteralEntryInfo? info = computeLiteralEntry(token);
7987+
LiteralEntryInfo? info = _computeLiteralEntry(token);
79877988
if (info == simpleEntry) {
79887989
// TODO(danrubel): Remove this section and use the while loop below
79897990
// once hasSetEntry is no longer needed.
@@ -7992,77 +7993,66 @@ class Parser {
79927993
hasSetEntry ??= !isMapEntry;
79937994
if (isMapEntry) {
79947995
Token colon = token.next!;
7995-
Token next = colon.next!;
7996-
if (next.isA(TokenType.QUESTION)) {
7997-
// Null-aware value. For example:
7998-
// <int, String>{ x: ?y }
7999-
token = parseExpression(next);
8000-
listener.handleLiteralMapEntry(
8001-
colon,
8002-
token,
8003-
nullAwareKeyToken: null,
8004-
nullAwareValueToken: next,
8005-
);
8006-
} else {
8007-
// Non null-aware entry. For example:
8008-
// <bool, num>{ x: y }
8009-
token = parseExpression(colon);
8010-
listener.handleLiteralMapEntry(colon, token.next!);
7996+
token = colon;
7997+
Token next = token.next!;
7998+
Token? nullAwareValueToken;
7999+
if (next.isA(TokenType.QUESTION_PERIOD)) {
8000+
token = nullAwareValueToken = _splitFollowingQuestionPeriod(token);
8001+
} else if (next.isA(TokenType.QUESTION)) {
8002+
token = nullAwareValueToken = next;
80118003
}
8004+
8005+
token = parseExpression(token);
8006+
listener.handleLiteralMapEntry(
8007+
colon,
8008+
token.next!,
8009+
nullAwareValueToken: nullAwareValueToken,
8010+
);
80128011
}
80138012
} else {
80148013
while (info != null) {
80158014
if (info.hasEntry) {
80168015
Token? nullAwareKeyToken;
8017-
if (token.next!.isA(TokenType.QUESTION)) {
8016+
Token next = token.next!;
8017+
if (next.isA(TokenType.QUESTION)) {
80188018
// Null-aware key, for example:
80198019
// <double, Symbol>{ if (b) ?x: y }
80208020
// <double, Symbol>{ if (b) ?x: ?y }
8021-
nullAwareKeyToken = token.next!;
8022-
8023-
// Parse the expression after '?'.
8021+
nullAwareKeyToken = next;
80248022
token = nullAwareKeyToken;
8025-
token = parseExpression(token);
8026-
} else {
8027-
token = parseExpression(token);
80288023
}
8024+
token = parseExpression(token);
8025+
80298026
if (token.next!.isA(TokenType.COLON)) {
80308027
Token colon = token.next!;
8031-
Token next = colon.next!;
8032-
if (next.isA(TokenType.QUESTION)) {
8033-
token = parseExpression(next);
8034-
// Null-aware value. For example:
8035-
// <double, Symbol>{ if (b) x: ?y }
8036-
// <double, Symbol>{ if (b) ?x: ?y }
8037-
listener.handleLiteralMapEntry(
8038-
colon,
8039-
token.next!,
8040-
nullAwareKeyToken: nullAwareKeyToken,
8041-
nullAwareValueToken: next,
8042-
);
8043-
} else {
8044-
// Non null-aware value. For example:
8045-
// <String, int>{ if (b) x : y }
8046-
// <String, int>{ if (b) ?x : y }
8047-
token = parseExpression(colon);
8048-
listener.handleLiteralMapEntry(
8049-
colon,
8050-
token.next!,
8051-
nullAwareKeyToken: nullAwareKeyToken,
8052-
);
8053-
}
8054-
} else {
8055-
if (nullAwareKeyToken != null) {
8056-
// Null-aware element. For example:
8057-
// <String>{ if (b) ?x }
8058-
listener.handleNullAwareElement(nullAwareKeyToken);
8028+
token = colon;
8029+
8030+
Token? nullAwareValueToken;
8031+
Token next = token.next!;
8032+
if (next.isA(TokenType.QUESTION_PERIOD)) {
8033+
token = nullAwareValueToken =
8034+
_splitFollowingQuestionPeriod(token);
8035+
} else if (next.isA(TokenType.QUESTION)) {
8036+
token = nullAwareValueToken = next;
80598037
}
8038+
8039+
token = parseExpression(token);
8040+
listener.handleLiteralMapEntry(
8041+
colon,
8042+
token.next!,
8043+
nullAwareKeyToken: nullAwareKeyToken,
8044+
nullAwareValueToken: nullAwareValueToken,
8045+
);
8046+
} else if (nullAwareKeyToken != null) {
8047+
// Null-aware element. For example:
8048+
// <String>{ if (b) ?x }
8049+
listener.handleNullAwareElement(nullAwareKeyToken);
80608050
}
80618051
} else {
80628052
token = info.parse(token, this);
80638053
}
80648054
ifCount += info.ifConditionDelta;
8065-
info = info.computeNext(token);
8055+
info = _nextLiteralEntry(info, token);
80668056
}
80678057
}
80688058
++count;
@@ -8121,6 +8111,35 @@ class Parser {
81218111
}
81228112
}
81238113

8114+
LiteralEntryInfo? _computeLiteralEntry(Token token) {
8115+
if (token.next!.isA(TokenType.QUESTION_PERIOD)) {
8116+
_splitFollowingQuestionPeriod(token);
8117+
}
8118+
return computeLiteralEntry(token);
8119+
}
8120+
8121+
LiteralEntryInfo? _nextLiteralEntry(LiteralEntryInfo info, Token token) {
8122+
if (token.next!.isA(TokenType.QUESTION_PERIOD)) {
8123+
_splitFollowingQuestionPeriod(token);
8124+
}
8125+
return info.computeNext(token);
8126+
}
8127+
8128+
Token _splitFollowingQuestionPeriod(Token token) {
8129+
Token next = token.next!;
8130+
assert(next.isA(TokenType.QUESTION_PERIOD));
8131+
int offset = next.charOffset;
8132+
Token newNext = rewriter.replaceTokenFollowing(
8133+
token,
8134+
new Token(TokenType.QUESTION, offset),
8135+
);
8136+
rewriter.insertToken(
8137+
newNext,
8138+
new Token(TokenType.PERIOD, offset + 1),
8139+
);
8140+
return newNext;
8141+
}
8142+
81248143
/// formalParameterList functionBody.
81258144
///
81268145
/// This is a suffix parser because it is assumed that type arguments have
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
files:
2+
- split_question_period.dart
3+
- unsplit_question_period.dart

pkg/front_end/parser_testcases/null_aware_elements/simple_positive.dart.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ beginCompilationUnit(foo1)
291291
handleNoTypeArguments(})
292292
handleNoArguments(})
293293
handleSend(y, y)
294-
handleLiteralMapEntry(:, y, null, ?)
294+
handleLiteralMapEntry(:, }, null, ?)
295295
handleLiteralSetOrMap(1, {, null, }, false)
296296
handleExpressionFunctionBody(=>, ;)
297297
endTopLevelMethod(bar4, null, ;)

pkg/front_end/parser_testcases/null_aware_elements/simple_positive.dart.intertwined.expect

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ parseUnit(foo1)
577577
parseArgumentsOpt(y)
578578
listener: handleNoArguments(})
579579
listener: handleSend(y, y)
580-
listener: handleLiteralMapEntry(:, y, null, ?)
580+
listener: handleLiteralMapEntry(:, }, null, ?)
581581
listener: handleLiteralSetOrMap(1, {, null, }, false)
582582
ensureSemicolon(})
583583
listener: handleExpressionFunctionBody(=>, ;)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// dart format off
2+
test1() {
3+
return <int>[
4+
? .tryParse("a"),
5+
? .tryParse("1"),
6+
];
7+
}
8+
9+
test2() {
10+
return <int>{
11+
? .tryParse("a"),
12+
? .tryParse("1"),
13+
};
14+
}
15+
16+
test3() {
17+
return <int, int>{
18+
? .tryParse("a"): 0,
19+
0: ? .tryParse("a"),
20+
? .tryParse("0"): ? .tryParse("a"),
21+
? .tryParse("a"): ? .tryParse("0"),
22+
? .tryParse("1"): ? .tryParse("1"),
23+
};
24+
}

0 commit comments

Comments
 (0)