Augment. Add AugmentedExpression, AugmentedInvocation.

Change-Id: I15ec8a3bed5ad66600c3b51bf8109ff2089590f3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/361002
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2024-04-05 06:25:03 +00:00 committed by Commit Queue
parent df707ac85e
commit 240d60c06b
11 changed files with 1151 additions and 14 deletions

View file

@ -51,6 +51,8 @@ export 'package:analyzer/src/dart/ast/ast.dart'
AstNode,
AstVisitor,
AugmentationImportDirective,
AugmentedExpression,
AugmentedInvocation,
AwaitExpression,
BinaryExpression,
Block,

View file

@ -163,6 +163,14 @@ class GeneralizingAstVisitor<R> implements AstVisitor<R> {
R? visitAugmentationImportDirective(AugmentationImportDirective node) =>
visitUriBasedDirective(node);
@override
R? visitAugmentedExpression(AugmentedExpression node) =>
visitExpression(node);
@override
R? visitAugmentedInvocation(AugmentedInvocation node) =>
visitExpression(node);
@override
R? visitAwaitExpression(AwaitExpression node) => visitExpression(node);
@ -857,6 +865,18 @@ class RecursiveAstVisitor<R> implements AstVisitor<R> {
return null;
}
@override
R? visitAugmentedExpression(AugmentedExpression node) {
node.visitChildren(this);
return null;
}
@override
R? visitAugmentedInvocation(AugmentedInvocation node) {
node.visitChildren(this);
return null;
}
@override
R? visitAwaitExpression(AwaitExpression node) {
node.visitChildren(this);
@ -1878,6 +1898,12 @@ class SimpleAstVisitor<R> implements AstVisitor<R> {
@override
R? visitAugmentationImportDirective(AugmentationImportDirective node) => null;
@override
R? visitAugmentedExpression(AugmentedExpression node) => null;
@override
R? visitAugmentedInvocation(AugmentedInvocation node) => null;
@override
R? visitAwaitExpression(AwaitExpression node) => null;
@ -2427,6 +2453,12 @@ class ThrowingAstVisitor<R> implements AstVisitor<R> {
R? visitAugmentationImportDirective(AugmentationImportDirective node) =>
_throw(node);
@override
R? visitAugmentedExpression(AugmentedExpression node) => _throw(node);
@override
R? visitAugmentedInvocation(AugmentedInvocation node) => _throw(node);
@override
R? visitAwaitExpression(AwaitExpression node) => _throw(node);
@ -3042,6 +3074,22 @@ class TimedAstVisitor<T> implements AstVisitor<T> {
return result;
}
@override
T? visitAugmentedExpression(AugmentedExpression node) {
stopwatch.start();
T? result = _baseVisitor.visitAugmentedExpression(node);
stopwatch.stop();
return result;
}
@override
T? visitAugmentedInvocation(AugmentedInvocation node) {
stopwatch.start();
T? result = _baseVisitor.visitAugmentedInvocation(node);
stopwatch.stop();
return result;
}
@override
T? visitAwaitExpression(AwaitExpression node) {
stopwatch.start();
@ -4394,6 +4442,12 @@ class UnifyingAstVisitor<R> implements AstVisitor<R> {
R? visitAugmentationImportDirective(AugmentationImportDirective node) =>
visitNode(node);
@override
R? visitAugmentedExpression(AugmentedExpression node) => visitNode(node);
@override
R? visitAugmentedInvocation(AugmentedInvocation node) => visitNode(node);
@override
R? visitAwaitExpression(AwaitExpression node) => visitNode(node);

View file

@ -1227,6 +1227,10 @@ abstract class AstVisitor<R> {
R? visitAugmentationImportDirective(AugmentationImportDirective node);
R? visitAugmentedExpression(AugmentedExpression node);
R? visitAugmentedInvocation(AugmentedInvocation node);
R? visitAwaitExpression(AwaitExpression node);
R? visitBinaryExpression(BinaryExpression node);
@ -1623,6 +1627,166 @@ final class AugmentationImportDirectiveImpl extends UriBasedDirectiveImpl
}
}
/// The augmented expression.
///
/// It is created only inside an augmentation.
/// The exact meaning depends on what is augmented, and where it is used.
///
/// Augmenting getters: `augmented` invokes the getter and evaluates to the
/// return value.
/// The [element] is the augmented getter.
/// The [staticType] is the return type of the getter.
///
/// Augmenting setters: `augmented` must be followed by an `=`, and will
/// directly invoke the augmented setter.
/// The [element] is the augmented setter.
/// The [staticType] is meaningless, and set to `null`.
///
/// Augmenting fields: `augmented` can only be used in an initializer
/// expression, and refers to the original field's initializer expression.
/// The [element] is the augmented field.
/// The [staticType] is the type of the field.
///
/// Augmenting binary operators: `augmented` must be the LHS, and followed by
/// the argument, e.g. `augmented + 1`.
/// The [element] is the augmented [MethodElement].
/// The [staticType] is the type of `this`.
///
/// Augmenting index operators: `augmented` must be the index target,
/// e.g. `augmented[0]`.
/// The [element] is the augmented [MethodElement].
/// The [staticType] is the type of `this`.
///
/// Augmenting prefix operators: `augmented` must be the target, e.g.
/// `~augmented`.
/// The [element] is the augmented [MethodElement].
/// The [staticType] is the type of `this`.
abstract final class AugmentedExpression implements Expression {
/// The 'augmented' keyword.
Token get augmentedKeyword;
/// The referenced augmented element: getter, setter, variable.
Element? get element;
}
final class AugmentedExpressionImpl extends ExpressionImpl
implements AugmentedExpression {
@override
final Token augmentedKeyword;
@override
Element? element;
AugmentedExpressionImpl({
required this.augmentedKeyword,
});
@override
Token get beginToken => augmentedKeyword;
@override
Token get endToken => augmentedKeyword;
@override
bool get isAssignable => true;
@override
Precedence get precedence => Precedence.primary;
@override
ChildEntities get _childEntities =>
ChildEntities()..addToken('augmentedKeyword', augmentedKeyword);
@override
E? accept<E>(AstVisitor<E> visitor) => visitor.visitAugmentedExpression(this);
@override
void resolveExpression(ResolverVisitor resolver, DartType contextType) {
resolver.visitAugmentedExpression(this);
}
@override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
}
/// Invocation of the augmented function, constructor, or method.
///
/// augmentedInvocation ::=
/// 'augmented' [TypeArgumentList]? [ArgumentList]
abstract final class AugmentedInvocation implements Expression {
/// The list of value arguments.
ArgumentList get arguments;
/// The 'augmented' keyword.
Token get augmentedKeyword;
/// The referenced augmented element: function, constructor, or method.
ExecutableElement? get element;
/// The list of type arguments.
///
/// In valid code cannot be provided for augmented constructor invocation.
TypeArgumentList? get typeArguments;
}
final class AugmentedInvocationImpl extends ExpressionImpl
implements AugmentedInvocation {
@override
final Token augmentedKeyword;
@override
ExecutableElement? element;
@override
final TypeArgumentListImpl? typeArguments;
@override
final ArgumentListImpl arguments;
AugmentedInvocationImpl({
required this.augmentedKeyword,
required this.typeArguments,
required this.arguments,
}) {
_becomeParentOf(typeArguments);
_becomeParentOf(arguments);
}
@override
Token get beginToken => augmentedKeyword;
@override
Token get endToken => arguments.endToken;
@override
Precedence get precedence => Precedence.postfix;
@override
ChildEntities get _childEntities => ChildEntities()
..addToken('augmentedKeyword', augmentedKeyword)
..addNode('typeArguments', typeArguments)
..addNode('arguments', arguments);
@override
E? accept<E>(AstVisitor<E> visitor) {
return visitor.visitAugmentedInvocation(this);
}
@override
void resolveExpression(ResolverVisitor resolver, DartType contextType) {
// TODO(scheglov): implement
throw UnimplementedError();
}
@override
void visitChildren(AstVisitor visitor) {
typeArguments?.accept(visitor);
arguments.accept(visitor);
}
}
/// An await expression.
///
/// awaitExpression ::=

View file

@ -89,6 +89,18 @@ class ToSourceVisitor implements AstVisitor<void> {
sink.write(';');
}
@override
void visitAugmentedExpression(AugmentedExpression node) {
sink.write('augmented');
}
@override
void visitAugmentedInvocation(AugmentedInvocation node) {
_visitToken(node.augmentedKeyword);
_visitNode(node.typeArguments);
_visitNode(node.arguments);
}
@override
void visitAwaitExpression(AwaitExpression node) {
sink.write('await ');

View file

@ -175,6 +175,20 @@ class AstComparator implements AstVisitor<bool> {
isEqualTokens(node.semicolon, other.semicolon);
}
@override
bool visitAugmentedExpression(AugmentedExpression node) {
final other = _other as AugmentedExpression;
return isEqualTokens(node.augmentedKeyword, other.augmentedKeyword);
}
@override
bool visitAugmentedInvocation(AugmentedInvocation node) {
final other = _other as AugmentedInvocation;
return isEqualTokens(node.augmentedKeyword, other.augmentedKeyword) &&
isEqualNodes(node.typeArguments, other.typeArguments) &&
isEqualNodes(node.arguments, other.arguments);
}
@override
bool visitAwaitExpression(AwaitExpression node) {
AwaitExpression other = _other as AwaitExpression;

View file

@ -156,6 +156,8 @@ class AstBuilder extends StackListener {
final LineInfo _lineInfo;
Token? _enclosingDeclarationAugmentToken;
AstBuilder(ErrorReporter? errorReporter, this.fileUri, this.isFullAst,
this._featureSet, this._lineInfo,
[Uri? uri])
@ -361,6 +363,33 @@ class AstBuilder extends StackListener {
..finalConstOrVarKeyword = constToken);
}
@override
void beginFields(
DeclarationKind declarationKind,
Token? abstractToken,
Token? augmentToken,
Token? externalToken,
Token? staticToken,
Token? covariantToken,
Token? lateToken,
Token? varFinalOrConst,
Token lastConsumed,
) {
_enclosingDeclarationAugmentToken = augmentToken;
super.beginFields(
declarationKind,
abstractToken,
augmentToken,
externalToken,
staticToken,
covariantToken,
lateToken,
varFinalOrConst,
lastConsumed,
);
}
@override
void beginFormalParameter(Token token, MemberKind kind, Token? requiredToken,
Token? covariantToken, Token? varFinalOrConst) {
@ -411,6 +440,7 @@ class AstBuilder extends StackListener {
if (augmentToken != null) {
assert(augmentToken.isModifier);
modifiers.augmentKeyword = augmentToken;
_enclosingDeclarationAugmentToken = augmentToken;
}
if (externalToken != null) {
assert(externalToken.isModifier);
@ -554,6 +584,7 @@ class AstBuilder extends StackListener {
@override
void beginTopLevelMethod(
Token lastConsumed, Token? augmentToken, Token? externalToken) {
_enclosingDeclarationAugmentToken = augmentToken;
push(_Modifiers()
..augmentKeyword = augmentToken
..externalKeyword = externalToken);
@ -823,20 +854,29 @@ class AstBuilder extends StackListener {
void doInvocation(
TypeArgumentListImpl? typeArguments, MethodInvocationImpl arguments) {
var receiver = pop() as ExpressionImpl;
if (receiver is SimpleIdentifierImpl) {
arguments.methodName = receiver;
if (typeArguments != null) {
arguments.typeArguments = typeArguments;
}
push(arguments);
} else {
push(
FunctionExpressionInvocationImpl(
function: receiver,
typeArguments: typeArguments,
argumentList: arguments.argumentList,
),
);
switch (receiver) {
case AugmentedExpressionImpl():
push(
AugmentedInvocationImpl(
augmentedKeyword: receiver.augmentedKeyword,
typeArguments: typeArguments,
arguments: arguments.argumentList,
),
);
case SimpleIdentifierImpl():
arguments.methodName = receiver;
if (typeArguments != null) {
arguments.typeArguments = typeArguments;
}
push(arguments);
default:
push(
FunctionExpressionInvocationImpl(
function: receiver,
typeArguments: typeArguments,
argumentList: arguments.argumentList,
),
);
}
}
@ -1151,6 +1191,7 @@ class AstBuilder extends StackListener {
endToken: endToken,
),
);
_enclosingDeclarationAugmentToken = null;
}
@override
@ -1247,6 +1288,7 @@ class AstBuilder extends StackListener {
semicolon: semicolon,
),
);
_enclosingDeclarationAugmentToken = null;
}
@override
@ -1318,6 +1360,7 @@ class AstBuilder extends StackListener {
body: body,
),
);
_enclosingDeclarationAugmentToken = null;
}
@override
@ -1347,6 +1390,8 @@ class AstBuilder extends StackListener {
void endCompilationUnit(int count, Token endToken) {
debugEvent("CompilationUnit");
assert(_enclosingDeclarationAugmentToken == null);
var beginToken = pop() as Token;
checkEmpty(endToken.charOffset);
@ -3348,6 +3393,7 @@ class AstBuilder extends StackListener {
semicolon: semicolon,
),
);
_enclosingDeclarationAugmentToken = null;
}
@override
@ -3385,6 +3431,7 @@ class AstBuilder extends StackListener {
),
),
);
_enclosingDeclarationAugmentToken = null;
}
@override
@ -4377,6 +4424,17 @@ class AstBuilder extends StackListener {
return;
}
if (_enclosingDeclarationAugmentToken != null) {
if (token.lexeme == 'augmented') {
push(
AugmentedExpressionImpl(
augmentedKeyword: token,
),
);
return;
}
}
final identifier = SimpleIdentifierImpl(token);
if (context.inLibraryOrPartOfDeclaration) {
if (!context.isContinuation) {

View file

@ -77,6 +77,18 @@ class LinterVisitor implements AstVisitor<void> {
node.visitChildren(this);
}
@override
void visitAugmentedExpression(AugmentedExpression node) {
_runSubscriptions(node, registry._forAugmentedExpression);
node.visitChildren(this);
}
@override
void visitAugmentedInvocation(AugmentedInvocation node) {
_runSubscriptions(node, registry._forAugmentedInvocation);
node.visitChildren(this);
}
@override
void visitAwaitExpression(AwaitExpression node) {
_runSubscriptions(node, registry._forAwaitExpression);
@ -1094,6 +1106,8 @@ class NodeLintRegistry {
final List<_Subscription<AssignmentExpression>> _forAssignmentExpression = [];
final List<_Subscription<AugmentationImportDirective>>
_forAugmentationImportDirective = [];
final List<_Subscription<AugmentedExpression>> _forAugmentedExpression = [];
final List<_Subscription<AugmentedInvocation>> _forAugmentedInvocation = [];
final List<_Subscription<AwaitExpression>> _forAwaitExpression = [];
final List<_Subscription<BinaryExpression>> _forBinaryExpression = [];
final List<_Subscription<Block>> _forBlock = [];
@ -1335,6 +1349,16 @@ class NodeLintRegistry {
.add(_Subscription(linter, visitor, _getTimer(linter)));
}
void addAugmentedExpression(LintRule linter, AstVisitor visitor) {
_forAugmentedExpression
.add(_Subscription(linter, visitor, _getTimer(linter)));
}
void addAugmentedInvocation(LintRule linter, AstVisitor visitor) {
_forAugmentedInvocation
.add(_Subscription(linter, visitor, _getTimer(linter)));
}
void addAwaitExpression(LintRule linter, AstVisitor visitor) {
_forAwaitExpression.add(_Subscription(linter, visitor, _getTimer(linter)));
}

View file

@ -39,6 +39,10 @@ class FindNode {
AugmentationImportDirective get singleAugmentationImportDirective =>
_single();
AugmentedExpression get singleAugmentedExpression => _single();
AugmentedInvocation get singleAugmentedInvocation => _single();
AwaitExpression get singleAwaitExpression => _single();
BinaryExpression get singleBinaryExpression => _single();

View file

@ -0,0 +1,783 @@
// Copyright (c) 2024, 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:test_reflective_loader/test_reflective_loader.dart';
import '../../diagnostics/parser_diagnostics.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AugmentedExpressionParserTest);
});
}
@reflectiveTest
class AugmentedExpressionParserTest extends ParserDiagnosticsTest {
test_class_constructor() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment class A {
augment A(int a) {
augmented(0);
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
arguments: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
rightParenthesis: )
semicolon: ;
rightBracket: }
''');
}
test_class_field() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment class A {
augment int foo = augmented + 1;
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBinaryExpression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: AugmentedExpression
augmentedKeyword: augmented
operator: +
rightOperand: IntegerLiteral
literal: 1
''');
}
test_class_getter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment class A {
augment int get foo {
return augmented;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ReturnStatement
returnKeyword: return
expression: AugmentedExpression
augmentedKeyword: augmented
semicolon: ;
rightBracket: }
''');
}
test_class_method() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment class A {
augment void foo<T>(T a) {
augmented<int>(0);
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
arguments: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
rightParenthesis: )
semicolon: ;
rightBracket: }
''');
}
test_class_operatorBinary() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment class A {
augment int operator+(int a) {
return augmented + 1;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ReturnStatement
returnKeyword: return
expression: BinaryExpression
leftOperand: AugmentedExpression
augmentedKeyword: augmented
operator: +
rightOperand: IntegerLiteral
literal: 1
semicolon: ;
rightBracket: }
''');
}
test_class_operatorIndexRead() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment class A {
augment int operator[](int index) {
return augmented[0];
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ReturnStatement
returnKeyword: return
expression: IndexExpression
target: AugmentedExpression
augmentedKeyword: augmented
leftBracket: [
index: IntegerLiteral
literal: 0
rightBracket: ]
semicolon: ;
rightBracket: }
''');
}
test_class_operatorIndexWrite() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment class A {
augment void operator[]=(int index, Object value) {
augmented[0] = value;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AssignmentExpression
leftHandSide: IndexExpression
target: AugmentedExpression
augmentedKeyword: augmented
leftBracket: [
index: IntegerLiteral
literal: 0
rightBracket: ]
operator: =
rightHandSide: SimpleIdentifier
token: value
semicolon: ;
rightBracket: }
''');
}
test_class_operatorPrefix() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment class A {
augment int operator-() {
return -augmented;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ReturnStatement
returnKeyword: return
expression: PrefixExpression
operator: -
operand: AugmentedExpression
augmentedKeyword: augmented
semicolon: ;
rightBracket: }
''');
}
test_class_setter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment class A {
augment set foo(int _) {
augmented = 0;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AssignmentExpression
leftHandSide: AugmentedExpression
augmentedKeyword: augmented
operator: =
rightHandSide: IntegerLiteral
literal: 0
semicolon: ;
rightBracket: }
''');
}
test_enum_getter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment enum A {
bar;
augment int get foo {
return augmented;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ReturnStatement
returnKeyword: return
expression: AugmentedExpression
augmentedKeyword: augmented
semicolon: ;
rightBracket: }
''');
}
test_enum_method() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment enum A {
bar;
augment void foo<T>(T a) {
augmented<int>(0);
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
arguments: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
rightParenthesis: )
semicolon: ;
rightBracket: }
''');
}
test_enum_setter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment enum A {
bar;
augment set foo(int _) {
augmented = 0;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AssignmentExpression
leftHandSide: AugmentedExpression
augmentedKeyword: augmented
operator: =
rightHandSide: IntegerLiteral
literal: 0
semicolon: ;
rightBracket: }
''');
}
test_extension_getter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment extension A {
augment int get foo {
return augmented;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ReturnStatement
returnKeyword: return
expression: AugmentedExpression
augmentedKeyword: augmented
semicolon: ;
rightBracket: }
''');
}
test_extension_method() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment extension A {
augment void foo<T>(T a) {
augmented<int>(0);
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
arguments: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
rightParenthesis: )
semicolon: ;
rightBracket: }
''');
}
test_extension_setter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment extension A {
augment set foo(int _) {
augmented = 0;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AssignmentExpression
leftHandSide: AugmentedExpression
augmentedKeyword: augmented
operator: =
rightHandSide: IntegerLiteral
literal: 0
semicolon: ;
rightBracket: }
''');
}
test_extensionType_getter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment extension type A(int it) {
augment int get foo {
return augmented;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ReturnStatement
returnKeyword: return
expression: AugmentedExpression
augmentedKeyword: augmented
semicolon: ;
rightBracket: }
''');
}
test_extensionType_method() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment extension type A(int it) {
augment void foo<T>(T a) {
augmented<int>(0);
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
arguments: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
rightParenthesis: )
semicolon: ;
rightBracket: }
''');
}
test_extensionType_setter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment extension type A(int it) {
augment set foo(int _) {
augmented = 0;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AssignmentExpression
leftHandSide: AugmentedExpression
augmentedKeyword: augmented
operator: =
rightHandSide: IntegerLiteral
literal: 0
semicolon: ;
rightBracket: }
''');
}
test_mixin_field() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment mixin A {
augment int foo = augmented + 1;
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBinaryExpression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: AugmentedExpression
augmentedKeyword: augmented
operator: +
rightOperand: IntegerLiteral
literal: 1
''');
}
test_mixin_getter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment mixin A {
augment int get foo {
return augmented;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ReturnStatement
returnKeyword: return
expression: AugmentedExpression
augmentedKeyword: augmented
semicolon: ;
rightBracket: }
''');
}
test_mixin_method() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment mixin A {
augment void foo<T>(T a) {
augmented<int>(0);
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
arguments: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
rightParenthesis: )
semicolon: ;
rightBracket: }
''');
}
test_mixin_setter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment mixin A {
augment set foo(int _) {
augmented = 0;
}
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AssignmentExpression
leftHandSide: AugmentedExpression
augmentedKeyword: augmented
operator: =
rightHandSide: IntegerLiteral
literal: 0
semicolon: ;
rightBracket: }
''');
}
test_topLevel_function() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment void foo<T>(T a) {
augmented<int>(0);
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AugmentedInvocation
augmentedKeyword: augmented
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
rightBracket: >
arguments: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
rightParenthesis: )
semicolon: ;
rightBracket: }
''');
}
test_topLevel_getter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment int get foo {
return augmented;
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ReturnStatement
returnKeyword: return
expression: AugmentedExpression
augmentedKeyword: augmented
semicolon: ;
rightBracket: }
''');
}
test_topLevel_setter() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment set foo(int _) {
augmented = 0;
}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: AssignmentExpression
leftHandSide: AugmentedExpression
augmentedKeyword: augmented
operator: =
rightHandSide: IntegerLiteral
literal: 0
semicolon: ;
rightBracket: }
''');
}
test_topLevel_variable() {
final parseResult = parseStringWithErrors(r'''
library augment 'test.dart';
augment int foo = augmented + 1;
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.singleBinaryExpression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: AugmentedExpression
augmentedKeyword: augmented
operator: +
rightOperand: IntegerLiteral
literal: 1
''');
}
}

View file

@ -6,6 +6,7 @@ import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'augmentation_import_directive_test.dart'
as augmentation_import_directive;
import 'augmented_expression_test.dart' as augmented_expression;
import 'class_test.dart' as class_;
import 'doc_comment_test.dart' as doc_comment;
import 'enum_test.dart' as enum_;
@ -22,6 +23,7 @@ import 'variable_declaration_statement_test.dart'
main() {
defineReflectiveSuite(() {
augmentation_import_directive.main();
augmented_expression.main();
class_.main();
doc_comment.main();
enum_.main();

View file

@ -131,6 +131,26 @@ class ResolvedAstPrinter extends ThrowingAstVisitor<void> {
});
}
@override
void visitAugmentedExpression(AugmentedExpression node) {
_sink.writeln('AugmentedExpression');
_sink.withIndent(() {
_writeNamedChildEntities(node);
_writeElement('element', node.element);
_writeType('staticType', node.staticType);
});
}
@override
void visitAugmentedInvocation(AugmentedInvocation node) {
_sink.writeln('AugmentedInvocation');
_sink.withIndent(() {
_writeNamedChildEntities(node);
_writeElement('element', node.element);
_writeType('staticType', node.staticType);
});
}
@override
void visitAwaitExpression(AwaitExpression node) {
_sink.writeln('AwaitExpression');