mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 12:57:42 +00:00
Remove INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES warnings
Fixes https://github.com/dart-lang/sdk/issues/49112 It was decided to remove the "override with equal default value" restriction both for null safe code, and for pre-null safe code. CFE had never issued this static warning, and her we remove it from analyzer. Change-Id: I1244e4fe46da8bb4bd8c3a77ec8beb95811e30a1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262267 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
33c1ff60da
commit
15be61ed9a
|
@ -28,7 +28,7 @@
|
|||
# - 206 for ParserErrorCodes.
|
||||
# - 68 "needsFix"
|
||||
# - 287 "hasFix"
|
||||
# - 57 "noFix"
|
||||
# - 55 "noFix"
|
||||
|
||||
AnalysisOptionsErrorCode.INCLUDED_FILE_PARSE_ERROR:
|
||||
status: noFix
|
||||
|
@ -2599,14 +2599,6 @@ StaticWarningCode.INVALID_NULL_AWARE_OPERATOR:
|
|||
status: hasFix
|
||||
StaticWarningCode.INVALID_NULL_AWARE_OPERATOR_AFTER_SHORT_CIRCUIT:
|
||||
status: hasFix
|
||||
StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED:
|
||||
status: noFix
|
||||
notes: |-
|
||||
This is a pre-null safety code. No need to add a fix.
|
||||
StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL:
|
||||
status: noFix
|
||||
notes: |-
|
||||
This is a pre-null safety code. No need to add a fix.
|
||||
StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH:
|
||||
status: hasFix
|
||||
StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION:
|
||||
|
|
|
@ -953,8 +953,6 @@ const List<ErrorCode> errorCodeValues = [
|
|||
StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION,
|
||||
StaticWarningCode.INVALID_NULL_AWARE_OPERATOR,
|
||||
StaticWarningCode.INVALID_NULL_AWARE_OPERATOR_AFTER_SHORT_CIRCUIT,
|
||||
StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
StaticWarningCode.MISSING_ENUM_CONSTANT_IN_SWITCH,
|
||||
StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION,
|
||||
TodoCode.TODO,
|
||||
|
|
|
@ -5213,40 +5213,6 @@ class StaticWarningCode extends AnalyzerErrorCode {
|
|||
uniqueName: 'INVALID_NULL_AWARE_OPERATOR_AFTER_SHORT_CIRCUIT',
|
||||
);
|
||||
|
||||
/// 7.1 Instance Methods: It is a static warning if an instance method
|
||||
/// <i>m1</i> overrides an instance member <i>m2</i>, the signature of
|
||||
/// <i>m2</i> explicitly specifies a default value for a formal parameter
|
||||
/// <i>p</i> and the signature of <i>m1</i> specifies a different default value
|
||||
/// for <i>p</i>.
|
||||
///
|
||||
/// Parameters:
|
||||
/// 0: the name of the super class
|
||||
/// 1: the name of the super method
|
||||
/// 2: the name of the overriding method
|
||||
static const StaticWarningCode
|
||||
INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED = StaticWarningCode(
|
||||
'INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED',
|
||||
"Parameters can't override default values, this method overrides '{0}.{1}' "
|
||||
"where '{2}' has a different value.",
|
||||
correctionMessage: "Try using the same default value in both methods.",
|
||||
);
|
||||
|
||||
/// 7.1 Instance Methods: It is a static warning if an instance method
|
||||
/// <i>m1</i> overrides an instance member <i>m2</i>, the signature of
|
||||
/// <i>m2</i> explicitly specifies a default value for a formal parameter
|
||||
/// <i>p</i> and the signature of <i>m1</i> specifies a different default value
|
||||
/// for <i>p</i>.
|
||||
/// Parameters:
|
||||
/// 0: the name of the super class
|
||||
/// 1: the name of the super method
|
||||
static const StaticWarningCode
|
||||
INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL = StaticWarningCode(
|
||||
'INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL',
|
||||
"Parameters can't override default values, this method overrides '{0}.{1}' "
|
||||
"where this positional parameter has a different value.",
|
||||
correctionMessage: "Try using the same default value in both methods.",
|
||||
);
|
||||
|
||||
/// Parameters:
|
||||
/// 0: the name of the constant that is missing
|
||||
static const StaticWarningCode MISSING_ENUM_CONSTANT_IN_SWITCH =
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:analyzer/dart/analysis/features.dart';
|
|||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/syntactic_entity.dart';
|
||||
import 'package:analyzer/dart/ast/token.dart';
|
||||
import 'package:analyzer/dart/constant/value.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/dart/element/type_provider.dart';
|
||||
|
@ -355,17 +354,6 @@ class _ClassVerifier {
|
|||
errorReporter: reporter,
|
||||
errorNode: node,
|
||||
);
|
||||
|
||||
if (!_isNonNullableByDefault &&
|
||||
superMember is MethodElement &&
|
||||
member is MethodElement &&
|
||||
methodParameterNodes != null) {
|
||||
_checkForOptionalParametersDifferentDefaultValues(
|
||||
superMember,
|
||||
member,
|
||||
methodParameterNodes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (mixinIndex == -1) {
|
||||
|
@ -504,98 +492,6 @@ class _ClassVerifier {
|
|||
return true;
|
||||
}
|
||||
|
||||
void _checkForOptionalParametersDifferentDefaultValues(
|
||||
MethodElement baseExecutable,
|
||||
MethodElement derivedExecutable,
|
||||
List<FormalParameter> derivedParameterNodes,
|
||||
) {
|
||||
var derivedIsAbstract = derivedExecutable.isAbstract;
|
||||
var derivedOptionalNodes = <FormalParameter>[];
|
||||
var derivedOptionalElements = <ParameterElementImpl>[];
|
||||
var derivedParameterElements = derivedExecutable.parameters;
|
||||
for (var i = 0; i < derivedParameterElements.length; i++) {
|
||||
var parameterElement =
|
||||
derivedParameterElements[i] as ParameterElementImpl;
|
||||
if (parameterElement.isOptional) {
|
||||
derivedOptionalNodes.add(derivedParameterNodes[i]);
|
||||
derivedOptionalElements.add(parameterElement);
|
||||
}
|
||||
}
|
||||
|
||||
var baseOptionalElements = <ParameterElementImpl>[];
|
||||
var baseParameterElements = baseExecutable.parameters;
|
||||
for (var i = 0; i < baseParameterElements.length; ++i) {
|
||||
var baseParameter = baseParameterElements[i];
|
||||
if (baseParameter.isOptional) {
|
||||
baseOptionalElements
|
||||
.add(baseParameter.declaration as ParameterElementImpl);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop if no optional parameters.
|
||||
if (baseOptionalElements.isEmpty || derivedOptionalElements.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (derivedOptionalElements[0].isNamed) {
|
||||
for (int i = 0; i < derivedOptionalElements.length; i++) {
|
||||
var derivedElement = derivedOptionalElements[i];
|
||||
if (_isNonNullableByDefault &&
|
||||
derivedIsAbstract &&
|
||||
!derivedElement.hasDefaultValue) {
|
||||
continue;
|
||||
}
|
||||
var name = derivedElement.name;
|
||||
for (var j = 0; j < baseOptionalElements.length; j++) {
|
||||
var baseParameter = baseOptionalElements[j];
|
||||
if (name == baseParameter.name && baseParameter.hasDefaultValue) {
|
||||
var baseValue = baseParameter.computeConstantValue();
|
||||
var derivedResult = derivedElement.evaluationResult!;
|
||||
if (!_constantValuesEqual(derivedResult.value, baseValue)) {
|
||||
reporter.reportErrorForNode(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
derivedOptionalNodes[i],
|
||||
[
|
||||
baseExecutable.enclosingElement.displayName,
|
||||
baseExecutable.displayName,
|
||||
name
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var i = 0;
|
||||
i < derivedOptionalElements.length && i < baseOptionalElements.length;
|
||||
i++) {
|
||||
var derivedElement = derivedOptionalElements[i];
|
||||
if (_isNonNullableByDefault &&
|
||||
derivedIsAbstract &&
|
||||
!derivedElement.hasDefaultValue) {
|
||||
continue;
|
||||
}
|
||||
var baseElement = baseOptionalElements[i];
|
||||
if (baseElement.hasDefaultValue) {
|
||||
var baseValue = baseElement.computeConstantValue();
|
||||
var derivedResult = derivedElement.evaluationResult!;
|
||||
if (!_constantValuesEqual(derivedResult.value, baseValue)) {
|
||||
reporter.reportErrorForNode(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
derivedOptionalNodes[i],
|
||||
[
|
||||
baseExecutable.enclosingElement.displayName,
|
||||
baseExecutable.displayName
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that [classElement] is not a superinterface to itself.
|
||||
/// The [path] is a list containing the potentially cyclic implements path.
|
||||
///
|
||||
|
@ -1030,12 +926,4 @@ class _ClassVerifier {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
static bool _constantValuesEqual(DartObject? x, DartObject? y) {
|
||||
// If either constant value couldn't be computed due to an error, the
|
||||
// corresponding DartObject will be `null`. Since an error has already been
|
||||
// reported, there's no need to report another.
|
||||
if (x == null || y == null) return true;
|
||||
return x == y;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22816,32 +22816,6 @@ StaticWarningCode:
|
|||
Parameters:
|
||||
0: the null-aware operator that is invalid
|
||||
1: the non-null-aware operator that can replace the invalid operator
|
||||
INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED:
|
||||
problemMessage: "Parameters can't override default values, this method overrides '{0}.{1}' where '{2}' has a different value."
|
||||
correctionMessage: Try using the same default value in both methods.
|
||||
comment: |-
|
||||
7.1 Instance Methods: It is a static warning if an instance method
|
||||
<i>m1</i> overrides an instance member <i>m2</i>, the signature of
|
||||
<i>m2</i> explicitly specifies a default value for a formal parameter
|
||||
<i>p</i> and the signature of <i>m1</i> specifies a different default value
|
||||
for <i>p</i>.
|
||||
|
||||
Parameters:
|
||||
0: the name of the super class
|
||||
1: the name of the super method
|
||||
2: the name of the overriding method
|
||||
INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL:
|
||||
problemMessage: "Parameters can't override default values, this method overrides '{0}.{1}' where this positional parameter has a different value."
|
||||
correctionMessage: Try using the same default value in both methods.
|
||||
comment: |-
|
||||
7.1 Instance Methods: It is a static warning if an instance method
|
||||
<i>m1</i> overrides an instance member <i>m2</i>, the signature of
|
||||
<i>m2</i> explicitly specifies a default value for a formal parameter
|
||||
<i>p</i> and the signature of <i>m1</i> specifies a different default value
|
||||
for <i>p</i>.
|
||||
Parameters:
|
||||
0: the name of the super class
|
||||
1: the name of the super method
|
||||
MISSING_ENUM_CONSTANT_IN_SWITCH:
|
||||
problemMessage: "Missing case clause for '{0}'."
|
||||
correctionMessage: Try adding a case clause for the missing constant, or adding a default clause.
|
||||
|
|
|
@ -1,346 +0,0 @@
|
|||
// Copyright (c) 2019, 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/error/codes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(InvalidOverrideDifferentDefaultValuesNamedTest);
|
||||
defineReflectiveTests(
|
||||
InvalidOverrideDifferentDefaultValuesNamedWithoutNullSafetyTest,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class InvalidOverrideDifferentDefaultValuesNamedTest
|
||||
extends InvalidOverrideDifferentDefaultValuesNamedWithoutNullSafetyTest {
|
||||
test_concrete_equal_optIn_extends_optOut() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
// @dart = 2.7
|
||||
class A {
|
||||
void foo({int a = 0}) {}
|
||||
}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
|
||||
class B extends A {
|
||||
void foo({int a = 0}) {}
|
||||
}
|
||||
''', [
|
||||
error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
|
||||
]);
|
||||
}
|
||||
|
||||
test_concrete_equal_optOut_extends_optIn() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A {
|
||||
void foo({int a = 0}) {}
|
||||
}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
// @dart = 2.7
|
||||
import 'a.dart';
|
||||
|
||||
class B extends A {
|
||||
void foo({int a = 0}) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class InvalidOverrideDifferentDefaultValuesNamedWithoutNullSafetyTest
|
||||
extends PubPackageResolutionTest {
|
||||
test_abstract_different_base_value() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
abstract class A {
|
||||
void foo({x = 0}) {}
|
||||
}
|
||||
|
||||
abstract class B extends A {
|
||||
void foo({x = 1});
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
86, 5),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
test_abstract_noDefault_base_noDefault() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A {
|
||||
void foo({x});
|
||||
}
|
||||
|
||||
abstract class B extends A {
|
||||
void foo({x});
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_abstract_noDefault_base_value() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
abstract class A {
|
||||
void foo({x = 0}) {}
|
||||
}
|
||||
|
||||
abstract class B extends A {
|
||||
void foo({x});
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(
|
||||
StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
86,
|
||||
1),
|
||||
]));
|
||||
}
|
||||
|
||||
test_abstract_noDefault_multipleBase_differentValue() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
abstract class A {
|
||||
void foo({x = 0}) {}
|
||||
}
|
||||
|
||||
abstract class B {
|
||||
void foo({x = 1});
|
||||
}
|
||||
|
||||
abstract class C extends A implements B {
|
||||
void foo({x});
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(
|
||||
StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
142,
|
||||
1),
|
||||
error(
|
||||
StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
142,
|
||||
1),
|
||||
]));
|
||||
}
|
||||
|
||||
test_abstract_noDefault_multipleBase_sameValue() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
abstract class A {
|
||||
void foo({x = 0});
|
||||
}
|
||||
|
||||
abstract class B {
|
||||
void foo({x = 0});
|
||||
}
|
||||
|
||||
abstract class C extends A implements B {
|
||||
void foo({x});
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(
|
||||
StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
140,
|
||||
1),
|
||||
error(
|
||||
StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
140,
|
||||
1),
|
||||
]));
|
||||
}
|
||||
|
||||
test_abstract_value_base_noDefault() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A {
|
||||
void foo({x});
|
||||
}
|
||||
|
||||
abstract class B extends A {
|
||||
void foo({x = 0});
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_different() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
class A {
|
||||
void foo({x = 0}) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo({x = 1}) {}
|
||||
}''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
67, 5),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
test_concrete_equal() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A {
|
||||
void foo({x = 1});
|
||||
}
|
||||
|
||||
class C extends A {
|
||||
void foo({x = 3 - 2}) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_equal_function() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
nothing() => 'nothing';
|
||||
|
||||
class A {
|
||||
void foo(String a, {orElse = nothing}) {}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
void foo(String a, {orElse = nothing}) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_equal_otherLibrary() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A {
|
||||
void foo([a = 0]) {}
|
||||
}
|
||||
''');
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
|
||||
class C extends A {
|
||||
void foo([a = 0]) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_equal_otherLibrary_listLiteral() async {
|
||||
newFile('$testPackageLibPath/other.dart', '''
|
||||
class C {
|
||||
void foo({x: const ['x']}) {}
|
||||
}
|
||||
''');
|
||||
await assertNoErrorsInCode('''
|
||||
import 'other.dart';
|
||||
class D extends C {
|
||||
void foo({x: const ['x']}) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_explicitNull_overriddenWith_implicitNull() async {
|
||||
// If the base class provided an explicit null value for a default
|
||||
// parameter, then it is ok for the derived class to let the default value
|
||||
// be implicit, because the implicit default value of null matches the
|
||||
// explicit default value of null.
|
||||
await assertNoErrorsInCode(r'''
|
||||
class A {
|
||||
void foo({x: null}) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo({x}) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_implicitNull_overriddenWith_value() async {
|
||||
// If the base class lets the default parameter be implicit, then it is ok
|
||||
// for the derived class to provide an explicit default value, even if it's
|
||||
// not null.
|
||||
await assertNoErrorsInCode(r'''
|
||||
class A {
|
||||
void foo({x}) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo({x = 1}) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_undefined_base() async {
|
||||
// Note: we expect some errors due to the constant referring to undefined
|
||||
// values, but there should not be any INVALID_OVERRIDE... error.
|
||||
await assertErrorsInCode('''
|
||||
class A {
|
||||
void foo({x = Undefined.value}) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo({x = 1}) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 26, 9),
|
||||
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 26, 9),
|
||||
]);
|
||||
}
|
||||
|
||||
test_concrete_undefined_both() async {
|
||||
// Note: we expect some errors due to the constant referring to undefined
|
||||
// values, but there should not be any INVALID_OVERRIDE... error.
|
||||
await assertErrorsInCode('''
|
||||
class A {
|
||||
void foo({x = Undefined.value}) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo({x = Undefined2.value2}) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 26, 9),
|
||||
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 26, 9),
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 85, 10),
|
||||
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 85, 10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_concrete_undefined_derived() async {
|
||||
// Note: we expect some errors due to the constant referring to undefined
|
||||
// values, but there should not be any INVALID_OVERRIDE... error.
|
||||
await assertErrorsInCode('''
|
||||
class A {
|
||||
void foo({x = 1}) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo({x = Undefined.value}) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 71, 9),
|
||||
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 71, 9),
|
||||
]);
|
||||
}
|
||||
|
||||
test_concrete_value_overriddenWith_implicitNull() async {
|
||||
// If the base class provided an explicit value for a default parameter,
|
||||
// then it is a static warning for the derived class to provide a different
|
||||
// value, even if implicitly.
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
class A {
|
||||
void foo({x: 1}) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo({x}) {}
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
|
||||
66, 1),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,363 +0,0 @@
|
|||
// Copyright (c) 2019, 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/error/codes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(
|
||||
InvalidOverrideDifferentDefaultValuesPositionalTest,
|
||||
);
|
||||
defineReflectiveTests(
|
||||
InvalidOverrideDifferentDefaultValuesPositionalWithoutNullSafetyTest,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class InvalidOverrideDifferentDefaultValuesPositionalTest
|
||||
extends InvalidOverrideDifferentDefaultValuesPositionalWithoutNullSafetyTest {
|
||||
test_concrete_equal_optIn_extends_optOut() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
// @dart = 2.7
|
||||
class A {
|
||||
void foo([int a = 0]) {}
|
||||
}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
|
||||
class B extends A {
|
||||
void foo([int a = 0]) {}
|
||||
}
|
||||
''', [
|
||||
error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
|
||||
]);
|
||||
}
|
||||
|
||||
test_concrete_equal_optOut_extends_optIn() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A {
|
||||
void foo([int a = 0]) {}
|
||||
}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
// @dart = 2.7
|
||||
import 'a.dart';
|
||||
|
||||
class B extends A {
|
||||
void foo([int a = 0]) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class InvalidOverrideDifferentDefaultValuesPositionalWithoutNullSafetyTest
|
||||
extends PubPackageResolutionTest {
|
||||
test_abstract_different_base_value() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
abstract class A {
|
||||
void foo([x = 0]) {}
|
||||
}
|
||||
|
||||
abstract class B extends A {
|
||||
void foo([x = 1]);
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
86,
|
||||
5),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
test_abstract_noDefault_base_noDefault() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A {
|
||||
void foo([x]);
|
||||
}
|
||||
|
||||
abstract class B extends A {
|
||||
void foo([x]);
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_abstract_noDefault_base_value() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
abstract class A {
|
||||
void foo([x = 0]) {}
|
||||
}
|
||||
|
||||
abstract class B extends A {
|
||||
void foo([x]);
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
86,
|
||||
1),
|
||||
]));
|
||||
}
|
||||
|
||||
test_abstract_noDefault_multipleBase_differentValue() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
abstract class A {
|
||||
void foo([x = 0]) {}
|
||||
}
|
||||
|
||||
abstract class B {
|
||||
void foo([x = 1]);
|
||||
}
|
||||
|
||||
abstract class C extends A implements B {
|
||||
void foo([x]);
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
142,
|
||||
1),
|
||||
error(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
142,
|
||||
1),
|
||||
]));
|
||||
}
|
||||
|
||||
test_abstract_noDefault_multipleBase_sameValue() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
abstract class A {
|
||||
void foo([x = 0]);
|
||||
}
|
||||
|
||||
abstract class B {
|
||||
void foo([x = 0]);
|
||||
}
|
||||
|
||||
abstract class C extends A implements B {
|
||||
void foo([x]);
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
140,
|
||||
1),
|
||||
error(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
140,
|
||||
1),
|
||||
]));
|
||||
}
|
||||
|
||||
test_abstract_value_base_noDefault() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A {
|
||||
void foo([x]);
|
||||
}
|
||||
|
||||
abstract class B extends A {
|
||||
void foo([x = 0]);
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_different() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
class A {
|
||||
void foo([x = 0]) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo([x = 1]) {}
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
67,
|
||||
5),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
test_concrete_equal() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
abstract class A {
|
||||
void foo([x = 1]);
|
||||
}
|
||||
|
||||
class C extends A {
|
||||
void foo([x = 3 - 2]) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_equal_function() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
nothing() => 'nothing';
|
||||
|
||||
class A {
|
||||
void foo(String a, [orElse = nothing]) {}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
void foo(String a, [orElse = nothing]) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_equal_otherLibrary() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A {
|
||||
void foo([x = 0]) {}
|
||||
}
|
||||
''');
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
|
||||
class C extends A {
|
||||
void foo([a = 0]) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_equal_otherLibrary_listLiteral() async {
|
||||
newFile('$testPackageLibPath/other.dart', '''
|
||||
class C {
|
||||
void foo([x = const ['x']]) {}
|
||||
}
|
||||
''');
|
||||
await assertNoErrorsInCode('''
|
||||
import 'other.dart';
|
||||
class D extends C {
|
||||
void foo([x = const ['x']]) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_explicitNull_overriddenWith_implicitNull() async {
|
||||
// If the base class provided an explicit null value for a default
|
||||
// parameter, then it is ok for the derived class to let the default value
|
||||
// be implicit, because the implicit default value of null matches the
|
||||
// explicit default value of null.
|
||||
await assertNoErrorsInCode(r'''
|
||||
class A {
|
||||
void foo([x = null]) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo([x]) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_implicitNull_overriddenWith_value() async {
|
||||
// If the base class lets the default parameter be implicit, then it is ok
|
||||
// for the derived class to provide an explicit default value, even if it's
|
||||
// not null.
|
||||
await assertNoErrorsInCode(r'''
|
||||
class A {
|
||||
void foo([x]) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo([x = 1]) {}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_concrete_undefined_base() async {
|
||||
// Note: we expect some errors due to the constant referring to undefined
|
||||
// values, but there should not be any INVALID_OVERRIDE... error.
|
||||
await assertErrorsInCode('''
|
||||
class A {
|
||||
void foo([x = Undefined.value]) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo([x = 1]) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 26, 9),
|
||||
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 26, 9),
|
||||
]);
|
||||
}
|
||||
|
||||
test_concrete_undefined_both() async {
|
||||
// Note: we expect some errors due to the constant referring to undefined
|
||||
// values, but there should not be any INVALID_OVERRIDE... error.
|
||||
await assertErrorsInCode('''
|
||||
class A {
|
||||
void foo([x = Undefined.value]) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo([x = Undefined2.value2]) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 26, 9),
|
||||
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 26, 9),
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 85, 10),
|
||||
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 85, 10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_concrete_undefined_derived() async {
|
||||
// Note: we expect some errors due to the constant referring to undefined
|
||||
// values, but there should not be any INVALID_OVERRIDE... error.
|
||||
await assertErrorsInCode('''
|
||||
class A {
|
||||
void foo([x = 1]) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo([x = Undefined.value]) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 71, 9),
|
||||
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 71, 9),
|
||||
]);
|
||||
}
|
||||
|
||||
test_concrete_value_overriddenWith_implicitNull() async {
|
||||
// If the base class provided an explicit value for a default parameter,
|
||||
// then it is a static warning for the derived class to provide a different
|
||||
// value, even if implicitly.
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
class A {
|
||||
void foo([x = 1]) {}
|
||||
}
|
||||
class B extends A {
|
||||
void foo([x]) {}
|
||||
}
|
||||
''',
|
||||
expectedErrorsByNullability(nullable: [], legacy: [
|
||||
error(
|
||||
StaticWarningCode
|
||||
.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
|
||||
67,
|
||||
1),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -369,10 +369,6 @@ import 'invalid_modifier_on_setter_test.dart' as invalid_modifier_on_setter;
|
|||
import 'invalid_non_virtual_annotation_test.dart'
|
||||
as invalid_non_virtual_annotation;
|
||||
import 'invalid_null_aware_operator_test.dart' as invalid_null_aware_operator;
|
||||
import 'invalid_override_different_default_values_named_test.dart'
|
||||
as invalid_override_different_default_values_named;
|
||||
import 'invalid_override_different_default_values_positional_test.dart'
|
||||
as invalid_override_different_default_values_positional;
|
||||
import 'invalid_override_of_non_virtual_member_test.dart'
|
||||
as invalid_override_of_non_virtual_member;
|
||||
import 'invalid_override_test.dart' as invalid_override;
|
||||
|
@ -1050,8 +1046,6 @@ main() {
|
|||
invalid_modifier_on_setter.main();
|
||||
invalid_non_virtual_annotation.main();
|
||||
invalid_null_aware_operator.main();
|
||||
invalid_override_different_default_values_named.main();
|
||||
invalid_override_different_default_values_positional.main();
|
||||
invalid_override_of_non_virtual_member.main();
|
||||
invalid_override.main();
|
||||
invalid_reference_to_generative_enum_constructor.main();
|
||||
|
|
|
@ -75,7 +75,7 @@ class B extends A {
|
|||
fooIntercept28() => confuse(super.lastWhere)(3, orElse: 77);
|
||||
|
||||
// Warning: overrides should not change default parameter values.
|
||||
bar([var optional]) => -1; // //# 01: static type warning
|
||||
bar([var optional]) => -1; // //# 01: ok
|
||||
bar2({namedOptional}) => -1; // //# 01: continued
|
||||
bar3(x, [var optional]) => -1; // //# 01: continued
|
||||
bar4(x, {namedOptional}) => -1; //# 01: continued
|
||||
|
|
Loading…
Reference in a new issue