mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:58:29 +00:00
Report EXPECTED_NAMED_TYPE_X when not a NamedType is parsed.
Change-Id: Ibebc276777075da12e36642f08291fa9a9f9ac91 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260073 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
959854769c
commit
1aa398d4be
|
@ -2167,6 +2167,14 @@ ParserErrorCode.EXPECTED_INSTEAD:
|
||||||
status: needsEvaluation
|
status: needsEvaluation
|
||||||
ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL:
|
ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL:
|
||||||
status: needsEvaluation
|
status: needsEvaluation
|
||||||
|
ParserErrorCode.EXPECTED_NAMED_TYPE_EXTENDS:
|
||||||
|
status: noFix
|
||||||
|
ParserErrorCode.EXPECTED_NAMED_TYPE_IMPLEMENTS:
|
||||||
|
status: noFix
|
||||||
|
ParserErrorCode.EXPECTED_NAMED_TYPE_ON:
|
||||||
|
status: noFix
|
||||||
|
ParserErrorCode.EXPECTED_NAMED_TYPE_WITH:
|
||||||
|
status: noFix
|
||||||
ParserErrorCode.EXPECTED_STRING_LITERAL:
|
ParserErrorCode.EXPECTED_STRING_LITERAL:
|
||||||
status: needsEvaluation
|
status: needsEvaluation
|
||||||
ParserErrorCode.EXPECTED_TOKEN:
|
ParserErrorCode.EXPECTED_TOKEN:
|
||||||
|
|
|
@ -758,6 +758,10 @@ const List<ErrorCode> errorCodeValues = [
|
||||||
ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD,
|
ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD,
|
||||||
ParserErrorCode.EXPECTED_INSTEAD,
|
ParserErrorCode.EXPECTED_INSTEAD,
|
||||||
ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
|
ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
|
||||||
|
ParserErrorCode.EXPECTED_NAMED_TYPE_EXTENDS,
|
||||||
|
ParserErrorCode.EXPECTED_NAMED_TYPE_IMPLEMENTS,
|
||||||
|
ParserErrorCode.EXPECTED_NAMED_TYPE_ON,
|
||||||
|
ParserErrorCode.EXPECTED_NAMED_TYPE_WITH,
|
||||||
ParserErrorCode.EXPECTED_STRING_LITERAL,
|
ParserErrorCode.EXPECTED_STRING_LITERAL,
|
||||||
ParserErrorCode.EXPECTED_TOKEN,
|
ParserErrorCode.EXPECTED_TOKEN,
|
||||||
ParserErrorCode.EXPECTED_TYPE_NAME,
|
ParserErrorCode.EXPECTED_TYPE_NAME,
|
||||||
|
|
|
@ -506,6 +506,36 @@ class ParserErrorCode extends ErrorCode {
|
||||||
"Try inserting a list or map literal, or remove the type arguments.",
|
"Try inserting a list or map literal, or remove the type arguments.",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static const ParserErrorCode EXPECTED_NAMED_TYPE_EXTENDS = ParserErrorCode(
|
||||||
|
'EXPECTED_NAMED_TYPE',
|
||||||
|
"Expected a class name.",
|
||||||
|
correctionMessage: "Try using a class name, possibly with type arguments.",
|
||||||
|
uniqueName: 'EXPECTED_NAMED_TYPE_EXTENDS',
|
||||||
|
);
|
||||||
|
|
||||||
|
static const ParserErrorCode EXPECTED_NAMED_TYPE_IMPLEMENTS = ParserErrorCode(
|
||||||
|
'EXPECTED_NAMED_TYPE',
|
||||||
|
"Expected the name of a class or mixin.",
|
||||||
|
correctionMessage:
|
||||||
|
"Try using a class or mixin name, possibly with type arguments.",
|
||||||
|
uniqueName: 'EXPECTED_NAMED_TYPE_IMPLEMENTS',
|
||||||
|
);
|
||||||
|
|
||||||
|
static const ParserErrorCode EXPECTED_NAMED_TYPE_ON = ParserErrorCode(
|
||||||
|
'EXPECTED_NAMED_TYPE',
|
||||||
|
"Expected the name of a class or mixin.",
|
||||||
|
correctionMessage:
|
||||||
|
"Try using a class or mixin name, possibly with type arguments.",
|
||||||
|
uniqueName: 'EXPECTED_NAMED_TYPE_ON',
|
||||||
|
);
|
||||||
|
|
||||||
|
static const ParserErrorCode EXPECTED_NAMED_TYPE_WITH = ParserErrorCode(
|
||||||
|
'EXPECTED_NAMED_TYPE',
|
||||||
|
"Expected a mixin name.",
|
||||||
|
correctionMessage: "Try using a mixin name, possibly with type arguments.",
|
||||||
|
uniqueName: 'EXPECTED_NAMED_TYPE_WITH',
|
||||||
|
);
|
||||||
|
|
||||||
static const ParserErrorCode EXPECTED_STRING_LITERAL = ParserErrorCode(
|
static const ParserErrorCode EXPECTED_STRING_LITERAL = ParserErrorCode(
|
||||||
'EXPECTED_STRING_LITERAL',
|
'EXPECTED_STRING_LITERAL',
|
||||||
"Expected a string literal.",
|
"Expected a string literal.",
|
||||||
|
|
|
@ -56,11 +56,13 @@ import 'package:_fe_analyzer_shared/src/scanner/token_constants.dart';
|
||||||
import 'package:analyzer/dart/analysis/features.dart';
|
import 'package:analyzer/dart/analysis/features.dart';
|
||||||
import 'package:analyzer/dart/ast/ast.dart';
|
import 'package:analyzer/dart/ast/ast.dart';
|
||||||
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
|
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
|
||||||
|
import 'package:analyzer/error/error.dart';
|
||||||
import 'package:analyzer/error/listener.dart';
|
import 'package:analyzer/error/listener.dart';
|
||||||
import 'package:analyzer/source/line_info.dart';
|
import 'package:analyzer/source/line_info.dart';
|
||||||
import 'package:analyzer/src/dart/analysis/experiments.dart';
|
import 'package:analyzer/src/dart/analysis/experiments.dart';
|
||||||
import 'package:analyzer/src/dart/ast/ast.dart';
|
import 'package:analyzer/src/dart/ast/ast.dart';
|
||||||
import 'package:analyzer/src/dart/ast/ast_factory.dart';
|
import 'package:analyzer/src/dart/ast/ast_factory.dart';
|
||||||
|
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
|
||||||
import 'package:analyzer/src/fasta/error_converter.dart';
|
import 'package:analyzer/src/fasta/error_converter.dart';
|
||||||
import 'package:analyzer/src/generated/utilities_dart.dart';
|
import 'package:analyzer/src/generated/utilities_dart.dart';
|
||||||
import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
|
import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
|
||||||
|
@ -2381,7 +2383,9 @@ class AstBuilder extends StackListener {
|
||||||
|
|
||||||
ImplementsClauseImpl? implementsClause;
|
ImplementsClauseImpl? implementsClause;
|
||||||
if (implementsKeyword != null) {
|
if (implementsKeyword != null) {
|
||||||
var interfaces = popTypeList();
|
var interfaces = _popNamedTypeList(
|
||||||
|
errorCode: ParserErrorCode.EXPECTED_NAMED_TYPE_IMPLEMENTS,
|
||||||
|
);
|
||||||
implementsClause = ImplementsClauseImpl(
|
implementsClause = ImplementsClauseImpl(
|
||||||
implementsKeyword: implementsKeyword,
|
implementsKeyword: implementsKeyword,
|
||||||
interfaces: interfaces,
|
interfaces: interfaces,
|
||||||
|
@ -3221,12 +3225,16 @@ class AstBuilder extends StackListener {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// TODO(brianwilkerson) Produce a diagnostic indicating that the type
|
|
||||||
// annotation is either missing or an invalid kind. Also, consider
|
|
||||||
// (a) extending `ExtendsClause` to accept any type annotation for
|
|
||||||
// recovery purposes, and (b) extending the parser to parse a generic
|
|
||||||
// function type at this location.
|
|
||||||
push(NullValue.ExtendsClause);
|
push(NullValue.ExtendsClause);
|
||||||
|
// TODO(brianwilkerson) Consider (a) extending `ExtendsClause` to accept
|
||||||
|
// any type annotation for recovery purposes, and (b) extending the
|
||||||
|
// parser to parse a generic function type at this location.
|
||||||
|
if (supertype != null) {
|
||||||
|
errorReporter.errorReporter?.reportErrorForNode(
|
||||||
|
ParserErrorCode.EXPECTED_NAMED_TYPE_EXTENDS,
|
||||||
|
supertype,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3281,7 +3289,9 @@ class AstBuilder extends StackListener {
|
||||||
@override
|
@override
|
||||||
void handleClassWithClause(Token withKeyword) {
|
void handleClassWithClause(Token withKeyword) {
|
||||||
assert(optional('with', withKeyword));
|
assert(optional('with', withKeyword));
|
||||||
var mixinTypes = popTypeList();
|
var mixinTypes = _popNamedTypeList(
|
||||||
|
errorCode: ParserErrorCode.EXPECTED_NAMED_TYPE_WITH,
|
||||||
|
);
|
||||||
push(ast.withClause(withKeyword, mixinTypes));
|
push(ast.withClause(withKeyword, mixinTypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3524,7 +3534,9 @@ class AstBuilder extends StackListener {
|
||||||
@override
|
@override
|
||||||
void handleEnumWithClause(Token withKeyword) {
|
void handleEnumWithClause(Token withKeyword) {
|
||||||
assert(optional('with', withKeyword));
|
assert(optional('with', withKeyword));
|
||||||
var mixinTypes = popTypeList();
|
var mixinTypes = _popNamedTypeList(
|
||||||
|
errorCode: ParserErrorCode.EXPECTED_NAMED_TYPE_WITH,
|
||||||
|
);
|
||||||
push(ast.withClause(withKeyword, mixinTypes));
|
push(ast.withClause(withKeyword, mixinTypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3781,9 +3793,10 @@ class AstBuilder extends StackListener {
|
||||||
debugEvent("Implements");
|
debugEvent("Implements");
|
||||||
|
|
||||||
if (implementsKeyword != null) {
|
if (implementsKeyword != null) {
|
||||||
var types = popTypedList2<TypeAnnotation>(interfacesCount);
|
endTypeList(interfacesCount);
|
||||||
// TODO(brianwilkerson) Report diagnostics for any type that's filtered out.
|
final interfaces = _popNamedTypeList(
|
||||||
var interfaces = types.whereType<NamedType>().toList();
|
errorCode: ParserErrorCode.EXPECTED_NAMED_TYPE_IMPLEMENTS,
|
||||||
|
);
|
||||||
push(
|
push(
|
||||||
ImplementsClauseImpl(
|
ImplementsClauseImpl(
|
||||||
implementsKeyword: implementsKeyword,
|
implementsKeyword: implementsKeyword,
|
||||||
|
@ -4086,9 +4099,10 @@ class AstBuilder extends StackListener {
|
||||||
debugEvent("MixinOn");
|
debugEvent("MixinOn");
|
||||||
|
|
||||||
if (onKeyword != null) {
|
if (onKeyword != null) {
|
||||||
var types = popTypedList2<TypeAnnotation>(typeCount);
|
endTypeList(typeCount);
|
||||||
// TODO(brianwilkerson) Report diagnostics for any type that's filtered out.
|
final onTypes = _popNamedTypeList(
|
||||||
var onTypes = types.whereType<NamedType>().toList();
|
errorCode: ParserErrorCode.EXPECTED_NAMED_TYPE_ON,
|
||||||
|
);
|
||||||
push(ast.onClause(onKeyword, onTypes));
|
push(ast.onClause(onKeyword, onTypes));
|
||||||
} else {
|
} else {
|
||||||
push(NullValue.IdentifierList);
|
push(NullValue.IdentifierList);
|
||||||
|
@ -4116,7 +4130,9 @@ class AstBuilder extends StackListener {
|
||||||
@override
|
@override
|
||||||
void handleNamedMixinApplicationWithClause(Token withKeyword) {
|
void handleNamedMixinApplicationWithClause(Token withKeyword) {
|
||||||
assert(optionalOrNull('with', withKeyword));
|
assert(optionalOrNull('with', withKeyword));
|
||||||
var mixinTypes = popTypeList();
|
var mixinTypes = _popNamedTypeList(
|
||||||
|
errorCode: ParserErrorCode.EXPECTED_NAMED_TYPE_WITH,
|
||||||
|
);
|
||||||
push(ast.withClause(withKeyword, mixinTypes));
|
push(ast.withClause(withKeyword, mixinTypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4676,21 +4692,6 @@ class AstBuilder extends StackListener {
|
||||||
return result.reversed.toList();
|
return result.reversed.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// List<T?>? popTypedList<T>(int count, [List<T>? list]) {
|
|
||||||
// if (count == 0) return null;
|
|
||||||
// assert(stack.length >= count);
|
|
||||||
//
|
|
||||||
// final tailList = list ?? List<T?>.filled(count, null, growable: true);
|
|
||||||
// stack.popList(count, tailList, null);
|
|
||||||
// return tailList;
|
|
||||||
// }
|
|
||||||
|
|
||||||
List<NamedType> popTypeList() {
|
|
||||||
var types = pop() as List<TypeAnnotation>;
|
|
||||||
// TODO(brianwilkerson) Report diagnostics for any type that's filtered out.
|
|
||||||
return types.whereType<NamedType>().toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reportErrorIfNullableType(Token? questionMark) {
|
void reportErrorIfNullableType(Token? questionMark) {
|
||||||
if (questionMark != null) {
|
if (questionMark != null) {
|
||||||
assert(optional('?', questionMark));
|
assert(optional('?', questionMark));
|
||||||
|
@ -4761,6 +4762,21 @@ class AstBuilder extends StackListener {
|
||||||
typeArguments: typeArguments));
|
typeArguments: typeArguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<NamedType> _popNamedTypeList({
|
||||||
|
required ErrorCode errorCode,
|
||||||
|
}) {
|
||||||
|
final types = pop() as List<TypeAnnotation>;
|
||||||
|
final namedTypes = <NamedType>[];
|
||||||
|
for (final type in types) {
|
||||||
|
if (type is NamedType) {
|
||||||
|
namedTypes.add(type);
|
||||||
|
} else {
|
||||||
|
errorReporter.errorReporter?.reportErrorForNode(errorCode, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return namedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
void _reportFeatureNotEnabled({
|
void _reportFeatureNotEnabled({
|
||||||
required ExperimentalFeature feature,
|
required ExperimentalFeature feature,
|
||||||
required Token startToken,
|
required Token startToken,
|
||||||
|
|
|
@ -21892,6 +21892,22 @@ ParserErrorCode:
|
||||||
EXPECTED_LIST_OR_MAP_LITERAL:
|
EXPECTED_LIST_OR_MAP_LITERAL:
|
||||||
problemMessage: Expected a list or map literal.
|
problemMessage: Expected a list or map literal.
|
||||||
correctionMessage: Try inserting a list or map literal, or remove the type arguments.
|
correctionMessage: Try inserting a list or map literal, or remove the type arguments.
|
||||||
|
EXPECTED_NAMED_TYPE_EXTENDS:
|
||||||
|
sharedName: EXPECTED_NAMED_TYPE
|
||||||
|
problemMessage: Expected a class name.
|
||||||
|
correctionMessage: Try using a class name, possibly with type arguments.
|
||||||
|
EXPECTED_NAMED_TYPE_IMPLEMENTS:
|
||||||
|
sharedName: EXPECTED_NAMED_TYPE
|
||||||
|
problemMessage: Expected the name of a class or mixin.
|
||||||
|
correctionMessage: Try using a class or mixin name, possibly with type arguments.
|
||||||
|
EXPECTED_NAMED_TYPE_ON:
|
||||||
|
sharedName: EXPECTED_NAMED_TYPE
|
||||||
|
problemMessage: Expected the name of a class or mixin.
|
||||||
|
correctionMessage: Try using a class or mixin name, possibly with type arguments.
|
||||||
|
EXPECTED_NAMED_TYPE_WITH:
|
||||||
|
sharedName: EXPECTED_NAMED_TYPE
|
||||||
|
problemMessage: Expected a mixin name.
|
||||||
|
correctionMessage: Try using a mixin name, possibly with type arguments.
|
||||||
EXPECTED_STRING_LITERAL:
|
EXPECTED_STRING_LITERAL:
|
||||||
problemMessage: Expected a string literal.
|
problemMessage: Expected a string literal.
|
||||||
EXPECTED_TOKEN:
|
EXPECTED_TOKEN:
|
||||||
|
|
|
@ -213,7 +213,9 @@ ConstructorDeclaration
|
||||||
var parseResult = parseStringWithErrors(r'''
|
var parseResult = parseStringWithErrors(r'''
|
||||||
class C extends (int, int) {}
|
class C extends (int, int) {}
|
||||||
''');
|
''');
|
||||||
parseResult.assertNoErrors();
|
parseResult.assertErrors([
|
||||||
|
error(ParserErrorCode.EXPECTED_NAMED_TYPE_EXTENDS, 16, 10),
|
||||||
|
]);
|
||||||
|
|
||||||
final node = parseResult.findNode.classDeclaration('class C');
|
final node = parseResult.findNode.classDeclaration('class C');
|
||||||
assertParsedNodeText(
|
assertParsedNodeText(
|
||||||
|
@ -230,9 +232,11 @@ ClassDeclaration
|
||||||
|
|
||||||
void test_class_implementsClause_recordType() {
|
void test_class_implementsClause_recordType() {
|
||||||
var parseResult = parseStringWithErrors(r'''
|
var parseResult = parseStringWithErrors(r'''
|
||||||
class C implements (int, int) {}
|
class C implements A, (int, int), B {}
|
||||||
''');
|
''');
|
||||||
parseResult.assertNoErrors();
|
parseResult.assertErrors([
|
||||||
|
error(ParserErrorCode.EXPECTED_NAMED_TYPE_IMPLEMENTS, 22, 10),
|
||||||
|
]);
|
||||||
|
|
||||||
final node = parseResult.findNode.classDeclaration('class C');
|
final node = parseResult.findNode.classDeclaration('class C');
|
||||||
assertParsedNodeText(
|
assertParsedNodeText(
|
||||||
|
@ -243,8 +247,15 @@ ClassDeclaration
|
||||||
name: C @6
|
name: C @6
|
||||||
implementsClause: ImplementsClause
|
implementsClause: ImplementsClause
|
||||||
implementsKeyword: implements @8
|
implementsKeyword: implements @8
|
||||||
leftBracket: { @30
|
interfaces
|
||||||
rightBracket: } @31
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: A @19
|
||||||
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: B @34
|
||||||
|
leftBracket: { @36
|
||||||
|
rightBracket: } @37
|
||||||
''',
|
''',
|
||||||
withOffsets: true);
|
withOffsets: true);
|
||||||
}
|
}
|
||||||
|
@ -268,23 +279,29 @@ ClassDeclaration
|
||||||
|
|
||||||
void test_class_withClause_recordType() {
|
void test_class_withClause_recordType() {
|
||||||
var parseResult = parseStringWithErrors(r'''
|
var parseResult = parseStringWithErrors(r'''
|
||||||
class C with (int, int) {}
|
class C with A, (int, int), B {}
|
||||||
''');
|
''');
|
||||||
parseResult.assertNoErrors();
|
parseResult.assertErrors([
|
||||||
|
error(ParserErrorCode.EXPECTED_NAMED_TYPE_WITH, 16, 10),
|
||||||
|
]);
|
||||||
|
|
||||||
final node = parseResult.findNode.classDeclaration('class C');
|
final node = parseResult.findNode.classDeclaration('class C');
|
||||||
assertParsedNodeText(
|
assertParsedNodeText(node, r'''
|
||||||
node,
|
|
||||||
r'''
|
|
||||||
ClassDeclaration
|
ClassDeclaration
|
||||||
classKeyword: class @0
|
classKeyword: class
|
||||||
name: C @6
|
name: C
|
||||||
withClause: WithClause
|
withClause: WithClause
|
||||||
withKeyword: with @8
|
withKeyword: with
|
||||||
leftBracket: { @24
|
mixinTypes
|
||||||
rightBracket: } @25
|
NamedType
|
||||||
''',
|
name: SimpleIdentifier
|
||||||
withOffsets: true);
|
token: A
|
||||||
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: B
|
||||||
|
leftBracket: {
|
||||||
|
rightBracket: }
|
||||||
|
''');
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_classAlias_macro() {
|
void test_classAlias_macro() {
|
||||||
|
@ -316,10 +333,12 @@ ClassTypeAlias
|
||||||
|
|
||||||
void test_classTypeAlias_implementsClause_recordType() {
|
void test_classTypeAlias_implementsClause_recordType() {
|
||||||
var parseResult = parseStringWithErrors(r'''
|
var parseResult = parseStringWithErrors(r'''
|
||||||
class C = Object with M implements (int, int);
|
class C = Object with M implements A, (int, int), B;
|
||||||
mixin M {}
|
mixin M {}
|
||||||
''');
|
''');
|
||||||
parseResult.assertNoErrors();
|
parseResult.assertErrors([
|
||||||
|
error(ParserErrorCode.EXPECTED_NAMED_TYPE_IMPLEMENTS, 38, 10),
|
||||||
|
]);
|
||||||
|
|
||||||
final node = parseResult.findNode.classTypeAlias('class C');
|
final node = parseResult.findNode.classTypeAlias('class C');
|
||||||
assertParsedNodeText(
|
assertParsedNodeText(
|
||||||
|
@ -340,16 +359,25 @@ ClassTypeAlias
|
||||||
token: M @22
|
token: M @22
|
||||||
implementsClause: ImplementsClause
|
implementsClause: ImplementsClause
|
||||||
implementsKeyword: implements @24
|
implementsKeyword: implements @24
|
||||||
semicolon: ; @45
|
interfaces
|
||||||
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: A @35
|
||||||
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: B @50
|
||||||
|
semicolon: ; @51
|
||||||
''',
|
''',
|
||||||
withOffsets: true);
|
withOffsets: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_classTypeAlias_withClause_recordType() {
|
void test_classTypeAlias_withClause_recordType() {
|
||||||
var parseResult = parseStringWithErrors(r'''
|
var parseResult = parseStringWithErrors(r'''
|
||||||
class C = Object with (int, int);
|
class C = Object with A, (int, int), B;
|
||||||
''');
|
''');
|
||||||
parseResult.assertNoErrors();
|
parseResult.assertErrors([
|
||||||
|
error(ParserErrorCode.EXPECTED_NAMED_TYPE_WITH, 25, 10),
|
||||||
|
]);
|
||||||
|
|
||||||
final node = parseResult.findNode.classTypeAlias('class C');
|
final node = parseResult.findNode.classTypeAlias('class C');
|
||||||
assertParsedNodeText(
|
assertParsedNodeText(
|
||||||
|
@ -364,7 +392,14 @@ ClassTypeAlias
|
||||||
token: Object @10
|
token: Object @10
|
||||||
withClause: WithClause
|
withClause: WithClause
|
||||||
withKeyword: with @17
|
withKeyword: with @17
|
||||||
semicolon: ; @32
|
mixinTypes
|
||||||
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: A @22
|
||||||
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: B @37
|
||||||
|
semicolon: ; @38
|
||||||
''',
|
''',
|
||||||
withOffsets: true);
|
withOffsets: true);
|
||||||
}
|
}
|
||||||
|
@ -716,9 +751,11 @@ LibraryAugmentationDirective
|
||||||
void test_mixin_implementsClause_recordType() {
|
void test_mixin_implementsClause_recordType() {
|
||||||
var parseResult = parseStringWithErrors(r'''
|
var parseResult = parseStringWithErrors(r'''
|
||||||
class C {}
|
class C {}
|
||||||
mixin M on C implements (int, int) {}
|
mixin M on C implements A, (int, int), B {}
|
||||||
''');
|
''');
|
||||||
parseResult.assertNoErrors();
|
parseResult.assertErrors([
|
||||||
|
error(ParserErrorCode.EXPECTED_NAMED_TYPE_IMPLEMENTS, 38, 10),
|
||||||
|
]);
|
||||||
|
|
||||||
final node = parseResult.findNode.mixinDeclaration('mixin M');
|
final node = parseResult.findNode.mixinDeclaration('mixin M');
|
||||||
assertParsedNodeText(
|
assertParsedNodeText(
|
||||||
|
@ -735,17 +772,26 @@ MixinDeclaration
|
||||||
token: C @22
|
token: C @22
|
||||||
implementsClause: ImplementsClause
|
implementsClause: ImplementsClause
|
||||||
implementsKeyword: implements @24
|
implementsKeyword: implements @24
|
||||||
leftBracket: { @46
|
interfaces
|
||||||
rightBracket: } @47
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: A @35
|
||||||
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: B @50
|
||||||
|
leftBracket: { @52
|
||||||
|
rightBracket: } @53
|
||||||
''',
|
''',
|
||||||
withOffsets: true);
|
withOffsets: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_mixin_onClause_recordType() {
|
void test_mixin_onClause_recordType() {
|
||||||
var parseResult = parseStringWithErrors(r'''
|
var parseResult = parseStringWithErrors(r'''
|
||||||
mixin M on (int, int) {}
|
mixin M on A, (int, int), B {}
|
||||||
''');
|
''');
|
||||||
parseResult.assertNoErrors();
|
parseResult.assertErrors([
|
||||||
|
error(ParserErrorCode.EXPECTED_NAMED_TYPE_ON, 14, 10),
|
||||||
|
]);
|
||||||
|
|
||||||
final node = parseResult.findNode.mixinDeclaration('mixin M');
|
final node = parseResult.findNode.mixinDeclaration('mixin M');
|
||||||
assertParsedNodeText(
|
assertParsedNodeText(
|
||||||
|
@ -756,8 +802,15 @@ MixinDeclaration
|
||||||
name: M @6
|
name: M @6
|
||||||
onClause: OnClause
|
onClause: OnClause
|
||||||
onKeyword: on @8
|
onKeyword: on @8
|
||||||
leftBracket: { @22
|
superclassConstraints
|
||||||
rightBracket: } @23
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: A @11
|
||||||
|
NamedType
|
||||||
|
name: SimpleIdentifier
|
||||||
|
token: B @26
|
||||||
|
leftBracket: { @28
|
||||||
|
rightBracket: } @29
|
||||||
''',
|
''',
|
||||||
withOffsets: true);
|
withOffsets: true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue