Skip to content

Commit aad9e57

Browse files
committed
Revert "Revert "[analyzer] new warning for nullable '==' parameter type""
This reverts commit 885457e. [analyzer] new warning for nullable '==' parameter type This rule checks that a parameter to an `operator ==` implementation has a non-nullable type. I intentionally did not enforce, in this rule, that the parameter is exactly `Object`. It is legal to narrow the parameter type to a different non-nullable type, like `int`. I can't imagine doing it, but it seems to be unrelated to whether the type should be nullable or not. Fixes https://github.com/dart-lang/linter/issues/3441 Replaces dart-archive/linter#3923 Change-Id: Ic0be2bfebaf59b0336e9a3a58e5b7f5359eb8646 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/291042 Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Stephen Adams <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent 38f6c82 commit aad9e57

File tree

14 files changed

+177
-20
lines changed

14 files changed

+177
-20
lines changed

pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ class ExtensionShowHideElementIdentifierContext extends IdentifierContext {
449449
}
450450

451451
@override
452-
bool operator ==(dynamic other) {
452+
bool operator ==(Object other) {
453453
return other is ExtensionShowHideElementIdentifierContext &&
454454
_kind == other._kind;
455455
}

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3699,6 +3699,11 @@ WarningCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW:
36993699
status: needsFix
37003700
notes: |-
37013701
The fix is to replace `new` with `const`.
3702+
WarningCode.NON_NULLABLE_EQUALS_PARAMETER:
3703+
status: needsFix
3704+
notes: |-
3705+
The fix is to remove the question mark if the parameter has one (if the
3706+
written type is an alias, it may not).
37023707
WarningCode.NULLABLE_TYPE_IN_CATCH_CLAUSE:
37033708
status: hasFix
37043709
WarningCode.NULL_ARGUMENT_TO_NON_NULL_TYPE:

pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ class Person {
688688
final String name = '';
689689
690690
@override
691-
operator ==(Object? other) =>
691+
operator ==(Object other) =>
692692
other != null &&
693693
other is Person &&
694694
name == other.name;
@@ -699,7 +699,7 @@ class Person {
699699
final String name = '';
700700
701701
@override
702-
operator ==(Object? other) =>
702+
operator ==(Object other) =>
703703
other is Person &&
704704
name == other.name;
705705
}
@@ -712,7 +712,7 @@ class Person {
712712
final String name = '';
713713
714714
@override
715-
operator ==(Object? other) {
715+
operator ==(Object other) {
716716
return other != null &&
717717
other is Person &&
718718
name == other.name;
@@ -724,7 +724,7 @@ class Person {
724724
final String name = '';
725725
726726
@override
727-
operator ==(Object? other) {
727+
operator ==(Object other) {
728728
return other is Person &&
729729
name == other.name;
730730
}
@@ -738,7 +738,7 @@ class Person {
738738
final String name = '';
739739
740740
@override
741-
operator ==(Object? other) {
741+
operator ==(Object other) {
742742
if (other is! Person) return false;
743743
other ??= Person();
744744
return other.name == name;

pkg/analysis_server/tool/code_completion/metrics_util.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ class Place {
458458
int get rank => _numerator;
459459

460460
@override
461-
bool operator ==(dynamic other) =>
461+
bool operator ==(Object other) =>
462462
other is Place &&
463463
_numerator == other._numerator &&
464464
_denominator == other._denominator;

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
593593
_checkForMissingReturn(node.body, node);
594594
_mustCallSuperVerifier.checkMethodDeclaration(node);
595595
_checkForUnnecessaryNoSuchMethod(node);
596+
_checkForNullableEqualsParameterType(node);
596597

597598
var name = Name(_currentLibrary.source.uri, element.name);
598599
var elementIsOverride = element is ClassMemberElement &&
@@ -1262,6 +1263,44 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
12621263
}
12631264
}
12641265

1266+
void _checkForNullableEqualsParameterType(MethodDeclaration node) {
1267+
if (!_typeSystem.isNonNullableByDefault) {
1268+
// Cannot specify non-nullable types before null safety.
1269+
return;
1270+
}
1271+
1272+
if (node.name.type != TokenType.EQ_EQ) {
1273+
return;
1274+
}
1275+
1276+
var parameters = node.parameters;
1277+
if (parameters == null) {
1278+
return;
1279+
}
1280+
1281+
if (parameters.parameters.length != 1) {
1282+
return;
1283+
}
1284+
1285+
var parameter = parameters.parameters.first;
1286+
var parameterElement = parameter.declaredElement;
1287+
if (parameterElement == null) {
1288+
return;
1289+
}
1290+
1291+
var type = parameterElement.type;
1292+
if (!type.isDartCoreObject && type is! DynamicType) {
1293+
// There is no legal way to define a nullable parameter type, which is not
1294+
// `dynamic` or `Object?`, so avoid double reporting here.
1295+
return;
1296+
}
1297+
1298+
if (_typeSystem.isNullable(parameterElement.type)) {
1299+
_errorReporter.reportErrorForToken(
1300+
WarningCode.NON_NULLABLE_EQUALS_PARAMETER, node.name);
1301+
}
1302+
}
1303+
12651304
void _checkForNullableTypeInCatchClause(CatchClause node) {
12661305
if (!_isNonNullableByDefault) {
12671306
return;

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6894,6 +6894,13 @@ class WarningCode extends AnalyzerErrorCode {
68946894
uniqueName: 'NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW',
68956895
);
68966896

6897+
/// No parameters.
6898+
static const WarningCode NON_NULLABLE_EQUALS_PARAMETER = WarningCode(
6899+
'NON_NULLABLE_EQUALS_PARAMETER',
6900+
"The parameter type of '==' operators should be non-nullable.",
6901+
correctionMessage: "Try using a non-nullable type.",
6902+
);
6903+
68976904
/// No parameters.
68986905
static const WarningCode NULLABLE_TYPE_IN_CATCH_CLAUSE = WarningCode(
68996906
'NULLABLE_TYPE_IN_CATCH_CLAUSE',

pkg/analyzer/lib/src/error/error_code_values.g.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,7 @@ const List<ErrorCode> errorCodeValues = [
10381038
WarningCode.MUST_CALL_SUPER,
10391039
WarningCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR,
10401040
WarningCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW,
1041+
WarningCode.NON_NULLABLE_EQUALS_PARAMETER,
10411042
WarningCode.NULLABLE_TYPE_IN_CATCH_CLAUSE,
10421043
WarningCode.NULL_ARGUMENT_TO_NON_NULL_TYPE,
10431044
WarningCode.NULL_CHECK_ALWAYS_FAILS,

pkg/analyzer/messages.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6906,7 +6906,7 @@ CompileTimeErrorCode:
69066906

69076907
```dart
69086908
mixin M on Enum {
6909-
bool operator [!==!](Object? other) => false;
6909+
bool operator [!==!](Object other) => false;
69106910
}
69116911
```
69126912

@@ -24835,6 +24835,11 @@ WarningCode:
2483524835

2483624836
void f() => const C();
2483724837
```
24838+
NON_NULLABLE_EQUALS_PARAMETER:
24839+
problemMessage: "The parameter type of '==' operators should be non-nullable."
24840+
correctionMessage: Try using a non-nullable type.
24841+
hasPublishedDocs: false
24842+
comment: No parameters.
2483824843
NULLABLE_TYPE_IN_CATCH_CLAUSE:
2483924844
problemMessage: "A potentially nullable type can't be used in an 'on' clause because it isn't valid to throw a nullable expression."
2484024845
correctionMessage: Try using a non-nullable type.

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,18 @@ extension E on String {
2828
test_instance_sameKind() async {
2929
await assertErrorsInCode('''
3030
extension E on String {
31-
bool operator==(_) => false;
31+
bool operator==(Object _) => false;
3232
int get hashCode => 0;
3333
String toString() => '';
3434
dynamic get runtimeType => null;
3535
dynamic noSuchMethod(_) => null;
3636
}
3737
''', [
3838
error(CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT, 39, 2),
39-
error(CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT, 65, 8),
40-
error(CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT, 89, 8),
41-
error(CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT, 121, 11),
42-
error(CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT, 152, 12),
39+
error(CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT, 72, 8),
40+
error(CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT, 96, 8),
41+
error(CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT, 128, 11),
42+
error(CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT, 159, 12),
4343
]);
4444
}
4545

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ extension type E(int it) {
2929
test_instance_sameKind() async {
3030
await assertErrorsInCode('''
3131
extension type E(int it) {
32-
bool operator==(_) => false;
32+
bool operator==(Object _) => false;
3333
int get hashCode => 0;
3434
String toString() => '';
3535
dynamic get runtimeType => null;
@@ -39,12 +39,12 @@ extension type E(int it) {
3939
error(
4040
CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT, 42, 2),
4141
error(
42-
CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT, 68, 8),
42+
CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT, 75, 8),
4343
error(
44-
CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT, 92, 8),
45-
error(CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT, 124,
44+
CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT, 99, 8),
45+
error(CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT, 131,
4646
11),
47-
error(CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT, 155,
47+
error(CompileTimeErrorCode.EXTENSION_TYPE_DECLARES_MEMBER_OF_OBJECT, 162,
4848
12),
4949
]);
5050
}

0 commit comments

Comments
 (0)