mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 12:48:10 +00:00
[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>
This commit is contained in:
parent
71bbeddf00
commit
f17e9732c5
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -2247,6 +2247,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:
|
||||
|
@ -2269,6 +2271,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:
|
||||
|
@ -2455,6 +2459,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.",
|
||||
|
|
|
@ -742,6 +742,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,
|
||||
|
@ -753,6 +754,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,
|
||||
|
@ -846,6 +848,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,
|
||||
|
|
|
@ -284,6 +284,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 {}
|
||||
|
@ -348,6 +368,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'''
|
||||
macro class A {}
|
||||
|
@ -419,6 +459,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
|
||||
|
@ -6458,4 +6485,4 @@ PatternAssignmentNotLocalVariable:
|
|||
var global;
|
||||
method(x) {
|
||||
[global] = x;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,6 @@
|
|||
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