[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:
Kallen Tu 2023-03-01 19:01:59 +00:00 committed by Commit Queue
parent 8627463c23
commit 4f6ccd9fee
20 changed files with 888 additions and 250 deletions

View file

@ -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.

View file

@ -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

View 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;
}
}

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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 {}
''');
}
}

View file

@ -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 {}
''');
}
}

View file

@ -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 {}
''');
}
}

View file

@ -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 {}
''');
}
}

View file

@ -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 {}
''');
}
}

View file

@ -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 {}

View file

@ -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.")
],
),
]);
}
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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