Fix analyzer/FE integration of some obscure invalid assignment cases.
This CL fixes handling of the following erroneous assignments:
- Assignment to postfix increment (e.g. "x++ = y;")
- Assignment to prefix increment (e.g. "++x = y;")
- Prefix increment of postfix increment (e.g. "++x++;")
Change-Id: I651c7cbcc4b3d43f7008f9d583e2057db9bc6e6e
Reviewed-on: https://dart-review.googlesource.com/71260
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index d872324..454fd79 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -956,6 +956,38 @@
assertElement(zRef, findElement.parameter('z'));
}
+ test_assign_to_postfix_increment() async {
+ addTestFile('''
+void f(num x, int y) {
+ x++ = y;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x++');
+ assertType(xRef, 'num');
+ assertElement(xRef, findElement.parameter('x'));
+ var yRef = findNode.simple('y;');
+ assertType(yRef, 'int');
+ assertElement(yRef, findElement.parameter('y'));
+ }
+
+ test_assign_to_prefix_increment() async {
+ addTestFile('''
+void f(num x, int y) {
+ ++x = y;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x =');
+ assertType(xRef, 'num');
+ assertElement(xRef, findElement.parameter('x'));
+ var yRef = findNode.simple('y;');
+ assertType(yRef, 'int');
+ assertElement(yRef, findElement.parameter('y'));
+ }
+
test_assign_with_synthetic_lhs() async {
addTestFile('''
void f(int x) {
@@ -7277,6 +7309,19 @@
assertElement(xRef, findElement.parameter('x'));
}
+ test_prefix_increment_of_postfix_increment() async {
+ addTestFile('''
+void f(int x) {
+ ++x++;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x++');
+ assertType(xRef, 'int');
+ assertElement(xRef, findElement.parameter('x'));
+ }
+
test_prefix_increment_of_prefix_increment() async {
addTestFile('''
void f(int x) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 0dfb764..477d2eb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -120,7 +120,8 @@
///
/// The returned expression evaluates to the assigned value, unless
/// [voidContext] is true, in which case it may evaluate to anything.
- Expression buildAssignment(Expression value, {bool voidContext});
+ Expression buildAssignment(Expression value,
+ {bool voidContext, int offset: -1});
/// Returns a [Expression] representing a null-aware assignment (`??=`) with
/// the generator on the LHS and [value] on the RHS.
@@ -780,7 +781,8 @@
}
@override
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return new SyntheticExpressionJudgment(buildError(
forest.arguments(<Expression>[value], token, token),
isSetter: true));
@@ -938,8 +940,18 @@
}
@override
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
- return makeInvalidWrite(value);
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
+ var lhs = buildSimpleRead();
+ // The lhs expression needs to have a parent so that type inference can be
+ // applied to it, but it doesn't matter what the parent is because the
+ // lhs expression won't appear in the tree. So just give it a quick and
+ // dirty parent.
+ new VariableDeclaration.forValue(lhs);
+
+ return new IllegalAssignmentJudgment(value,
+ assignmentOffset: offset, desugared: makeInvalidWrite(value))
+ ..write = lhs;
}
@override
@@ -962,7 +974,18 @@
@override
Expression buildPrefixIncrement(Name binaryOperator,
{int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
- return makeInvalidWrite(null);
+ var innerExpression = buildSimpleRead();
+ // The inner expression needs to have a parent so that type inference can be
+ // applied to it, but it doesn't matter what the parent is because the
+ // inner expression won't appear in the tree. So just give it a quick and
+ // dirty parent.
+ new VariableDeclaration.forValue(innerExpression);
+
+ return new IllegalAssignmentJudgment(
+ forest.literalInt(1, null, isSynthetic: true),
+ assignmentOffset: offset,
+ desugared: makeInvalidWrite(null))
+ ..write = innerExpression;
}
@override
@@ -1038,7 +1061,8 @@
Expression makeAssignmentExpression(bool voidContext) {
if (identical("=", assignmentOperator)) {
- return generator.buildAssignment(value, voidContext: voidContext);
+ return generator.buildAssignment(value,
+ voidContext: voidContext, offset: token.offset);
} else if (identical("+=", assignmentOperator)) {
return generator.buildCompoundAssignment(plusName, value,
offset: offsetForToken(token), voidContext: voidContext);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
index fe7cb08..9927ce07 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
@@ -142,7 +142,8 @@
}
@override
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
var complexAssignment = startComplexAssignment(value);
return _finish(_makeSimpleWrite(value, voidContext, complexAssignment),
complexAssignment);
@@ -1531,7 +1532,8 @@
: super(helper, token);
@override
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return _buildUnresolvedVariableAssignment(false, value);
}
@@ -1596,7 +1598,8 @@
super(helper, token);
@override
- Expression buildAssignment(Expression value, {bool voidContext}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext, int offset: -1}) {
return new PropertySet(receiver, name, value)
..fileOffset = offsetForToken(token);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
index cbff91f..c9cfbf9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
@@ -135,7 +135,8 @@
}
}
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return buildAssignmentError();
}
@@ -260,7 +261,8 @@
return unsupported("buildSimpleRead", offsetForToken(token), uri);
}
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return unsupported("buildAssignment", offsetForToken(token), uri);
}
@@ -331,7 +333,8 @@
return unsupported("buildSimpleRead", offsetForToken(token), uri);
}
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return unsupported("buildAssignment", offsetForToken(token), uri);
}