analyzer: Reduce redundant errors with invalid covariant use
Fixes https://github.com/dart-lang/sdk/issues/47248
Change-Id: I75c4a1e4fcb6cb26fbc8a6aa54e62b740e264783
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/218782
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index b53caa5..ffac3f2 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -4750,12 +4750,27 @@
void _checkUseOfCovariantInParameters(FormalParameterList node) {
var parent = node.parent;
- if (_enclosingClass != null &&
- parent is MethodDeclaration &&
- !parent.isStatic) {
+ if (_enclosingClass != null && parent is MethodDeclaration) {
+ // Either [parent] is a static method, in which case `EXTRANEOUS_MODIFIER`
+ // is reported by the parser, or [parent] is an instance method, in which
+ // case any use of `covariant` is legal.
return;
}
+ if (_enclosingExtension != null) {
+ // `INVALID_USE_OF_COVARIANT_IN_EXTENSION` is reported by the parser.
+ return;
+ }
+
+ if (parent is FunctionExpression) {
+ var parent2 = parent.parent;
+ if (parent2 is FunctionDeclaration && parent2.parent is CompilationUnit) {
+ // `EXTRANEOUS_MODIFIER` is reported by the parser, for library-level
+ // functions.
+ return;
+ }
+ }
+
NodeList<FormalParameter> parameters = node.parameters;
int length = parameters.length;
for (int i = 0; i < length; i++) {
@@ -4765,14 +4780,10 @@
}
var keyword = parameter.covariantKeyword;
if (keyword != null) {
- if (_enclosingExtension != null) {
- // Reported by the parser.
- } else {
- errorReporter.reportErrorForToken(
- CompileTimeErrorCode.INVALID_USE_OF_COVARIANT,
- keyword,
- );
- }
+ errorReporter.reportErrorForToken(
+ CompileTimeErrorCode.INVALID_USE_OF_COVARIANT,
+ keyword,
+ );
}
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_use_of_covariant_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_use_of_covariant_test.dart
new file mode 100644
index 0000000..20b7d5c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_use_of_covariant_test.dart
@@ -0,0 +1,121 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/error/hint_codes.g.dart';
+import 'package:analyzer/src/error/codes.g.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(InvalidUseOfCovariantTest);
+ });
+}
+
+@reflectiveTest
+class InvalidUseOfCovariantTest extends PubPackageResolutionTest {
+ test_functionExpression() async {
+ await assertErrorsInCode('''
+Function f = (covariant int x) {};
+''', [
+ error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT, 14, 9),
+ ]);
+ }
+
+ test_functionType_inFunctionTypedParameterOfInstanceMethod() async {
+ await assertErrorsInCode('''
+class C {
+ void m(void p(covariant int)) {}
+}
+''', [
+ error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT, 26, 9),
+ ]);
+ }
+
+ test_functionType_inParameterOfInstanceMethod() async {
+ await assertErrorsInCode('''
+class C {
+ void m(void Function(covariant int) p) {}
+}
+''', [
+ error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT, 33, 9),
+ ]);
+ }
+
+ test_functionType_inTypeAlias() async {
+ await assertErrorsInCode('''
+typedef F = void Function(covariant int);
+''', [
+ error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT, 26, 9),
+ ]);
+ }
+
+ test_functionType_inTypeArgument() async {
+ await assertErrorsInCode('''
+List<void Function(covariant int)> a = [];
+}
+''', [
+ error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT, 19, 9),
+ // TODO(srawlins): Recover better from this situation (`covariant` in
+ // parameter in type argument).
+ error(ParserErrorCode.EXPECTED_EXECUTABLE, 43, 1),
+ ]);
+ }
+
+ test_functionType_inTypeParameterBound() async {
+ await assertErrorsInCode('''
+void foo<T extends void Function(covariant int)>() {}
+}
+''', [
+ error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT, 33, 9),
+ // TODO(srawlins): Recover better from this situation (`covariant` in
+ // parameter in bound).
+ error(ParserErrorCode.EXPECTED_EXECUTABLE, 54, 1),
+ ]);
+ }
+
+ test_localFunction() async {
+ await assertErrorsInCode('''
+void foo() {
+ void f(covariant int x) {}
+}
+''', [
+ error(HintCode.UNUSED_ELEMENT, 20, 1),
+ error(CompileTimeErrorCode.INVALID_USE_OF_COVARIANT, 22, 9),
+ ]);
+ }
+
+ test_staticFunction() async {
+ await assertErrorsInCode('''
+class C {
+ static void m(covariant int x) {}
+}
+''', [
+ // INVALID_USE_OF_COVARIANT is not reported here; it would be redundant.
+ error(ParserErrorCode.EXTRANEOUS_MODIFIER, 26, 9),
+ ]);
+ }
+
+ test_staticFunction_onMixin() async {
+ await assertErrorsInCode('''
+mixin M {
+ static void m(covariant int x) {}
+}
+''', [
+ // INVALID_USE_OF_COVARIANT is not reported here; it would be redundant.
+ error(ParserErrorCode.EXTRANEOUS_MODIFIER, 26, 9),
+ ]);
+ }
+
+ test_topLevelFunction() async {
+ await assertErrorsInCode('''
+void f(covariant int x) {}
+''', [
+ // INVALID_USE_OF_COVARIANT is not reported here; it would be redundant.
+ error(ParserErrorCode.EXTRANEOUS_MODIFIER, 7, 9),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 263958a..3d245fa 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -354,6 +354,7 @@
import 'invalid_uri_test.dart' as invalid_uri;
import 'invalid_use_of_covariant_in_extension_test.dart'
as invalid_use_of_covariant_in_extension;
+import 'invalid_use_of_covariant_test.dart' as invalid_use_of_covariant;
import 'invalid_use_of_internal_member_test.dart'
as invalid_use_of_internal_member;
import 'invalid_use_of_protected_member_test.dart'
@@ -951,6 +952,7 @@
invalid_type_argument_in_const_map.main();
invalid_type_argument_in_const_set.main();
invalid_uri.main();
+ invalid_use_of_covariant.main();
invalid_use_of_covariant_in_extension.main();
invalid_use_of_internal_member.main();
invalid_use_of_protected_member.main();