mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 15:09:04 +00:00
Reland "[analyzer/cfe] Report an error when declaring a mixin class with final, interface, or sealed."
This is a reland of commit f17e9732c5
Original change's description:
> [analyzer/cfe] Report an error when declaring a mixin class with final, interface, or sealed.
>
> Change-Id: Ia1393851dffaab55c31d04d4e81bfae83a7bd67f
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/283126
> Commit-Queue: Kallen Tu <kallentu@google.com>
> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
> Reviewed-by: Johnni Winther <johnniwinther@google.com>
Change-Id: Ic8185f38477b2eeff624ee391868d7260e0ed4cd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/284486
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
This commit is contained in:
parent
d412939c3b
commit
b34f480e0d
|
@ -5296,6 +5296,15 @@ Message _withArgumentsFinalFieldWithoutInitializer(String name) {
|
|||
arguments: {'name': name});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeFinalMixinClass = messageFinalMixinClass;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageFinalMixinClass = const MessageCode("FinalMixinClass",
|
||||
index: 142,
|
||||
problemMessage: r"""A mixin class can't be declared 'final'.""",
|
||||
correctionMessage: r"""Try removing the 'final' keyword.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Template<
|
||||
Message Function(
|
||||
|
@ -6418,6 +6427,16 @@ Message _withArgumentsInterfaceClassExtendedOutsideOfLibrary(String name) {
|
|||
arguments: {'name': name});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeInterfaceMixinClass = messageInterfaceMixinClass;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageInterfaceMixinClass = const MessageCode(
|
||||
"InterfaceMixinClass",
|
||||
index: 143,
|
||||
problemMessage: r"""A mixin class can't be declared 'interface'.""",
|
||||
correctionMessage: r"""Try removing the 'interface' keyword.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Template<
|
||||
Message Function(
|
||||
|
@ -11306,6 +11325,16 @@ Message _withArgumentsSealedClassSubtypeOutsideOfLibrary(String name) {
|
|||
arguments: {'name': name});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeSealedMixinClass = messageSealedMixinClass;
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const MessageCode messageSealedMixinClass = const MessageCode(
|
||||
"SealedMixinClass",
|
||||
index: 144,
|
||||
problemMessage: r"""A mixin class can't be declared 'sealed'.""",
|
||||
correctionMessage: r"""Try removing the 'sealed' keyword.""");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Template<
|
||||
Message Function(
|
||||
|
|
|
@ -568,7 +568,7 @@ class Parser {
|
|||
optional('class', next.next!)) {
|
||||
macroToken = next;
|
||||
next = next.next!;
|
||||
} else if (next.isIdentifier && next.lexeme == 'sealed') {
|
||||
} else if (next.isIdentifier && optional('sealed', next)) {
|
||||
sealedToken = next;
|
||||
if (optional('class', next.next!) || optional('mixin', next.next!)) {
|
||||
next = next.next!;
|
||||
|
@ -579,12 +579,12 @@ class Parser {
|
|||
start = next;
|
||||
next = next.next!.next!;
|
||||
}
|
||||
} else if (next.isIdentifier && next.lexeme == 'base') {
|
||||
} else if (next.isIdentifier && optional('base', next)) {
|
||||
baseToken = next;
|
||||
if (optional('class', next.next!) || optional('mixin', next.next!)) {
|
||||
next = next.next!;
|
||||
}
|
||||
} else if (next.isIdentifier && next.lexeme == 'interface') {
|
||||
} else if (next.isIdentifier && optional('interface', next)) {
|
||||
interfaceToken = next;
|
||||
if (optional('class', next.next!) || optional('mixin', next.next!)) {
|
||||
next = next.next!;
|
||||
|
@ -712,8 +712,6 @@ class Parser {
|
|||
return parseTypedef(keyword);
|
||||
} else if (identical(value, 'mixin')) {
|
||||
if (identical(nextValue, 'class')) {
|
||||
// TODO(kallentu): Error handling for any class modifier here other
|
||||
// than base. Only base mixin classes are allowed.
|
||||
return _handleModifiersForClassDeclaration(
|
||||
start,
|
||||
keyword.next!,
|
||||
|
@ -721,7 +719,7 @@ class Parser {
|
|||
inlineToken,
|
||||
sealedToken,
|
||||
baseToken,
|
||||
/* interfaceToken = */ null,
|
||||
interfaceToken,
|
||||
keyword,
|
||||
directiveState);
|
||||
}
|
||||
|
@ -767,6 +765,19 @@ class Parser {
|
|||
ModifierContext context = new ModifierContext(this);
|
||||
if (mixinToken != null) {
|
||||
context.parseClassModifiers(start, mixinToken);
|
||||
|
||||
// Mixin classes can't have any modifier other than a base modifier.
|
||||
if (context.finalToken != null) {
|
||||
reportRecoverableError(
|
||||
context.finalToken!, codes.messageFinalMixinClass);
|
||||
}
|
||||
if (interfaceToken != null) {
|
||||
reportRecoverableError(
|
||||
interfaceToken, codes.messageInterfaceMixinClass);
|
||||
}
|
||||
if (sealedToken != null) {
|
||||
reportRecoverableError(sealedToken, codes.messageSealedMixinClass);
|
||||
}
|
||||
} else {
|
||||
context.parseClassModifiers(start, classKeyword);
|
||||
}
|
||||
|
|
|
@ -2240,6 +2240,8 @@ ParserErrorCode.FINAL_ENUM:
|
|||
status: needsEvaluation
|
||||
ParserErrorCode.FINAL_METHOD:
|
||||
status: needsEvaluation
|
||||
ParserErrorCode.FINAL_MIXIN_CLASS:
|
||||
status: needsEvaluation
|
||||
ParserErrorCode.FINAL_TYPEDEF:
|
||||
status: needsEvaluation
|
||||
ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR:
|
||||
|
@ -2262,6 +2264,8 @@ ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE:
|
|||
status: needsEvaluation
|
||||
ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH:
|
||||
status: needsEvaluation
|
||||
ParserErrorCode.INTERFACE_MIXIN_CLASS:
|
||||
status: needsEvaluation
|
||||
ParserErrorCode.INVALID_AWAIT_IN_FOR:
|
||||
status: needsEvaluation
|
||||
ParserErrorCode.INVALID_CODE_POINT:
|
||||
|
@ -2448,6 +2452,8 @@ ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY:
|
|||
status: needsEvaluation
|
||||
ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR:
|
||||
status: needsEvaluation
|
||||
ParserErrorCode.SEALED_MIXIN_CLASS:
|
||||
status: needsEvaluation
|
||||
ParserErrorCode.SETTER_CONSTRUCTOR:
|
||||
status: needsEvaluation
|
||||
ParserErrorCode.SETTER_IN_FUNCTION:
|
||||
|
|
|
@ -156,6 +156,9 @@ final fastaAnalyzerErrorCodes = <ErrorCode?>[
|
|||
ParserErrorCode.INVALID_CONSTANT_PATTERN_GENERIC,
|
||||
ParserErrorCode.INVALID_CONSTANT_CONST_PREFIX,
|
||||
ParserErrorCode.INVALID_CONSTANT_PATTERN_BINARY,
|
||||
ParserErrorCode.FINAL_MIXIN_CLASS,
|
||||
ParserErrorCode.INTERFACE_MIXIN_CLASS,
|
||||
ParserErrorCode.SEALED_MIXIN_CLASS,
|
||||
];
|
||||
|
||||
class ParserErrorCode extends ErrorCode {
|
||||
|
@ -820,6 +823,12 @@ class ParserErrorCode extends ErrorCode {
|
|||
correctionMessage: "Try removing the keyword 'final'.",
|
||||
);
|
||||
|
||||
static const ParserErrorCode FINAL_MIXIN_CLASS = ParserErrorCode(
|
||||
'FINAL_MIXIN_CLASS',
|
||||
"A mixin class can't be declared 'final'.",
|
||||
correctionMessage: "Try removing the 'final' keyword.",
|
||||
);
|
||||
|
||||
static const ParserErrorCode FINAL_TYPEDEF = ParserErrorCode(
|
||||
'FINAL_TYPEDEF',
|
||||
"Typedefs can't be declared to be 'final'.",
|
||||
|
@ -897,6 +906,12 @@ class ParserErrorCode extends ErrorCode {
|
|||
"Try removing the initializer, or using a different kind of loop.",
|
||||
);
|
||||
|
||||
static const ParserErrorCode INTERFACE_MIXIN_CLASS = ParserErrorCode(
|
||||
'INTERFACE_MIXIN_CLASS',
|
||||
"A mixin class can't be declared 'interface'.",
|
||||
correctionMessage: "Try removing the 'interface' keyword.",
|
||||
);
|
||||
|
||||
static const ParserErrorCode INVALID_AWAIT_IN_FOR = ParserErrorCode(
|
||||
'INVALID_AWAIT_IN_FOR',
|
||||
"The keyword 'await' isn't allowed for a normal 'for' statement.",
|
||||
|
@ -1544,6 +1559,12 @@ class ParserErrorCode extends ErrorCode {
|
|||
"Try making this a factory constructor, or remove the redirection.",
|
||||
);
|
||||
|
||||
static const ParserErrorCode SEALED_MIXIN_CLASS = ParserErrorCode(
|
||||
'SEALED_MIXIN_CLASS',
|
||||
"A mixin class can't be declared 'sealed'.",
|
||||
correctionMessage: "Try removing the 'sealed' keyword.",
|
||||
);
|
||||
|
||||
static const ParserErrorCode SETTER_CONSTRUCTOR = ParserErrorCode(
|
||||
'SETTER_CONSTRUCTOR',
|
||||
"Constructors can't be a setter.",
|
||||
|
|
|
@ -736,6 +736,7 @@ const List<ErrorCode> errorCodeValues = [
|
|||
ParserErrorCode.FINAL_CONSTRUCTOR,
|
||||
ParserErrorCode.FINAL_ENUM,
|
||||
ParserErrorCode.FINAL_METHOD,
|
||||
ParserErrorCode.FINAL_MIXIN_CLASS,
|
||||
ParserErrorCode.FINAL_TYPEDEF,
|
||||
ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR,
|
||||
ParserErrorCode.GETTER_CONSTRUCTOR,
|
||||
|
@ -747,6 +748,7 @@ const List<ErrorCode> errorCodeValues = [
|
|||
ParserErrorCode.IMPLEMENTS_BEFORE_WITH,
|
||||
ParserErrorCode.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
|
||||
ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH,
|
||||
ParserErrorCode.INTERFACE_MIXIN_CLASS,
|
||||
ParserErrorCode.INVALID_AWAIT_IN_FOR,
|
||||
ParserErrorCode.INVALID_CODE_POINT,
|
||||
ParserErrorCode.INVALID_COMMENT_REFERENCE,
|
||||
|
@ -840,6 +842,7 @@ const List<ErrorCode> errorCodeValues = [
|
|||
ParserErrorCode.RECORD_TYPE_ONE_POSITIONAL_NO_TRAILING_COMMA,
|
||||
ParserErrorCode.REDIRECTING_CONSTRUCTOR_WITH_BODY,
|
||||
ParserErrorCode.REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
|
||||
ParserErrorCode.SEALED_MIXIN_CLASS,
|
||||
ParserErrorCode.SETTER_CONSTRUCTOR,
|
||||
ParserErrorCode.SETTER_IN_FUNCTION,
|
||||
ParserErrorCode.STACK_OVERFLOW,
|
||||
|
|
|
@ -302,6 +302,26 @@ ClassDeclaration
|
|||
''');
|
||||
}
|
||||
|
||||
void test_class_final_mixin() {
|
||||
var parseResult = parseStringWithErrors(r'''
|
||||
final mixin class A {}
|
||||
''');
|
||||
parseResult.assertErrors([
|
||||
error(ParserErrorCode.FINAL_MIXIN_CLASS, 0, 5),
|
||||
]);
|
||||
|
||||
var node = parseResult.findNode.classDeclaration('class A {}');
|
||||
assertParsedNodeText(node, r'''
|
||||
ClassDeclaration
|
||||
finalKeyword: final
|
||||
mixinKeyword: mixin
|
||||
classKeyword: class
|
||||
name: A
|
||||
leftBracket: {
|
||||
rightBracket: }
|
||||
''');
|
||||
}
|
||||
|
||||
void test_class_implementsClause_recordType() {
|
||||
var parseResult = parseStringWithErrors(r'''
|
||||
class C implements A, (int, int), B {}
|
||||
|
@ -374,6 +394,26 @@ ClassDeclaration
|
|||
''');
|
||||
}
|
||||
|
||||
void test_class_interface_mixin() {
|
||||
var parseResult = parseStringWithErrors(r'''
|
||||
interface mixin class A {}
|
||||
''');
|
||||
parseResult.assertErrors([
|
||||
error(ParserErrorCode.INTERFACE_MIXIN_CLASS, 0, 9),
|
||||
]);
|
||||
|
||||
var node = parseResult.findNode.classDeclaration('class A {}');
|
||||
assertParsedNodeText(node, r'''
|
||||
ClassDeclaration
|
||||
interfaceKeyword: interface
|
||||
mixinKeyword: mixin
|
||||
classKeyword: class
|
||||
name: A
|
||||
leftBracket: {
|
||||
rightBracket: }
|
||||
''');
|
||||
}
|
||||
|
||||
void test_class_macro() {
|
||||
var parseResult = parseStringWithErrors(r'''
|
||||
/// text
|
||||
|
@ -458,6 +498,26 @@ ClassDeclaration
|
|||
''');
|
||||
}
|
||||
|
||||
void test_class_sealed_mixin() {
|
||||
var parseResult = parseStringWithErrors(r'''
|
||||
sealed mixin class A {}
|
||||
''');
|
||||
parseResult.assertErrors([
|
||||
error(ParserErrorCode.SEALED_MIXIN_CLASS, 0, 6),
|
||||
]);
|
||||
|
||||
var node = parseResult.findNode.classDeclaration('class A {}');
|
||||
assertParsedNodeText(node, r'''
|
||||
ClassDeclaration
|
||||
sealedKeyword: sealed
|
||||
mixinKeyword: mixin
|
||||
classKeyword: class
|
||||
name: A
|
||||
leftBracket: {
|
||||
rightBracket: }
|
||||
''');
|
||||
}
|
||||
|
||||
void test_class_withClause_recordType() {
|
||||
var parseResult = parseStringWithErrors(r'''
|
||||
class C with A, (int, int), B {}
|
||||
|
|
|
@ -6068,6 +6068,33 @@ CantUseClassAsMixin:
|
|||
lib.dart:
|
||||
class A {}
|
||||
|
||||
FinalMixinClass:
|
||||
index: 142
|
||||
problemMessage: "A mixin class can't be declared 'final'."
|
||||
correctionMessage: "Try removing the 'final' keyword."
|
||||
analyzerCode: ParserErrorCode.FINAL_MIXIN_CLASS
|
||||
experiments: class-modifiers
|
||||
script:
|
||||
- "final mixin class C {}"
|
||||
|
||||
InterfaceMixinClass:
|
||||
index: 143
|
||||
problemMessage: "A mixin class can't be declared 'interface'."
|
||||
correctionMessage: "Try removing the 'interface' keyword."
|
||||
analyzerCode: ParserErrorCode.INTERFACE_MIXIN_CLASS
|
||||
experiments: class-modifiers
|
||||
script:
|
||||
- "interface mixin class C {}"
|
||||
|
||||
SealedMixinClass:
|
||||
index: 144
|
||||
problemMessage: "A mixin class can't be declared 'sealed'."
|
||||
correctionMessage: "Try removing the 'sealed' keyword."
|
||||
analyzerCode: ParserErrorCode.SEALED_MIXIN_CLASS
|
||||
experiments: class-modifiers,sealed-class
|
||||
script:
|
||||
- "sealed mixin class C {}"
|
||||
|
||||
BaseClassImplementedOutsideOfLibrary:
|
||||
problemMessage: "The class '#name' can't be implemented outside of its library because it's a base class."
|
||||
analyzerCode: BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY
|
||||
|
|
|
@ -1 +1 @@
|
|||
--enable-experiment=class-modifiers
|
||||
--enable-experiment=class-modifiers,sealed-class
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// 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.
|
||||
|
||||
final mixin class A {}
|
||||
interface mixin class B {}
|
||||
sealed mixin class C {}
|
|
@ -0,0 +1,37 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:5:1: Error: A mixin class can't be declared 'final'.
|
||||
// Try removing the 'final' keyword.
|
||||
// final mixin class A {}
|
||||
// ^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:6:1: Error: A mixin class can't be declared 'interface'.
|
||||
// Try removing the 'interface' keyword.
|
||||
// interface mixin class B {}
|
||||
// ^^^^^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:7:1: Error: A mixin class can't be declared 'sealed'.
|
||||
// Try removing the 'sealed' keyword.
|
||||
// sealed mixin class C {}
|
||||
// ^^^^^^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
final mixin class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
interface mixin class B extends core::Object {
|
||||
synthetic constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
abstract sealed mixin class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:5:1: Error: A mixin class can't be declared 'final'.
|
||||
// Try removing the 'final' keyword.
|
||||
// final mixin class A {}
|
||||
// ^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:6:1: Error: A mixin class can't be declared 'interface'.
|
||||
// Try removing the 'interface' keyword.
|
||||
// interface mixin class B {}
|
||||
// ^^^^^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:7:1: Error: A mixin class can't be declared 'sealed'.
|
||||
// Try removing the 'sealed' keyword.
|
||||
// sealed mixin class C {}
|
||||
// ^^^^^^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
final mixin class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
interface mixin class B extends core::Object {
|
||||
synthetic constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
abstract sealed mixin class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
final mixin class A {}
|
||||
interface mixin class B {}
|
||||
sealed mixin class C {}
|
|
@ -0,0 +1,37 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:5:1: Error: A mixin class can't be declared 'final'.
|
||||
// Try removing the 'final' keyword.
|
||||
// final mixin class A {}
|
||||
// ^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:6:1: Error: A mixin class can't be declared 'interface'.
|
||||
// Try removing the 'interface' keyword.
|
||||
// interface mixin class B {}
|
||||
// ^^^^^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:7:1: Error: A mixin class can't be declared 'sealed'.
|
||||
// Try removing the 'sealed' keyword.
|
||||
// sealed mixin class C {}
|
||||
// ^^^^^^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
final mixin class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
interface mixin class B extends core::Object {
|
||||
synthetic constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
abstract sealed mixin class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:5:1: Error: A mixin class can't be declared 'final'.
|
||||
// Try removing the 'final' keyword.
|
||||
// final mixin class A {}
|
||||
// ^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:6:1: Error: A mixin class can't be declared 'interface'.
|
||||
// Try removing the 'interface' keyword.
|
||||
// interface mixin class B {}
|
||||
// ^^^^^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:7:1: Error: A mixin class can't be declared 'sealed'.
|
||||
// Try removing the 'sealed' keyword.
|
||||
// sealed mixin class C {}
|
||||
// ^^^^^^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
final mixin class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
interface mixin class B extends core::Object {
|
||||
synthetic constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
abstract sealed mixin class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:5:1: Error: A mixin class can't be declared 'final'.
|
||||
// Try removing the 'final' keyword.
|
||||
// final mixin class A {}
|
||||
// ^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:6:1: Error: A mixin class can't be declared 'interface'.
|
||||
// Try removing the 'interface' keyword.
|
||||
// interface mixin class B {}
|
||||
// ^^^^^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:7:1: Error: A mixin class can't be declared 'sealed'.
|
||||
// Try removing the 'sealed' keyword.
|
||||
// sealed mixin class C {}
|
||||
// ^^^^^^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
final mixin class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
;
|
||||
}
|
||||
interface mixin class B extends core::Object {
|
||||
synthetic constructor •() → self::B
|
||||
;
|
||||
}
|
||||
abstract sealed mixin class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:5:1: Error: A mixin class can't be declared 'final'.
|
||||
// Try removing the 'final' keyword.
|
||||
// final mixin class A {}
|
||||
// ^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:6:1: Error: A mixin class can't be declared 'interface'.
|
||||
// Try removing the 'interface' keyword.
|
||||
// interface mixin class B {}
|
||||
// ^^^^^^^^^
|
||||
//
|
||||
// pkg/front_end/testcases/class_modifiers/mixin/mixin_class_invalid_modifiers.dart:7:1: Error: A mixin class can't be declared 'sealed'.
|
||||
// Try removing the 'sealed' keyword.
|
||||
// sealed mixin class C {}
|
||||
// ^^^^^^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
final mixin class A extends core::Object {
|
||||
synthetic constructor •() → self::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
interface mixin class B extends core::Object {
|
||||
synthetic constructor •() → self::B
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
||||
abstract sealed mixin class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
: super core::Object::•()
|
||||
;
|
||||
}
|
|
@ -26,6 +26,7 @@ class_modifiers/final/final_class_declaration: FormatterCrash
|
|||
class_modifiers/interface/interface_class_declaration: FormatterCrash
|
||||
class_modifiers/mixin/mixin_class_declaration: FormatterCrash
|
||||
class_modifiers/mixin/mixin_class_generative_constructor: FormatterCrash
|
||||
class_modifiers/mixin/mixin_class_invalid_modifiers: FormatterCrash
|
||||
class_modifiers/mixin/mixin_class_superclass_not_object: FormatterCrash
|
||||
const_functions/const_functions_const_ctor: FormatterCrash
|
||||
const_functions/const_functions_const_ctor_error: FormatterCrash
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
// 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.
|
||||
|
||||
// SharedOptions=--enable-experiment=class-modifiers
|
||||
|
||||
// Allow base mixin classes.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
base mixin class BaseMixinClass {
|
||||
int foo = 0;
|
||||
}
|
||||
|
||||
main() {
|
||||
Expect.equals(0, BaseMixinClass().foo);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// 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.
|
||||
|
||||
// SharedOptions=--enable-experiment=class-modifiers,sealed-class
|
||||
|
||||
// Error when applying any other modifier to mixin classes other than base.
|
||||
|
||||
final mixin class A {}
|
||||
// [error column 1, length 5]
|
||||
// [analyzer] SYNTACTIC_ERROR.FINAL_MIXIN_CLASS
|
||||
// [cfe] A mixin class can't be declared 'final'.
|
||||
|
||||
interface mixin class B {}
|
||||
// [error column 1, length 9]
|
||||
// [analyzer] SYNTACTIC_ERROR.INTERFACE_MIXIN_CLASS
|
||||
// [cfe] A mixin class can't be declared 'interface'.
|
||||
|
||||
sealed mixin class C {}
|
||||
// [error column 1, length 6]
|
||||
// [analyzer] SYNTACTIC_ERROR.SEALED_MIXIN_CLASS
|
||||
// [cfe] A mixin class can't be declared 'sealed'.
|
Loading…
Reference in a new issue