blob: 23a69ac54f1f632e1c3f1760d5b15a80a8d800ac [file] [log] [blame]
// Copyright (c) 2014, 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 'dart:collection';
import 'dart:math' as math;
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/syntactic_entity.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/constant_verifier.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/fasta/token_utils.dart' as util show findPrevious;
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
import 'package:analyzer/src/generated/utilities_dart.dart';
/**
* Two or more string literals that are implicitly concatenated because of being
* adjacent (separated only by whitespace).
*
* While the grammar only allows adjacent strings when all of the strings are of
* the same kind (single line or multi-line), this class doesn't enforce that
* restriction.
*
* adjacentStrings ::=
* [StringLiteral] [StringLiteral]+
*/
class AdjacentStringsImpl extends StringLiteralImpl implements AdjacentStrings {
/**
* The strings that are implicitly concatenated.
*/
NodeList<StringLiteral> _strings;
/**
* Initialize a newly created list of adjacent strings. To be syntactically
* valid, the list of [strings] must contain at least two elements.
*/
AdjacentStringsImpl(List<StringLiteral> strings) {
_strings = new NodeListImpl<StringLiteral>(this, strings);
}
@override
Token get beginToken => _strings.beginToken;
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..addAll(_strings);
@override
Token get endToken => _strings.endToken;
@override
NodeList<StringLiteral> get strings => _strings;
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitAdjacentStrings(this);
@override
void visitChildren(AstVisitor visitor) {
_strings.accept(visitor);
}
@override
void _appendStringValue(StringBuffer buffer) {
int length = strings.length;
for (int i = 0; i < length; i++) {
StringLiteralImpl stringLiteral = strings[i];
stringLiteral._appendStringValue(buffer);
}
}
}
/**
* An AST node that can be annotated with both a documentation comment and a
* list of annotations.
*/
abstract class AnnotatedNodeImpl extends AstNodeImpl implements AnnotatedNode {
/**
* The documentation comment associated with this node, or `null` if this node
* does not have a documentation comment associated with it.
*/
CommentImpl _comment;
/**
* The annotations associated with this node.
*/
NodeList<Annotation> _metadata;
/**
* Initialize a newly created annotated node. Either or both of the [comment]
* and [metadata] can be `null` if the node does not have the corresponding
* attribute.
*/
AnnotatedNodeImpl(CommentImpl comment, List<Annotation> metadata) {
_comment = _becomeParentOf(comment);
_metadata = new NodeListImpl<Annotation>(this, metadata);
}
@override
Token get beginToken {
if (_comment == null) {
if (_metadata.isEmpty) {
return firstTokenAfterCommentAndMetadata;
}
return _metadata.beginToken;
} else if (_metadata.isEmpty) {
return _comment.beginToken;
}
Token commentToken = _comment.beginToken;
Token metadataToken = _metadata.beginToken;
if (commentToken.offset < metadataToken.offset) {
return commentToken;
}
return metadataToken;
}
@override
Comment get documentationComment => _comment;
@override
void set documentationComment(Comment comment) {
_comment = _becomeParentOf(comment as CommentImpl);
}
@override
NodeList<Annotation> get metadata => _metadata;
@override
List<AstNode> get sortedCommentAndAnnotations {
return <AstNode>[]
..add(_comment)
..addAll(_metadata)
..sort(AstNode.LEXICAL_ORDER);
}
/**
* Return a holder of child entities that subclasses can add to.
*/
ChildEntities get _childEntities {
ChildEntities result = new ChildEntities();
if (_commentIsBeforeAnnotations()) {
result
..add(_comment)
..addAll(_metadata);
} else {
result.addAll(sortedCommentAndAnnotations);
}
return result;
}
@override
void visitChildren(AstVisitor visitor) {
if (_commentIsBeforeAnnotations()) {
_comment?.accept(visitor);
_metadata.accept(visitor);
} else {
List<AstNode> children = sortedCommentAndAnnotations;
int length = children.length;
for (int i = 0; i < length; i++) {
children[i].accept(visitor);
}
}
}
/**
* Return `true` if there are no annotations before the comment. Note that a
* result of `true` does not imply that there is a comment, nor that there are
* annotations associated with this node.
*/
bool _commentIsBeforeAnnotations() {
if (_comment == null || _metadata.isEmpty) {
return true;
}
Annotation firstAnnotation = _metadata[0];
return _comment.offset < firstAnnotation.offset;
}
}
/**
* An annotation that can be associated with an AST node.
*
* metadata ::=
* annotation*
*
* annotation ::=
* '@' [Identifier] ('.' [SimpleIdentifier])? [ArgumentList]?
*/
class AnnotationImpl extends AstNodeImpl implements Annotation {
/**
* The at sign that introduced the annotation.
*/
@override
Token atSign;
/**
* The name of the class defining the constructor that is being invoked or the
* name of the field that is being referenced.
*/
IdentifierImpl _name;
/**
* The period before the constructor name, or `null` if this annotation is not
* the invocation of a named constructor.
*/
@override
Token period;
/**
* The name of the constructor being invoked, or `null` if this annotation is
* not the invocation of a named constructor.
*/
SimpleIdentifierImpl _constructorName;
/**
* The arguments to the constructor being invoked, or `null` if this
* annotation is not the invocation of a constructor.
*/
ArgumentListImpl _arguments;
/**
* The element associated with this annotation, or `null` if the AST structure
* has not been resolved or if this annotation could not be resolved.
*/
Element _element;
/**
* The element annotation representing this annotation in the element model.
*/
@override
ElementAnnotation elementAnnotation;
/**
* Initialize a newly created annotation. Both the [period] and the
* [constructorName] can be `null` if the annotation is not referencing a
* named constructor. The [arguments] can be `null` if the annotation is not
* referencing a constructor.
*/
AnnotationImpl(this.atSign, IdentifierImpl name, this.period,
SimpleIdentifierImpl constructorName, ArgumentListImpl arguments) {
_name = _becomeParentOf(name);
_constructorName = _becomeParentOf(constructorName);
_arguments = _becomeParentOf(arguments);
}
@override
ArgumentList get arguments => _arguments;
@override
void set arguments(ArgumentList arguments) {
_arguments = _becomeParentOf(arguments as ArgumentListImpl);
}
@override
Token get beginToken => atSign;
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(atSign)
..add(_name)
..add(period)
..add(_constructorName)
..add(_arguments);
@override
SimpleIdentifier get constructorName => _constructorName;
@override
void set constructorName(SimpleIdentifier name) {
_constructorName = _becomeParentOf(name as SimpleIdentifierImpl);
}
@override
Element get element {
if (_element != null) {
return _element;
} else if (_constructorName == null && _name != null) {
return _name.staticElement;
}
return null;
}
@override
void set element(Element element) {
_element = element;
}
@override
Token get endToken {
if (_arguments != null) {
return _arguments.endToken;
} else if (_constructorName != null) {
return _constructorName.endToken;
}
return _name.endToken;
}
@override
Identifier get name => _name;
@override
void set name(Identifier name) {
_name = _becomeParentOf(name as IdentifierImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitAnnotation(this);
@override
void visitChildren(AstVisitor visitor) {
_name?.accept(visitor);
_constructorName?.accept(visitor);
_arguments?.accept(visitor);
}
}
/**
* A list of arguments in the invocation of an executable element (that is, a
* function, method, or constructor).
*
* argumentList ::=
* '(' arguments? ')'
*
* arguments ::=
* [NamedExpression] (',' [NamedExpression])*
* | [Expression] (',' [Expression])* (',' [NamedExpression])*
*/
class ArgumentListImpl extends AstNodeImpl implements ArgumentList {
/**
* The left parenthesis.
*/
@override
Token leftParenthesis;
/**
* The expressions producing the values of the arguments.
*/
NodeList<Expression> _arguments;
/**
* The right parenthesis.
*/
@override
Token rightParenthesis;
/**
* A list containing the elements representing the parameters corresponding to
* each of the arguments in this list, or `null` if the AST has not been
* resolved or if the function or method being invoked could not be determined
* based on static type information. The list must be the same length as the
* number of arguments, but can contain `null` entries if a given argument
* does not correspond to a formal parameter.
*/
List<ParameterElement> _correspondingStaticParameters;
/**
* Initialize a newly created list of arguments. The list of [arguments] can
* be `null` if there are no arguments.
*/
ArgumentListImpl(
this.leftParenthesis, List<Expression> arguments, this.rightParenthesis) {
_arguments = new NodeListImpl<Expression>(this, arguments);
}
@override
NodeList<Expression> get arguments => _arguments;
@override
Token get beginToken => leftParenthesis;
@override
// TODO(paulberry): Add commas.
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(leftParenthesis)
..addAll(_arguments)
..add(rightParenthesis);
@deprecated
List<ParameterElement> get correspondingPropagatedParameters => null;
@deprecated
@override
void set correspondingPropagatedParameters(
List<ParameterElement> parameters) {
if (parameters != null && parameters.length != _arguments.length) {
throw new ArgumentError(
"Expected ${_arguments.length} parameters, not ${parameters.length}");
}
}
List<ParameterElement> get correspondingStaticParameters =>
_correspondingStaticParameters;
@override
void set correspondingStaticParameters(List<ParameterElement> parameters) {
if (parameters != null && parameters.length != _arguments.length) {
throw new ArgumentError(
"Expected ${_arguments.length} parameters, not ${parameters.length}");
}
_correspondingStaticParameters = parameters;
}
@override
Token get endToken => rightParenthesis;
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitArgumentList(this);
@override
void visitChildren(AstVisitor visitor) {
_arguments.accept(visitor);
}
/**
* If
* * the given [expression] is a child of this list,
* * the AST structure has been resolved,
* * the function being invoked is known based on static type information, and
* * the expression corresponds to one of the parameters of the function being
* invoked,
* then return the parameter element representing the parameter to which the
* value of the given expression will be bound. Otherwise, return `null`.
*/
ParameterElement _getStaticParameterElementFor(Expression expression) {
if (_correspondingStaticParameters == null ||
_correspondingStaticParameters.length != _arguments.length) {
// Either the AST structure has not been resolved, the invocation of which
// this list is a part could not be resolved, or the argument list was
// modified after the parameters were set.
return null;
}
int index = _arguments.indexOf(expression);
if (index < 0) {
// The expression isn't a child of this node.
return null;
}
return _correspondingStaticParameters[index];
}
}
/**
* An as expression.
*
* asExpression ::=
* [Expression] 'as' [TypeName]
*/
class AsExpressionImpl extends ExpressionImpl implements AsExpression {
/**
* The expression used to compute the value being cast.
*/
ExpressionImpl _expression;
/**
* The 'as' operator.
*/
@override
Token asOperator;
/**
* The type being cast to.
*/
TypeAnnotationImpl _type;
/**
* Initialize a newly created as expression.
*/
AsExpressionImpl(
ExpressionImpl expression, this.asOperator, TypeAnnotationImpl type) {
_expression = _becomeParentOf(expression);
_type = _becomeParentOf(type);
}
@override
Token get beginToken => _expression.beginToken;
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..add(_expression)..add(asOperator)..add(_type);
@override
Token get endToken => _type.endToken;
@override
Expression get expression => _expression;
@override
void set expression(Expression expression) {
_expression = _becomeParentOf(expression as ExpressionImpl);
}
@override
int get precedence => 7;
@override
TypeAnnotation get type => _type;
@override
void set type(TypeAnnotation type) {
_type = _becomeParentOf(type as TypeAnnotationImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitAsExpression(this);
@override
void visitChildren(AstVisitor visitor) {
_expression?.accept(visitor);
_type?.accept(visitor);
}
}
/**
* An assert in the initializer list of a constructor.
*
* assertInitializer ::=
* 'assert' '(' [Expression] (',' [Expression])? ')'
*/
class AssertInitializerImpl extends ConstructorInitializerImpl
implements AssertInitializer {
@override
Token assertKeyword;
@override
Token leftParenthesis;
/**
* The condition that is being asserted to be `true`.
*/
ExpressionImpl _condition;
@override
Token comma;
/**
* The message to report if the assertion fails, or `null` if no message was
* supplied.
*/
ExpressionImpl _message;
@override
Token rightParenthesis;
/**
* Initialize a newly created assert initializer.
*/
AssertInitializerImpl(
this.assertKeyword,
this.leftParenthesis,
ExpressionImpl condition,
this.comma,
ExpressionImpl message,
this.rightParenthesis) {
_condition = _becomeParentOf(condition);
_message = _becomeParentOf(message);
}
@override
Token get beginToken => assertKeyword;
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(assertKeyword)
..add(leftParenthesis)
..add(_condition)
..add(comma)
..add(_message)
..add(rightParenthesis);
@override
Expression get condition => _condition;
@override
void set condition(Expression condition) {
_condition = _becomeParentOf(condition as ExpressionImpl);
}
@override
Token get endToken => rightParenthesis;
@override
Expression get message => _message;
@override
void set message(Expression expression) {
_message = _becomeParentOf(expression as ExpressionImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitAssertInitializer(this);
@override
void visitChildren(AstVisitor visitor) {
_condition?.accept(visitor);
message?.accept(visitor);
}
}
/**
* An assert statement.
*
* assertStatement ::=
* 'assert' '(' [Expression] ')' ';'
*/
class AssertStatementImpl extends StatementImpl implements AssertStatement {
@override
Token assertKeyword;
@override
Token leftParenthesis;
/**
* The condition that is being asserted to be `true`.
*/
ExpressionImpl _condition;
@override
Token comma;
/**
* The message to report if the assertion fails, or `null` if no message was
* supplied.
*/
ExpressionImpl _message;
@override
Token rightParenthesis;
@override
Token semicolon;
/**
* Initialize a newly created assert statement.
*/
AssertStatementImpl(
this.assertKeyword,
this.leftParenthesis,
ExpressionImpl condition,
this.comma,
ExpressionImpl message,
this.rightParenthesis,
this.semicolon) {
_condition = _becomeParentOf(condition);
_message = _becomeParentOf(message);
}
@override
Token get beginToken => assertKeyword;
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(assertKeyword)
..add(leftParenthesis)
..add(_condition)
..add(comma)
..add(_message)
..add(rightParenthesis)
..add(semicolon);
@override
Expression get condition => _condition;
@override
void set condition(Expression condition) {
_condition = _becomeParentOf(condition as ExpressionImpl);
}
@override
Token get endToken => semicolon;
@override
Expression get message => _message;
@override
void set message(Expression expression) {
_message = _becomeParentOf(expression as ExpressionImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitAssertStatement(this);
@override
void visitChildren(AstVisitor visitor) {
_condition?.accept(visitor);
message?.accept(visitor);
}
}
/**
* An assignment expression.
*
* assignmentExpression ::=
* [Expression] operator [Expression]
*/
class AssignmentExpressionImpl extends ExpressionImpl
implements AssignmentExpression {
/**
* The expression used to compute the left hand side.
*/
ExpressionImpl _leftHandSide;
/**
* The assignment operator being applied.
*/
@override
Token operator;
/**
* The expression used to compute the right hand side.
*/
ExpressionImpl _rightHandSide;
/**
* The element associated with the operator based on the static type of the
* left-hand-side, or `null` if the AST structure has not been resolved, if
* the operator is not a compound operator, or if the operator could not be
* resolved.
*/
@override
MethodElement staticElement;
/**
* Initialize a newly created assignment expression.
*/
AssignmentExpressionImpl(ExpressionImpl leftHandSide, this.operator,
ExpressionImpl rightHandSide) {
if (leftHandSide == null || rightHandSide == null) {
String message;
if (leftHandSide == null) {
if (rightHandSide == null) {
message = "Both the left-hand and right-hand sides are null";
} else {
message = "The left-hand size is null";
}
} else {
message = "The right-hand size is null";
}
AnalysisEngine.instance.logger.logError(
message, new CaughtException(new AnalysisException(message), null));
}
_leftHandSide = _becomeParentOf(leftHandSide);
_rightHandSide = _becomeParentOf(rightHandSide);
}
@override
Token get beginToken => _leftHandSide.beginToken;
@override
@deprecated
MethodElement get bestElement => staticElement;
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(_leftHandSide)
..add(operator)
..add(_rightHandSide);
@override
Token get endToken => _rightHandSide.endToken;
@override
Expression get leftHandSide => _leftHandSide;
@override
void set leftHandSide(Expression expression) {
_leftHandSide = _becomeParentOf(expression as ExpressionImpl);
}
@override
int get precedence => 1;
@deprecated
@override
MethodElement get propagatedElement => null;
@deprecated
@override
set propagatedElement(MethodElement element) {}
@override
Expression get rightHandSide => _rightHandSide;
@override
void set rightHandSide(Expression expression) {
_rightHandSide = _becomeParentOf(expression as ExpressionImpl);
}
/**
* If the AST structure has been resolved, and the function being invoked is
* known based on static type information, then return the parameter element
* representing the parameter to which the value of the right operand will be
* bound. Otherwise, return `null`.
*/
ParameterElement get _staticParameterElementForRightHandSide {
ExecutableElement executableElement = null;
if (staticElement != null) {
executableElement = staticElement;
} else {
Expression left = _leftHandSide;
if (left is Identifier) {
Element leftElement = left.staticElement;
if (leftElement is ExecutableElement) {
executableElement = leftElement;
}
} else if (left is PropertyAccess) {
Element leftElement = left.propertyName.staticElement;
if (leftElement is ExecutableElement) {
executableElement = leftElement;
}
}
}
if (executableElement == null) {
return null;
}
List<ParameterElement> parameters = executableElement.parameters;
if (parameters.length < 1) {
return null;
}
return parameters[0];
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitAssignmentExpression(this);
@override
void visitChildren(AstVisitor visitor) {
_leftHandSide?.accept(visitor);
_rightHandSide?.accept(visitor);
}
}
/**
* A node in the AST structure for a Dart program.
*/
abstract class AstNodeImpl implements AstNode {
/**
* The parent of the node, or `null` if the node is the root of an AST
* structure.
*/
AstNode _parent;
/**
* A table mapping the names of properties to their values, or `null` if this
* node does not have any properties associated with it.
*/
Map<String, Object> _propertyMap;
@override
int get end => offset + length;
@override
bool get isSynthetic => false;
@override
int get length {
Token beginToken = this.beginToken;
Token endToken = this.endToken;
if (beginToken == null || endToken == null) {
return -1;
}
return endToken.offset + endToken.length - beginToken.offset;
}
@override
int get offset {
Token beginToken = this.beginToken;
if (beginToken == null) {
return -1;
}
return beginToken.offset;
}
@override
AstNode get parent => _parent;
@override
AstNode get root {
AstNode root = this;
AstNode parent = this.parent;
while (parent != null) {
root = parent;
parent = root.parent;
}
return root;
}
Token findPrevious(Token target) =>
util.findPrevious(beginToken, target) ?? parent?.findPrevious(target);
@override
@deprecated
E getAncestor<E extends AstNode>(Predicate<AstNode> predicate) =>
thisOrAncestorMatching(predicate);
@override
E getProperty<E>(String name) {
if (_propertyMap == null) {
return null;
}
return _propertyMap[name] as E;
}
@override
void setProperty(String name, Object value) {
if (value == null) {
if (_propertyMap != null) {
_propertyMap.remove(name);
if (_propertyMap.isEmpty) {
_propertyMap = null;
}
}
} else {
if (_propertyMap == null) {
_propertyMap = new HashMap<String, Object>();
}
_propertyMap[name] = value;
}
}
@override
E thisOrAncestorMatching<E extends AstNode>(Predicate<AstNode> predicate) {
// TODO(brianwilkerson) It is a bug that this method can return `this`.
AstNode node = this;
while (node != null && !predicate(node)) {
node = node.parent;
}
return node as E;
}
@override
T thisOrAncestorOfType<T extends AstNode>() {
AstNode node = this;
while (node != null && node is! T) {
node = node.parent;
}
return node as T;
}
@override
String toSource() {
StringBuffer buffer = new StringBuffer();
accept(new ToSourceVisitor2(buffer));
return buffer.toString();
}
@override
String toString() => toSource();
/**
* Make this node the parent of the given [child] node. Return the child node.
*/
T _becomeParentOf<T extends AstNodeImpl>(T child) {
if (child != null) {
child._parent = this;
}
return child;
}
}
/**
* An await expression.
*
* awaitExpression ::=
* 'await' [Expression]
*/
class AwaitExpressionImpl extends ExpressionImpl implements AwaitExpression {
/**
* The 'await' keyword.
*/
@override
Token awaitKeyword;
/**
* The expression whose value is being waited on.
*/
ExpressionImpl _expression;
/**
* Initialize a newly created await expression.
*/
AwaitExpressionImpl(this.awaitKeyword, ExpressionImpl expression) {
_expression = _becomeParentOf(expression);
}
@override
Token get beginToken {
if (awaitKeyword != null) {
return awaitKeyword;
}
return _expression.beginToken;
}
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..add(awaitKeyword)..add(_expression);
@override
Token get endToken => _expression.endToken;
@override
Expression get expression => _expression;
@override
void set expression(Expression expression) {
_expression = _becomeParentOf(expression as ExpressionImpl);
}
@override
int get precedence => 14;
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitAwaitExpression(this);
@override
void visitChildren(AstVisitor visitor) {
_expression?.accept(visitor);
}
}
/**
* A binary (infix) expression.
*
* binaryExpression ::=
* [Expression] [Token] [Expression]
*/
class BinaryExpressionImpl extends ExpressionImpl implements BinaryExpression {
/**
* The expression used to compute the left operand.
*/
ExpressionImpl _leftOperand;
/**
* The binary operator being applied.
*/
@override
Token operator;
/**
* The expression used to compute the right operand.
*/
ExpressionImpl _rightOperand;
/**
* The element associated with the operator based on the static type of the
* left operand, or `null` if the AST structure has not been resolved, if the
* operator is not user definable, or if the operator could not be resolved.
*/
@override
MethodElement staticElement;
@override
FunctionType staticInvokeType;
/**
* Initialize a newly created binary expression.
*/
BinaryExpressionImpl(
ExpressionImpl leftOperand, this.operator, ExpressionImpl rightOperand) {
_leftOperand = _becomeParentOf(leftOperand);
_rightOperand = _becomeParentOf(rightOperand);
}
@override
Token get beginToken => _leftOperand.beginToken;
@override
@deprecated
MethodElement get bestElement => staticElement;
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..add(_leftOperand)..add(operator)..add(_rightOperand);
@override
Token get endToken => _rightOperand.endToken;
@override
Expression get leftOperand => _leftOperand;
@override
void set leftOperand(Expression expression) {
_leftOperand = _becomeParentOf(expression as ExpressionImpl);
}
@override
int get precedence => operator.type.precedence;
@deprecated
@override
MethodElement get propagatedElement => null;
@deprecated
@override
set propagatedElement(MethodElement element) {}
@override
Expression get rightOperand => _rightOperand;
@override
void set rightOperand(Expression expression) {
_rightOperand = _becomeParentOf(expression as ExpressionImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitBinaryExpression(this);
@override
void visitChildren(AstVisitor visitor) {
_leftOperand?.accept(visitor);
_rightOperand?.accept(visitor);
}
}
/**
* A function body that consists of a block of statements.
*
* blockFunctionBody ::=
* ('async' | 'async' '*' | 'sync' '*')? [Block]
*/
class BlockFunctionBodyImpl extends FunctionBodyImpl
implements BlockFunctionBody {
/**
* The token representing the 'async' or 'sync' keyword, or `null` if there is
* no such keyword.
*/
@override
Token keyword;
/**
* The star optionally following the 'async' or 'sync' keyword, or `null` if
* there is wither no such keyword or no star.
*/
@override
Token star;
/**
* The block representing the body of the function.
*/
BlockImpl _block;
/**
* Initialize a newly created function body consisting of a block of
* statements. The [keyword] can be `null` if there is no keyword specified
* for the block. The [star] can be `null` if there is no star following the
* keyword (and must be `null` if there is no keyword).
*/
BlockFunctionBodyImpl(this.keyword, this.star, BlockImpl block) {
_block = _becomeParentOf(block);
}
@override
Token get beginToken {
if (keyword != null) {
return keyword;
}
return _block.beginToken;
}
@override
Block get block => _block;
@override
void set block(Block block) {
_block = _becomeParentOf(block as BlockImpl);
}
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..add(keyword)..add(star)..add(_block);
@override
Token get endToken => _block.endToken;
@override
bool get isAsynchronous => keyword != null && keyword.lexeme == Parser.ASYNC;
@override
bool get isGenerator => star != null;
@override
bool get isSynchronous => keyword == null || keyword.lexeme != Parser.ASYNC;
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitBlockFunctionBody(this);
@override
void visitChildren(AstVisitor visitor) {
_block?.accept(visitor);
}
}
/**
* A sequence of statements.
*
* block ::=
* '{' statement* '}'
*/
class BlockImpl extends StatementImpl implements Block {
/**
* The left curly bracket.
*/
@override
Token leftBracket;
/**
* The statements contained in the block.
*/
NodeList<Statement> _statements;
/**
* The right curly bracket.
*/
@override
Token rightBracket;
/**
* Initialize a newly created block of code.
*/
BlockImpl(this.leftBracket, List<Statement> statements, this.rightBracket) {
_statements = new NodeListImpl<Statement>(this, statements);
}
@override
Token get beginToken => leftBracket;
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(leftBracket)
..addAll(_statements)
..add(rightBracket);
@override
Token get endToken => rightBracket;
@override
NodeList<Statement> get statements => _statements;
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitBlock(this);
@override
void visitChildren(AstVisitor visitor) {
_statements.accept(visitor);
}
}
/**
* A boolean literal expression.
*
* booleanLiteral ::=
* 'false' | 'true'
*/
class BooleanLiteralImpl extends LiteralImpl implements BooleanLiteral {
/**
* The token representing the literal.
*/
@override
Token literal;
/**
* The value of the literal.
*/
@override
bool value = false;
/**
* Initialize a newly created boolean literal.
*/
BooleanLiteralImpl(this.literal, this.value);
@override
Token get beginToken => literal;
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..add(literal);
@override
Token get endToken => literal;
@override
bool get isSynthetic => literal.isSynthetic;
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitBooleanLiteral(this);
@override
void visitChildren(AstVisitor visitor) {
// There are no children to visit.
}
}
/**
* A break statement.
*
* breakStatement ::=
* 'break' [SimpleIdentifier]? ';'
*/
class BreakStatementImpl extends StatementImpl implements BreakStatement {
/**
* The token representing the 'break' keyword.
*/
@override
Token breakKeyword;
/**
* The label associated with the statement, or `null` if there is no label.
*/
SimpleIdentifierImpl _label;
/**
* The semicolon terminating the statement.
*/
@override
Token semicolon;
/**
* The AstNode which this break statement is breaking from. This will be
* either a [Statement] (in the case of breaking out of a loop), a
* [SwitchMember] (in the case of a labeled break statement whose label
* matches a label on a switch case in an enclosing switch statement), or
* `null` if the AST has not yet been resolved or if the target could not be
* resolved. Note that if the source code has errors, the target might be
* invalid (e.g. trying to break to a switch case).
*/
@override
AstNode target;
/**
* Initialize a newly created break statement. The [label] can be `null` if
* there is no label associated with the statement.
*/
BreakStatementImpl(
this.breakKeyword, SimpleIdentifierImpl label, this.semicolon) {
_label = _becomeParentOf(label);
}
@override
Token get beginToken => breakKeyword;
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..add(breakKeyword)..add(_label)..add(semicolon);
@override
Token get endToken => semicolon;
@override
SimpleIdentifier get label => _label;
@override
void set label(SimpleIdentifier identifier) {
_label = _becomeParentOf(identifier as SimpleIdentifierImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitBreakStatement(this);
@override
void visitChildren(AstVisitor visitor) {
_label?.accept(visitor);
}
}
/**
* A sequence of cascaded expressions: expressions that share a common target.
* There are three kinds of expressions that can be used in a cascade
* expression: [IndexExpression], [MethodInvocation] and [PropertyAccess].
*
* cascadeExpression ::=
* [Expression] cascadeSection*
*
* cascadeSection ::=
* '..' (cascadeSelector arguments*) (assignableSelector arguments*)*
* (assignmentOperator expressionWithoutCascade)?
*
* cascadeSelector ::=
* '[ ' expression '] '
* | identifier
*/
class CascadeExpressionImpl extends ExpressionImpl
implements CascadeExpression {
/**
* The target of the cascade sections.
*/
ExpressionImpl _target;
/**
* The cascade sections sharing the common target.
*/
NodeList<Expression> _cascadeSections;
/**
* Initialize a newly created cascade expression. The list of
* [cascadeSections] must contain at least one element.
*/
CascadeExpressionImpl(
ExpressionImpl target, List<Expression> cascadeSections) {
_target = _becomeParentOf(target);
_cascadeSections = new NodeListImpl<Expression>(this, cascadeSections);
}
@override
Token get beginToken => _target.beginToken;
@override
NodeList<Expression> get cascadeSections => _cascadeSections;
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(_target)
..addAll(_cascadeSections);
@override
Token get endToken => _cascadeSections.endToken;
@override
int get precedence => 2;
@override
Expression get target => _target;
@override
void set target(Expression target) {
_target = _becomeParentOf(target as ExpressionImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitCascadeExpression(this);
@override
void visitChildren(AstVisitor visitor) {
_target?.accept(visitor);
_cascadeSections.accept(visitor);
}
}
/**
* A catch clause within a try statement.
*
* onPart ::=
* catchPart [Block]
* | 'on' type catchPart? [Block]
*
* catchPart ::=
* 'catch' '(' [SimpleIdentifier] (',' [SimpleIdentifier])? ')'
*/
class CatchClauseImpl extends AstNodeImpl implements CatchClause {
/**
* The token representing the 'on' keyword, or `null` if there is no 'on'
* keyword.
*/
@override
Token onKeyword;
/**
* The type of exceptions caught by this catch clause, or `null` if this catch
* clause catches every type of exception.
*/
TypeAnnotationImpl _exceptionType;
/**
* The token representing the 'catch' keyword, or `null` if there is no
* 'catch' keyword.
*/
@override
Token catchKeyword;
/**
* The left parenthesis, or `null` if there is no 'catch' keyword.
*/
@override
Token leftParenthesis;
/**
* The parameter whose value will be the exception that was thrown, or `null`
* if there is no 'catch' keyword.
*/
SimpleIdentifierImpl _exceptionParameter;
/**
* The comma separating the exception parameter from the stack trace
* parameter, or `null` if there is no stack trace parameter.
*/
@override
Token comma;
/**
* The parameter whose value will be the stack trace associated with the
* exception, or `null` if there is no stack trace parameter.
*/
SimpleIdentifierImpl _stackTraceParameter;
/**
* The right parenthesis, or `null` if there is no 'catch' keyword.
*/
@override
Token rightParenthesis;
/**
* The body of the catch block.
*/
BlockImpl _body;
/**
* Initialize a newly created catch clause. The [onKeyword] and
* [exceptionType] can be `null` if the clause will catch all exceptions. The
* [comma] and [stackTraceParameter] can be `null` if the stack trace
* parameter is not defined.
*/
CatchClauseImpl(
this.onKeyword,
TypeAnnotationImpl exceptionType,
this.catchKeyword,
this.leftParenthesis,
SimpleIdentifierImpl exceptionParameter,
this.comma,
SimpleIdentifierImpl stackTraceParameter,
this.rightParenthesis,
BlockImpl body) {
_exceptionType = _becomeParentOf(exceptionType);
_exceptionParameter = _becomeParentOf(exceptionParameter);
_stackTraceParameter = _becomeParentOf(stackTraceParameter);
_body = _becomeParentOf(body);
}
@override
Token get beginToken {
if (onKeyword != null) {
return onKeyword;
}
return catchKeyword;
}
@override
Block get body => _body;
@override
void set body(Block block) {
_body = _becomeParentOf(block as BlockImpl);
}
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(onKeyword)
..add(_exceptionType)
..add(catchKeyword)
..add(leftParenthesis)
..add(_exceptionParameter)
..add(comma)
..add(_stackTraceParameter)
..add(rightParenthesis)
..add(_body);
@override
Token get endToken => _body.endToken;
@override
SimpleIdentifier get exceptionParameter => _exceptionParameter;
@override
void set exceptionParameter(SimpleIdentifier parameter) {
_exceptionParameter = _becomeParentOf(parameter as SimpleIdentifierImpl);
}
@override
TypeAnnotation get exceptionType => _exceptionType;
@override
void set exceptionType(TypeAnnotation exceptionType) {
_exceptionType = _becomeParentOf(exceptionType as TypeAnnotationImpl);
}
@override
SimpleIdentifier get stackTraceParameter => _stackTraceParameter;
@override
void set stackTraceParameter(SimpleIdentifier parameter) {
_stackTraceParameter = _becomeParentOf(parameter as SimpleIdentifierImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitCatchClause(this);
@override
void visitChildren(AstVisitor visitor) {
_exceptionType?.accept(visitor);
_exceptionParameter?.accept(visitor);
_stackTraceParameter?.accept(visitor);
_body?.accept(visitor);
}
}
/**
* Helper class to allow iteration of child entities of an AST node.
*/
class ChildEntities
with IterableMixin<SyntacticEntity>
implements Iterable<SyntacticEntity> {
/**
* The list of child entities to be iterated over.
*/
List<SyntacticEntity> _entities = [];
@override
Iterator<SyntacticEntity> get iterator => _entities.iterator;
/**
* Add an AST node or token as the next child entity, if it is not null.
*/
void add(SyntacticEntity entity) {
if (entity != null) {
_entities.add(entity);
}
}
/**
* Add the given items as the next child entities, if [items] is not null.
*/
void addAll(Iterable<SyntacticEntity> items) {
if (items != null) {
_entities.addAll(items);
}
}
}
/**
* The declaration of a class.
*
* classDeclaration ::=
* 'abstract'? 'class' [SimpleIdentifier] [TypeParameterList]?
* ([ExtendsClause] [WithClause]?)?
* [ImplementsClause]?
* '{' [ClassMember]* '}'
*/
class ClassDeclarationImpl extends ClassOrMixinDeclarationImpl
implements ClassDeclaration {
/**
* The 'abstract' keyword, or `null` if the keyword was absent.
*/
@override
Token abstractKeyword;
/**
* The token representing the 'class' keyword.
*/
@override
Token classKeyword;
/**
* The extends clause for the class, or `null` if the class does not extend
* any other class.
*/
ExtendsClauseImpl _extendsClause;
/**
* The with clause for the class, or `null` if the class does not have a with
* clause.
*/
WithClauseImpl _withClause;
/**
* The native clause for the class, or `null` if the class does not have a
* native clause.
*/
NativeClauseImpl _nativeClause;
/**
* Initialize a newly created class declaration. Either or both of the
* [comment] and [metadata] can be `null` if the class does not have the
* corresponding attribute. The [abstractKeyword] can be `null` if the class
* is not abstract. The [typeParameters] can be `null` if the class does not
* have any type parameters. Any or all of the [extendsClause], [withClause],
* and [implementsClause] can be `null` if the class does not have the
* corresponding clause. The list of [members] can be `null` if the class does
* not have any members.
*/
ClassDeclarationImpl(
CommentImpl comment,
List<Annotation> metadata,
this.abstractKeyword,
this.classKeyword,
SimpleIdentifierImpl name,
TypeParameterListImpl typeParameters,
ExtendsClauseImpl extendsClause,
WithClauseImpl withClause,
ImplementsClauseImpl implementsClause,
Token leftBracket,
List<ClassMember> members,
Token rightBracket)
: super(comment, metadata, name, typeParameters, implementsClause,
leftBracket, members, rightBracket) {
_extendsClause = _becomeParentOf(extendsClause);
_withClause = _becomeParentOf(withClause);
}
@override
Iterable<SyntacticEntity> get childEntities => super._childEntities
..add(abstractKeyword)
..add(classKeyword)
..add(_name)
..add(_typeParameters)
..add(_extendsClause)
..add(_withClause)
..add(_implementsClause)
..add(_nativeClause)
..add(leftBracket)
..addAll(members)
..add(rightBracket);
@override
ClassElement get declaredElement => _name?.staticElement as ClassElement;
@deprecated
@override
ClassElement get element => declaredElement;
@override
ExtendsClause get extendsClause => _extendsClause;
@override
void set extendsClause(ExtendsClause extendsClause) {
_extendsClause = _becomeParentOf(extendsClause as ExtendsClauseImpl);
}
@override
Token get firstTokenAfterCommentAndMetadata {
if (abstractKeyword != null) {
return abstractKeyword;
}
return classKeyword;
}
@override
bool get isAbstract => abstractKeyword != null;
@override
NativeClause get nativeClause => _nativeClause;
@override
void set nativeClause(NativeClause nativeClause) {
_nativeClause = _becomeParentOf(nativeClause as NativeClauseImpl);
}
@override
WithClause get withClause => _withClause;
@override
void set withClause(WithClause withClause) {
_withClause = _becomeParentOf(withClause as WithClauseImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitClassDeclaration(this);
@override
ConstructorDeclaration getConstructor(String name) {
int length = _members.length;
for (int i = 0; i < length; i++) {
ClassMember classMember = _members[i];
if (classMember is ConstructorDeclaration) {
ConstructorDeclaration constructor = classMember;
SimpleIdentifier constructorName = constructor.name;
if (name == null && constructorName == null) {
return constructor;
}
if (constructorName != null && constructorName.name == name) {
return constructor;
}
}
}
return null;
}
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
_name?.accept(visitor);
_typeParameters?.accept(visitor);
_extendsClause?.accept(visitor);
_withClause?.accept(visitor);
_implementsClause?.accept(visitor);
_nativeClause?.accept(visitor);
members.accept(visitor);
}
}
/**
* A node that declares a name within the scope of a class.
*/
abstract class ClassMemberImpl extends DeclarationImpl implements ClassMember {
/**
* Initialize a newly created member of a class. Either or both of the
* [comment] and [metadata] can be `null` if the member does not have the
* corresponding attribute.
*/
ClassMemberImpl(CommentImpl comment, List<Annotation> metadata)
: super(comment, metadata);
}
abstract class ClassOrMixinDeclarationImpl
extends NamedCompilationUnitMemberImpl implements ClassOrMixinDeclaration {
/**
* The type parameters for the class or mixin,
* or `null` if the declaration does not have any type parameters.
*/
TypeParameterListImpl _typeParameters;
/**
* The implements clause for the class or mixin,
* or `null` if the declaration does not implement any interfaces.
*/
ImplementsClauseImpl _implementsClause;
/**
* The left curly bracket.
*/
Token leftBracket;
/**
* The members defined by the class or mixin.
*/
NodeList<ClassMember> _members;
/**
* The right curly bracket.
*/
Token rightBracket;
ClassOrMixinDeclarationImpl(
CommentImpl comment,
List<Annotation> metadata,
SimpleIdentifierImpl name,
TypeParameterListImpl typeParameters,
ImplementsClauseImpl implementsClause,
this.leftBracket,
List<ClassMember> members,
this.rightBracket)
: super(comment, metadata, name) {
_typeParameters = _becomeParentOf(typeParameters);
_implementsClause = _becomeParentOf(implementsClause);
_members = new NodeListImpl<ClassMember>(this, members);
}
Token get endToken => rightBracket;
ImplementsClause get implementsClause => _implementsClause;
void set implementsClause(ImplementsClause implementsClause) {
_implementsClause =
_becomeParentOf(implementsClause as ImplementsClauseImpl);
}
NodeList<ClassMember> get members => _members;
TypeParameterList get typeParameters => _typeParameters;
void set typeParameters(TypeParameterList typeParameters) {
_typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl);
}
VariableDeclaration getField(String name) {
int memberLength = _members.length;
for (int i = 0; i < memberLength; i++) {
ClassMember classMember = _members[i];
if (classMember is FieldDeclaration) {
FieldDeclaration fieldDeclaration = classMember;
NodeList<VariableDeclaration> fields =
fieldDeclaration.fields.variables;
int fieldLength = fields.length;
for (int i = 0; i < fieldLength; i++) {
VariableDeclaration field = fields[i];
SimpleIdentifier fieldName = field.name;
if (fieldName != null && name == fieldName.name) {
return field;
}
}
}
}
return null;
}
MethodDeclaration getMethod(String name) {
int length = _members.length;
for (int i = 0; i < length; i++) {
ClassMember classMember = _members[i];
if (classMember is MethodDeclaration) {
MethodDeclaration method = classMember;
SimpleIdentifier methodName = method.name;
if (methodName != null && name == methodName.name) {
return method;
}
}
}
return null;
}
}
/**
* A class type alias.
*
* classTypeAlias ::=
* [SimpleIdentifier] [TypeParameterList]? '=' 'abstract'? mixinApplication
*
* mixinApplication ::=
* [TypeName] [WithClause] [ImplementsClause]? ';'
*/
class ClassTypeAliasImpl extends TypeAliasImpl implements ClassTypeAlias {
/**
* The type parameters for the class, or `null` if the class does not have any
* type parameters.
*/
TypeParameterListImpl _typeParameters;
/**
* The token for the '=' separating the name from the definition.
*/
@override
Token equals;
/**
* The token for the 'abstract' keyword, or `null` if this is not defining an
* abstract class.
*/
@override
Token abstractKeyword;
/**
* The name of the superclass of the class being declared.
*/
TypeNameImpl _superclass;
/**
* The with clause for this class.
*/
WithClauseImpl _withClause;
/**
* The implements clause for this class, or `null` if there is no implements
* clause.
*/
ImplementsClauseImpl _implementsClause;
/**
* Initialize a newly created class type alias. Either or both of the
* [comment] and [metadata] can be `null` if the class type alias does not
* have the corresponding attribute. The [typeParameters] can be `null` if the
* class does not have any type parameters. The [abstractKeyword] can be
* `null` if the class is not abstract. The [implementsClause] can be `null`
* if the class does not implement any interfaces.
*/
ClassTypeAliasImpl(
CommentImpl comment,
List<Annotation> metadata,
Token keyword,
SimpleIdentifierImpl name,
TypeParameterListImpl typeParameters,
this.equals,
this.abstractKeyword,
TypeNameImpl superclass,
WithClauseImpl withClause,
ImplementsClauseImpl implementsClause,
Token semicolon)
: super(comment, metadata, keyword, name, semicolon) {
_typeParameters = _becomeParentOf(typeParameters);
_superclass = _becomeParentOf(superclass);
_withClause = _becomeParentOf(withClause);
_implementsClause = _becomeParentOf(implementsClause);
}
@override
Iterable<SyntacticEntity> get childEntities => super._childEntities
..add(typedefKeyword)
..add(_name)
..add(_typeParameters)
..add(equals)
..add(abstractKeyword)
..add(_superclass)
..add(_withClause)
..add(_implementsClause)
..add(semicolon);
@override
ClassElement get declaredElement => _name?.staticElement as ClassElement;
@deprecated
@override
ClassElement get element => declaredElement;
@override
Token get firstTokenAfterCommentAndMetadata {
if (abstractKeyword != null) {
return abstractKeyword;
}
return typedefKeyword;
}
@override
ImplementsClause get implementsClause => _implementsClause;
@override
void set implementsClause(ImplementsClause implementsClause) {
_implementsClause =
_becomeParentOf(implementsClause as ImplementsClauseImpl);
}
@override
bool get isAbstract => abstractKeyword != null;
@override
TypeName get superclass => _superclass;
@override
void set superclass(TypeName superclass) {
_superclass = _becomeParentOf(superclass as TypeNameImpl);
}
@override
TypeParameterList get typeParameters => _typeParameters;
@override
void set typeParameters(TypeParameterList typeParameters) {
_typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl);
}
@override
WithClause get withClause => _withClause;
@override
void set withClause(WithClause withClause) {
_withClause = _becomeParentOf(withClause as WithClauseImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitClassTypeAlias(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
_name?.accept(visitor);
_typeParameters?.accept(visitor);
_superclass?.accept(visitor);
_withClause?.accept(visitor);
_implementsClause?.accept(visitor);
}
}
/**
* A combinator associated with an import or export directive.
*
* combinator ::=
* [HideCombinator]
* | [ShowCombinator]
*/
abstract class CombinatorImpl extends AstNodeImpl implements Combinator {
/**
* The 'hide' or 'show' keyword specifying what kind of processing is to be
* done on the names.
*/
@override
Token keyword;
/**
* Initialize a newly created combinator.
*/
CombinatorImpl(this.keyword);
@override
Token get beginToken => keyword;
}
/**
* A comment within the source code.
*
* comment ::=
* endOfLineComment
* | blockComment
* | documentationComment
*
* endOfLineComment ::=
* '//' (CHARACTER - EOL)* EOL
*
* blockComment ::=
* '/ *' CHARACTER* '&#42;/'
*
* documentationComment ::=
* '/ **' (CHARACTER | [CommentReference])* '&#42;/'
* | ('///' (CHARACTER - EOL)* EOL)+
*/
class CommentImpl extends AstNodeImpl implements Comment {
/**
* The tokens representing the comment.
*/
@override
final List<Token> tokens;
/**
* The type of the comment.
*/
final CommentType _type;
/**
* The references embedded within the documentation comment. This list will be
* empty unless this is a documentation comment that has references embedded
* within it.
*/
NodeList<CommentReference> _references;
/**
* Initialize a newly created comment. The list of [tokens] must contain at
* least one token. The [_type] is the type of the comment. The list of
* [references] can be empty if the comment does not contain any embedded
* references.
*/
CommentImpl(this.tokens, this._type, List<CommentReference> references) {
_references = new NodeListImpl<CommentReference>(this, references);
}
@override
Token get beginToken => tokens[0];
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..addAll(tokens);
@override
Token get endToken => tokens[tokens.length - 1];
@override
bool get isBlock => _type == CommentType.BLOCK;
@override
bool get isDocumentation => _type == CommentType.DOCUMENTATION;
@override
bool get isEndOfLine => _type == CommentType.END_OF_LINE;
@override
NodeList<CommentReference> get references => _references;
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitComment(this);
@override
void visitChildren(AstVisitor visitor) {
_references.accept(visitor);
}
/**
* Create a block comment consisting of the given [tokens].
*/
static Comment createBlockComment(List<Token> tokens) =>
new CommentImpl(tokens, CommentType.BLOCK, null);
/**
* Create a documentation comment consisting of the given [tokens].
*/
static Comment createDocumentationComment(List<Token> tokens) =>
new CommentImpl(
tokens, CommentType.DOCUMENTATION, new List<CommentReference>());
/**
* Create a documentation comment consisting of the given [tokens] and having
* the given [references] embedded within it.
*/
static Comment createDocumentationCommentWithReferences(
List<Token> tokens, List<CommentReference> references) =>
new CommentImpl(tokens, CommentType.DOCUMENTATION, references);
/**
* Create an end-of-line comment consisting of the given [tokens].
*/
static Comment createEndOfLineComment(List<Token> tokens) =>
new CommentImpl(tokens, CommentType.END_OF_LINE, null);
}
/**
* A reference to a Dart element that is found within a documentation comment.
*
* commentReference ::=
* '[' 'new'? [Identifier] ']'
*/
class CommentReferenceImpl extends AstNodeImpl implements CommentReference {
/**
* The token representing the 'new' keyword, or `null` if there was no 'new'
* keyword.
*/
@override
Token newKeyword;
/**
* The identifier being referenced.
*/
IdentifierImpl _identifier;
/**
* Initialize a newly created reference to a Dart element. The [newKeyword]
* can be `null` if the reference is not to a constructor.
*/
CommentReferenceImpl(this.newKeyword, IdentifierImpl identifier) {
_identifier = _becomeParentOf(identifier);
}
@override
Token get beginToken => newKeyword ?? _identifier.beginToken;
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..add(newKeyword)..add(_identifier);
@override
Token get endToken => _identifier.endToken;
@override
Identifier get identifier => _identifier;
@override
void set identifier(Identifier identifier) {
_identifier = _becomeParentOf(identifier as IdentifierImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitCommentReference(this);
@override
void visitChildren(AstVisitor visitor) {
_identifier?.accept(visitor);
}
}
/**
* The possible types of comments that are recognized by the parser.
*/
class CommentType {
/**
* A block comment.
*/
static const CommentType BLOCK = const CommentType('BLOCK');
/**
* A documentation comment.
*/
static const CommentType DOCUMENTATION = const CommentType('DOCUMENTATION');
/**
* An end-of-line comment.
*/
static const CommentType END_OF_LINE = const CommentType('END_OF_LINE');
/**
* The name of the comment type.
*/
final String name;
/**
* Initialize a newly created comment type to have the given [name].
*/
const CommentType(this.name);
@override
String toString() => name;
}
/**
* A compilation unit.
*
* While the grammar restricts the order of the directives and declarations
* within a compilation unit, this class does not enforce those restrictions.
* In particular, the children of a compilation unit will be visited in lexical
* order even if lexical order does not conform to the restrictions of the
* grammar.
*
* compilationUnit ::=
* directives declarations
*
* directives ::=
* [ScriptTag]? [LibraryDirective]? namespaceDirective* [PartDirective]*
* | [PartOfDirective]
*
* namespaceDirective ::=
* [ImportDirective]
* | [ExportDirective]
*
* declarations ::=
* [CompilationUnitMember]*
*/
class CompilationUnitImpl extends AstNodeImpl implements CompilationUnit {
/**
* The first token in the token stream that was parsed to form this
* compilation unit.
*/
@override
Token beginToken;
/**
* The script tag at the beginning of the compilation unit, or `null` if there
* is no script tag in this compilation unit.
*/
ScriptTagImpl _scriptTag;
/**
* The directives contained in this compilation unit.
*/
NodeList<Directive> _directives;
/**
* The declarations contained in this compilation unit.
*/
NodeList<CompilationUnitMember> _declarations;
/**
* The last token in the token stream that was parsed to form this compilation
* unit. This token should always have a type of [TokenType.EOF].
*/
@override
Token endToken;
/**
* The element associated with this compilation unit, or `null` if the AST
* structure has not been resolved.
*/
@override
CompilationUnitElement declaredElement;
/**
* The line information for this compilation unit.
*/
@override
LineInfo lineInfo;
Map<int, AstNode> localDeclarations;
/**
* Initialize a newly created compilation unit to have the given directives
* and declarations. The [scriptTag] can be `null` if there is no script tag
* in the compilation unit. The list of [directives] can be `null` if there
* are no directives in the compilation unit. The list of [declarations] can
* be `null` if there are no declarations in the compilation unit.
*/
CompilationUnitImpl(
this.beginToken,
ScriptTagImpl scriptTag,
List<Directive> directives,
List<CompilationUnitMember> declarations,
this.endToken) {
_scriptTag = _becomeParentOf(scriptTag);
_directives = new NodeListImpl<Directive>(this, directives);
_declarations = new NodeListImpl<CompilationUnitMember>(this, declarations);
}
@override
Iterable<SyntacticEntity> get childEntities {
ChildEntities result = new ChildEntities()..add(_scriptTag);
if (_directivesAreBeforeDeclarations) {
result..addAll(_directives)..addAll(_declarations);
} else {
result.addAll(sortedDirectivesAndDeclarations);
}
return result;
}
@override
NodeList<CompilationUnitMember> get declarations => _declarations;
@override
NodeList<Directive> get directives => _directives;
@deprecated
@override
CompilationUnitElement get element => declaredElement;
@override
set element(CompilationUnitElement element) {
declaredElement = element;
}
@override
int get length {
Token endToken = this.endToken;
if (endToken == null) {
return 0;
}
return endToken.offset + endToken.length;
}
@override
int get offset => 0;
@override
ScriptTag get scriptTag => _scriptTag;
@override
void set scriptTag(ScriptTag scriptTag) {
_scriptTag = _becomeParentOf(scriptTag as ScriptTagImpl);
}
@override
List<AstNode> get sortedDirectivesAndDeclarations {
return <AstNode>[]
..addAll(_directives)
..addAll(_declarations)
..sort(AstNode.LEXICAL_ORDER);
}
/**
* Return `true` if all of the directives are lexically before any
* declarations.
*/
bool get _directivesAreBeforeDeclarations {
if (_directives.isEmpty || _declarations.isEmpty) {
return true;
}
Directive lastDirective = _directives[_directives.length - 1];
CompilationUnitMember firstDeclaration = _declarations[0];
return lastDirective.offset < firstDeclaration.offset;
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitCompilationUnit(this);
@override
void visitChildren(AstVisitor visitor) {
_scriptTag?.accept(visitor);
if (_directivesAreBeforeDeclarations) {
_directives.accept(visitor);
_declarations.accept(visitor);
} else {
List<AstNode> sortedMembers = sortedDirectivesAndDeclarations;
int length = sortedMembers.length;
for (int i = 0; i < length; i++) {
AstNode child = sortedMembers[i];
child.accept(visitor);
}
}
}
}
/**
* A node that declares one or more names within the scope of a compilation
* unit.
*
* compilationUnitMember ::=
* [ClassDeclaration]
* | [TypeAlias]
* | [FunctionDeclaration]
* | [MethodDeclaration]
* | [VariableDeclaration]
* | [VariableDeclaration]
*/
abstract class CompilationUnitMemberImpl extends DeclarationImpl
implements CompilationUnitMember {
/**
* Initialize a newly created generic compilation unit member. Either or both
* of the [comment] and [metadata] can be `null` if the member does not have
* the corresponding attribute.
*/
CompilationUnitMemberImpl(CommentImpl comment, List<Annotation> metadata)
: super(comment, metadata);
}
/**
* A conditional expression.
*
* conditionalExpression ::=
* [Expression] '?' [Expression] ':' [Expression]
*/
class ConditionalExpressionImpl extends ExpressionImpl
implements ConditionalExpression {
/**
* The condition used to determine which of the expressions is executed next.
*/
ExpressionImpl _condition;
/**
* The token used to separate the condition from the then expression.
*/
@override
Token question;
/**
* The expression that is executed if the condition evaluates to `true`.
*/
ExpressionImpl _thenExpression;
/**
* The token used to separate the then expression from the else expression.
*/
@override
Token colon;
/**
* The expression that is executed if the condition evaluates to `false`.
*/
ExpressionImpl _elseExpression;
/**
* Initialize a newly created conditional expression.
*/
ConditionalExpressionImpl(
ExpressionImpl condition,
this.question,
ExpressionImpl thenExpression,
this.colon,
ExpressionImpl elseExpression) {
_condition = _becomeParentOf(condition);
_thenExpression = _becomeParentOf(thenExpression);
_elseExpression = _becomeParentOf(elseExpression);
}
@override
Token get beginToken => _condition.beginToken;
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(_condition)
..add(question)
..add(_thenExpression)
..add(colon)
..add(_elseExpression);
@override
Expression get condition => _condition;
@override
void set condition(Expression expression) {
_condition = _becomeParentOf(expression as ExpressionImpl);
}
@override
Expression get elseExpression => _elseExpression;
@override
void set elseExpression(Expression expression) {
_elseExpression = _becomeParentOf(expression as ExpressionImpl);
}
@override
Token get endToken => _elseExpression.endToken;
@override
int get precedence => 3;
@override
Expression get thenExpression => _thenExpression;
@override
void set thenExpression(Expression expression) {
_thenExpression = _becomeParentOf(expression as ExpressionImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) =>
visitor.visitConditionalExpression(this);
@override
void visitChildren(AstVisitor visitor) {
_condition?.accept(visitor);
_thenExpression?.accept(visitor);
_elseExpression?.accept(visitor);
}
}
/**
* A configuration in either an import or export directive.
*
* configuration ::=
* 'if' '(' test ')' uri
*
* test ::=
* dottedName ('==' stringLiteral)?
*
* dottedName ::=
* identifier ('.' identifier)*
*/
class ConfigurationImpl extends AstNodeImpl implements Configuration {
@override
Token ifKeyword;
@override
Token leftParenthesis;
DottedNameImpl _name;
@override
Token equalToken;
StringLiteralImpl _value;
@override
Token rightParenthesis;
StringLiteralImpl _uri;
@override
Source uriSource;
ConfigurationImpl(
this.ifKeyword,
this.leftParenthesis,
DottedNameImpl name,
this.equalToken,
StringLiteralImpl value,
this.rightParenthesis,
StringLiteralImpl libraryUri) {
_name = _becomeParentOf(name);
_value = _becomeParentOf(value);
_uri = _becomeParentOf(libraryUri);
}
@override
Token get beginToken => ifKeyword;
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(ifKeyword)
..add(leftParenthesis)
..add(_name)
..add(equalToken)
..add(_value)
..add(rightParenthesis)
..add(_uri);
@override
Token get endToken => _uri.endToken;
@deprecated
@override
StringLiteral get libraryUri => _uri;
@deprecated
@override
void set libraryUri(StringLiteral libraryUri) {
_uri = _becomeParentOf(libraryUri as StringLiteralImpl);
}
@override
DottedName get name => _name;
@override
void set name(DottedName name) {
_name = _becomeParentOf(name as DottedNameImpl);
}
@override
StringLiteral get uri => _uri;
@override
void set uri(StringLiteral uri) {
_uri = _becomeParentOf(uri as StringLiteralImpl);
}
@override
StringLiteral get value => _value;
@override
void set value(StringLiteral value) {
_value = _becomeParentOf(value as StringLiteralImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitConfiguration(this);
@override
void visitChildren(AstVisitor visitor) {
_name?.accept(visitor);
_value?.accept(visitor);
_uri?.accept(visitor);
}
}
/**
* An error listener that only records whether any constant related errors have
* been reported.
*/
class ConstantAnalysisErrorListener extends AnalysisErrorListener {
/**
* A flag indicating whether any constant related errors have been reported to
* this listener.
*/
bool hasConstError = false;
@override
void onError(AnalysisError error) {
ErrorCode errorCode = error.errorCode;
if (errorCode is CompileTimeErrorCode) {
switch (errorCode) {
case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL:
case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT:
case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING:
case CompileTimeErrorCode.CONST_EVAL_TYPE_INT:
case CompileTimeErrorCode.CONST_EVAL_TYPE_NUM:
case CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION:
case CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE:
case CompileTimeErrorCode.CONST_WITH_NON_CONST:
case CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT:
case CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER:
case CompileTimeErrorCode
.CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST:
case CompileTimeErrorCode.INVALID_CONSTANT:
case CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL:
case CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL:
case CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL:
hasConstError = true;
}
}
}
}
/**
* A constructor declaration.
*
* constructorDeclaration ::=
* constructorSignature [FunctionBody]?
* | constructorName formalParameterList ':' 'this' ('.' [SimpleIdentifier])? arguments
*
* constructorSignature ::=
* 'external'? constructorName formalParameterList initializerList?
* | 'external'? 'factory' factoryName formalParameterList initializerList?
* | 'external'? 'const' constructorName formalParameterList initializerList?
*
* constructorName ::=
* [SimpleIdentifier] ('.' [SimpleIdentifier])?
*
* factoryName ::=
* [Identifier] ('.' [SimpleIdentifier])?
*
* initializerList ::=
* ':' [ConstructorInitializer] (',' [ConstructorInitializer])*
*/
class ConstructorDeclarationImpl extends ClassMemberImpl
implements ConstructorDeclaration {
/**
* The token for the 'external' keyword, or `null` if the constructor is not
* external.
*/
@override
Token externalKeyword;
/**
* The token for the 'const' keyword, or `null` if the constructor is not a
* const constructor.
*/
@override
Token constKeyword;
/**
* The token for the 'factory' keyword, or `null` if the constructor is not a
* factory constructor.
*/
@override
Token factoryKeyword;
/**
* The type of object being created. This can be different than the type in
* which the constructor is being declared if the constructor is the
* implementation of a factory constructor.
*/
IdentifierImpl _returnType;
/**
* The token for the period before the constructor name, or `null` if the
* constructor being declared is unnamed.
*/
@override
Token period;
/**
* The name of the constructor, or `null` if the constructor being declared is
* unnamed.
*/
SimpleIdentifierImpl _name;
/**
* The parameters associated with the constructor.
*/
FormalParameterListImpl _parameters;
/**
* The token for the separator (colon or equals) before the initializer list
* or redirection, or `null` if there are no initializers.
*/
@override
Token separator;
/**
* The initializers associated with the constructor.
*/
NodeList<ConstructorInitializer> _initializers;
/**
* The name of the constructor to which this constructor will be redirected,
* or `null` if this is not a redirecting factory constructor.
*/
ConstructorNameImpl _redirectedConstructor;
/**
* The body of the constructor, or `null` if the constructor does not have a
* body.
*/
FunctionBodyImpl _body;
/**
* The element associated with this constructor, or `null` if the AST
* structure has not been resolved or if this constructor could not be
* resolved.
*/
@override
ConstructorElement declaredElement;
/**
* Initialize a newly created constructor declaration. The [externalKeyword]
* can be `null` if the constructor is not external. Either or both of the
* [comment] and [metadata] can be `null` if the constructor does not have the
* corresponding attribute. The [constKeyword] can be `null` if the
* constructor cannot be used to create a constant. The [factoryKeyword] can
* be `null` if the constructor is not a factory. The [period] and [name] can
* both be `null` if the constructor is not a named constructor. The
* [separator] can be `null` if the constructor does not have any initializers
* and does not redirect to a different constructor. The list of
* [initializers] can be `null` if the constructor does not have any
* initializers. The [redirectedConstructor] can be `null` if the constructor
* does not redirect to a different constructor. The [body] can be `null` if
* the constructor does not have a body.
*/
ConstructorDeclarationImpl(
CommentImpl comment,
List<Annotation> metadata,
this.externalKeyword,
this.constKeyword,
this.factoryKeyword,
IdentifierImpl returnType,
this.period,
SimpleIdentifierImpl name,
FormalParameterListImpl parameters,
this.separator,
List<ConstructorInitializer> initializers,
ConstructorNameImpl redirectedConstructor,
FunctionBodyImpl body)
: super(comment, metadata) {
_returnType = _becomeParentOf(returnType);
_name = _becomeParentOf(name);
_parameters = _becomeParentOf(parameters);
_initializers =
new NodeListImpl<ConstructorInitializer>(this, initializers);
_redirectedConstructor = _becomeParentOf(redirectedConstructor);
_body = _becomeParentOf(body);
}
@override
FunctionBody get body => _body;
@override
void set body(FunctionBody functionBody) {
_body = _becomeParentOf(functionBody as FunctionBodyImpl);
}
@override
Iterable<SyntacticEntity> get childEntities => super._childEntities
..add(externalKeyword)
..add(constKeyword)
..add(factoryKeyword)
..add(_returnType)
..add(period)
..add(_name)
..add(_parameters)
..add(separator)
..addAll(initializers)
..add(_redirectedConstructor)
..add(_body);
@deprecated
@override
ConstructorElement get element => declaredElement;
@deprecated
@override
set element(ConstructorElement element) {
declaredElement = element;
}
@override
Token get endToken {
if (_body != null) {
return _body.endToken;
} else if (!_initializers.isEmpty) {
return _initializers.endToken;
}
return _parameters.endToken;
}
@override
Token get firstTokenAfterCommentAndMetadata {
Token leftMost =
Token.lexicallyFirst([externalKeyword, constKeyword, factoryKeyword]);
if (leftMost != null) {
return leftMost;
}
return _returnType.beginToken;
}
@override
NodeList<ConstructorInitializer> get initializers => _initializers;
@override
SimpleIdentifier get name => _name;
@override
void set name(SimpleIdentifier identifier) {
_name = _becomeParentOf(identifier as SimpleIdentifierImpl);
}
@override
FormalParameterList get parameters => _parameters;
@override
void set parameters(FormalParameterList parameters) {
_parameters = _becomeParentOf(parameters as FormalParameterListImpl);
}
@override
ConstructorName get redirectedConstructor => _redirectedConstructor;
@override
void set redirectedConstructor(ConstructorName redirectedConstructor) {
_redirectedConstructor =
_becomeParentOf(redirectedConstructor as ConstructorNameImpl);
}
@override
Identifier get returnType => _returnType;
@override
void set returnType(Identifier typeName) {
_returnType = _becomeParentOf(typeName as IdentifierImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) =>
visitor.visitConstructorDeclaration(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
_returnType?.accept(visitor);
_name?.accept(visitor);
_parameters?.accept(visitor);
_initializers.accept(visitor);
_redirectedConstructor?.accept(visitor);
_body?.accept(visitor);
}
}
/**
* The initialization of a field within a constructor's initialization list.
*
* fieldInitializer ::=
* ('this' '.')? [SimpleIdentifier] '=' [Expression]
*/
class ConstructorFieldInitializerImpl extends ConstructorInitializerImpl
implements ConstructorFieldInitializer {
/**
* The token for the 'this' keyword, or `null` if there is no 'this' keyword.
*/
@override
Token thisKeyword;
/**
* The token for the period after the 'this' keyword, or `null` if there is no
* 'this' keyword.
*/
@override
Token period;
/**
* The name of the field being initialized.
*/
SimpleIdentifierImpl _fieldName;
/**
* The token for the equal sign between the field name and the expression.
*/
@override
Token equals;
/**
* The expression computing the value to which the field will be initialized.
*/
ExpressionImpl _expression;
/**
* Initialize a newly created field initializer to initialize the field with
* the given name to the value of the given expression. The [thisKeyword] and
* [period] can be `null` if the 'this' keyword was not specified.
*/
ConstructorFieldInitializerImpl(this.thisKeyword, this.period,
SimpleIdentifierImpl fieldName, this.equals, ExpressionImpl expression) {
_fieldName = _becomeParentOf(fieldName);
_expression = _becomeParentOf(expression);
}
@override
Token get beginToken {
if (thisKeyword != null) {
return thisKeyword;
}
return _fieldName.beginToken;
}
@override
Iterable<SyntacticEntity> get childEntities => new ChildEntities()
..add(thisKeyword)
..add(period)
..add(_fieldName)
..add(equals)
..add(_expression);
@override
Token get endToken => _expression.endToken;
@override
Expression get expression => _expression;
@override
void set expression(Expression expression) {
_expression = _becomeParentOf(expression as ExpressionImpl);
}
@override
SimpleIdentifier get fieldName => _fieldName;
@override
void set fieldName(SimpleIdentifier identifier) {
_fieldName = _becomeParentOf(identifier as SimpleIdentifierImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) =>
visitor.visitConstructorFieldInitializer(this);
@override
void visitChildren(AstVisitor visitor) {
_fieldName?.accept(visitor);
_expression?.accept(visitor);
}
}
/**
* A node that can occur in the initializer list of a constructor declaration.
*
* constructorInitializer ::=
* [SuperConstructorInvocation]
* | [ConstructorFieldInitializer]
* | [RedirectingConstructorInvocation]
*/
abstract class ConstructorInitializerImpl extends AstNodeImpl
implements ConstructorInitializer {}
/**
* The name of the constructor.
*
* constructorName ::=
* type ('.' identifier)?
*/
class ConstructorNameImpl extends AstNodeImpl implements ConstructorName {
/**
* The name of the type defining the constructor.
*/
TypeNameImpl _type;
/**
* The token for the period before the constructor name, or `null` if the
* specified constructor is the unnamed constructor.
*/
@override
Token period;
/**
* The name of the constructor, or `null` if the specified constructor is the
* unnamed constructor.
*/
SimpleIdentifierImpl _name;
/**
* The element associated with this constructor name based on static type
* information, or `null` if the AST structure has not been resolved or if
* this constructor name could not be resolved.
*/
@override
ConstructorElement staticElement;
/**
* Initialize a newly created constructor name. The [period] and [name] can be
* `null` if the constructor being named is the unnamed constructor.
*/
ConstructorNameImpl(
TypeNameImpl type, this.period, SimpleIdentifierImpl name) {
_type = _becomeParentOf(type);
_name = _becomeParentOf(name);
}
@override
Token get beginToken => _type.beginToken;
@override
Iterable<SyntacticEntity> get childEntities =>
new ChildEntities()..add(_type)..add(period)..add(_name);
@override
Token get endToken {
if (_name != null) {
return _name.endToken;
}
return _type.endToken;
}
@override
SimpleIdentifier get name => _name;
@override
void set name(SimpleIdentifier name) {
_name = _becomeParentOf(name as SimpleIdentifierImpl);
}
@override
TypeName get type => _type;
@override
void set type(TypeName type) {
_type = _becomeParentOf(type as TypeNameImpl);
}
@override
E accept<E>(AstVisitor<E> visitor) => visitor.visitConstructorName(this);
@override
void visitChildren(AstVisitor visitor) {
_type?.accept(visitor);
_name?.accept(visitor);
}
}