Update to use the new null-aware subscript syntax.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5983369..feb8afe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@
* Always place a blank line after script tags (#782).
* Don't add unneeded splits on if elements near comments (#888).
* Indent blocks in initializers of multiple-variable declarations.
+* Update the null-aware subscript syntax from `?.[]` to `?[]`.
# 1.3.3
diff --git a/lib/src/source_visitor.dart b/lib/src/source_visitor.dart
index 6ffa262..46c0bf7 100644
--- a/lib/src/source_visitor.dart
+++ b/lib/src/source_visitor.dart
@@ -1180,11 +1180,11 @@
token(node.semicolon);
}
- /// A period (`.`) token constructed to replace the given [operator].
+ /// Synthesize a token with [type] to replace the given [operator].
///
/// Offset, comments, and previous/next links are all preserved.
- static Token _period(Token operator) =>
- Token(TokenType.PERIOD, operator.offset, operator.precedingComments)
+ static Token _synthesizeToken(TokenType type, Token operator) =>
+ Token(type, operator.offset, operator.precedingComments)
..previous = operator.previous
..next = operator.next;
@@ -1214,7 +1214,7 @@
_insertCascadeTargetIntoExpression(expressionTarget, cascadeTarget),
// If we've reached the end, replace the `..` operator with `.`
expressionTarget == cascadeTarget
- ? _period(expression.operator)
+ ? _synthesizeToken(TokenType.PERIOD, expression.operator)
: expression.operator,
expression.propertyName);
} else if (expression is MethodInvocation) {
@@ -1222,17 +1222,28 @@
_insertCascadeTargetIntoExpression(expressionTarget, cascadeTarget),
// If we've reached the end, replace the `..` operator with `.`
expressionTarget == cascadeTarget
- ? _period(expression.operator)
+ ? _synthesizeToken(TokenType.PERIOD, expression.operator)
: expression.operator,
expression.methodName,
expression.typeArguments,
expression.argumentList);
} else if (expression is IndexExpression) {
- return astFactory.indexExpressionForTarget(
- _insertCascadeTargetIntoExpression(expressionTarget, cascadeTarget),
- expression.leftBracket,
- expression.index,
- expression.rightBracket);
+ var question = expression.question;
+
+ // A null-aware cascade treats the `?` in `?..` as part of the token, but
+ // for a non-cascade index, it is a separate `?` token.
+ if (expression.period != null &&
+ expression.period.type == TokenType.QUESTION_PERIOD_PERIOD) {
+ question = _synthesizeToken(TokenType.QUESTION, expression.period);
+ }
+
+ return astFactory.indexExpressionForTarget2(
+ target: _insertCascadeTargetIntoExpression(
+ expressionTarget, cascadeTarget),
+ question: question,
+ leftBracket: expression.leftBracket,
+ index: expression.index,
+ rightBracket: expression.rightBracket);
}
throw UnimplementedError('Unhandled ${expression.runtimeType}'
'($expression)');
@@ -2061,6 +2072,7 @@
}
builder.startSpan(Cost.index);
+ token(node.question);
token(node.leftBracket);
soloZeroSplit();
visit(node.index);
diff --git a/pubspec.lock b/pubspec.lock
index cd23c27..eea1964 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -7,14 +7,14 @@
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.3"
+ version: "2.0.0"
analyzer:
dependency: "direct main"
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
- version: "0.39.4"
+ version: "0.39.5"
archive:
dependency: transitive
description:
@@ -28,14 +28,14 @@
name: args
url: "https://pub.dartlang.org"
source: hosted
- version: "1.5.3"
+ version: "1.6.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.4.0"
+ version: "2.4.1"
boolean_selector:
dependency: transitive
description:
@@ -77,7 +77,7 @@
name: coverage
url: "https://pub.dartlang.org"
source: hosted
- version: "0.13.8"
+ version: "0.13.9"
crypto:
dependency: transitive
description:
@@ -105,7 +105,7 @@
name: grinder
url: "https://pub.dartlang.org"
source: hosted
- version: "0.8.3+1"
+ version: "0.8.4"
html:
dependency: transitive
description:
@@ -133,14 +133,14 @@
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
- version: "3.1.3"
+ version: "3.1.4"
io:
dependency: transitive
description:
name: io
url: "https://pub.dartlang.org"
source: hosted
- version: "0.3.3"
+ version: "0.3.4"
js:
dependency: "direct dev"
description:
@@ -210,7 +210,7 @@
name: package_config
url: "https://pub.dartlang.org"
source: hosted
- version: "1.9.1"
+ version: "1.9.3"
path:
dependency: "direct main"
description:
@@ -238,7 +238,7 @@
name: pub_semver
url: "https://pub.dartlang.org"
source: hosted
- version: "1.4.3"
+ version: "1.4.4"
shelf:
dependency: transitive
description:
@@ -287,7 +287,7 @@
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.6.0"
+ version: "1.7.0"
stack_trace:
dependency: transitive
description:
@@ -322,7 +322,7 @@
name: test
url: "https://pub.dartlang.org"
source: hosted
- version: "1.14.1"
+ version: "1.14.2"
test_api:
dependency: transitive
description:
@@ -336,7 +336,7 @@
name: test_core
url: "https://pub.dartlang.org"
source: hosted
- version: "0.3.2"
+ version: "0.3.3"
test_descriptor:
dependency: "direct dev"
description:
@@ -364,14 +364,14 @@
name: vm_service
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.0+1"
+ version: "4.0.0"
watcher:
dependency: transitive
description:
name: watcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.9.7+13"
+ version: "0.9.7+14"
web_socket_channel:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index bcb2d5c..c89986c 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -10,7 +10,7 @@
sdk: '>=2.3.0 <3.0.0'
dependencies:
- analyzer: ">=0.38.3 <0.40.0"
+ analyzer: ">=0.39.5 <0.40.0"
args: ^1.0.0
path: ^1.0.0
source_span: ^1.4.0
diff --git a/test/fixes/single_cascade_statements.stmt b/test/fixes/single_cascade_statements.stmt
index 3ffe5a0..2c769c8 100644
--- a/test/fixes/single_cascade_statements.stmt
+++ b/test/fixes/single_cascade_statements.stmt
@@ -15,6 +15,18 @@
obj..[subscript] = 3;
<<<
obj[subscript] = 3;
+>>>
+obj?..[subscript] = 3;
+<<<
+obj?[subscript] = 3;
+>>>
+obj..index[subscript] = 3;
+<<<
+obj.index[subscript] = 3;
+>>>
+obj..index?[subscript] = 3;
+<<<
+obj.index?[subscript] = 3;
>>> targets that don't need parentheses
{
null..method();
diff --git a/test/splitting/expressions.stmt b/test/splitting/expressions.stmt
index 01fd186..3911eb1 100644
--- a/test/splitting/expressions.stmt
+++ b/test/splitting/expressions.stmt
@@ -132,11 +132,11 @@
[longArgument][longArgument]
[longArgument];
>>> null-aware indexes
-identifier?.[longArgument][longArgument]?.[longArgument][longArgument]?.[longArgument];
+identifier?[longArgument][longArgument]?[longArgument][longArgument]?[longArgument];
<<<
-identifier?.[longArgument][longArgument]
- ?.[longArgument][longArgument]
- ?.[longArgument];
+identifier?[longArgument][longArgument]
+ ?[longArgument][longArgument]
+ ?[longArgument];
>>> is
verylongIdentifier.property is LongTypeName;
<<<
diff --git a/test/splitting/invocations.stmt b/test/splitting/invocations.stmt
index 702726e..17948be 100644
--- a/test/splitting/invocations.stmt
+++ b/test/splitting/invocations.stmt
@@ -434,11 +434,11 @@
})!;
>>> null-aware index
receiver.property1.property2
- .property3?.[0][1]?.[2]
- .method1()?.[0][1]?.[2]
+ .property3?[0][1]?[2]
+ .method1()?[0][1]?[2]
.method2();
<<<
receiver.property1.property2
- .property3?.[0][1]?.[2]
- .method1()?.[0][1]?.[2]
+ .property3?[0][1]?[2]
+ .method1()?[0][1]?[2]
.method2();
\ No newline at end of file
diff --git a/test/whitespace/expressions.stmt b/test/whitespace/expressions.stmt
index 2514101..daff76b 100644
--- a/test/whitespace/expressions.stmt
+++ b/test/whitespace/expressions.stmt
@@ -160,6 +160,6 @@
<<<
obj![index]!(call)! + 3;
>>> null-aware index expressions
-obj ?.[ foo];
+obj ?[ foo];
<<<
-obj?.[foo];
\ No newline at end of file
+obj?[foo];
\ No newline at end of file