blob: 62cbe5f92ad8de29879b74568fad4df5989ed950 [file] [log] [blame]
// Copyright (c) 2017, 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/dart/error/syntactic_errors.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/node_text_expectations.dart';
import '../diagnostics/parser_diagnostics.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AstBuilderTest);
defineReflectiveTests(UpdateNodeTextExpectations);
});
}
@reflectiveTest
class AstBuilderTest extends ParserDiagnosticsTest {
void test_class_abstract_final_base() {
var parseResult = parseStringWithErrors(r'''
/// text
abstract final base class A {}
''');
parseResult.assertErrors([
error(ParserErrorCode.abstractFinalBaseClass, 18, 10),
]);
var node = parseResult.findNode.classDeclaration('class A {}');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
tokens
/// text
abstractKeyword: abstract
baseKeyword: base
finalKeyword: final
classKeyword: class
name: A
leftBracket: {
rightBracket: }
''');
}
void test_class_abstract_final_interface() {
var parseResult = parseStringWithErrors(r'''
/// text
abstract final interface class A {}
''');
parseResult.assertErrors([
error(ParserErrorCode.abstractFinalInterfaceClass, 18, 15),
]);
var node = parseResult.findNode.classDeclaration('class A {}');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
tokens
/// text
abstractKeyword: abstract
interfaceKeyword: interface
finalKeyword: final
classKeyword: class
name: A
leftBracket: {
rightBracket: }
''');
}
void test_class_abstract_sealed() {
var parseResult = parseStringWithErrors(r'''
/// text
abstract sealed class A {}
''');
parseResult.assertErrors([
error(ParserErrorCode.abstractSealedClass, 18, 6),
]);
var node = parseResult.findNode.classDeclaration('class A {}');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
tokens
/// text
abstractKeyword: abstract
sealedKeyword: sealed
classKeyword: class
name: A
leftBracket: {
rightBracket: }
''');
}
void test_class_base() {
var parseResult = parseStringWithErrors(r'''
/// text
base class A {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classDeclaration('class A {}');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
tokens
/// text
baseKeyword: base
classKeyword: class
name: A
leftBracket: {
rightBracket: }
''');
}
void test_class_commentReferences_beforeAbstract() {
var parseResult = parseStringWithErrors(r'''
/** [String] */ abstract class A {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classDeclaration('class A');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
references
CommentReference
expression: SimpleIdentifier
token: String @5
tokens
/** [String] */
offset: 0
abstractKeyword: abstract @16
classKeyword: class @25
name: A @31
leftBracket: { @33
rightBracket: } @34
''', withOffsets: true);
}
void test_class_commentReferences_beforeAnnotation() {
var parseResult = parseStringWithErrors(r'''
/// See [int] and [String]
/// and [Object].
@Annotation
abstract class A {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classDeclaration('class A');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
references
CommentReference
expression: SimpleIdentifier
token: int @9
CommentReference
expression: SimpleIdentifier
token: String @19
CommentReference
expression: SimpleIdentifier
token: Object @36
tokens
/// See [int] and [String]
offset: 0
/// and [Object].
offset: 27
metadata
Annotation
atSign: @ @45
name: SimpleIdentifier
token: Annotation @46
abstractKeyword: abstract @57
classKeyword: class @66
name: A @72
leftBracket: { @74
rightBracket: } @75
''', withOffsets: true);
}
void test_class_commentReferences_complex() {
var parseResult = parseStringWithErrors(r'''
/// This dartdoc comment [should] be ignored
@Annotation
/// This dartdoc comment is [included].
// a non dartdoc comment [inbetween]
/// See [int] and [String] but `not [a]`
/// ```
/// This [code] block should be ignored
/// ```
/// and [Object].
abstract class A {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classDeclaration('class A');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
references
CommentReference
expression: SimpleIdentifier
token: included @86
CommentReference
expression: SimpleIdentifier
token: int @143
CommentReference
expression: SimpleIdentifier
token: String @153
CommentReference
expression: SimpleIdentifier
token: Object @240
tokens
/// This dartdoc comment is [included].
offset: 57
/// See [int] and [String] but `not [a]`
offset: 134
/// ```
offset: 175
/// This [code] block should be ignored
offset: 183
/// ```
offset: 223
/// and [Object].
offset: 231
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 178
length: 4
MdCodeBlockLine
offset: 186
length: 36
MdCodeBlockLine
offset: 226
length: 4
metadata
Annotation
atSign: @ @45
name: SimpleIdentifier
token: Annotation @46
abstractKeyword: abstract @249
classKeyword: class @258
name: A @264
leftBracket: { @266
rightBracket: } @267
''', withOffsets: true);
}
void test_class_constructor_named() {
var parseResult = parseStringWithErrors(r'''
class A {
A.named();
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.constructor('A.named()');
assertParsedNodeText(node, r'''
ConstructorDeclaration
returnType: SimpleIdentifier
token: A
period: .
name: named
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: EmptyFunctionBody
semicolon: ;
''');
}
void test_class_constructor_unnamed() {
var parseResult = parseStringWithErrors(r'''
class A {
A();
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.constructor('A()');
assertParsedNodeText(node, r'''
ConstructorDeclaration
returnType: SimpleIdentifier
token: A
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: EmptyFunctionBody
semicolon: ;
''');
}
void test_class_extendsClause_recordType() {
var parseResult = parseStringWithErrors(r'''
class C extends (int, int) {}
''');
parseResult.assertErrors([
error(ParserErrorCode.expectedNamedTypeExtends, 16, 10),
]);
var node = parseResult.findNode.classDeclaration('class C');
assertParsedNodeText(node, r'''
ClassDeclaration
classKeyword: class @0
name: C @6
leftBracket: { @27
rightBracket: } @28
''', withOffsets: true);
}
void test_class_final() {
var parseResult = parseStringWithErrors(r'''
/// text
final class A {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classDeclaration('class A {}');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
tokens
/// text
finalKeyword: final
classKeyword: class
name: A
leftBracket: {
rightBracket: }
''');
}
void test_class_final_mixin() {
var parseResult = parseStringWithErrors(r'''
final mixin class A {}
''');
parseResult.assertErrors([error(ParserErrorCode.finalMixinClass, 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 {}
''');
parseResult.assertErrors([
error(ParserErrorCode.expectedNamedTypeImplements, 22, 10),
]);
var node = parseResult.findNode.classDeclaration('class C');
assertParsedNodeText(node, r'''
ClassDeclaration
classKeyword: class @0
name: C @6
implementsClause: ImplementsClause
implementsKeyword: implements @8
interfaces
NamedType
name: A @19
NamedType
name: B @34
leftBracket: { @36
rightBracket: } @37
''', withOffsets: true);
}
void test_class_interface() {
var parseResult = parseStringWithErrors(r'''
/// text
interface class A {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classDeclaration('class A {}');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
tokens
/// text
interfaceKeyword: interface
classKeyword: class
name: A
leftBracket: {
rightBracket: }
''');
}
void test_class_interface_mixin() {
var parseResult = parseStringWithErrors(r'''
interface mixin class A {}
''');
parseResult.assertErrors([
error(ParserErrorCode.interfaceMixinClass, 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_mixin() {
var parseResult = parseStringWithErrors(r'''
/// text
mixin class A {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classDeclaration('class A {}');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
tokens
/// text
mixinKeyword: mixin
classKeyword: class
name: A
leftBracket: {
rightBracket: }
''');
}
void test_class_sealed() {
var parseResult = parseStringWithErrors(r'''
/// text
sealed class A {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classDeclaration('class A {}');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
tokens
/// text
sealedKeyword: sealed
classKeyword: class
name: A
leftBracket: {
rightBracket: }
''');
}
void test_class_sealed_abstract() {
var parseResult = parseStringWithErrors(r'''
/// text
sealed abstract class A {}
''');
parseResult.assertErrors([
error(ParserErrorCode.abstractSealedClass, 9, 6),
]);
var node = parseResult.findNode.classDeclaration('class A {}');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
tokens
/// text
abstractKeyword: abstract
sealedKeyword: sealed
classKeyword: class
name: A
leftBracket: {
rightBracket: }
''');
}
void test_class_sealed_mixin() {
var parseResult = parseStringWithErrors(r'''
sealed mixin class A {}
''');
parseResult.assertErrors([error(ParserErrorCode.sealedMixinClass, 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 {}
''');
parseResult.assertErrors([
error(ParserErrorCode.expectedNamedTypeWith, 16, 10),
]);
var node = parseResult.findNode.classDeclaration('class C');
assertParsedNodeText(node, r'''
ClassDeclaration
classKeyword: class
name: C
withClause: WithClause
withKeyword: with
mixinTypes
NamedType
name: A
NamedType
name: B
leftBracket: {
rightBracket: }
''');
}
void test_classAlias_mixin() {
var parseResult = parseStringWithErrors(r'''
mixin M {}
/// text
mixin class A = Object with M;
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classTypeAlias('class A');
assertParsedNodeText(node, r'''
ClassTypeAlias
documentationComment: Comment
tokens
/// text
mixinKeyword: mixin
typedefKeyword: class
name: A
equals: =
superclass: NamedType
name: Object
withClause: WithClause
withKeyword: with
mixinTypes
NamedType
name: M
semicolon: ;
''');
}
void test_classAlias_notNamedType() {
var parseResult = parseStringWithErrors(r'''
class C = A Function() with M;
''');
parseResult.assertErrors([
error(ParserErrorCode.expectedNamedTypeExtends, 10, 12),
]);
var node = parseResult.findNode.classTypeAlias('class');
assertParsedNodeText(node, r'''
ClassTypeAlias
typedefKeyword: class
name: C
equals: =
superclass: NamedType
name: identifier <synthetic>
withClause: WithClause
withKeyword: with
mixinTypes
NamedType
name: M
semicolon: ;
''');
}
void test_classTypeAlias_base() {
var parseResult = parseStringWithErrors(r'''
mixin M {}
/// text
base class A = Object with M;
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classTypeAlias('class A');
assertParsedNodeText(node, r'''
ClassTypeAlias
documentationComment: Comment
tokens
/// text
baseKeyword: base
typedefKeyword: class
name: A
equals: =
superclass: NamedType
name: Object
withClause: WithClause
withKeyword: with
mixinTypes
NamedType
name: M
semicolon: ;
''');
}
void test_classTypeAlias_final() {
var parseResult = parseStringWithErrors(r'''
mixin M {}
/// text
final class A = Object with M;
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classTypeAlias('class A');
assertParsedNodeText(node, r'''
ClassTypeAlias
documentationComment: Comment
tokens
/// text
finalKeyword: final
typedefKeyword: class
name: A
equals: =
superclass: NamedType
name: Object
withClause: WithClause
withKeyword: with
mixinTypes
NamedType
name: M
semicolon: ;
''');
}
void test_classTypeAlias_implementsClause_recordType() {
var parseResult = parseStringWithErrors(r'''
class C = Object with M implements A, (int, int), B;
mixin M {}
''');
parseResult.assertErrors([
error(ParserErrorCode.expectedNamedTypeImplements, 38, 10),
]);
var node = parseResult.findNode.classTypeAlias('class C');
assertParsedNodeText(node, r'''
ClassTypeAlias
typedefKeyword: class @0
name: C @6
equals: = @8
superclass: NamedType
name: Object @10
withClause: WithClause
withKeyword: with @17
mixinTypes
NamedType
name: M @22
implementsClause: ImplementsClause
implementsKeyword: implements @24
interfaces
NamedType
name: A @35
NamedType
name: B @50
semicolon: ; @51
''', withOffsets: true);
}
void test_classTypeAlias_interface() {
var parseResult = parseStringWithErrors(r'''
mixin M {}
/// text
interface class A = Object with M;
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classTypeAlias('class A');
assertParsedNodeText(node, r'''
ClassTypeAlias
documentationComment: Comment
tokens
/// text
interfaceKeyword: interface
typedefKeyword: class
name: A
equals: =
superclass: NamedType
name: Object
withClause: WithClause
withKeyword: with
mixinTypes
NamedType
name: M
semicolon: ;
''');
}
void test_classTypeAlias_sealed() {
var parseResult = parseStringWithErrors(r'''
mixin M {}
/// text
sealed class A = Object with M;
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.classTypeAlias('class A');
assertParsedNodeText(node, r'''
ClassTypeAlias
documentationComment: Comment
tokens
/// text
sealedKeyword: sealed
typedefKeyword: class
name: A
equals: =
superclass: NamedType
name: Object
withClause: WithClause
withKeyword: with
mixinTypes
NamedType
name: M
semicolon: ;
''');
}
void test_classTypeAlias_withClause_recordType() {
var parseResult = parseStringWithErrors(r'''
class C = Object with A, (int, int), B;
''');
parseResult.assertErrors([
error(ParserErrorCode.expectedNamedTypeWith, 25, 10),
]);
var node = parseResult.findNode.classTypeAlias('class C');
assertParsedNodeText(node, r'''
ClassTypeAlias
typedefKeyword: class @0
name: C @6
equals: = @8
superclass: NamedType
name: Object @10
withClause: WithClause
withKeyword: with @17
mixinTypes
NamedType
name: A @22
NamedType
name: B @37
semicolon: ; @38
''', withOffsets: true);
}
void test_constructor_factory_misnamed() {
var parseResult = parseStringWithErrors(r'''
class A {
factory B() => null;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.constructor('B()');
assertParsedNodeText(node, r'''
ConstructorDeclaration
factoryKeyword: factory
returnType: SimpleIdentifier
token: B
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: ExpressionFunctionBody
functionDefinition: =>
expression: NullLiteral
literal: null
semicolon: ;
''');
}
void test_constructor_initilizer_assignmentWithSuperCallAsTarget() {
var parseResult = parseStringWithErrors(r'''
class A {
A() : super() = 0;
}
''');
parseResult.assertErrors([
error(ParserErrorCode.missingAssignableSelector, 18, 7),
error(ParserErrorCode.invalidInitializer, 18, 11),
]);
var node = parseResult.findNode.constructor('A()');
assertParsedNodeText(node, r'''
ConstructorDeclaration
returnType: SimpleIdentifier
token: A
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
separator: :
body: EmptyFunctionBody
semicolon: ;
''');
}
void test_constructor_superParamAndSuperInitializer() {
var parseResult = parseStringWithErrors(r'''
abstract class A {
final String f1;
final int f2;
const A(this.f1, this.f2);
}
class B extends A {
const B(super.f1): super(2);
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.constructor('B(');
assertParsedNodeText(node, r'''
ConstructorDeclaration
constKeyword: const
returnType: SimpleIdentifier
token: B
parameters: FormalParameterList
leftParenthesis: (
parameter: SuperFormalParameter
superKeyword: super
period: .
name: f1
rightParenthesis: )
separator: :
initializers
SuperConstructorInvocation
superKeyword: super
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 2
rightParenthesis: )
body: EmptyFunctionBody
semicolon: ;
''');
}
void test_constructor_wrongName() {
var parseResult = parseStringWithErrors(r'''
class A {
B() : super();
}
''');
parseResult.assertErrors([
error(ParserErrorCode.invalidConstructorName, 12, 1),
]);
var node = parseResult.findNode.constructor('B()');
assertParsedNodeText(node, r'''
ConstructorDeclaration
returnType: SimpleIdentifier
token: B
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
separator: :
initializers
SuperConstructorInvocation
superKeyword: super
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
body: EmptyFunctionBody
semicolon: ;
''');
}
void test_dotShorthand_invocation() {
var parseResult = parseStringWithErrors(r'''
class C {}
void main() {
C c = .new();
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.dotShorthandInvocation('.new()');
assertParsedNodeText(node, r'''
DotShorthandInvocation
period: .
memberName: SimpleIdentifier
token: new
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
isDotShorthand: true
''');
}
void test_dotShorthand_propertyAccess() {
var parseResult = parseStringWithErrors(r'''
enum E { a }
void main() {
E e = .a;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.dotShorthandPropertyAccess('.a');
assertParsedNodeText(node, r'''
DotShorthandPropertyAccess
period: .
propertyName: SimpleIdentifier
token: a
isDotShorthand: true
''');
}
void test_enum_base() {
var parseResult = parseStringWithErrors(r'''
base enum E { v }
''');
parseResult.assertErrors([error(ParserErrorCode.baseEnum, 0, 4)]);
var node = parseResult.findNode.enumDeclaration('enum E');
assertParsedNodeText(node, r'''
EnumDeclaration
enumKeyword: enum
name: E
leftBracket: {
constants
EnumConstantDeclaration
name: v
rightBracket: }
''');
}
void test_enum_constant_name_dot() {
var parseResult = parseStringWithErrors(r'''
enum E {
v.
}
''');
parseResult.assertErrors([
error(ParserErrorCode.missingIdentifier, 14, 1),
error(ParserErrorCode.expectedToken, 14, 1),
]);
var node = parseResult.findNode.enumConstantDeclaration('v.');
assertParsedNodeText(node, r'''
EnumConstantDeclaration
name: v
arguments: EnumConstantArguments
constructorSelector: ConstructorSelector
period: .
name: SimpleIdentifier
token: <empty> <synthetic>
argumentList: ArgumentList
leftParenthesis: ( <synthetic>
rightParenthesis: ) <synthetic>
''');
}
void test_enum_constant_name_dot_identifier_semicolon() {
var parseResult = parseStringWithErrors(r'''
enum E {
v.named;
}
''');
parseResult.assertErrors([error(ParserErrorCode.expectedToken, 13, 5)]);
var node = parseResult.findNode.enumConstantDeclaration('v.');
assertParsedNodeText(node, r'''
EnumConstantDeclaration
name: v
arguments: EnumConstantArguments
constructorSelector: ConstructorSelector
period: .
name: SimpleIdentifier
token: named
argumentList: ArgumentList
leftParenthesis: ( <synthetic>
rightParenthesis: ) <synthetic>
''');
}
void test_enum_constant_name_dot_semicolon() {
var parseResult = parseStringWithErrors(r'''
enum E {
v.;
}
''');
parseResult.assertErrors([
error(ParserErrorCode.expectedToken, 13, 1),
error(ParserErrorCode.missingIdentifier, 13, 1),
]);
var node = parseResult.findNode.enumConstantDeclaration('v.');
assertParsedNodeText(node, r'''
EnumConstantDeclaration
name: v
arguments: EnumConstantArguments
constructorSelector: ConstructorSelector
period: .
name: SimpleIdentifier
token: <empty> <synthetic>
argumentList: ArgumentList
leftParenthesis: ( <synthetic>
rightParenthesis: ) <synthetic>
''');
}
void test_enum_constant_name_typeArguments_dot() {
var parseResult = parseStringWithErrors(r'''
enum E {
v<int>.
}
''');
parseResult.assertErrors([
error(ParserErrorCode.missingIdentifier, 19, 1),
error(ParserErrorCode.expectedToken, 19, 1),
]);
var node = parseResult.findNode.enumConstantDeclaration('v<int>.');
assertParsedNodeText(node, r'''
EnumConstantDeclaration
name: v
arguments: EnumConstantArguments
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
constructorSelector: ConstructorSelector
period: .
name: SimpleIdentifier
token: <empty> <synthetic>
argumentList: ArgumentList
leftParenthesis: ( <synthetic>
rightParenthesis: ) <synthetic>
''');
}
void test_enum_constant_name_typeArguments_dot_semicolon() {
var parseResult = parseStringWithErrors(r'''
enum E {
v<int>.;
}
''');
parseResult.assertErrors([
error(ParserErrorCode.missingIdentifier, 18, 1),
error(ParserErrorCode.expectedToken, 18, 1),
]);
var node = parseResult.findNode.enumConstantDeclaration('v<int>');
assertParsedNodeText(node, r'''
EnumConstantDeclaration
name: v
arguments: EnumConstantArguments
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
constructorSelector: ConstructorSelector
period: .
name: SimpleIdentifier
token: <empty> <synthetic>
argumentList: ArgumentList
leftParenthesis: ( <synthetic>
rightParenthesis: ) <synthetic>
''');
}
void test_enum_constant_withTypeArgumentsWithoutArguments() {
var parseResult = parseStringWithErrors(r'''
enum E<T> {
v<int>;
}
''');
parseResult.assertErrors([error(ParserErrorCode.expectedToken, 19, 1)]);
var node = parseResult.findNode.enumConstantDeclaration('v<int>');
assertParsedNodeText(node, r'''
EnumConstantDeclaration
name: v
arguments: EnumConstantArguments
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: ( <synthetic>
rightParenthesis: ) <synthetic>
''');
}
void test_enum_final() {
var parseResult = parseStringWithErrors(r'''
final enum E { v }
''');
parseResult.assertErrors([error(ParserErrorCode.finalEnum, 0, 5)]);
var node = parseResult.findNode.enumDeclaration('enum E');
assertParsedNodeText(node, r'''
EnumDeclaration
enumKeyword: enum
name: E
leftBracket: {
constants
EnumConstantDeclaration
name: v
rightBracket: }
''');
}
void test_enum_interface() {
var parseResult = parseStringWithErrors(r'''
interface enum E { v }
''');
parseResult.assertErrors([error(ParserErrorCode.interfaceEnum, 0, 9)]);
var node = parseResult.findNode.enumDeclaration('enum E');
assertParsedNodeText(node, r'''
EnumDeclaration
enumKeyword: enum
name: E
leftBracket: {
constants
EnumConstantDeclaration
name: v
rightBracket: }
''');
}
void test_enum_sealed() {
var parseResult = parseStringWithErrors(r'''
sealed enum E { v }
''');
parseResult.assertErrors([error(ParserErrorCode.sealedEnum, 0, 6)]);
var node = parseResult.findNode.enumDeclaration('enum E');
assertParsedNodeText(node, r'''
EnumDeclaration
enumKeyword: enum
name: E
leftBracket: {
constants
EnumConstantDeclaration
name: v
rightBracket: }
''');
}
void test_enum_semicolon_null() {
var parseResult = parseStringWithErrors(r'''
enum E {
v
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.enumDeclaration('enum E');
assertParsedNodeText(node, r'''
EnumDeclaration
enumKeyword: enum
name: E
leftBracket: {
constants
EnumConstantDeclaration
name: v
rightBracket: }
''');
}
void test_enum_semicolon_optional() {
var parseResult = parseStringWithErrors(r'''
enum E {
v;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.enumDeclaration('enum E');
assertParsedNodeText(node, r'''
EnumDeclaration
enumKeyword: enum
name: E
leftBracket: {
constants
EnumConstantDeclaration
name: v
semicolon: ;
rightBracket: }
''');
}
void test_extension_onClause_recordType() {
var parseResult = parseStringWithErrors(r'''
extension E on (int, int) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.extensionDeclaration('extension E');
assertParsedNodeText(node, r'''
ExtensionDeclaration
extensionKeyword: extension @0
name: E @10
onClause: ExtensionOnClause
onKeyword: on @12
extendedType: RecordTypeAnnotation
leftParenthesis: ( @15
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int @16
RecordTypeAnnotationPositionalField
type: NamedType
name: int @21
rightParenthesis: ) @24
leftBracket: { @26
rightBracket: } @27
''', withOffsets: true);
}
void test_getter_sameNameAsClass() {
var parseResult = parseStringWithErrors(r'''
class A {
get A => 0;
}
''');
parseResult.assertErrors([
error(ParserErrorCode.memberWithClassName, 16, 1),
]);
var node = parseResult.findNode.methodDeclaration('get A');
assertParsedNodeText(node, r'''
MethodDeclaration
propertyKeyword: get
name: A
body: ExpressionFunctionBody
functionDefinition: =>
expression: IntegerLiteral
literal: 0
semicolon: ;
''');
}
void test_library_with_name() {
var parseResult = parseStringWithErrors(r'''
library name.and.dots;
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.library('library');
assertParsedNodeText(node, r'''
LibraryDirective
libraryKeyword: library
name2: LibraryIdentifier
components
SimpleIdentifier
token: name
SimpleIdentifier
token: and
SimpleIdentifier
token: dots
semicolon: ;
''');
}
void test_library_without_name() {
var parseResult = parseStringWithErrors(r'''
library;
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.library('library');
assertParsedNodeText(node, r'''
LibraryDirective
libraryKeyword: library
semicolon: ;
''');
}
void test_mixin_base() {
var parseResult = parseStringWithErrors(r'''
/// text
base mixin M {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.mixinDeclaration('mixin M');
assertParsedNodeText(node, r'''
MixinDeclaration
documentationComment: Comment
tokens
/// text
baseKeyword: base
mixinKeyword: mixin
name: M
leftBracket: {
rightBracket: }
''');
}
void test_mixin_final() {
var parseResult = parseStringWithErrors(r'''
final mixin M {}
''');
parseResult.assertErrors([error(ParserErrorCode.finalMixin, 0, 5)]);
var node = parseResult.findNode.mixinDeclaration('mixin M');
assertParsedNodeText(node, r'''
MixinDeclaration
mixinKeyword: mixin
name: M
leftBracket: {
rightBracket: }
''');
}
void test_mixin_implementsClause_recordType() {
var parseResult = parseStringWithErrors(r'''
class C {}
mixin M on C implements A, (int, int), B {}
''');
parseResult.assertErrors([
error(ParserErrorCode.expectedNamedTypeImplements, 38, 10),
]);
var node = parseResult.findNode.mixinDeclaration('mixin M');
assertParsedNodeText(node, r'''
MixinDeclaration
mixinKeyword: mixin @11
name: M @17
onClause: MixinOnClause
onKeyword: on @19
superclassConstraints
NamedType
name: C @22
implementsClause: ImplementsClause
implementsKeyword: implements @24
interfaces
NamedType
name: A @35
NamedType
name: B @50
leftBracket: { @52
rightBracket: } @53
''', withOffsets: true);
}
void test_mixin_interface() {
var parseResult = parseStringWithErrors(r'''
interface mixin M {}
''');
parseResult.assertErrors([error(ParserErrorCode.interfaceMixin, 0, 9)]);
var node = parseResult.findNode.mixinDeclaration('mixin M');
assertParsedNodeText(node, r'''
MixinDeclaration
mixinKeyword: mixin
name: M
leftBracket: {
rightBracket: }
''');
}
void test_mixin_onClause_recordType() {
var parseResult = parseStringWithErrors(r'''
mixin M on A, (int, int), B {}
''');
parseResult.assertErrors([
error(ParserErrorCode.expectedNamedTypeOn, 14, 10),
]);
var node = parseResult.findNode.mixinDeclaration('mixin M');
assertParsedNodeText(node, r'''
MixinDeclaration
mixinKeyword: mixin @0
name: M @6
onClause: MixinOnClause
onKeyword: on @8
superclassConstraints
NamedType
name: A @11
NamedType
name: B @26
leftBracket: { @28
rightBracket: } @29
''', withOffsets: true);
}
void test_mixin_sealed() {
var parseResult = parseStringWithErrors(r'''
sealed mixin M {}
''');
parseResult.assertErrors([error(ParserErrorCode.sealedMixin, 0, 6)]);
var node = parseResult.findNode.mixinDeclaration('mixin M');
assertParsedNodeText(node, r'''
MixinDeclaration
mixinKeyword: mixin
name: M
leftBracket: {
rightBracket: }
''');
}
void test_recordLiteral() {
var parseResult = parseStringWithErrors(r'''
final x = (0, a: 1);
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordLiteral('(0');
assertParsedNodeText(node, r'''
RecordLiteral
leftParenthesis: (
fields
IntegerLiteral
literal: 0
NamedExpression
name: Label
label: SimpleIdentifier
token: a
colon: :
expression: IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
void test_recordLiteral_named_trailingComma() {
var parseResult = parseStringWithErrors(r'''
final x = (0, a: 1,);
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordLiteral('(0');
assertParsedNodeText(node, r'''
RecordLiteral
leftParenthesis: (
fields
IntegerLiteral
literal: 0
NamedExpression
name: Label
label: SimpleIdentifier
token: a
colon: :
expression: IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
void test_recordLiteral_positional_one_trailingComma() {
var parseResult = parseStringWithErrors(r'''
final x = (0,);
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordLiteral('(0');
assertParsedNodeText(node, r'''
RecordLiteral
leftParenthesis: (
fields
IntegerLiteral
literal: 0
rightParenthesis: )
''');
}
void test_recordLiteral_positional_trailingComma() {
var parseResult = parseStringWithErrors(r'''
final x = (0, 1,);
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordLiteral('(0');
assertParsedNodeText(node, r'''
RecordLiteral
leftParenthesis: (
fields
IntegerLiteral
literal: 0
IntegerLiteral
literal: 1
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_empty() {
var parseResult = parseStringWithErrors(r'''
() f() {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('() f');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_mixed() {
var parseResult = parseStringWithErrors(r'''
void f((int, bool, {int a, bool b}) r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
RecordTypeAnnotationPositionalField
type: NamedType
name: bool
namedFields: RecordTypeAnnotationNamedFields
leftBracket: {
fields
RecordTypeAnnotationNamedField
type: NamedType
name: int
name: a
RecordTypeAnnotationNamedField
type: NamedType
name: bool
name: b
rightBracket: }
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_named() {
var parseResult = parseStringWithErrors(r'''
void f(({int a, bool b}) r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('({int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
namedFields: RecordTypeAnnotationNamedFields
leftBracket: {
fields
RecordTypeAnnotationNamedField
type: NamedType
name: int
name: a
RecordTypeAnnotationNamedField
type: NamedType
name: bool
name: b
rightBracket: }
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_named_trailingComma() {
var parseResult = parseStringWithErrors(r'''
void f(({int a, bool b,}) r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('({int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
namedFields: RecordTypeAnnotationNamedFields
leftBracket: {
fields
RecordTypeAnnotationNamedField
type: NamedType
name: int
name: a
RecordTypeAnnotationNamedField
type: NamedType
name: bool
name: b
rightBracket: }
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_nullable() {
var parseResult = parseStringWithErrors(r'''
void f((int, bool)? r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
RecordTypeAnnotationPositionalField
type: NamedType
name: bool
rightParenthesis: )
question: ?
''');
}
void test_recordTypeAnnotation_positional() {
var parseResult = parseStringWithErrors(r'''
void f((int, bool) r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
RecordTypeAnnotationPositionalField
type: NamedType
name: bool
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_positional_one() {
var parseResult = parseStringWithErrors(r'''
void f((int) r) {}
''');
parseResult.assertErrors([
error(ParserErrorCode.recordTypeOnePositionalNoTrailingComma, 11, 1),
]);
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_positional_one_trailingComma() {
var parseResult = parseStringWithErrors(r'''
void f((int, ) r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_positional_trailingComma() {
var parseResult = parseStringWithErrors(r'''
void f((int, bool,) r) {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
RecordTypeAnnotationPositionalField
type: NamedType
name: bool
rightParenthesis: )
''');
}
void test_recordTypeAnnotation_topFunction_returnType_withTypeParameter() {
var parseResult = parseStringWithErrors(r'''
(int, T) f<T>() {}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.recordTypeAnnotation('(int');
assertParsedNodeText(node, r'''
RecordTypeAnnotation
leftParenthesis: (
positionalFields
RecordTypeAnnotationPositionalField
type: NamedType
name: int
RecordTypeAnnotationPositionalField
type: NamedType
name: T
rightParenthesis: )
''');
}
void test_superFormalParameter() {
var parseResult = parseStringWithErrors(r'''
class A {
A(super.a);
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.superFormalParameter('super.a');
assertParsedNodeText(node, r'''
SuperFormalParameter
superKeyword: super
period: .
name: a
''');
}
void test_switchStatement_withPatternCase_whenDisabled() {
var parseResult = parseStringWithErrors(r'''
// @dart = 2.19
void f(Object value) {
switch (value) {
case (int a,) when a == 0:
}
}
''');
parseResult.assertErrors([error(ParserErrorCode.expectedToken, 72, 1)]);
var node = parseResult.findNode.switchCase('case');
assertParsedNodeText(node, r'''
SwitchCase
keyword: case
expression: ParenthesizedExpression
leftParenthesis: (
expression: SimpleIdentifier
token: int
rightParenthesis: )
colon: :
''');
}
}