Version 2.11.0-275.0.dev
Merge commit 'd38b366eb669c2776a95efb449844e2c8da6c71c' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_if_null.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_if_null.dart
index bf576ec..17e9a2d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_if_null.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_if_null.dart
@@ -6,6 +6,8 @@
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/source/source_range.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
@@ -16,41 +18,44 @@
@override
Future<void> compute(ChangeBuilder builder) async {
- //
- // Find the dead if-null expression.
- //
- BinaryExpression findIfNull() {
- var child = node;
- var parent = node.parent;
- while (parent != null) {
- if (parent is BinaryExpression &&
- parent.operator.type == TokenType.QUESTION_QUESTION &&
- parent.rightOperand == child) {
- return parent;
- }
- child = parent;
- parent = parent.parent;
- }
- return null;
- }
-
- var expression = findIfNull();
- if (expression == null) {
+ var sourceRange = findIfNull();
+ if (sourceRange == null) {
return;
}
- //
- // Extract the information needed to build the edit.
- //
- var sourceRange =
- range.endEnd(expression.leftOperand, expression.rightOperand);
- //
- // Build the edit.
- //
+
await builder.addDartFileEdit(file, (builder) {
builder.addDeletion(sourceRange);
});
}
- /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ /// Finds the dead if-null expression above [node].
+ SourceRange findIfNull() {
+ var child = node;
+ var parent = node.parent;
+ while (parent != null) {
+ if (parent is BinaryExpression &&
+ parent.operator.type == TokenType.QUESTION_QUESTION &&
+ parent.rightOperand == child) {
+ return range.endEnd(parent.leftOperand, parent.rightOperand);
+ }
+ if (parent is AssignmentExpression &&
+ parent.operator.type == TokenType.QUESTION_QUESTION_EQ &&
+ parent.rightHandSide == child) {
+ var assignee = parent.leftHandSide;
+ if (parent.parent is ExpressionStatement &&
+ assignee is SimpleIdentifier &&
+ assignee.staticElement is PromotableElement) {
+ return utils.getLinesRange(range.node(parent.parent));
+ } else {
+ return range.endEnd(parent.leftHandSide, parent.rightHandSide);
+ }
+ }
+ child = parent;
+ parent = parent.parent;
+ }
+ return null;
+ }
+
+ /// Returns an instance of this class. Used as a tear-off in `FixProcessor`.
static RemoveDeadIfNull newInstance() => RemoveDeadIfNull();
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart
index 3797ce9..3f86e17 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart
@@ -12,12 +12,78 @@
void main() {
defineReflectiveSuite(() {
+ defineReflectiveTests(DeadNullAwareAssignmentExpressionTest);
defineReflectiveTests(DeadNullAwareExpressionTest);
defineReflectiveTests(UnnecessaryNullInIfNullOperatorsTest);
});
}
@reflectiveTest
+class DeadNullAwareAssignmentExpressionTest extends FixProcessorTest
+ with WithNullSafetyMixin {
+ @override
+ FixKind get kind => DartFixKind.REMOVE_IF_NULL_OPERATOR;
+
+ Future<void> test_assignmentExpression_nonPromotable() async {
+ await resolveTestCode('''
+class C {
+ int a = 1;
+ void f(int b) {
+ a ??= b;
+ }
+}
+''');
+ await assertHasFix('''
+class C {
+ int a = 1;
+ void f(int b) {
+ a;
+ }
+}
+''');
+ }
+
+ Future<void> test_assignmentExpression_promotable() async {
+ await resolveTestCode('''
+void f(int a, int b) {
+ a ??= b;
+}
+''');
+ await assertHasFix('''
+void f(int a, int b) {
+}
+''');
+ }
+
+ Future<void> test_immediateChild() async {
+ await resolveTestCode('''
+void f(int a, int b) => a ??= b;
+''');
+ await assertHasFix('''
+void f(int a, int b) => a;
+''');
+ }
+
+ Future<void> test_nestedChild() async {
+ await resolveTestCode('''
+void f(int a, int b) => a ??= b * 2 + 1;
+''');
+ await assertHasFix('''
+void f(int a, int b) => a;
+''');
+ }
+
+ Future<void> test_nestedChild_onRight() async {
+ await resolveTestCode('''
+void f(int a, int b, int c) => a = b ??= c;
+''');
+ await assertHasFix('''
+void f(int a, int b, int c) => a = b;
+''');
+ }
+}
+
+@reflectiveTest
class DeadNullAwareExpressionTest extends FixProcessorTest
with WithNullSafetyMixin {
@override
diff --git a/tools/VERSION b/tools/VERSION
index ce12cbe..d9154c3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 274
+PRERELEASE 275
PRERELEASE_PATCH 0
\ No newline at end of file