mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 13:08:10 +00:00
[analyzer] Report an error when a subtype of a base or final type is not base, final or sealed.
Change-Id: Ie9c943e6ce7d3b1c746ccd4ee3757886dd619c5f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/285441 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Kallen Tu <kallentu@google.com>
This commit is contained in:
parent
8627463c23
commit
4f6ccd9fee
|
@ -1055,6 +1055,8 @@ 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:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED:
|
||||
status: hasFix
|
||||
since: 2.17
|
||||
|
@ -2862,4 +2864,4 @@ WarningCode.UNUSED_RESULT:
|
|||
WarningCode.UNUSED_RESULT_WITH_MESSAGE:
|
||||
status: noFix
|
||||
notes: |-
|
||||
There is no predictable common way in which a result _should_ be used.
|
||||
There is no predictable common way in which a result _should_ be used.
|
||||
|
|
|
@ -73,10 +73,10 @@ class ErrorReporter {
|
|||
/// Report an error with the given [errorCode] and [arguments]. The [element]
|
||||
/// is used to compute the location of the error.
|
||||
void reportErrorForElement(ErrorCode errorCode, Element element,
|
||||
[List<Object>? arguments]) {
|
||||
[List<Object>? arguments, List<DiagnosticMessage>? messages]) {
|
||||
var nonSynthetic = element.nonSynthetic;
|
||||
reportErrorForOffset(
|
||||
errorCode, nonSynthetic.nameOffset, nonSynthetic.nameLength, arguments);
|
||||
reportErrorForOffset(errorCode, nonSynthetic.nameOffset,
|
||||
nonSynthetic.nameLength, arguments, messages);
|
||||
}
|
||||
|
||||
/// Report a diagnostic with the given [code] and [arguments]. The
|
||||
|
|
128
pkg/analyzer/lib/src/error/base_or_final_type_verifier.dart
Normal file
128
pkg/analyzer/lib/src/error/base_or_final_type_verifier.dart
Normal file
|
@ -0,0 +1,128 @@
|
|||
// 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/dart/ast/token.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/diagnostic/diagnostic.dart';
|
||||
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.
|
||||
class BaseOrFinalTypeVerifier {
|
||||
final LibraryElement _definingLibrary;
|
||||
final ErrorReporter _errorReporter;
|
||||
|
||||
/// Maps an element to a base or final superelement.
|
||||
/// May be null if the type does not have one.
|
||||
final Map<ClassOrMixinElementImpl, ClassOrMixinElementImpl?>
|
||||
_elementToBaseOrFinalSuperElement = {};
|
||||
|
||||
BaseOrFinalTypeVerifier({
|
||||
required LibraryElement definingLibrary,
|
||||
required ErrorReporter errorReporter,
|
||||
}) : _definingLibrary = definingLibrary,
|
||||
_errorReporter = errorReporter;
|
||||
|
||||
/// 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]
|
||||
void checkElement(ClassOrMixinElementImpl element) {
|
||||
if (_elementToBaseOrFinalSuperElement.containsKey(element)) {
|
||||
// We've already visited this element. Don't check it again.
|
||||
return;
|
||||
} else {
|
||||
_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);
|
||||
}
|
||||
|
||||
for (final supertype in supertypes) {
|
||||
final supertypeElement = supertype.element;
|
||||
if (supertypeElement is ClassOrMixinElementImpl) {
|
||||
// Ensure that all superelements are properly cached in
|
||||
// [_elementToBaseOrFinalSuperElement].
|
||||
checkElement(supertypeElement);
|
||||
|
||||
// Return early if an error has been reported to prevent reporting
|
||||
// multiple errors on one element.
|
||||
if (_reportRestrictionError(element, supertypeElement)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if a element modifier restriction error has been reported.
|
||||
///
|
||||
/// Reports an error based on the modifier of the superElement.
|
||||
bool _reportRestrictionError(
|
||||
ClassOrMixinElementImpl element, ClassOrMixinElementImpl superElement) {
|
||||
final cachedBaseOrFinalSuperElement =
|
||||
_elementToBaseOrFinalSuperElement[superElement];
|
||||
final hasCachedBaseOrFinalSuperElement =
|
||||
cachedBaseOrFinalSuperElement != null;
|
||||
ClassOrMixinElementImpl? baseOrFinalSuperElement;
|
||||
|
||||
if (superElement.isBase || superElement.isFinal) {
|
||||
// Prefer the direct base or final superelement.
|
||||
baseOrFinalSuperElement = superElement;
|
||||
} else if (hasCachedBaseOrFinalSuperElement) {
|
||||
// There's a base or final element higher up in the class hierarchy.
|
||||
// The superelement is a sealed element.
|
||||
baseOrFinalSuperElement = cachedBaseOrFinalSuperElement;
|
||||
} else {
|
||||
// There are no restrictions on this element's modifiers.
|
||||
return false;
|
||||
}
|
||||
|
||||
_elementToBaseOrFinalSuperElement[element] = baseOrFinalSuperElement;
|
||||
|
||||
if (element.library != _definingLibrary) {
|
||||
// Only report errors on elements within the current library.
|
||||
return false;
|
||||
}
|
||||
if (!element.isBase && !element.isFinal && !element.isSealed) {
|
||||
final contextMessage = <DiagnosticMessage>[
|
||||
DiagnosticMessageImpl(
|
||||
filePath: superElement.source.fullName,
|
||||
length: superElement.nameLength,
|
||||
message: "The type '${superElement.name}' is a subtype of "
|
||||
"'${baseOrFinalSuperElement.name}', and "
|
||||
"'${superElement.name}' is defined here.",
|
||||
offset: superElement.nameOffset,
|
||||
url: null,
|
||||
)
|
||||
];
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -4422,6 +4422,18 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
|||
hasPublishedDocs: true,
|
||||
);
|
||||
|
||||
/// 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
|
||||
static const CompileTimeErrorCode
|
||||
SUBTYPE_OF_BASE_OR_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 '{2}'.",
|
||||
);
|
||||
|
||||
/// Parameters:
|
||||
/// 0: the type of super-parameter
|
||||
/// 1: the type of associated super-constructor parameter
|
||||
|
|
|
@ -448,6 +448,7 @@ 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.SUPER_FORMAL_PARAMETER_TYPE_IS_NOT_SUBTYPE_OF_ASSOCIATED,
|
||||
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_NAMED,
|
||||
CompileTimeErrorCode.SUPER_FORMAL_PARAMETER_WITHOUT_ASSOCIATED_POSITIONAL,
|
||||
|
|
|
@ -74,6 +74,7 @@ import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
|
|||
import 'package:analyzer/src/dart/resolver/variable_declaration_resolver.dart';
|
||||
import 'package:analyzer/src/dart/resolver/yield_statement_resolver.dart';
|
||||
import 'package:analyzer/src/diagnostic/diagnostic.dart';
|
||||
import 'package:analyzer/src/error/base_or_final_type_verifier.dart';
|
||||
import 'package:analyzer/src/error/bool_expression_verifier.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:analyzer/src/error/dead_code_verifier.dart';
|
||||
|
@ -204,6 +205,10 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
|
|||
|
||||
final MigrationResolutionHooks? migrationResolutionHooks;
|
||||
|
||||
/// Helper for checking that subtypes of a base or final type must be base,
|
||||
/// final, or sealed.
|
||||
late final BaseOrFinalTypeVerifier baseOrFinalTypeVerifier;
|
||||
|
||||
/// Helper for checking expression that should have the `bool` type.
|
||||
late final BoolExpressionVerifier boolExpressionVerifier;
|
||||
|
||||
|
@ -374,6 +379,8 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
|
|||
errorReporter: errorReporter,
|
||||
resolver: this,
|
||||
);
|
||||
baseOrFinalTypeVerifier = BaseOrFinalTypeVerifier(
|
||||
definingLibrary: definingLibrary, errorReporter: errorReporter);
|
||||
boolExpressionVerifier = BoolExpressionVerifier(
|
||||
resolver: this,
|
||||
errorReporter: errorReporter,
|
||||
|
@ -2034,6 +2041,9 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
|
|||
} finally {
|
||||
enclosingClass = outerType;
|
||||
}
|
||||
|
||||
baseOrFinalTypeVerifier
|
||||
.checkElement(node.declaredElement as ClassOrMixinElementImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -2959,6 +2969,9 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
|
|||
} finally {
|
||||
enclosingClass = outerType;
|
||||
}
|
||||
|
||||
baseOrFinalTypeVerifier
|
||||
.checkElement(node.declaredElement as ClassOrMixinElementImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -12890,6 +12890,13 @@ 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}'."
|
||||
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
|
||||
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.
|
||||
|
@ -23644,4 +23651,4 @@ WarningCode:
|
|||
|
||||
Parameters:
|
||||
0: the name of the annotated method, property or function
|
||||
1: message details
|
||||
1: message details
|
||||
|
|
|
@ -19,7 +19,7 @@ class BaseClassImplementedOutsideOfLibraryTest
|
|||
test_class_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
base class Foo {}
|
||||
class Bar implements Foo {}
|
||||
base class Bar implements Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,9 @@ base class Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar implements Foo {}
|
||||
base class Bar implements Foo {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 45,
|
||||
3),
|
||||
]);
|
||||
}
|
||||
|
@ -45,9 +45,9 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar implements FooTypedef {}
|
||||
base class Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 45,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
@ -60,25 +60,13 @@ base class Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
class Bar implements FooTypedef {}
|
||||
base class Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 71,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_subtypeOfBase_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base class Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar2 implements Bar {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_enum_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
base class Foo {}
|
||||
|
@ -130,22 +118,10 @@ enum Bar implements FooTypedef { bar }
|
|||
]);
|
||||
}
|
||||
|
||||
test_enum_subtypeOfBase_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base class Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
enum Bar2 implements Bar { bar }
|
||||
''');
|
||||
}
|
||||
|
||||
test_mixin_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
base class Foo {}
|
||||
mixin Bar implements Foo {}
|
||||
base mixin Bar implements Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -156,9 +132,9 @@ base class Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar implements Foo {}
|
||||
base mixin Bar implements Foo {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 45,
|
||||
3),
|
||||
]);
|
||||
}
|
||||
|
@ -171,9 +147,9 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar implements FooTypedef {}
|
||||
base mixin Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 45,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
@ -186,22 +162,10 @@ base class Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
mixin Bar implements FooTypedef {}
|
||||
base mixin Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
|
||||
error(CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 71,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_subtypeOfBase_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base class Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar2 implements Bar {}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class BaseMixinImplementedOutsideOfLibraryTest
|
|||
test_class_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
base mixin Foo {}
|
||||
class Bar implements Foo {}
|
||||
base class Bar implements Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,9 @@ base mixin Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar implements Foo {}
|
||||
base class Bar implements Foo {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 45,
|
||||
3),
|
||||
]);
|
||||
}
|
||||
|
@ -45,9 +45,9 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar implements FooTypedef {}
|
||||
base class Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 45,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
@ -60,25 +60,13 @@ base mixin Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
class Bar implements FooTypedef {}
|
||||
base class Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 71,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_subtypeOfBase_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base mixin Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar2 implements Bar {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_enum_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
base mixin Foo {}
|
||||
|
@ -130,22 +118,10 @@ enum Bar implements FooTypedef { bar }
|
|||
]);
|
||||
}
|
||||
|
||||
test_enum_subtypeOfBase_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base mixin Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
enum Bar2 implements Bar { bar }
|
||||
''');
|
||||
}
|
||||
|
||||
test_mixin_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
base mixin Foo {}
|
||||
mixin Bar implements Foo {}
|
||||
base mixin Bar implements Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -156,9 +132,9 @@ base mixin Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar implements Foo {}
|
||||
base mixin Bar implements Foo {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 45,
|
||||
3),
|
||||
]);
|
||||
}
|
||||
|
@ -171,9 +147,9 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar implements FooTypedef {}
|
||||
base mixin Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 45,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
@ -186,22 +162,10 @@ base mixin Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
mixin Bar implements FooTypedef {}
|
||||
base mixin Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
|
||||
error(CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 71,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_subtypeOfBase_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
base mixin Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar2 implements Bar {}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class FinalClassExtendedOutsideOfLibraryTest extends PubPackageResolutionTest {
|
|||
test_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
final class Foo {}
|
||||
class Bar extends Foo {}
|
||||
final class Bar extends Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,10 @@ final class Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar extends Foo {}
|
||||
final class Bar extends Foo {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 37, 3),
|
||||
CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 43, 3),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -44,10 +44,10 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar extends FooTypedef {}
|
||||
final class Bar extends FooTypedef {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 37, 10),
|
||||
CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 43, 10),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -59,22 +59,10 @@ final class Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
class Bar extends FooTypedef {}
|
||||
final class Bar extends FooTypedef {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 63, 10),
|
||||
CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 69, 10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_subtypeOfBase_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
final class Foo {}
|
||||
class Bar extends Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar2 extends Bar {}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class FinalClassImplementedOutsideOfLibraryTest
|
|||
test_class_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
final class Foo {}
|
||||
class Bar implements Foo {}
|
||||
final class Bar implements Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,9 @@ final class Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar implements Foo {}
|
||||
final class Bar implements Foo {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 46,
|
||||
3),
|
||||
]);
|
||||
}
|
||||
|
@ -45,9 +45,9 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar implements FooTypedef {}
|
||||
final class Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 46,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
@ -60,25 +60,13 @@ final class Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
class Bar implements FooTypedef {}
|
||||
final class Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 72,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_subtypeOfFinal_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
final class Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar2 implements Bar {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_enum_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
final class Foo {}
|
||||
|
@ -145,7 +133,7 @@ enum Bar2 implements Bar { bar }
|
|||
test_mixin_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
final class Foo {}
|
||||
mixin Bar implements Foo {}
|
||||
final mixin Bar implements Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -156,9 +144,9 @@ final class Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar implements Foo {}
|
||||
final mixin Bar implements Foo {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 46,
|
||||
3),
|
||||
]);
|
||||
}
|
||||
|
@ -171,9 +159,9 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar implements FooTypedef {}
|
||||
final mixin Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 46,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
@ -186,22 +174,10 @@ final class Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
mixin Bar implements FooTypedef {}
|
||||
final mixin Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
|
||||
error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 72,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_subtypeOfFinal_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
final class Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar2 implements Bar {}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class FinalMixinImplementedOutsideOfLibraryTest
|
|||
test_class_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
final mixin Foo {}
|
||||
class Bar implements Foo {}
|
||||
final class Bar implements Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,9 @@ final mixin Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar implements Foo {}
|
||||
final class Bar implements Foo {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 46,
|
||||
3),
|
||||
]);
|
||||
}
|
||||
|
@ -45,9 +45,9 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar implements FooTypedef {}
|
||||
final class Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 46,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
@ -60,25 +60,13 @@ final mixin Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
class Bar implements FooTypedef {}
|
||||
final class Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 72,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_subtypeOfFinal_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
final mixin Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar2 implements Bar {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_enum_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
final mixin Foo {}
|
||||
|
@ -145,7 +133,7 @@ enum Bar2 implements Bar { bar }
|
|||
test_mixin_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
final mixin Foo {}
|
||||
mixin Bar implements Foo {}
|
||||
final mixin Bar implements Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -156,9 +144,9 @@ final mixin Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar implements Foo {}
|
||||
final mixin Bar implements Foo {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 46,
|
||||
3),
|
||||
]);
|
||||
}
|
||||
|
@ -171,9 +159,9 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar implements FooTypedef {}
|
||||
final mixin Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 46,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
@ -186,22 +174,10 @@ final mixin Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
mixin Bar implements FooTypedef {}
|
||||
final mixin Bar implements FooTypedef {}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
|
||||
error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 72,
|
||||
10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mixin_subtypeOfFinal_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
final mixin Foo {}
|
||||
class Bar implements Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
mixin Bar2 implements Bar {}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class FinalMixinMixedInOutsideOfLibraryTest extends PubPackageResolutionTest {
|
|||
test_class_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
final mixin Foo {}
|
||||
class Bar with Foo {}
|
||||
final class Bar with Foo {}
|
||||
''');
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,10 @@ final mixin Foo {}
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar with Foo {}
|
||||
final class Bar with Foo {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 34, 3),
|
||||
CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 40, 3),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -44,10 +44,10 @@ typedef FooTypedef = Foo;
|
|||
|
||||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar with FooTypedef {}
|
||||
final class Bar with FooTypedef {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 34, 10),
|
||||
CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 40, 10),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -59,25 +59,13 @@ final mixin Foo {}
|
|||
await assertErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
typedef FooTypedef = Foo;
|
||||
class Bar with FooTypedef {}
|
||||
final class Bar with FooTypedef {}
|
||||
''', [
|
||||
error(
|
||||
CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 60, 10),
|
||||
CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 66, 10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_class_subtypeOfBase_outside() async {
|
||||
newFile('$testPackageLibPath/foo.dart', r'''
|
||||
final mixin Foo {}
|
||||
class Bar with Foo {}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'foo.dart';
|
||||
class Bar2 extends Bar {}
|
||||
''');
|
||||
}
|
||||
|
||||
test_enum_inside() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
final mixin Foo {}
|
||||
|
|
|
@ -0,0 +1,570 @@
|
|||
// 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('$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('$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.")
|
||||
],
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -741,6 +741,8 @@ 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_ffi_class_test.dart' as subtype_of_ffi_class;
|
||||
import 'subtype_of_sealed_class_test.dart' as subtype_of_sealed_class;
|
||||
import 'subtype_of_struct_class_test.dart' as subtype_of_struct_class;
|
||||
|
@ -1351,6 +1353,7 @@ 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_ffi_class.main();
|
||||
subtype_of_sealed_class.main();
|
||||
subtype_of_struct_class.main();
|
||||
|
|
|
@ -79,7 +79,7 @@ class CollectingReporter extends ErrorReporter {
|
|||
|
||||
@override
|
||||
void reportErrorForElement(ErrorCode errorCode, Element element,
|
||||
[List<Object?>? arguments]) {
|
||||
[List<Object?>? arguments, List<DiagnosticMessage>? messages]) {
|
||||
code = errorCode;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
import 'base_class_extend_lib.dart';
|
||||
|
||||
abstract class AOutside extends BaseClass {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class BOutside extends BaseClass {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
|
|
@ -2,35 +2,58 @@
|
|||
// 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.
|
||||
|
||||
// SharedOptions=--enable-experiment=class-modifiers
|
||||
// SharedOptions=--enable-experiment=class-modifiers,sealed-class
|
||||
|
||||
// Error when subtyping a base class where the subtype is not base, final or
|
||||
// sealed.
|
||||
|
||||
base class BaseClass {}
|
||||
base mixin BaseMixin {}
|
||||
final class FinalClass extends BaseClass {}
|
||||
sealed class SubtypeOfBase extends BaseClass {}
|
||||
class RegularClass {}
|
||||
|
||||
class Extends extends BaseClass {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class Implements implements BaseClass {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
mixin MixinImplements implements BaseMixin {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class With with BaseMixin {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
mixin On on BaseClass {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class ExtendsExtends extends Extends {}
|
||||
// ^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class Multiple extends FinalClass implements BaseMixin {}
|
||||
// ^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class Multiple2 extends RegularClass implements BaseClass {}
|
||||
// ^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class IndirectSubtype extends SubtypeOfBase {}
|
||||
// ^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
import 'base_mixin_with_lib.dart';
|
||||
|
||||
abstract class AOutside with BaseMixin {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class BOutside with BaseMixin {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
|
|
@ -2,35 +2,58 @@
|
|||
// 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.
|
||||
|
||||
// SharedOptions=--enable-experiment=class-modifiers
|
||||
// SharedOptions=--enable-experiment=class-modifiers,sealed-class
|
||||
|
||||
// Error when subtyping a final class where the subtype is not base, final or
|
||||
// sealed.
|
||||
|
||||
final class FinalClass {}
|
||||
final mixin FinalMixin {}
|
||||
base class BaseClass extends FinalClass {}
|
||||
sealed class SubtypeOfFinal extends FinalClass {}
|
||||
class RegularClass {}
|
||||
|
||||
class Extends extends FinalClass {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class Implements implements FinalClass {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
mixin MixinImplements implements FinalMixin {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class With with FinalMixin {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
mixin On on FinalClass {}
|
||||
// ^
|
||||
// [analyzer] unspecified
|
||||
// ^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class ExtendsExtends extends Extends {}
|
||||
// ^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class Multiple extends BaseClass implements FinalMixin {}
|
||||
// ^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class Multiple2 extends RegularClass implements FinalClass {}
|
||||
// ^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
||||
class IndirectSubtype extends SubtypeOfFinal {}
|
||||
// ^^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_BASE_OR_FINAL_IS_NOT_BASE_FINAL_OR_SEALED
|
||||
// [cfe] unspecified
|
||||
|
|
Loading…
Reference in a new issue