Skip to content

Commit b472d7a

Browse files
Unnecessary null aware spread hint
Change-Id: I33645c0bf948c5a3c3b06a5c81a7b77b82fe191c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105734 Commit-Queue: Mike Fairhurst <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent f939ad3 commit b472d7a

File tree

6 files changed

+80
-4
lines changed

6 files changed

+80
-4
lines changed

pkg/analyzer/lib/error/error.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,13 +687,14 @@ const List<ErrorCode> errorCodeValues = const [
687687
StaticWarningCode.TYPE_PARAMETER_REFERENCED_BY_STATIC,
688688
StaticWarningCode.TYPE_TEST_WITH_NON_TYPE,
689689
StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME,
690+
StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE,
690691
StaticWarningCode.UNDEFINED_CLASS,
691692
StaticWarningCode.UNDEFINED_CLASS_BOOLEAN,
692693
StaticWarningCode.UNDEFINED_IDENTIFIER,
693694
StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT,
694695
StaticWarningCode.UNDEFINED_NAMED_PARAMETER,
696+
StaticWarningCode.UNNECESSARY_NULL_AWARE_SPREAD,
695697
StaticWarningCode.USE_OF_VOID_RESULT,
696-
StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE,
697698
StrongModeCode.ASSIGNMENT_CAST,
698699
StrongModeCode.COULD_NOT_INFER,
699700
StrongModeCode.DOWN_CAST_COMPOSITE,

pkg/analyzer/lib/src/dart/error/hint_codes.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ class HintCode extends ErrorCode {
802802
static const HintCode UNNECESSARY_NO_SUCH_METHOD = const HintCode(
803803
'UNNECESSARY_NO_SUCH_METHOD', "Unnecessary 'noSuchMethod' declaration.",
804804
correction: "Try removing the declaration of 'noSuchMethod'.");
805+
805806
/**
806807
* When the '?.' operator is used on a target that we know to be non-null,
807808
* it is unnecessary.

pkg/analyzer/lib/src/error/codes.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4904,6 +4904,15 @@ class StaticWarningCode extends ErrorCode {
49044904
correction:
49054905
"Try casting or check the value is not null before using it.");
49064906

4907+
/**
4908+
* When the '...?' operator is used on a value that we know to be non-null,
4909+
* it is unnecessary.
4910+
*/
4911+
static const StaticWarningCode UNNECESSARY_NULL_AWARE_SPREAD =
4912+
const StaticWarningCode('UNNECESSARY_NULL_AWARE_SPREAD',
4913+
"The target expression cannot be null, and so '?' is not necessary.",
4914+
correction: "Replace the '...?' with a '...' in the spread.");
4915+
49074916
/**
49084917
* It is a static warning to assign void to any non-void type in dart.
49094918
* compile-time error). Report that error specially for a better user

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,8 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
13031303
void visitSpreadElement(SpreadElement node) {
13041304
if (node.spreadOperator.type != TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
13051305
_checkForNullableDereference(node.expression);
1306+
} else {
1307+
_checkForUnnecessaryNullAware(node.expression, node.spreadOperator);
13061308
}
13071309
super.visitSpreadElement(node);
13081310
}
@@ -5570,15 +5572,23 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
55705572
}
55715573

55725574
void _checkForUnnecessaryNullAware(Expression target, Token operator) {
5573-
if (operator.type != TokenType.QUESTION_PERIOD || !_isNonNullable) {
5575+
if (!_isNonNullable) {
5576+
return;
5577+
}
5578+
5579+
ErrorCode errorCode;
5580+
if (operator.type == TokenType.QUESTION_PERIOD) {
5581+
errorCode = HintCode.UNNECESSARY_NULL_AWARE_CALL;
5582+
} else if (operator.type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION) {
5583+
errorCode = StaticWarningCode.UNNECESSARY_NULL_AWARE_SPREAD;
5584+
} else {
55745585
return;
55755586
}
55765587

55775588
if (target.staticType != null &&
55785589
(target.staticType as TypeImpl).nullabilitySuffix ==
55795590
NullabilitySuffix.none) {
5580-
_errorReporter.reportErrorForToken(
5581-
HintCode.UNNECESSARY_NULL_AWARE_CALL, operator, []);
5591+
_errorReporter.reportErrorForToken(errorCode, operator, []);
55825592
}
55835593
}
55845594

pkg/analyzer/test/src/diagnostics/test_all.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ import 'undefined_shown_name_test.dart' as undefined_shown_name;
162162
import 'unnecessary_cast_test.dart' as unnecessary_cast;
163163
import 'unnecessary_no_such_method_test.dart' as unnecessary_no_such_method;
164164
import 'unnecessary_null_aware_call_test.dart' as unnecessary_null_aware_call;
165+
import 'unnecessary_null_aware_spread_test.dart'
166+
as unnecessary_null_aware_spread;
165167
import 'unnecessary_type_check_false_test.dart' as unnecessary_type_check_false;
166168
import 'unnecessary_type_check_true_test.dart' as unnecessary_type_check_true;
167169
import 'unused_catch_clause_test.dart' as unused_catch_clause;
@@ -291,6 +293,7 @@ main() {
291293
unnecessary_cast.main();
292294
unnecessary_no_such_method.main();
293295
unnecessary_null_aware_call.main();
296+
unnecessary_null_aware_spread.main();
294297
unnecessary_type_check_false.main();
295298
unnecessary_type_check_true.main();
296299
unused_catch_clause.main();
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analyzer/src/dart/analysis/experiments.dart';
6+
import 'package:analyzer/src/error/codes.dart';
7+
import 'package:analyzer/src/generated/engine.dart';
8+
import 'package:test_reflective_loader/test_reflective_loader.dart';
9+
10+
import '../dart/resolution/driver_resolution.dart';
11+
12+
main() {
13+
defineReflectiveSuite(() {
14+
defineReflectiveTests(UnnecessaryNullAwareSpreadTest);
15+
});
16+
}
17+
18+
@reflectiveTest
19+
class UnnecessaryNullAwareSpreadTest extends DriverResolutionTest {
20+
@override
21+
AnalysisOptionsImpl get analysisOptions =>
22+
AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
23+
24+
test_local_nonNullableSpread_nullableType() async {
25+
await assertNoErrorsInCode('''
26+
f() {
27+
List x = [];
28+
[...x];
29+
}
30+
''');
31+
}
32+
33+
test_local_nullableSpread_nonNullableType() async {
34+
await assertErrorsInCode('''
35+
f() {
36+
List x = [];
37+
[...?x];
38+
}
39+
''', [
40+
error(StaticWarningCode.UNNECESSARY_NULL_AWARE_SPREAD, 24, 4),
41+
]);
42+
}
43+
44+
test_local_nullableSpread_nullableType() async {
45+
await assertNoErrorsInCode('''
46+
f() {
47+
List? x;
48+
[...?x];
49+
}
50+
''');
51+
}
52+
}

0 commit comments

Comments
 (0)