[analysis_server] associate `UNNECESSARY_TYPE_CHECK_*` with `RemoveComparison`
Fixes #47793
Fixes #51013
Change-Id: I50c080d51284cf669918d41c2aa7310b2c4a90f4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279351
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
index a373a1b..6cfd5af 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
@@ -16,39 +16,47 @@
class RemoveComparison extends CorrectionProducer {
@override
+ final FixKind fixKind;
+
+ @override
+ final FixKind multiFixKind;
+
+ /// Initialize a newly created instance with [DartFixKind.REMOVE_COMPARISON].
+ RemoveComparison()
+ : fixKind = DartFixKind.REMOVE_COMPARISON,
+ multiFixKind = DartFixKind.REMOVE_COMPARISON_MULTI;
+
+ /// Initialize a newly created instance with [DartFixKind.REMOVE_TYPE_CHECK].
+ RemoveComparison.typeCheck()
+ : fixKind = DartFixKind.REMOVE_TYPE_CHECK,
+ multiFixKind = DartFixKind.REMOVE_TYPE_CHECK_MULTI;
+
+ @override
bool get canBeAppliedInBulk => true;
@override
bool get canBeAppliedToFile => true;
- @override
- FixKind get fixKind => DartFixKind.REMOVE_COMPARISON;
-
- @override
- FixKind get multiFixKind => DartFixKind.REMOVE_COMPARISON_MULTI;
-
- /// Return `true` if the null comparison will always return `false`.
+ /// Return `true` if the condition will always return `false`.
bool get _conditionIsFalse {
var errorCode = (diagnostic as AnalysisError).errorCode;
return errorCode == HintCode.UNNECESSARY_NAN_COMPARISON_FALSE ||
- errorCode == HintCode.UNNECESSARY_NULL_COMPARISON_FALSE;
+ errorCode == HintCode.UNNECESSARY_NULL_COMPARISON_FALSE ||
+ errorCode == HintCode.UNNECESSARY_TYPE_CHECK_FALSE;
}
- /// Return `true` if the null comparison will always return `true`.
+ /// Return `true` if the condition will always return `true`.
bool get _conditionIsTrue {
var errorCode = (diagnostic as AnalysisError).errorCode;
return errorCode == HintCode.UNNECESSARY_NAN_COMPARISON_TRUE ||
errorCode == HintCode.UNNECESSARY_NULL_COMPARISON_TRUE ||
+ errorCode == HintCode.UNNECESSARY_TYPE_CHECK_TRUE ||
errorCode.name == LintNames.avoid_null_checks_in_equality_operators;
}
@override
Future<void> compute(ChangeBuilder builder) async {
- var binaryExpression = node;
- if (binaryExpression is! BinaryExpression) {
- return;
- }
- var parent = binaryExpression.parent;
+ var parent = node.parent;
if (parent is AssertInitializer && _conditionIsTrue) {
var constructor = parent.parent as ConstructorDeclaration;
var list = constructor.initializers;
@@ -66,12 +74,10 @@
builder.addDeletion(utils.getLinesRange(range.node(parent)));
});
} else if (parent is BinaryExpression) {
- if (parent.operator.type == TokenType.AMPERSAND_AMPERSAND &&
- _conditionIsTrue) {
- await _removeOperatorAndOperand(builder, parent, binaryExpression);
- } else if (parent.operator.type == TokenType.BAR_BAR &&
- _conditionIsFalse) {
- await _removeOperatorAndOperand(builder, parent, binaryExpression);
+ var type = parent.operator.type;
+ if ((type == TokenType.AMPERSAND_AMPERSAND && _conditionIsTrue) ||
+ (type == TokenType.BAR_BAR && _conditionIsFalse)) {
+ await _removeOperatorAndOperand(builder, parent);
}
} else if (parent is IfStatement) {
if (parent.elseStatement == null && _conditionIsTrue) {
@@ -109,8 +115,8 @@
/// Use the [builder] to add an edit to delete the operator and given
/// [operand] from the [binary] expression.
- Future<void> _removeOperatorAndOperand(ChangeBuilder builder,
- BinaryExpression binary, Expression operand) async {
+ Future<void> _removeOperatorAndOperand(
+ ChangeBuilder builder, BinaryExpression binary) async {
SourceRange operatorAndOperand;
if (binary.leftOperand == node) {
operatorAndOperand = range.startStart(node, binary.rightOperand);
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
index de8bf35..f8c211b 100644
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -1630,11 +1630,9 @@
HintCode.UNNECESSARY_QUESTION_MARK:
status: hasFix
HintCode.UNNECESSARY_TYPE_CHECK_FALSE:
- status: needsFix
- issue: https://github.com/dart-lang/sdk/issues/47793
+ status: hasFix
HintCode.UNNECESSARY_TYPE_CHECK_TRUE:
- status: needsFix
- issue: https://github.com/dart-lang/sdk/issues/47793
+ status: hasFix
HintCode.TEXT_DIRECTION_CODE_POINT_IN_COMMENT:
status: hasFix
HintCode.TEXT_DIRECTION_CODE_POINT_IN_LITERAL:
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 2a9faaf..2948fc1 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -1198,6 +1198,16 @@
49,
'Remove type arguments',
);
+ static const REMOVE_TYPE_CHECK = FixKind(
+ 'dart.fix.remove.typeCheck',
+ DartFixKindPriority.DEFAULT,
+ 'Remove type check',
+ );
+ static const REMOVE_TYPE_CHECK_MULTI = FixKind(
+ 'dart.fix.remove.comparison.multi',
+ DartFixKindPriority.IN_FILE,
+ 'Remove type check everywhere in file',
+ );
static const REMOVE_UNNECESSARY_CAST = FixKind(
'dart.fix.remove.unnecessaryCast',
DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 990b05b..43a2096 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1465,12 +1465,12 @@
HintCode.UNNECESSARY_QUESTION_MARK: [
RemoveQuestionMark.new,
],
-// HintCode.UNNECESSARY_TYPE_CHECK_FALSE: [
-// TODO(brianwilkerson) Add a fix to remove the type check.
-// ],
-// HintCode.UNNECESSARY_TYPE_CHECK_TRUE: [
-// TODO(brianwilkerson) Add a fix to remove the type check.
-// ],
+ HintCode.UNNECESSARY_TYPE_CHECK_FALSE: [
+ RemoveComparison.typeCheck,
+ ],
+ HintCode.UNNECESSARY_TYPE_CHECK_TRUE: [
+ RemoveComparison.typeCheck,
+ ],
HintCode.UNUSED_CATCH_CLAUSE: [
RemoveUnusedCatchClause.new,
],
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
index d284780..9982a59 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
@@ -4,7 +4,6 @@
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
-import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -13,6 +12,8 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(RemoveComparisonTest);
+ defineReflectiveTests(RemoveTypeCheckTest);
+ defineReflectiveTests(RemoveTypeCheckBulkTest);
defineReflectiveTests(RemoveNullCheckComparisonTest);
defineReflectiveTests(RemoveNullCheckComparisonBulkTest);
});
@@ -372,66 +373,74 @@
''');
await assertNoFix();
}
+}
- /// todo(pq): consider implementing
- @FailingTest(reason: 'Fix unimplemented')
- Future<void> test_ifNullStatement() async {
+@reflectiveTest
+class RemoveTypeCheckBulkTest extends BulkFixProcessorTest {
+ Future<void> test_singleFile() async {
await resolveTestCode('''
-class Person {
- final String name = '';
-
- @override
- operator ==(Object? other) {
- if (other is! Person) return false;
- final toCompare = other ?? Person();
- return toCompare.name == name;
+void f(int a, int b) {
+ if (a is! num || b == 0) {
+ print('');
}
}
-''');
-
- await assertHasFix('''
-class Person {
- final String name = '';
-
- @override
- operator ==(Object? other) {
- if (other is! Person) return false;
- final toCompare = other;
- return toCompare.name == name;
- }
-}
-''',
- errorFilter: (error) =>
- error.errorCode == StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION);
- }
-
- /// todo(pq): implement or remove the lint (see: https://github.com/dart-lang/linter/issues/2864)
- @FailingTest(reason: 'Fix unimplemented')
- Future<void> test_ifStatement() async {
- await resolveTestCode('''
-class Person {
- final String name = '';
-
- @override
- operator ==(Object? other) {
- if (other == null) return false;
- return other is Person &&
- name == other.name;
+void g(int a, int b) {
+ if (b == 0 && a is num) {
+ print('');
}
}
''');
await assertHasFix('''
-class Person {
- final String name = '';
-
- @override
- operator ==(Object? other) {
- return other is Person &&
- name == other.name;
+void f(int a, int b) {
+ if (b == 0) {
+ print('');
}
}
-''',
- errorFilter: (error) =>
- error.errorCode == HintCode.UNNECESSARY_NULL_COMPARISON_FALSE);
+void g(int a, int b) {
+ if (b == 0) {
+ print('');
+ }
+}
+''');
+ }
+}
+
+@reflectiveTest
+class RemoveTypeCheckTest extends FixProcessorTest {
+ @override
+ FixKind get kind => DartFixKind.REMOVE_TYPE_CHECK;
+
+ Future<void> test_unnecessaryTypeCheck_false() async {
+ await resolveTestCode('''
+void f(int a, int b) {
+ if (a is! num || b == 0) {
+ print('');
+ }
+}
+''');
+ await assertHasFix('''
+void f(int a, int b) {
+ if (b == 0) {
+ print('');
+ }
+}
+''');
+ }
+
+ Future<void> test_unnecessaryTypeCheck_true() async {
+ await resolveTestCode('''
+void f(int a, int b) {
+ if (b == 0 && a is num) {
+ print('');
+ }
+}
+''');
+ await assertHasFix('''
+void f(int a, int b) {
+ if (b == 0) {
+ print('');
+ }
+}
+''');
}
}