blob: 436b7338a9b5c27451471c0f11c4f24e50378d96 [file] [log] [blame]
// Copyright (c) 2018, 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/dart/ast/ast.dart' hide Identifier;
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/fasta/analyzer_expression_generator.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:front_end/src/fasta/kernel/body_builder.dart' show LabelTarget;
import 'package:front_end/src/fasta/kernel/forest.dart';
import 'package:kernel/ast.dart' as kernel;
/// A data holder used to conform to the [Forest] API.
class Arguments {
List<TypeAnnotation> typeArguments = <TypeAnnotation>[];
List<Expression> positionalArguments = <Expression>[];
List<Expression> namedArguments = <Expression>[];
}
/// An implementation of a [Forest] that can be used to build an AST structure.
class AstBuildingForest
implements Forest<Expression, Statement, Token, Arguments> {
/// The type provider used to resolve the types of literal nodes, or `null` if
/// type resolution is not being performed.
final TypeProvider _typeProvider;
/// The factory used to create AST nodes.
AstFactoryImpl astFactory = new AstFactoryImpl();
/// Initialize a newly created AST-building forest.
AstBuildingForest(this._typeProvider);
@override
Arguments arguments(List<Expression> positional, Token location,
{covariant List types, covariant List named}) {
Arguments arguments = new Arguments();
if (types != null) {
arguments.typeArguments = types.cast<TypeAnnotation>();
}
arguments.positionalArguments = positional.cast<Expression>();
if (named != null) {
arguments.namedArguments = named.cast<Expression>();
}
return arguments;
}
@override
Arguments argumentsEmpty(Token location) => new Arguments();
@override
List argumentsNamed(Arguments arguments) => arguments.namedArguments;
@override
List<Expression> argumentsPositional(Arguments arguments) =>
arguments.positionalArguments;
@override
void argumentsSetTypeArguments(Arguments arguments, covariant List types) {
arguments.typeArguments = types.cast<TypeAnnotation>();
}
@override
List argumentsTypeArguments(Arguments arguments) => arguments.typeArguments;
@override
Expression asExpression(Expression expression, type, Token location) =>
astFactory.asExpression(expression, location, type);
@override
Expression asLiteralString(Expression value) => value;
@override
ConstructorInitializer assertInitializer(
Token assertKeyword,
Token leftParenthesis,
Expression condition,
Token comma,
Expression message) =>
astFactory.assertInitializer(assertKeyword, leftParenthesis, condition,
comma, message, leftParenthesis.endGroup);
@override
Statement assertStatement(
Token assertKeyword,
Token leftParenthesis,
Expression condition,
Token comma,
Expression message,
Token semicolon) =>
astFactory.assertStatement(assertKeyword, leftParenthesis, condition,
comma, message, leftParenthesis.endGroup, semicolon);
@override
Expression awaitExpression(Expression operand, Token awaitKeyword) =>
astFactory.awaitExpression(awaitKeyword, operand);
@override
Block block(Token openBrace, List<Statement> statements, Token closeBrace) =>
astFactory.block(openBrace, statements, closeBrace);
@override
Statement breakStatement(
Token breakKeyword, Identifier label, Token semicolon) =>
astFactory.breakStatement(
breakKeyword,
label == null ? null : astFactory.simpleIdentifier(label.token),
semicolon);
@override
kernel.Arguments castArguments(Arguments arguments) {
// TODO(brianwilkerson) Implement this or remove it from the API.
throw new UnimplementedError();
}
@override
CatchClause catchClause(
Token onKeyword,
TypeAnnotation exceptionType,
Token catchKeyword,
SimpleIdentifier exceptionParameter,
SimpleIdentifier stackTraceParameter,
TypeAnnotation stackTraceType,
Statement body) {
// TODO(brianwilkerson) The following is not reliable in the presence of
// recovery. Consider passing the required tokens from the Parser to the
// BodyBuilder to here.
Token leftParenthesis;
if (catchKeyword != null) {
leftParenthesis = catchKeyword.next;
}
Token comma;
if (stackTraceParameter != null) {
comma = exceptionParameter.endToken.next;
}
Token rightParenthesis;
if (catchKeyword != null) {
if (stackTraceParameter != null) {
rightParenthesis = stackTraceParameter.endToken.next;
} else if (comma != null) {
rightParenthesis = comma.next;
} else {
rightParenthesis = exceptionParameter.endToken.next;
}
}
return astFactory.catchClause(
onKeyword,
exceptionType,
catchKeyword,
leftParenthesis,
exceptionParameter,
comma,
stackTraceParameter,
rightParenthesis,
body);
}
@override
Expression checkLibraryIsLoaded(dependency) {
// TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
}
@override
Expression conditionalExpression(Expression condition, Token question,
Expression thenExpression, Token colon, Expression elseExpression) =>
astFactory.conditionalExpression(
condition, question, thenExpression, colon, elseExpression);
@override
Statement continueStatement(
Token continueKeyword, Identifier label, Token semicolon) =>
astFactory.continueStatement(
continueKeyword,
label == null ? null : astFactory.simpleIdentifier(label.token),
semicolon);
@override
Generator<Expression, Statement, Arguments> deferredAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
PrefixBuilder builder,
Generator<Expression, Statement, Arguments> generator) {
return new AnalyzerDeferredAccessGenerator(
helper, astFactory, token, builder, generator);
}
@override
Generator<Expression, Statement, Arguments> delayedAssignment(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
Generator<Expression, Statement, Arguments> generator,
Expression value,
String assignmentOperator) {
return new AnalyzerDelayedAssignmentGenerator(
helper, astFactory, token, generator, assignmentOperator, value);
}
@override
Generator<Expression, Statement, Arguments> delayedPostfixIncrement(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
Generator<Expression, Statement, Arguments> generator,
kernel.Name binaryOperator,
kernel.Procedure interfaceTarget) {
return new AnalyzerDelayedPostfixIncrementGenerator(
helper, astFactory, token, generator, binaryOperator, interfaceTarget);
}
@override
Statement doStatement(Token doKeyword, Statement body, Token whileKeyword,
ParenthesizedExpression condition, Token semicolon) =>
astFactory.doStatement(
doKeyword,
body,
whileKeyword,
condition.leftParenthesis,
condition.expression,
condition.rightParenthesis,
semicolon);
@override
Statement emptyStatement(Token semicolon) =>
astFactory.emptyStatement(semicolon);
@override
Statement expressionStatement(Expression expression, Token semicolon) =>
astFactory.expressionStatement(expression, semicolon);
@override
Statement forStatement(
Token forKeyword,
Token leftParenthesis,
covariant variableList,
covariant initialization,
Token leftSeparator,
Expression condition,
Statement conditionStatement,
List<Expression> updaters,
Token rightParenthesis,
Statement body) =>
astFactory.forStatement(
forKeyword,
leftParenthesis,
variableList,
initialization,
leftSeparator,
condition,
getSemicolon(conditionStatement),
updaters,
rightParenthesis,
body);
@override
Expression getExpressionFromExpressionStatement(Statement statement) =>
(statement as ExpressionStatement).expression;
String getLabelName(Label label) => label.label.name;
@override
int getLabelOffset(Label label) => label.offset;
/// Return the semicolon at the end of the given [statement], or `null` if the
/// statement is not terminated by a semicolon.
Token getSemicolon(Statement statement) {
if (statement is ExpressionStatement) {
return statement.semicolon;
}
if (statement is EmptyStatement) {
return statement.semicolon;
}
return null;
}
@override
kernel.DartType getTypeAt(TypeArgumentList typeArguments, int index) {
return null; // typeArguments.arguments[index].type.kernelType;
}
@override
int getTypeCount(TypeArgumentList typeArguments) =>
typeArguments.arguments.length;
@override
String getVariableDeclarationName(VariableDeclaration declaration) {
return declaration.name.name;
}
@override
Statement ifStatement(
Token ifKeyword,
ParenthesizedExpression condition,
Statement thenStatement,
Token elseKeyword,
Statement elseStatement) =>
astFactory.ifStatement(
ifKeyword,
condition.leftParenthesis,
condition.expression,
condition.rightParenthesis,
thenStatement,
elseKeyword,
elseStatement);
@override
Generator<Expression, Statement, Arguments> indexedAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
Expression receiver,
Expression index,
kernel.Procedure getter,
kernel.Procedure setter) {
return new AnalyzerIndexedAccessGenerator(
helper, astFactory, receiver, token, index, token.endGroup);
}
@override
bool isBlock(Object node) => node is Block;
@override
bool isEmptyStatement(Statement statement) => statement is EmptyStatement;
@override
bool isErroneousNode(Object node) => false /* ??? */;
@override
Expression isExpression(Expression expression, Token isOperator,
Token notOperator, Object type) =>
astFactory.isExpression(expression, isOperator, notOperator, type);
@override
bool isExpressionStatement(Statement statement) =>
statement is ExpressionStatement;
@override
bool isLabel(covariant node) => node is Label;
@override
bool isThisExpression(Object node) => node is ThisExpression;
@override
bool isVariablesDeclaration(Object node) =>
node is VariableDeclarationStatement && node.variables != 1;
@override
Label label(Token identifier, Token colon) => astFactory.label(
astFactory.simpleIdentifier(identifier, isDeclaration: true), colon);
@override
Statement labeledStatement(
LabelTarget<Statement> target, Statement statement) =>
astFactory.labeledStatement(target.labels.cast<Label>(), statement);
@override
Generator<Expression, Statement, Arguments> largeIntAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token) {
return new AnalyzerLargeIntAccessGenerator(helper, astFactory, token);
}
@override
Expression literalBool(bool value, Token location) =>
astFactory.booleanLiteral(location, value)
..staticType = _typeProvider?.boolType;
@override
Expression literalDouble(double value, Token location) =>
astFactory.doubleLiteral(location, value)
..staticType = _typeProvider?.doubleType;
@override
Expression literalInt(int value, Token location) =>
astFactory.integerLiteral(location, value)
..staticType = _typeProvider?.intType;
@override
Expression literalList(
Token constKeyword,
bool isConst,
Object typeArgument,
Object typeArguments,
Token leftBracket,
List<Expression> expressions,
Token rightBracket) =>
astFactory.listLiteral(
constKeyword, typeArguments, leftBracket, expressions, rightBracket);
@override
Expression literalMap(
Token constKeyword,
bool isConst,
covariant keyType,
covariant valueType,
Object typeArguments,
Token leftBracket,
covariant List entries,
Token rightBracket) =>
astFactory.mapLiteral(
constKeyword, typeArguments, leftBracket, entries, rightBracket);
@override
Expression literalNull(Token location) =>
astFactory.nullLiteral(location)..staticType = _typeProvider?.nullType;
@override
Expression literalString(String value, Token location) =>
astFactory.simpleStringLiteral(location, value)
..staticType = _typeProvider?.stringType;
@override
Expression literalSymbolMultiple(
String value, Token hash, List<Identifier> components) =>
astFactory.symbolLiteral(
hash, components.map((identifier) => identifier.token).toList())
..staticType = _typeProvider?.symbolType;
@override
Expression literalSymbolSingluar(String value, Token hash, Object component) {
Token token;
if (component is Identifier) {
token = component.token;
} else if (component is Operator) {
token = component.token;
} else {
throw new ArgumentError(
'Unexpected class of component: ${component.runtimeType}');
}
return astFactory.symbolLiteral(hash, <Token>[token])
..staticType = _typeProvider?.symbolType;
}
@override
Expression literalType(covariant type, Token location) {
// TODO(brianwilkerson) Capture the type information.
return astFactory.simpleIdentifier(location)
..staticType = _typeProvider?.typeType;
}
@override
Expression loadLibrary(dependency) {
// TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
}
@override
Generator<Expression, Statement, Arguments> loadLibraryGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
LoadLibraryBuilder builder) {
return new AnalyzerLoadLibraryGenerator(helper, astFactory, token, builder);
}
@override
Expression logicalExpression(
Expression leftOperand, Token operator, Expression rightOperand) =>
astFactory.binaryExpression(leftOperand, operator, rightOperand);
@override
Object mapEntry(Expression key, Token colon, Expression value) =>
astFactory.mapLiteralEntry(key, colon, value);
@override
List mapEntryList(int length) => new List<MapLiteralEntry>(length);
@override
Expression notExpression(Expression operand, Token operator) =>
astFactory.prefixExpression(operator, operand)
..staticType = _typeProvider?.boolType;
@override
Generator<Expression, Statement, Arguments> nullAwarePropertyAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
Expression receiverExpression,
kernel.Name name,
kernel.Member getter,
kernel.Member setter,
kernel.DartType type) {
return new AnalyzerNullAwarePropertyAccessGenerator(
helper, astFactory, receiverExpression, token, null /*name*/);
}
@override
Object parenthesizedCondition(Token leftParenthesis, Expression expression,
Token rightParenthesis) =>
astFactory.parenthesizedExpression(
leftParenthesis, expression, rightParenthesis);
@override
Generator<Expression, Statement, Arguments> propertyAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
Expression receiver,
kernel.Name name,
kernel.Member getter,
kernel.Member setter) {
return new AnalyzerPropertyAccessGenerator(
helper, astFactory, token, receiver, name, getter, setter);
}
@override
int readOffset(AstNode node) => node.offset;
@override
Generator<Expression, Statement, Arguments> readOnlyAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
Expression expression,
String plainNameForRead) {
return new AnalyzerReadOnlyAccessGenerator(
helper, astFactory, token, expression, plainNameForRead);
}
@override
void resolveBreak(Statement target, BreakStatement user) {
user.target = target;
}
@override
void resolveContinue(Statement target, ContinueStatement user) {
user.target = target;
}
@override
void resolveContinueInSwitch(SwitchStatement target, ContinueStatement user) {
user.target = target;
}
@override
Statement rethrowStatement(Token rethrowKeyword, Token semicolon) =>
astFactory.expressionStatement(
astFactory.rethrowExpression(rethrowKeyword), semicolon);
@override
Statement returnStatement(
Token returnKeyword, Expression expression, Token semicolon) =>
astFactory.returnStatement(returnKeyword, expression, semicolon);
@override
void setParameterType(FormalParameter parameter, TypeAnnotation type) {
parameter.identifier.staticType = type.type;
}
@override
Generator<Expression, Statement, Arguments> staticAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
kernel.Member getter,
kernel.Member setter) {
return new AnalyzerStaticAccessGenerator(
helper, astFactory, token, getter, setter);
}
@override
Expression stringConcatenationExpression(
List<Expression> strings, Token location) =>
astFactory.adjacentStrings(strings.cast<StringLiteral>());
@override
Generator<Expression, Statement, Arguments> superIndexedAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
Expression index,
kernel.Member getter,
kernel.Member setter) {
// TODO(brianwilkerson) Figure out how to get the token for `super`.
return new AnalyzerIndexedAccessGenerator(
helper, astFactory, null, token, index, token.endGroup);
}
@override
Generator<Expression, Statement, Arguments> superPropertyAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
kernel.Name name,
kernel.Member getter,
kernel.Member setter) {
// TODO(brianwilkerson) Figure out how to get the token for the name.
return new AnalyzerSuperPropertyAccessGenerator(
helper, astFactory, null, null, null /*name*/);
}
@override
Statement syntheticLabeledStatement(Statement statement) => statement;
@override
Expression thisExpression(Token thisKeyword) =>
astFactory.thisExpression(thisKeyword);
@override
Generator<Expression, Statement, Arguments> thisIndexedAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
Expression index,
kernel.Procedure getter,
kernel.Procedure setter) {
// TODO(brianwilkerson) Figure out how to get the token for `this`.
return new AnalyzerIndexedAccessGenerator(
helper, astFactory, null, token, index, token.endGroup);
}
@override
Generator<Expression, Statement, Arguments> thisPropertyAccessGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token location,
kernel.Name name,
kernel.Member getter,
kernel.Member setter) {
// TODO(brianwilkerson) Figure out how to get the token for the name.
return new AnalyzerThisPropertyAccessGenerator(
helper, astFactory, location, name, getter, setter);
}
@override
Expression throwExpression(Token throwKeyword, Expression expression) =>
astFactory.throwExpression(throwKeyword, expression);
@override
Statement tryStatement(
Token tryKeyword,
Statement body,
List<CatchClause> catchClauses,
Token finallyKeyword,
Statement finallyBlock) =>
astFactory.tryStatement(
tryKeyword, body, catchClauses, finallyKeyword, finallyBlock);
@override
Generator<Expression, Statement, Arguments> typeUseGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
PrefixBuilder prefix,
int declarationReferenceOffset,
TypeDeclarationBuilder declaration,
String plainNameForRead) {
return new AnalyzerTypeUseGenerator(helper, astFactory, token, prefix,
declarationReferenceOffset, declaration, plainNameForRead);
}
@override
Generator<Expression, Statement, Arguments> unlinkedGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
UnlinkedDeclaration declaration) {
return new AnalyzerUnlinkedNameGenerator(
helper, astFactory, token, declaration);
}
@override
Generator<Expression, Statement, Arguments> unresolvedNameGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
kernel.Name name) {
return new AnalyzerUnresolvedNameGenerator(helper, astFactory, token, name);
}
@override
VariableDeclarationStatement variablesDeclaration(
List<VariableDeclaration> declarations, Uri uri) {
// TODO(brianwilkerson) Implement this.
throw new UnimplementedError();
}
@override
NodeList<VariableDeclaration> variablesDeclarationExtractDeclarations(
VariableDeclarationStatement variablesDeclaration) =>
variablesDeclaration.variables.variables;
@override
Generator<Expression, Statement, Arguments> variableUseGenerator(
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
Token token,
VariableDeclarationStatement variable,
kernel.DartType promotedType) {
return new AnalyzerVariableUseGenerator(helper, astFactory, token);
}
Statement whileStatement(Token whileKeyword,
ParenthesizedExpression condition, Statement body) =>
astFactory.whileStatement(whileKeyword, condition.leftParenthesis,
condition.expression, condition.rightParenthesis, body);
@override
Statement wrapVariables(Statement statement) => statement;
@override
Statement yieldStatement(Token yieldKeyword, Token star,
Expression expression, Token semicolon) =>
astFactory.yieldStatement(yieldKeyword, star, expression, semicolon);
}