mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 08:24:39 +00:00
[analyzer] Avoid reporting subtype modifier errors on final supertypes outside of library.
Change-Id: If4fba1c08d7dc9d4f65ea56760298e47c65742fa Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/287340 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Kallen Tu <kallentu@google.com>
This commit is contained in:
parent
d029b866f4
commit
919eb05b27
|
@ -1059,7 +1059,9 @@ CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY:
|
|||
status: needsEvaluation
|
||||
CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED:
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED:
|
||||
status: hasFix
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import 'package:analysis_server/src/services/correction/fix.dart';
|
||||
import 'package:analyzer/src/dart/error/ffi_code.g.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
|
@ -55,13 +54,9 @@ class ExtendsDisallowedClassTest extends FixProcessorTest {
|
|||
await resolveTestCode('''
|
||||
class C extends String {}
|
||||
''');
|
||||
await assertHasFix(
|
||||
'''
|
||||
await assertHasFix('''
|
||||
class C {}
|
||||
''',
|
||||
errorFilter: (error) =>
|
||||
error.errorCode == CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
|
||||
);
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,26 +101,18 @@ class ImplementsDisallowedClassTest extends FixProcessorTest {
|
|||
await resolveTestCode('''
|
||||
class C implements String {}
|
||||
''');
|
||||
await assertHasFix(
|
||||
'''
|
||||
await assertHasFix('''
|
||||
class C {}
|
||||
''',
|
||||
errorFilter: (error) =>
|
||||
error.errorCode == CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
|
||||
);
|
||||
''');
|
||||
}
|
||||
|
||||
Future<void> test_twoNames() async {
|
||||
await resolveTestCode('''
|
||||
abstract class C implements String, List<int> {}
|
||||
''');
|
||||
await assertHasFix(
|
||||
'''
|
||||
await assertHasFix('''
|
||||
abstract class C implements List<int> {}
|
||||
''',
|
||||
errorFilter: (error) =>
|
||||
error.errorCode == CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
|
||||
);
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,13 +176,9 @@ class MixinOfDisallowedClassTest extends FixProcessorTest {
|
|||
await resolveTestCode('''
|
||||
abstract class C with String {}
|
||||
''');
|
||||
await assertHasFix(
|
||||
'''
|
||||
await assertHasFix('''
|
||||
abstract class C {}
|
||||
''',
|
||||
errorFilter: (error) =>
|
||||
error.errorCode == CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS,
|
||||
);
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/dart/analysis/features.dart';
|
||||
import 'package:analyzer/dart/ast/token.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/diagnostic/diagnostic.dart';
|
||||
|
@ -11,7 +10,6 @@ import 'package:analyzer/error/listener.dart';
|
|||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/diagnostic/diagnostic.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:analyzer/src/utilities/extensions/collection.dart';
|
||||
|
||||
/// Helper for verifying that subelements of a base or final element must be
|
||||
/// base, final, or sealed.
|
||||
|
@ -33,8 +31,8 @@ class BaseOrFinalTypeVerifier {
|
|||
/// Check to ensure the subelement of a base or final element must be base,
|
||||
/// final, or sealed. Otherwise, an error is reported on that element.
|
||||
///
|
||||
/// See [CompileTimeErrorCode.
|
||||
/// SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED]
|
||||
/// See [CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED],
|
||||
/// [CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED]
|
||||
void checkElement(ClassOrMixinElementImpl element) {
|
||||
if (_elementToBaseOrFinalSuperElement.containsKey(element)) {
|
||||
// We've already visited this element. Don't check it again.
|
||||
|
@ -43,14 +41,29 @@ class BaseOrFinalTypeVerifier {
|
|||
_elementToBaseOrFinalSuperElement[element] = null;
|
||||
}
|
||||
|
||||
List<InterfaceType> supertypes = [];
|
||||
supertypes.addIfNotNull(element.supertype);
|
||||
supertypes.addAll(element.interfaces);
|
||||
supertypes.addAll(element.mixins);
|
||||
if (element is MixinElementImpl) {
|
||||
supertypes.addAll(element.superclassConstraints);
|
||||
final supertype = element.supertype;
|
||||
if (supertype != null && _checkSupertypes([supertype], element)) {
|
||||
return;
|
||||
}
|
||||
if (_checkSupertypes(element.interfaces, element)) {
|
||||
return;
|
||||
}
|
||||
if (_checkSupertypes(element.mixins, element)) {
|
||||
return;
|
||||
}
|
||||
if (_checkSupertypes(element.interfaces, element)) {
|
||||
return;
|
||||
}
|
||||
if (element is MixinElementImpl &&
|
||||
_checkSupertypes(element.superclassConstraints, element,
|
||||
areSuperclassConstraints: true)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool _checkSupertypes(
|
||||
List<InterfaceType> supertypes, ClassOrMixinElementImpl subElement,
|
||||
{bool areSuperclassConstraints = false}) {
|
||||
for (final supertype in supertypes) {
|
||||
final supertypeElement = supertype.element;
|
||||
if (supertypeElement is ClassOrMixinElementImpl) {
|
||||
|
@ -60,11 +73,13 @@ class BaseOrFinalTypeVerifier {
|
|||
|
||||
// Return early if an error has been reported to prevent reporting
|
||||
// multiple errors on one element.
|
||||
if (_reportRestrictionError(element, supertypeElement)) {
|
||||
return;
|
||||
if (_reportRestrictionError(subElement, supertypeElement,
|
||||
isSuperclassConstraint: areSuperclassConstraints)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Checks whether a `final`, `base` or `interface` modifier can be ignored.
|
||||
|
@ -91,7 +106,8 @@ class BaseOrFinalTypeVerifier {
|
|||
///
|
||||
/// Reports an error based on the modifier of the superElement.
|
||||
bool _reportRestrictionError(
|
||||
ClassOrMixinElementImpl element, ClassOrMixinElementImpl superElement) {
|
||||
ClassOrMixinElementImpl element, ClassOrMixinElementImpl superElement,
|
||||
{bool isSuperclassConstraint = false}) {
|
||||
final cachedBaseOrFinalSuperElement =
|
||||
_elementToBaseOrFinalSuperElement[superElement];
|
||||
final hasCachedBaseOrFinalSuperElement =
|
||||
|
@ -133,19 +149,28 @@ class BaseOrFinalTypeVerifier {
|
|||
)
|
||||
];
|
||||
|
||||
_errorReporter.reportErrorForElement(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
element,
|
||||
[
|
||||
element.displayName,
|
||||
baseOrFinalSuperElement.displayName,
|
||||
baseOrFinalSuperElement.isBase
|
||||
? Keyword.BASE.lexeme
|
||||
: Keyword.FINAL.lexeme
|
||||
],
|
||||
hasCachedBaseOrFinalSuperElement ? contextMessage : null);
|
||||
return true;
|
||||
if (baseOrFinalSuperElement.isFinal) {
|
||||
if (!isSuperclassConstraint &&
|
||||
baseOrFinalSuperElement.library != element.library) {
|
||||
// If you can't extend, implement or mix in a final element outside of
|
||||
// its library anyways, it's not helpful to report a subelement
|
||||
// modifier error.
|
||||
return false;
|
||||
}
|
||||
_errorReporter.reportErrorForElement(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
element,
|
||||
[element.displayName, baseOrFinalSuperElement.displayName],
|
||||
hasCachedBaseOrFinalSuperElement ? contextMessage : null);
|
||||
return true;
|
||||
} else if (baseOrFinalSuperElement.isBase) {
|
||||
_errorReporter.reportErrorForElement(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
element,
|
||||
[element.displayName, baseOrFinalSuperElement.displayName],
|
||||
hasCachedBaseOrFinalSuperElement ? contextMessage : null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -4449,14 +4449,24 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
|||
|
||||
/// Parameters:
|
||||
/// 0: the name of the subtype that is not 'base', 'final', or 'sealed'
|
||||
/// 1: the name of the supertype which is 'base' or 'final'
|
||||
/// 2: the modifier on the supertype
|
||||
/// 1: the name of the 'base' supertype
|
||||
static const CompileTimeErrorCode
|
||||
SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED =
|
||||
CompileTimeErrorCode(
|
||||
SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED = CompileTimeErrorCode(
|
||||
'SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED',
|
||||
"The type '{0}' must be 'base', 'final' or 'sealed' because the supertype "
|
||||
"'{1}' is '{2}'.",
|
||||
"'{1}' is 'base'.",
|
||||
uniqueName: 'SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED',
|
||||
);
|
||||
|
||||
/// Parameters:
|
||||
/// 0: the name of the subtype that is not 'base', 'final', or 'sealed'
|
||||
/// 1: the name of the 'final' supertype
|
||||
static const CompileTimeErrorCode
|
||||
SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED = CompileTimeErrorCode(
|
||||
'SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED',
|
||||
"The type '{0}' must be 'base', 'final' or 'sealed' because the supertype "
|
||||
"'{1}' is 'final'.",
|
||||
uniqueName: 'SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED',
|
||||
);
|
||||
|
||||
/// Parameters:
|
||||
|
|
|
@ -451,7 +451,8 @@ const List<ErrorCode> errorCodeValues = [
|
|||
CompileTimeErrorCode.SHARED_DEFERRED_PREFIX,
|
||||
CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY,
|
||||
CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
|
||||
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED,
|
||||
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
|
||||
|
|
|
@ -12902,13 +12902,20 @@ CompileTimeErrorCode:
|
|||
|
||||
int f(C c) => c.b;
|
||||
```
|
||||
SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED:
|
||||
problemMessage: "The type '{0}' must be 'base', 'final' or 'sealed' because the supertype '{1}' is '{2}'."
|
||||
SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED:
|
||||
sharedName: SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
problemMessage: "The type '{0}' must be 'base', 'final' or 'sealed' because the supertype '{1}' is 'base'."
|
||||
comment: |-
|
||||
Parameters:
|
||||
0: the name of the subtype that is not 'base', 'final', or 'sealed'
|
||||
1: the name of the supertype which is 'base' or 'final'
|
||||
2: the modifier on the supertype
|
||||
1: the name of the 'base' supertype
|
||||
SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED:
|
||||
sharedName: SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
problemMessage: "The type '{0}' must be 'base', 'final' or 'sealed' because the supertype '{1}' is 'final'."
|
||||
comment: |-
|
||||
Parameters:
|
||||
0: the name of the subtype that is not 'base', 'final', or 'sealed'
|
||||
1: the name of the 'final' supertype
|
||||
SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED:
|
||||
problemMessage: The type '{0}' of this parameter isn't a subtype of the type '{1}' of the associated super constructor parameter.
|
||||
correctionMessage: Try removing the explicit type annotation from the parameter.
|
||||
|
|
|
@ -19,11 +19,6 @@ class ExtendsDisallowedClassTest extends PubPackageResolutionTest {
|
|||
await assertErrorsInCode('''
|
||||
class A extends bool {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 4),
|
||||
]);
|
||||
}
|
||||
|
@ -32,11 +27,6 @@ class A extends bool {}
|
|||
await assertErrorsInCode('''
|
||||
class A extends double {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 6),
|
||||
]);
|
||||
}
|
||||
|
@ -82,11 +72,6 @@ class A<T> extends FutureOr<T> {}
|
|||
await assertErrorsInCode('''
|
||||
class A extends int {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 3),
|
||||
]);
|
||||
}
|
||||
|
@ -111,11 +96,6 @@ class A extends num {}
|
|||
await assertErrorsInCode('''
|
||||
class A extends Record {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 6),
|
||||
]);
|
||||
}
|
||||
|
@ -124,11 +104,6 @@ class A extends Record {}
|
|||
await assertErrorsInCode('''
|
||||
class A extends String {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, 16, 6),
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -19,11 +19,6 @@ class ImplementsDisallowedClassTest extends PubPackageResolutionTest {
|
|||
await assertErrorsInCode('''
|
||||
class A implements bool {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 4),
|
||||
]);
|
||||
}
|
||||
|
@ -56,11 +51,6 @@ class A implements Enum {}
|
|||
await assertErrorsInCode('''
|
||||
class A implements double {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
|
||||
]);
|
||||
}
|
||||
|
@ -106,11 +96,6 @@ class A<T> implements FutureOr<T> {}
|
|||
await assertErrorsInCode('''
|
||||
class A implements int {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 3),
|
||||
]);
|
||||
}
|
||||
|
@ -135,11 +120,6 @@ class A implements num {}
|
|||
await assertErrorsInCode('''
|
||||
class A implements Record {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
|
||||
]);
|
||||
}
|
||||
|
@ -148,11 +128,6 @@ class A implements Record {}
|
|||
await assertErrorsInCode('''
|
||||
class A implements String {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
|
||||
]);
|
||||
}
|
||||
|
@ -161,11 +136,6 @@ class A implements String {}
|
|||
await assertErrorsInCode('''
|
||||
class A implements String, num {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 6),
|
||||
error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 27, 3),
|
||||
]);
|
||||
|
@ -309,11 +279,6 @@ mixin M implements Enum {}
|
|||
await assertErrorsInCode(r'''
|
||||
mixin M implements int {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, 19, 3),
|
||||
]);
|
||||
|
||||
|
|
|
@ -19,11 +19,6 @@ class MixinOfDisallowedClassTest extends PubPackageResolutionTest {
|
|||
await assertErrorsInCode('''
|
||||
class A extends Object with bool {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 4),
|
||||
]);
|
||||
}
|
||||
|
@ -32,11 +27,6 @@ class A extends Object with bool {}
|
|||
await assertErrorsInCode('''
|
||||
class A extends Object with double {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
|
||||
]);
|
||||
}
|
||||
|
@ -72,11 +62,6 @@ class A<T> extends Object with FutureOr<T> {}
|
|||
await assertErrorsInCode('''
|
||||
class A extends Object with int {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 3),
|
||||
]);
|
||||
}
|
||||
|
@ -101,11 +86,6 @@ class A extends Object with num {}
|
|||
await assertErrorsInCode('''
|
||||
class A extends Object with Record {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
|
||||
]);
|
||||
}
|
||||
|
@ -114,11 +94,6 @@ class A extends Object with Record {}
|
|||
await assertErrorsInCode('''
|
||||
class A extends Object with String {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS, 28, 6),
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -46,11 +46,8 @@ mixin M on Enum {}
|
|||
await assertErrorsInCode(r'''
|
||||
mixin M on int {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1),
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6, 1),
|
||||
error(CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS,
|
||||
11, 3),
|
||||
]);
|
||||
|
|
|
@ -0,0 +1,352 @@
|
|||
// Copyright (c) 2023, 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 '../../generated/test_support.dart';
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(SubtypeOfBaseIsNotBaseFinalOrSealedTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class SubtypeOfBaseIsNotBaseFinalOrSealedTest extends PubPackageResolutionTest {
|
||||
test_class_extends() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
class B extends A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_extends_multiple() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
base class B extends A {}
|
||||
class C extends A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
48, 1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_extends_multiple_files() async {
|
||||
final a = newFile('$testPackageLibPath/a.dart', r'''
|
||||
base class A {}
|
||||
class B extends A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInFile2(a.path, [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(a.path, 22, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_extends_outside() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
base class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
class B extends A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
class B implements A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_mixin_mixedIn() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base mixin class A {}
|
||||
class B with A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
28, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_mixin_mixedIn_outside() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
base mixin class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
class B with A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_extends() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed class B extends A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
50,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 29, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_extends_multiple() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed class B extends A {}
|
||||
sealed class C extends B {}
|
||||
class D extends C {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
78,
|
||||
1,
|
||||
text:
|
||||
"The type 'D' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 57, 1,
|
||||
text:
|
||||
"The type 'C' is a subtype of 'A', and 'C' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_extends_outside() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
base class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
sealed class B extends A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
51,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_extends_unordered() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class C extends B {}
|
||||
sealed class B extends A {}
|
||||
base class A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 34, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed class B implements A {}
|
||||
class C implements B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
53,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 29, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_mixin_mixedIn() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base mixin class A {}
|
||||
sealed class B with A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
53,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 35, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_mixin_mixedIn_outside() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
base mixin class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
sealed class B with A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
48,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
mixin B implements A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_on() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
mixin B on A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_sealed_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed mixin B implements A {}
|
||||
mixin C implements B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
53,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 29, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_sealed_on() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed mixin B on A {}
|
||||
mixin C on B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_BASE_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
45,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 29, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -1,572 +0,0 @@
|
|||
// Copyright (c) 2023, 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 '../../generated/test_support.dart';
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(SubtypeOfBaseOrFinalIsNotBaseFinalOrSealedTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class SubtypeOfBaseOrFinalIsNotBaseFinalOrSealedTest
|
||||
extends PubPackageResolutionTest {
|
||||
test_class_base_extends() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
class B extends A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_base_extends_multiple() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
base class B extends A {}
|
||||
class C extends A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
48,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_base_extends_multiple_files() async {
|
||||
await assertErrorsInFile(
|
||||
resourceProvider.convertPath('$testPackageLibPath/a.dart'), r'''
|
||||
base class A {}
|
||||
class B extends A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
await assertErrorsInFile(
|
||||
resourceProvider.convertPath('$testPackageLibPath/c.dart'), r'''
|
||||
import 'a.dart';
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/a.dart', 22, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
class D extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23,
|
||||
1,
|
||||
text:
|
||||
"The type 'D' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/a.dart', 22, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_base_extends_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class B extends A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
25,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_base_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
class B implements A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_base_mixin_mixedIn() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base mixin class A {}
|
||||
class B with A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
28,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_base_mixin_mixedIn_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base mixin class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class B with A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
25,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_base_multiple() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
final class B {}
|
||||
class C extends B implements A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
39,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'B' is 'final'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_final_extends() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
class B extends A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_final_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
class B implements A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_base_extends() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed class B extends A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
50,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 29, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_base_extends_multiple() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed class B extends A {}
|
||||
sealed class C extends B {}
|
||||
class D extends C {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
78,
|
||||
1,
|
||||
text:
|
||||
"The type 'D' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 57, 1,
|
||||
text:
|
||||
"The type 'C' is a subtype of 'A', and 'C' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_base_extends_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
sealed class B extends A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
53,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 32, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_base_extends_unordered() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class C extends B {}
|
||||
sealed class B extends A {}
|
||||
base class A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 34, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_base_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed class B implements A {}
|
||||
class C implements B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
53,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 29, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_base_mixin_mixedIn() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base mixin class A {}
|
||||
sealed class B with A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
53,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 35, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_base_mixin_mixedIn_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base mixin class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
sealed class B with A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
50,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 32, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_final_extends() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
sealed class B extends A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
51,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_final_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
sealed class B implements A {}
|
||||
class C implements B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
54,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_base_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
mixin B implements A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_base_on() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
mixin B on A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
22,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_final_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
mixin B implements A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_final_on() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
mixin B on A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23,
|
||||
1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_sealed_base_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed mixin B implements A {}
|
||||
mixin C implements B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
53,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 29, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_sealed_base_on() async {
|
||||
await assertErrorsInCode(r'''
|
||||
base class A {}
|
||||
sealed mixin B on A {}
|
||||
mixin C on B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
45,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'base'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 29, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_sealed_final_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
sealed mixin B implements A {}
|
||||
mixin C implements B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
54,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_sealed_final_on() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
sealed mixin B on A {}
|
||||
mixin C on B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode
|
||||
.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
46,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage('/home/test/lib/test.dart', 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
// Copyright (c) 2023, 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 '../../generated/test_support.dart';
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(SubtypeOfFinalIsNotBaseFinalOrSealedTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class SubtypeOfFinalIsNotBaseFinalOrSealedTest
|
||||
extends PubPackageResolutionTest {
|
||||
test_class_extends() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
class B extends A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
class B implements A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_outside() async {
|
||||
// No [SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED] reported outside of
|
||||
// library.
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
final class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
class B extends A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 33, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_outside_on() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
final mixin A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
mixin B on A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_extends() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
sealed class B extends A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
51,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_extends_multiple() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
sealed class B extends A {}
|
||||
sealed class C extends B {}
|
||||
class D extends C {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
79,
|
||||
1,
|
||||
text:
|
||||
"The type 'D' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 58, 1,
|
||||
text:
|
||||
"The type 'C' is a subtype of 'A', and 'C' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_extends_outside() async {
|
||||
// No [SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED] reported outside of
|
||||
// library.
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
final class A {}
|
||||
''');
|
||||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'a.dart';
|
||||
sealed class B extends A {}
|
||||
class C extends B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 40, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_extends_unordered() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class C extends B {}
|
||||
sealed class B extends A {}
|
||||
final class A {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
6,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 34, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_sealed_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
sealed class B implements A {}
|
||||
class C implements B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
54,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
mixin B implements A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_on() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
mixin B on A {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
23, 1,
|
||||
text:
|
||||
"The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'."),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_sealed_implements() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
sealed mixin B implements A {}
|
||||
mixin C implements B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
54,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_sealed_on() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final class A {}
|
||||
sealed mixin B on A {}
|
||||
mixin C on B {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.SUBTYPE_OF_FINAL_IS_NOT_BASE_FINAL_OR_SEALED,
|
||||
46,
|
||||
1,
|
||||
text:
|
||||
"The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'A' is 'final'.",
|
||||
contextMessages: [
|
||||
ExpectedContextMessage(testFile.path, 30, 1,
|
||||
text:
|
||||
"The type 'B' is a subtype of 'A', and 'B' is defined here.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -741,9 +741,11 @@ import 'spread_expression_from_deferred_library_test.dart'
|
|||
import 'static_access_to_instance_member_test.dart'
|
||||
as static_access_to_instance_member;
|
||||
import 'strict_raw_type_test.dart' as strict_raw_type;
|
||||
import 'subtype_of_base_or_final_is_not_base_final_or_sealed_test.dart'
|
||||
as subtype_of_base_or_final_is_not_base_final_or_sealed;
|
||||
import 'subtype_of_base_is_not_base_final_or_sealed_test.dart'
|
||||
as subtype_of_base_is_not_base_final_or_sealed;
|
||||
import 'subtype_of_ffi_class_test.dart' as subtype_of_ffi_class;
|
||||
import 'subtype_of_final_is_not_base_final_or_sealed_test.dart'
|
||||
as subtype_of_final_is_not_base_final_or_sealed;
|
||||
import 'subtype_of_sealed_class_test.dart' as subtype_of_sealed_class;
|
||||
import 'subtype_of_struct_class_test.dart' as subtype_of_struct_class;
|
||||
import 'super_formal_parameter_type_is_not_subtype_of_associated_test.dart'
|
||||
|
@ -1353,8 +1355,9 @@ main() {
|
|||
spread_expression_from_deferred_library.main();
|
||||
static_access_to_instance_member.main();
|
||||
strict_raw_type.main();
|
||||
subtype_of_base_or_final_is_not_base_final_or_sealed.main();
|
||||
subtype_of_base_is_not_base_final_or_sealed.main();
|
||||
subtype_of_ffi_class.main();
|
||||
subtype_of_final_is_not_base_final_or_sealed.main();
|
||||
subtype_of_sealed_class.main();
|
||||
subtype_of_struct_class.main();
|
||||
super_formal_parameter_type_is_not_subtype_of_associated.main();
|
||||
|
|
Loading…
Reference in a new issue