DeCo. Build PrimaryConstructorBody.

Bug: https://github.com/dart-lang/sdk/issues/61701
Change-Id: I8ad2dc544c6a91092e266ae52697c78ee57bc306
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/460884
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Konstantin Shcheglov
2025-11-11 09:04:41 -08:00
committed by Commit Queue
parent 1e6debf40f
commit 3c522839cf
25 changed files with 565 additions and 8 deletions
@@ -105,6 +105,8 @@ class BindToField extends ResolvedCorrectionProducer {
ConstructorDeclaration() => false,
FieldDeclaration() => false,
MethodDeclaration() => member.name.lexeme == parameter.name?.lexeme,
// ignore: experimental_member_use
PrimaryConstructorBody() => false,
},
)) {
return;
@@ -160,6 +160,8 @@ class CreateMethod extends ResolvedCorrectionProducer {
fields: VariableDeclarationList(:var isLate),
) =>
isStatic || !isLate,
// ignore: experimental_member_use
PrimaryConstructorBody() => false,
};
}
} else {
+14 -1
View File
@@ -247,6 +247,7 @@ package:analyzer/analysis_rule/rule_visitor_registry.dart:
addPostfixExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
addPrefixExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
addPrefixedIdentifier (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
addPrimaryConstructorBody (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>), experimental)
addPrimaryConstructorDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>), experimental)
addPrimaryConstructorName (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>), experimental)
addPropertyAccess (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
@@ -771,6 +772,7 @@ package:analyzer/dart/ast/ast.dart:
visitPostfixExpression (method: R? Function(PostfixExpression))
visitPrefixExpression (method: R? Function(PrefixExpression))
visitPrefixedIdentifier (method: R? Function(PrefixedIdentifier))
visitPrimaryConstructorBody (method: R? Function(PrimaryConstructorBody), experimental)
visitPrimaryConstructorDeclaration (method: R? Function(PrimaryConstructorDeclaration), experimental)
visitPrimaryConstructorName (method: R? Function(PrimaryConstructorName), experimental)
visitPropertyAccess (method: R? Function(PropertyAccess))
@@ -893,7 +895,7 @@ package:analyzer/dart/ast/ast.dart:
sealedKeyword (getter: Token?)
typeParameters (getter: TypeParameterList?)
withClause (getter: WithClause?)
ClassMember (class extends Object implements Declaration, sealed (immediate subtypes: ClassMemberImpl, ConstructorDeclaration, FieldDeclaration, MethodDeclaration))
ClassMember (class extends Object implements Declaration, sealed (immediate subtypes: ClassMemberImpl, ConstructorDeclaration, FieldDeclaration, MethodDeclaration, PrimaryConstructorBody))
ClassNamePart (class extends Object implements AstNode, sealed (immediate subtypes: ClassNamePartImpl, NameWithTypeParameters, PrimaryConstructorDeclaration), experimental):
typeName (getter: Token)
typeParameters (getter: TypeParameterList?)
@@ -1555,6 +1557,11 @@ package:analyzer/dart/ast/ast.dart:
isDeferred (getter: bool)
period (getter: Token)
prefix (getter: SimpleIdentifier)
PrimaryConstructorBody (class extends Object implements ClassMember, experimental):
body (getter: FunctionBody)
colon (getter: Token?)
initializers (getter: NodeList<ConstructorInitializer>)
thisKeyword (getter: Token)
PrimaryConstructorDeclaration (class extends Object implements ClassNamePart, experimental):
constKeyword (getter: Token?)
constructorName (getter: PrimaryConstructorName?)
@@ -2343,6 +2350,7 @@ package:analyzer/dart/ast/visitor.dart:
visitPostfixExpression (method: R? Function(PostfixExpression))
visitPrefixExpression (method: R? Function(PrefixExpression))
visitPrefixedIdentifier (method: R? Function(PrefixedIdentifier))
visitPrimaryConstructorBody (method: R? Function(PrimaryConstructorBody), experimental)
visitPrimaryConstructorDeclaration (method: R? Function(PrimaryConstructorDeclaration), experimental)
visitPrimaryConstructorName (method: R? Function(PrimaryConstructorName), experimental)
visitPropertyAccess (method: R? Function(PropertyAccess))
@@ -2534,6 +2542,7 @@ package:analyzer/dart/ast/visitor.dart:
visitPostfixExpression (method: R? Function(PostfixExpression))
visitPrefixExpression (method: R? Function(PrefixExpression))
visitPrefixedIdentifier (method: R? Function(PrefixedIdentifier))
visitPrimaryConstructorBody (method: R? Function(PrimaryConstructorBody), experimental)
visitPrimaryConstructorDeclaration (method: R? Function(PrimaryConstructorDeclaration), experimental)
visitPrimaryConstructorName (method: R? Function(PrimaryConstructorName), experimental)
visitPropertyAccess (method: R? Function(PropertyAccess))
@@ -2715,6 +2724,7 @@ package:analyzer/dart/ast/visitor.dart:
visitPostfixExpression (method: R? Function(PostfixExpression))
visitPrefixExpression (method: R? Function(PrefixExpression))
visitPrefixedIdentifier (method: R? Function(PrefixedIdentifier))
visitPrimaryConstructorBody (method: R? Function(PrimaryConstructorBody), experimental)
visitPrimaryConstructorDeclaration (method: R? Function(PrimaryConstructorDeclaration), experimental)
visitPrimaryConstructorName (method: R? Function(PrimaryConstructorName), experimental)
visitPropertyAccess (method: R? Function(PropertyAccess))
@@ -2896,6 +2906,7 @@ package:analyzer/dart/ast/visitor.dart:
visitPostfixExpression (method: R? Function(PostfixExpression))
visitPrefixExpression (method: R? Function(PrefixExpression))
visitPrefixedIdentifier (method: R? Function(PrefixedIdentifier))
visitPrimaryConstructorBody (method: R? Function(PrimaryConstructorBody), experimental)
visitPrimaryConstructorDeclaration (method: R? Function(PrimaryConstructorDeclaration), experimental)
visitPrimaryConstructorName (method: R? Function(PrimaryConstructorName), experimental)
visitPropertyAccess (method: R? Function(PropertyAccess))
@@ -3078,6 +3089,7 @@ package:analyzer/dart/ast/visitor.dart:
visitPostfixExpression (method: T? Function(PostfixExpression))
visitPrefixExpression (method: T? Function(PrefixExpression))
visitPrefixedIdentifier (method: T? Function(PrefixedIdentifier))
visitPrimaryConstructorBody (method: T? Function(PrimaryConstructorBody), experimental)
visitPrimaryConstructorDeclaration (method: T? Function(PrimaryConstructorDeclaration), experimental)
visitPrimaryConstructorName (method: T? Function(PrimaryConstructorName), experimental)
visitPropertyAccess (method: T? Function(PropertyAccess))
@@ -3260,6 +3272,7 @@ package:analyzer/dart/ast/visitor.dart:
visitPostfixExpression (method: R? Function(PostfixExpression))
visitPrefixExpression (method: R? Function(PrefixExpression))
visitPrefixedIdentifier (method: R? Function(PrefixedIdentifier))
visitPrimaryConstructorBody (method: R? Function(PrimaryConstructorBody), experimental)
visitPrimaryConstructorDeclaration (method: R? Function(PrimaryConstructorDeclaration), experimental)
visitPrimaryConstructorName (method: R? Function(PrimaryConstructorName), experimental)
visitPropertyAccess (method: R? Function(PropertyAccess))
@@ -335,6 +335,9 @@ abstract class RuleVisitorRegistry {
void addPrefixExpression(AbstractAnalysisRule rule, AstVisitor visitor);
@experimental
void addPrimaryConstructorBody(AbstractAnalysisRule rule, AstVisitor visitor);
@experimental
void addPrimaryConstructorDeclaration(
AbstractAnalysisRule rule,
+1
View File
@@ -203,6 +203,7 @@ export 'package:analyzer/src/dart/ast/ast.dart'
PostfixExpression,
PrefixedIdentifier,
PrefixExpression,
PrimaryConstructorBody,
PrimaryConstructorDeclaration,
PrimaryConstructorName,
PropertyAccess,
+34
View File
@@ -535,6 +535,11 @@ class GeneralizingAstVisitor<R> implements AstVisitor<R> {
@override
R? visitPrefixExpression(PrefixExpression node) => visitExpression(node);
@experimental
@override
R? visitPrimaryConstructorBody(PrimaryConstructorBody node) =>
visitClassMember(node);
@experimental
@override
R? visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) =>
@@ -1529,6 +1534,13 @@ class RecursiveAstVisitor<R> implements AstVisitor<R> {
return null;
}
@experimental
@override
R? visitPrimaryConstructorBody(PrimaryConstructorBody node) {
node.visitChildren(this);
return null;
}
@experimental
@override
R? visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) {
@@ -2245,6 +2257,10 @@ class SimpleAstVisitor<R> implements AstVisitor<R> {
@override
R? visitPrefixExpression(PrefixExpression node) => null;
@experimental
@override
R? visitPrimaryConstructorBody(PrimaryConstructorBody node) => null;
@experimental
@override
R? visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) =>
@@ -2825,6 +2841,10 @@ class ThrowingAstVisitor<R> implements AstVisitor<R> {
@override
R? visitPrefixExpression(PrefixExpression node) => _throw(node);
@experimental
@override
R? visitPrimaryConstructorBody(PrimaryConstructorBody node) => _throw(node);
@experimental
@override
R? visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) =>
@@ -4054,6 +4074,15 @@ class TimedAstVisitor<T> implements AstVisitor<T> {
return result;
}
@experimental
@override
T? visitPrimaryConstructorBody(PrimaryConstructorBody node) {
stopwatch.start();
T? result = _baseVisitor.visitPrimaryConstructorBody(node);
stopwatch.stop();
return result;
}
@experimental
@override
T? visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) {
@@ -4901,6 +4930,11 @@ class UnifyingAstVisitor<R> implements AstVisitor<R> {
@override
R? visitPrefixExpression(PrefixExpression node) => visitNode(node);
@experimental
@override
R? visitPrimaryConstructorBody(PrimaryConstructorBody node) =>
visitNode(node);
@experimental
@override
R? visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) =>
@@ -24,6 +24,7 @@ class _UnitApiSignatureComputer {
static const int _kindConstructorDeclaration = 1;
static const int _kindFieldDeclaration = 2;
static const int _kindMethodDeclaration = 3;
static const int _kindPrimaryConstructorBody = 4;
static const int _nullNode = 0;
static const int _notNullNode = 1;
static const int _nullToken = 0;
@@ -89,6 +90,8 @@ class _UnitApiSignatureComputer {
_addFieldDeclaration(member, hasConstConstructor);
} else if (member is MethodDeclaration) {
_addMethodDeclaration(member);
} else if (member is PrimaryConstructorBody) {
_addPrimaryConstructorBody(member);
} else {
throw UnimplementedError('(${member.runtimeType}) $member');
}
@@ -188,6 +191,11 @@ class _UnitApiSignatureComputer {
}
}
void _addPrimaryConstructorBody(PrimaryConstructorBody node) {
signature.addInt(_kindPrimaryConstructorBody);
_addTokens(node.beginToken, node.body.beginToken);
}
void _addToken(Token? token) {
if (token != null) {
signature.addInt(_notNullToken);
+120
View File
@@ -20035,6 +20035,126 @@ final class PrefixExpressionImpl extends ExpressionImpl
}
}
/// The body of a primary constructor.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
@experimental
// TODO(scheglov): This should not be a `Declaration`.
abstract final class PrimaryConstructorBody implements ClassMember {
/// The body of the constructor.
FunctionBody get body;
/// The token for the separator before [initializers], or `null` if there
/// are no initializers.
Token? get colon;
/// The initializers associated with the constructor.
NodeList<ConstructorInitializer> get initializers;
/// The token for the `this` keyword.
Token get thisKeyword;
}
@GenerateNodeImpl(
childEntitiesOrder: [
GenerateNodeProperty('thisKeyword'),
GenerateNodeProperty('colon'),
GenerateNodeProperty('initializers'),
GenerateNodeProperty('body'),
],
)
final class PrimaryConstructorBodyImpl extends ClassMemberImpl
implements PrimaryConstructorBody {
@generated
@override
final Token thisKeyword;
@generated
@override
final Token? colon;
@generated
@override
final NodeListImpl<ConstructorInitializerImpl> initializers =
NodeListImpl._();
@generated
FunctionBodyImpl _body;
@generated
PrimaryConstructorBodyImpl({
required super.comment,
required super.metadata,
required this.thisKeyword,
required this.colon,
required List<ConstructorInitializerImpl> initializers,
required FunctionBodyImpl body,
}) : _body = body {
this.initializers._initialize(this, initializers);
_becomeParentOf(body);
}
@generated
@override
FunctionBodyImpl get body => _body;
@generated
set body(FunctionBodyImpl body) {
_body = _becomeParentOf(body);
}
@generated
@override
Token get endToken {
return body.endToken;
}
@generated
@override
Token get firstTokenAfterCommentAndMetadata {
return thisKeyword;
}
@generated
@override
ChildEntities get _childEntities => super._childEntities
..addToken('thisKeyword', thisKeyword)
..addToken('colon', colon)
..addNodeList('initializers', initializers)
..addNode('body', body);
@generated
@override
E? accept<E>(AstVisitor<E> visitor) =>
visitor.visitPrimaryConstructorBody(this);
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@generated
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
initializers.accept(visitor);
body.accept(visitor);
}
@generated
@override
AstNodeImpl? _childContainingRange(int rangeOffset, int rangeEnd) {
if (super._childContainingRange(rangeOffset, rangeEnd) case var result?) {
return result;
}
if (initializers._elementContainingRange(rangeOffset, rangeEnd)
case var result?) {
return result;
}
if (body._containsOffset(rangeOffset, rangeEnd)) {
return body;
}
return null;
}
}
/// The declaration of a primary constructor.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
@experimental
+3
View File
@@ -287,6 +287,9 @@ abstract class AstVisitor<R> {
R? visitPrefixExpression(PrefixExpression node);
@experimental
R? visitPrimaryConstructorBody(PrimaryConstructorBody node);
@experimental
R? visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node);
@@ -1151,6 +1151,17 @@ class ToSourceVisitor implements AstVisitor<void> {
_writeOperand(node, node.operand);
}
@override
void visitPrimaryConstructorBody(PrimaryConstructorBody node) {
_visitNodeList(node.metadata, separator: ' ', suffix: ' ');
_visitToken(node.thisKeyword);
if (node.initializers.isNotEmpty) {
_visitToken(node.colon, prefix: ' ', suffix: ' ');
_visitNodeList(node.initializers, separator: ', ');
}
_visitFunctionBody(node.body);
}
@override
void visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) {
_visitToken(node.constKeyword, suffix: ' ');
@@ -477,6 +477,9 @@ class MemberDuplicateDefinitionVerifier {
_checkValuesDeclarationInEnum(member.name);
}
}
case PrimaryConstructorBodyImpl():
// TODO(scheglov): Handle this case.
throw UnimplementedError();
}
}
+16 -7
View File
@@ -3167,15 +3167,24 @@ class AstBuilder extends StackListener {
Token? beginInitializers,
Token endToken,
) {
// TODO(declaring-constructors): Implement primary constructor body.
// ignore: unused_local_variable
var bodyObject = pop();
// ignore: unused_local_variable
assert(optional('this', beginToken));
var body = pop() as FunctionBodyImpl;
var initializers = (pop() as List<ConstructorInitializerImpl>?) ?? const [];
// ignore: unused_local_variable
var separator = pop() as Token?;
// ignore: unused_local_variable
var colon = pop() as Token?;
var metadata = pop() as List<AnnotationImpl>?;
var comment = _findComment(metadata, beginToken);
_classLikeBuilder!.members.add(
PrimaryConstructorBodyImpl(
comment: comment,
metadata: metadata,
thisKeyword: beginToken,
colon: colon,
initializers: initializers,
body: body,
),
);
}
@override
@@ -804,6 +804,13 @@ class AnalysisRuleVisitor implements AstVisitor<void> {
node.visitChildren(this);
}
@experimental
@override
void visitPrimaryConstructorBody(PrimaryConstructorBody node) {
_runSubscriptions(node, _registry._forPrimaryConstructorBody);
node.visitChildren(this);
}
@experimental
@override
void visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) {
@@ -1462,6 +1469,9 @@ class RuleVisitorRegistryImpl implements RuleVisitorRegistry {
final List<_Subscription<PrefixExpression>> _forPrefixExpression = [];
final List<_Subscription<PrimaryConstructorBody>> _forPrimaryConstructorBody =
[];
final List<_Subscription<PrimaryConstructorDeclaration>>
_forPrimaryConstructorDeclaration = [];
@@ -2356,6 +2366,16 @@ class RuleVisitorRegistryImpl implements RuleVisitorRegistry {
_forPrefixExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
}
@override
void addPrimaryConstructorBody(
AbstractAnalysisRule rule,
AstVisitor visitor,
) {
_forPrimaryConstructorBody.add(
_Subscription(rule, visitor, _getTimer(rule)),
);
}
@override
void addPrimaryConstructorDeclaration(
AbstractAnalysisRule rule,
@@ -156,6 +156,8 @@ class FindNode {
PrefixExpression get singlePrefixExpression => _single();
PrimaryConstructorBody get singlePrimaryConstructorBody => _single();
PropertyAccess get singlePropertyAccess => _single();
RecordLiteral get singleRecordLiteral => _single();
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/analysis/unlinked_api_signature.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -17,6 +19,10 @@ main() {
@reflectiveTest
class UnitApiSignatureTest {
void tearDown() {
useDeclaringConstructorsAst = default_useDeclaringConstructorsAst;
}
test_class_annotation() async {
_assertNotSameSignature(
r'''
@@ -503,6 +509,57 @@ abstract class C {}
);
}
test_class_primaryConstructorBody_body() {
useDeclaringConstructorsAst = true;
_assertSameSignature(
r'''
class C() {
this { 0; }
}
''',
r'''
class C() {
this { 1; }
}
''',
);
}
test_class_primaryConstructorBody_initializer_const() {
useDeclaringConstructorsAst = true;
_assertNotSameSignature(
r'''
class const C() {
final int f;
this: f = 1;
}
''',
r'''
class const C() {
final int f;
this: f = 2;
}
''',
);
}
test_class_primaryConstructorBody_metadata() {
useDeclaringConstructorsAst = true;
_assertNotSameSignature(
r'''
class C() {
this;
}
''',
r'''
class C() {
@deprecated
this;
}
''',
);
}
test_class_with() {
_assertNotSameSignature(
r'''
@@ -3953,6 +3953,48 @@ class ToSourceVisitorTest_declaringConstructors extends ToSourceVisitorTest {
var findNode = _parseStringToFindNode(code);
_assertSource(code, findNode.extensionTypeDeclaration(code));
}
void test_visitPrimaryConstructorBody_block() {
var code = 'this {foo();}';
var findNode = _parseStringToFindNode('''
class A() {
$code
}
''');
_assertSource(code, findNode.singlePrimaryConstructorBody);
}
void test_visitPrimaryConstructorBody_initializers() {
var code = 'this : x = 0, y = 1;';
var findNode = _parseStringToFindNode('''
class A() {
final int x;
final int y;
$code
}
''');
_assertSource(code, findNode.singlePrimaryConstructorBody);
}
void test_visitPrimaryConstructorBody_metadata() {
var code = '@deprecated this;';
var findNode = _parseStringToFindNode('''
class A() {
$code
}
''');
_assertSource(code, findNode.singlePrimaryConstructorBody);
}
void test_visitPrimaryConstructorBody_simple() {
var code = 'this;';
var findNode = _parseStringToFindNode('''
class A() {
$code
}
''');
_assertSource(code, findNode.singlePrimaryConstructorBody);
}
}
@reflectiveTest
@@ -1156,6 +1156,108 @@ ClassDeclaration
''');
}
test_primaryConstructorBody_body_blockFunctionBody() {
useDeclaringConstructorsAst = true;
var parseResult = parseStringWithErrors(r'''
class A() {
this {
0;
}
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singlePrimaryConstructorBody;
assertParsedNodeText(node, r'''
PrimaryConstructorBody
thisKeyword: this
body: BlockFunctionBody
block: Block
leftBracket: {
statements
ExpressionStatement
expression: IntegerLiteral
literal: 0
semicolon: ;
rightBracket: }
''');
}
test_primaryConstructorBody_comment() {
useDeclaringConstructorsAst = true;
var parseResult = parseStringWithErrors(r'''
class A() {
/// foo
/// bar
this;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singlePrimaryConstructorBody;
assertParsedNodeText(node, r'''
PrimaryConstructorBody
documentationComment: Comment
tokens
/// foo
/// bar
thisKeyword: this
body: EmptyFunctionBody
semicolon: ;
''');
}
test_primaryConstructorBody_fieldInitializer() {
useDeclaringConstructorsAst = true;
var parseResult = parseStringWithErrors(r'''
class A() {
final int x;
this : x = 0;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singlePrimaryConstructorBody;
assertParsedNodeText(node, r'''
PrimaryConstructorBody
thisKeyword: this
colon: :
initializers
ConstructorFieldInitializer
fieldName: SimpleIdentifier
token: x
equals: =
expression: IntegerLiteral
literal: 0
body: EmptyFunctionBody
semicolon: ;
''');
}
test_primaryConstructorBody_metadata() {
useDeclaringConstructorsAst = true;
var parseResult = parseStringWithErrors(r'''
class A() {
@deprecated
this;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singlePrimaryConstructorBody;
assertParsedNodeText(node, r'''
PrimaryConstructorBody
metadata
Annotation
atSign: @
name: SimpleIdentifier
token: deprecated
thisKeyword: this
body: EmptyFunctionBody
semicolon: ;
''');
}
test_setter_formalParameters_absent() {
var parseResult = parseStringWithErrors(r'''
class A {
@@ -626,6 +626,25 @@ EnumDeclaration
EnumConstantDeclaration
name: v
rightBracket: }
''');
}
test_primaryConstructorBody() {
useDeclaringConstructorsAst = true;
var parseResult = parseStringWithErrors(r'''
enum E() {
v;
this;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singlePrimaryConstructorBody;
assertParsedNodeText(node, r'''
PrimaryConstructorBody
thisKeyword: this
body: EmptyFunctionBody
semicolon: ;
''');
}
}
@@ -289,4 +289,33 @@ ExtensionDeclaration
''');
}
}
test_primaryConstructorBody() {
useDeclaringConstructorsAst = true;
var parseResult = parseStringWithErrors(r'''
extension A on int {
this;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExtensionDeclaration;
assertParsedNodeText(node, r'''
ExtensionDeclaration
extensionKeyword: extension
name: A
onClause: ExtensionOnClause
onKeyword: on
extendedType: NamedType
name: int
body: BlockClassBody
leftBracket: {
members
PrimaryConstructorBody
thisKeyword: this
body: EmptyFunctionBody
semicolon: ;
rightBracket: }
''');
}
}
@@ -2159,6 +2159,40 @@ ExtensionTypeDeclaration
}
}
test_primaryConstructorBody() {
useDeclaringConstructorsAst = true;
var parseResult = parseStringWithErrors(r'''
extension type A(int it) {
this;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExtensionTypeDeclaration;
assertParsedNodeText(node, r'''
ExtensionTypeDeclaration
extensionKeyword: extension
typeKeyword: type
primaryConstructor: PrimaryConstructorDeclaration
typeName: A
formalParameters: FormalParameterList
leftParenthesis: (
parameter: SimpleFormalParameter
type: NamedType
name: int
name: it
rightParenthesis: )
body: BlockClassBody
leftBracket: {
members
PrimaryConstructorBody
thisKeyword: this
body: EmptyFunctionBody
semicolon: ;
rightBracket: }
''');
}
test_withImplementsClause() {
var parseResult = parseStringWithErrors(r'''
extension type A(int it) implements B, C {}
@@ -287,6 +287,31 @@ MixinDeclaration
name: A
leftBracket: {
rightBracket: }
''');
}
test_primaryConstructorBody() {
useDeclaringConstructorsAst = true;
var parseResult = parseStringWithErrors(r'''
mixin A {
this;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleMixinDeclaration;
assertParsedNodeText(node, r'''
MixinDeclaration
mixinKeyword: mixin
name: A
body: BlockClassBody
leftBracket: {
members
PrimaryConstructorBody
thisKeyword: this
body: EmptyFunctionBody
semicolon: ;
rightBracket: }
''');
}
}
@@ -1347,6 +1347,14 @@ class ResolvedAstPrinter extends ThrowingAstVisitor<void> {
});
}
@override
void visitPrimaryConstructorBody(PrimaryConstructorBody node) {
_sink.writeln('PrimaryConstructorBody');
_sink.withIndent(() {
_writeNamedChildEntities(node);
});
}
@override
void visitPrimaryConstructorDeclaration(PrimaryConstructorDeclaration node) {
_sink.writeln('PrimaryConstructorDeclaration');
@@ -708,6 +708,8 @@ void visitChildren(AstVisitor visitor) {''');
implClass.doNotGenerateLookupNames.add(memberName);
continue;
}
case PrimaryConstructorBodyImpl():
throw UnimplementedError();
}
if (implClass.generatedLookupNames.contains(memberName)) {
replacements.add(_Replacement(member.offset, member.end, ''));
@@ -151,6 +151,10 @@ class _Visitor extends SimpleAstVisitor<void> {
trackingAnnotations.forEach(_reportBad);
}
}
// ignore: experimental_member_use
case PrimaryConstructorBody():
// TODO(scheglov): Handle this case.
throw UnimplementedError();
}
}
}
@@ -137,6 +137,10 @@ class _DeclarationGatherer {
declarations.add(member);
}
}
// ignore: experimental_member_use
case PrimaryConstructorBody():
// TODO(scheglov): Handle this case.
throw UnimplementedError();
}
}
}