Skip to content

Commit

Permalink
add quick fix for cast_nullable_to_non_nullable
Browse files Browse the repository at this point in the history
See: dart-lang/lints#28

Change-Id: Ic0dac81467a3a3fbe7f7bf805ee59e3844edb6a1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/303681
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
  • Loading branch information
pq authored and Commit Queue committed May 17, 2023
1 parent 1b9198c commit 1178e96
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,25 @@ import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

class AddNullCheck extends CorrectionProducer {
final bool skipAssignabilityCheck;

@override
final bool canBeAppliedInBulk;

@override
FixKind fixKind = DartFixKind.ADD_NULL_CHECK;

@override
List<Object>? fixArguments;

AddNullCheck()
: skipAssignabilityCheck = false,
canBeAppliedInBulk = false;

AddNullCheck.withoutAssignabilityCheck()
: skipAssignabilityCheck = true,
canBeAppliedInBulk = true;

@override
Future<void> compute(ChangeBuilder builder) async {
if (!unit.featureSet.isEnabled(Feature.non_nullable)) {
Expand Down Expand Up @@ -80,6 +93,8 @@ class AddNullCheck extends CorrectionProducer {
target = coveredNode.rightOperand;
}
}
} else if (coveredNode is AsExpression) {
target = coveredNode.expression;
}

if (target == null) {
Expand All @@ -103,6 +118,8 @@ class AddNullCheck extends CorrectionProducer {
var parent = target.parent;
if (parent is AssignmentExpression && target == parent.rightHandSide) {
toType = parent.writeType;
} else if (parent is AsExpression) {
toType = parent.staticType;
} else if (parent is VariableDeclaration && target == parent.initializer) {
toType = parent.declaredElement?.type;
} else if (parent is ArgumentList) {
Expand Down Expand Up @@ -156,6 +173,7 @@ class AddNullCheck extends CorrectionProducer {
return;
}
if (toType != null &&
!skipAssignabilityCheck &&
!typeSystem.isAssignableTo(
typeSystem.promoteToNonNull(fromType), toType)) {
// The reason that `fromType` can't be assigned to `toType` is more than
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1989,9 +1989,7 @@ LintCode.cancel_subscriptions:
LintCode.cascade_invocations:
status: hasFix
LintCode.cast_nullable_to_non_nullable:
status: needsFix
notes: |-
The fix is to add an explicit null check (`!`).
status: hasFix
LintCode.close_sinks:
status: noFix
LintCode.collection_methods_unrelated_type:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,9 @@ class FixProcessor extends BaseProcessor {
LintNames.cascade_invocations: [
ConvertToCascade.new,
],
LintNames.cast_nullable_to_non_nullable: [
AddNullCheck.withoutAssignabilityCheck,
],
LintNames.combinators_ordering: [
SortCombinators.new,
],
Expand Down
2 changes: 2 additions & 0 deletions pkg/analysis_server/lib/src/services/linter/lint_names.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class LintNames {
static const String avoid_void_async = 'avoid_void_async';
static const String await_only_futures = 'await_only_futures';
static const String cascade_invocations = 'cascade_invocations';
static const String cast_nullable_to_non_nullable =
'cast_nullable_to_non_nullable';
static const String combinators_ordering = 'combinators_ordering';
static const String curly_braces_in_flow_control_structures =
'curly_braces_in_flow_control_structures';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
Expand All @@ -14,6 +15,7 @@ void main() {
defineReflectiveSuite(() {
defineReflectiveTests(AddNullCheckTest);
defineReflectiveTests(AddNullCheckReplaceWithNullAwareTest);
defineReflectiveTests(CastNullableToNonNullableTest);
});
}

Expand Down Expand Up @@ -646,3 +648,35 @@ Iterable<String> f(List<String>? args) sync* {
error.errorCode != CompileTimeErrorCode.YIELD_EACH_OF_INVALID_TYPE);
}
}

@reflectiveTest
class CastNullableToNonNullableTest extends FixProcessorLintTest {
@override
FixKind get kind => DartFixKind.ADD_NULL_CHECK;

@override
String get lintCode => LintNames.cast_nullable_to_non_nullable;

Future<void> test_castNullable() async {
await resolveTestCode(r'''
num? n;
var i = n as int;
''');
await assertHasFix(r'''
num? n;
var i = n! as int;
''');
}

Future<void> test_castNullable_unnecessaryCast() async {
// todo(pq): consider removing unnecessary 'as String' cast
await resolveTestCode(r'''
String? s;
var a = s as String;
''');
await assertHasFix(r'''
String? s;
var a = s! as String;
''');
}
}

0 comments on commit 1178e96

Please sign in to comment.