| // 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/analysis/features.dart'; |
| import 'package:analyzer/dart/ast/ast.dart'; |
| import 'package:analyzer/dart/ast/precedence.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/scope.dart'; |
| import 'package:analyzer/dart/element/type.dart'; |
| import 'package:analyzer/src/dart/ast/to_source_visitor.dart'; |
| import 'package:analyzer/src/dart/ast/token.dart'; |
| import 'package:analyzer/src/dart/element/element.dart'; |
| import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart'; |
| import 'package:analyzer/src/fasta/token_utils.dart' as util show findPrevious; |
| import 'package:analyzer/src/generated/resolver.dart'; |
| import 'package:analyzer/src/generated/source.dart' show LineInfo, Source; |
| import 'package:analyzer/src/generated/utilities_dart.dart'; |
| import 'package:meta/meta.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. |
| final NodeListImpl<StringLiteral> _strings = NodeListImpl._(); |
| |
| /// Initialize a newly created list of adjacent strings. To be syntactically |
| /// valid, the list of [strings] must contain at least two elements. |
| AdjacentStringsImpl({ |
| required List<StringLiteral> strings, |
| }) { |
| _strings._initialize(this, strings); |
| } |
| |
| @override |
| Token get beginToken => _strings.beginToken!; |
| |
| @override |
| Token get endToken => _strings.endToken!; |
| |
| @override |
| NodeListImpl<StringLiteral> get strings => _strings; |
| |
| @override |
| ChildEntities get _childEntities { |
| return ChildEntities()..addNodeList('strings', strings); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitAdjacentStrings(this); |
| |
| @override |
| void resolveExpression(ResolverVisitor resolver, DartType? contextType) { |
| resolver.visitAdjacentStrings(this, contextType: contextType); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _strings.accept(visitor); |
| } |
| |
| @override |
| void _appendStringValue(StringBuffer buffer) { |
| int length = strings.length; |
| for (int i = 0; i < length; i++) { |
| var stringLiteral = strings[i] as StringLiteralImpl; |
| 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. |
| final NodeListImpl<Annotation> _metadata = NodeListImpl._(); |
| |
| /// 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(this._comment, List<Annotation>? metadata) { |
| _becomeParentOf(_comment); |
| _metadata._initialize(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 |
| CommentImpl? get documentationComment => _comment; |
| |
| set documentationComment(Comment? comment) { |
| _comment = _becomeParentOf(comment as CommentImpl?); |
| } |
| |
| @override |
| NodeListImpl<Annotation> get metadata => _metadata; |
| |
| @override |
| List<AstNode> get sortedCommentAndAnnotations { |
| var comment = _comment; |
| return <AstNode>[ |
| if (comment != null) comment, |
| ..._metadata, |
| ]..sort(AstNode.LEXICAL_ORDER); |
| } |
| |
| @override |
| ChildEntities get _childEntities { |
| return ChildEntities() |
| ..addNode('documentationComment', documentationComment) |
| ..addNodeList('metadata', metadata); |
| } |
| |
| @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 type arguments to the constructor being invoked, or `null` if (a) this |
| /// annotation is not the invocation of a constructor or (b) this annotation |
| /// does not specify type arguments explicitly. |
| /// |
| /// Note that type arguments are only valid if [Feature.generic_metadata] is |
| /// enabled. |
| TypeArgumentListImpl? _typeArguments; |
| |
| /// 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. |
| /// |
| /// Note that type arguments are only valid if [Feature.generic_metadata] is |
| /// enabled. |
| AnnotationImpl(this.atSign, this._name, this._typeArguments, this.period, |
| this._constructorName, this._arguments) { |
| _becomeParentOf(_name); |
| _becomeParentOf(_typeArguments); |
| _becomeParentOf(_constructorName); |
| _becomeParentOf(_arguments); |
| } |
| |
| @override |
| ArgumentListImpl? get arguments => _arguments; |
| |
| set arguments(ArgumentList? arguments) { |
| _arguments = _becomeParentOf(arguments as ArgumentListImpl?); |
| } |
| |
| @override |
| Token get beginToken => atSign; |
| |
| @override |
| SimpleIdentifierImpl? get constructorName => _constructorName; |
| |
| set constructorName(SimpleIdentifier? name) { |
| _constructorName = _becomeParentOf(name as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| Element? get element { |
| if (_element != null) { |
| return _element!; |
| } else if (_constructorName == null) { |
| return _name.staticElement; |
| } |
| return null; |
| } |
| |
| 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 |
| IdentifierImpl get name => _name; |
| |
| set name(Identifier name) { |
| _name = _becomeParentOf(name as IdentifierImpl)!; |
| } |
| |
| @override |
| AstNode get parent => super.parent!; |
| |
| @override |
| TypeArgumentListImpl? get typeArguments => _typeArguments; |
| |
| /// Sets the type arguments to the constructor being invoked to the given |
| /// [typeArguments]. |
| set typeArguments(TypeArgumentList? typeArguments) { |
| _typeArguments = _becomeParentOf(typeArguments as TypeArgumentListImpl?); |
| } |
| |
| @override |
| ChildEntities get _childEntities { |
| return ChildEntities() |
| ..addToken('atSign', atSign) |
| ..addNode('name', name) |
| ..addNode('typeArguments', typeArguments) |
| ..addToken('period', period) |
| ..addNode('constructorName', constructorName) |
| ..addNode('arguments', arguments); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitAnnotation(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _name.accept(visitor); |
| _typeArguments?.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. |
| final NodeListImpl<Expression> _arguments = NodeListImpl._(); |
| |
| /// 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({ |
| required this.leftParenthesis, |
| required List<Expression> arguments, |
| required this.rightParenthesis, |
| }) { |
| _arguments._initialize(this, arguments); |
| } |
| |
| @override |
| NodeListImpl<Expression> get arguments => _arguments; |
| |
| @override |
| Token get beginToken => leftParenthesis; |
| |
| List<ParameterElement?>? get correspondingStaticParameters => |
| _correspondingStaticParameters; |
| |
| set correspondingStaticParameters(List<ParameterElement?>? parameters) { |
| if (parameters != null && parameters.length != _arguments.length) { |
| throw ArgumentError( |
| "Expected ${_arguments.length} parameters, not ${parameters.length}"); |
| } |
| _correspondingStaticParameters = parameters; |
| } |
| |
| @override |
| Token get endToken => rightParenthesis; |
| |
| @override |
| // TODO(paulberry): Add commas. |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('leftParenthesis', leftParenthesis) |
| ..addNodeList('arguments', arguments) |
| ..addToken('rightParenthesis', 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({ |
| required ExpressionImpl expression, |
| required this.asOperator, |
| required TypeAnnotationImpl type, |
| }) : _expression = expression, |
| _type = type { |
| _becomeParentOf(_expression); |
| _becomeParentOf(_type); |
| } |
| |
| @override |
| Token get beginToken => _expression.beginToken; |
| |
| @override |
| Token get endToken => _type.endToken; |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.relational; |
| |
| @override |
| TypeAnnotationImpl get type => _type; |
| |
| set type(TypeAnnotation type) { |
| _type = _becomeParentOf(type as TypeAnnotationImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addNode('expression', expression) |
| ..addToken('asOperator', asOperator) |
| ..addNode('type', type); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitAsExpression(this); |
| |
| @override |
| void resolveExpression(ResolverVisitor resolver, DartType? contextType) { |
| resolver.visitAsExpression(this, contextType: contextType); |
| } |
| |
| @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({ |
| required this.assertKeyword, |
| required this.leftParenthesis, |
| required ExpressionImpl condition, |
| required this.comma, |
| required ExpressionImpl? message, |
| required this.rightParenthesis, |
| }) : _condition = condition, |
| _message = message { |
| _becomeParentOf(_condition); |
| _becomeParentOf(_message); |
| } |
| |
| @override |
| Token get beginToken => assertKeyword; |
| |
| @override |
| ExpressionImpl get condition => _condition; |
| |
| set condition(Expression condition) { |
| _condition = _becomeParentOf(condition as ExpressionImpl); |
| } |
| |
| @override |
| Token get endToken => rightParenthesis; |
| |
| @override |
| ExpressionImpl? get message => _message; |
| |
| set message(Expression? expression) { |
| _message = _becomeParentOf(expression as ExpressionImpl?); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('assertKeyword', assertKeyword) |
| ..addToken('leftParenthesis', leftParenthesis) |
| ..addNode('condition', condition) |
| ..addToken('comma', comma) |
| ..addNode('message', message) |
| ..addToken('rightParenthesis', rightParenthesis); |
| |
| @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({ |
| required this.assertKeyword, |
| required this.leftParenthesis, |
| required ExpressionImpl condition, |
| required this.comma, |
| required ExpressionImpl? message, |
| required this.rightParenthesis, |
| required this.semicolon, |
| }) : _condition = condition, |
| _message = message { |
| _becomeParentOf(_condition); |
| _becomeParentOf(_message); |
| } |
| |
| @override |
| Token get beginToken => assertKeyword; |
| |
| @override |
| ExpressionImpl get condition => _condition; |
| |
| set condition(Expression condition) { |
| _condition = _becomeParentOf(condition as ExpressionImpl); |
| } |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| ExpressionImpl? get message => _message; |
| |
| set message(Expression? expression) { |
| _message = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('assertKeyword', assertKeyword) |
| ..addToken('leftParenthesis', leftParenthesis) |
| ..addNode('condition', condition) |
| ..addToken('comma', comma) |
| ..addNode('message', message) |
| ..addToken('rightParenthesis', rightParenthesis) |
| ..addToken('semicolon', semicolon); |
| |
| @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 |
| with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl |
| 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({ |
| required ExpressionImpl leftHandSide, |
| required this.operator, |
| required ExpressionImpl rightHandSide, |
| }) : _leftHandSide = leftHandSide, |
| _rightHandSide = rightHandSide { |
| _becomeParentOf(_leftHandSide); |
| _becomeParentOf(_rightHandSide); |
| } |
| |
| @override |
| Token get beginToken => _leftHandSide.beginToken; |
| |
| @override |
| Token get endToken => _rightHandSide.endToken; |
| |
| @override |
| ExpressionImpl get leftHandSide => _leftHandSide; |
| |
| set leftHandSide(Expression expression) { |
| _leftHandSide = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.assignment; |
| |
| @override |
| ExpressionImpl get rightHandSide => _rightHandSide; |
| |
| set rightHandSide(Expression expression) { |
| _rightHandSide = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addNode('leftHandSide', leftHandSide) |
| ..addToken('operator', operator) |
| ..addNode('rightHandSide', rightHandSide); |
| |
| @override |
| AstNode? get _nullShortingExtensionCandidate => parent; |
| |
| /// 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 { |
| Element? executableElement; |
| if (operator.type != TokenType.EQ) { |
| executableElement = staticElement; |
| } else { |
| executableElement = writeElement; |
| } |
| |
| if (executableElement is ExecutableElement) { |
| List<ParameterElement> parameters = executableElement.parameters; |
| if (parameters.isEmpty) { |
| return null; |
| } |
| if (operator.type == TokenType.EQ && leftHandSide is IndexExpression) { |
| return parameters.length == 2 ? parameters[1] : null; |
| } |
| return parameters[0]; |
| } |
| |
| return null; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitAssignmentExpression(this); |
| |
| @override |
| void resolveExpression(ResolverVisitor resolver, DartType? contextType) { |
| resolver.visitAssignmentExpression(this, contextType: contextType); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _leftHandSide.accept(visitor); |
| _rightHandSide.accept(visitor); |
| } |
| |
| @override |
| bool _extendsNullShorting(Expression descendant) => |
| identical(descendant, _leftHandSide); |
| } |
| |
| /// 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 |
| Iterable<SyntacticEntity> get childEntities => |
| _childEntities.syntacticEntities; |
| |
| @override |
| int get end => offset + length; |
| |
| @override |
| bool get isSynthetic => false; |
| |
| @override |
| int get length { |
| final beginToken = this.beginToken; |
| final endToken = this.endToken; |
| return endToken.offset + endToken.length - beginToken.offset; |
| } |
| |
| /// Return properties (tokens and nodes) of this node, with names, in the |
| /// order in which these entities should normally appear, not necessary in |
| /// the order they really are (because of recovery). |
| Iterable<ChildEntity> get namedChildEntities => _childEntities.entities; |
| |
| @override |
| int get offset { |
| final beginToken = this.beginToken; |
| return beginToken.offset; |
| } |
| |
| @override |
| AstNode? get parent => _parent; |
| |
| @override |
| AstNode get root { |
| AstNode root = this; |
| var rootParent = parent; |
| while (rootParent != null) { |
| root = rootParent; |
| rootParent = root.parent; |
| } |
| return root; |
| } |
| |
| ChildEntities get _childEntities => ChildEntities(); |
| |
| void detachFromParent() { |
| _parent = null; |
| } |
| |
| @override |
| Token? findPrevious(Token target) => |
| util.findPrevious(beginToken, target) ?? parent?.findPrevious(target); |
| |
| @override |
| E? getProperty<E>(String name) { |
| return _propertyMap?[name] as E?; |
| } |
| |
| @override |
| void setProperty(String name, Object? value) { |
| if (value == null) { |
| final propertyMap = _propertyMap; |
| if (propertyMap != null) { |
| propertyMap.remove(name); |
| if (propertyMap.isEmpty) { |
| _propertyMap = null; |
| } |
| } |
| } else { |
| (_propertyMap ??= HashMap<String, Object>())[name] = value; |
| } |
| } |
| |
| @override |
| E? thisOrAncestorMatching<E extends AstNode>( |
| bool Function(AstNode) predicate, |
| ) { |
| AstNode? node = this; |
| while (node != null && !predicate(node)) { |
| node = node.parent; |
| } |
| return node as E?; |
| } |
| |
| @override |
| E? thisOrAncestorOfType<E extends AstNode>() { |
| AstNode? node = this; |
| while (node != null && node is! E) { |
| node = node.parent; |
| } |
| return node as E?; |
| } |
| |
| @override |
| String toSource() { |
| StringBuffer buffer = StringBuffer(); |
| accept(ToSourceVisitor(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) { |
| child?._parent = this; |
| return child; |
| } |
| } |
| |
| /// An augmentation import directive. |
| /// |
| /// importDirective ::= |
| /// [Annotation] 'import' 'augment' [StringLiteral] ';' |
| class AugmentationImportDirectiveImpl extends UriBasedDirectiveImpl |
| implements AugmentationImportDirective { |
| @override |
| Token importKeyword; |
| |
| @override |
| Token augmentKeyword; |
| |
| @override |
| Token semicolon; |
| |
| AugmentationImportDirectiveImpl({ |
| required CommentImpl? comment, |
| required List<Annotation>? metadata, |
| required this.importKeyword, |
| required this.augmentKeyword, |
| required this.semicolon, |
| required StringLiteralImpl uri, |
| }) : super(comment, metadata, uri) { |
| _becomeParentOf(_uri); |
| } |
| |
| @override |
| AugmentationImportElement? get element { |
| return super.element as AugmentationImportElement?; |
| } |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => importKeyword; |
| |
| @Deprecated('Use specific xyzToken instead') |
| @override |
| Token get keyword => importKeyword; |
| |
| @override |
| LibraryAugmentationElement? get uriElement { |
| return element?.augmentation; |
| } |
| |
| @override |
| ChildEntities get _childEntities => super._childEntities |
| ..addToken('importKeyword', importKeyword) |
| ..addToken('augmentKeyword', augmentKeyword) |
| ..addNode('uri', uri) |
| ..addToken('semicolon', semicolon); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) { |
| return visitor.visitAugmentationImportDirective(this); |
| } |
| } |
| |
| /// 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({ |
| required this.awaitKeyword, |
| required ExpressionImpl expression, |
| }) : _expression = expression { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken { |
| return awaitKeyword; |
| } |
| |
| @override |
| Token get endToken => _expression.endToken; |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.prefix; |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('awaitKeyword', awaitKeyword) |
| ..addNode('expression', expression); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitAwaitExpression(this); |
| |
| @override |
| void resolveExpression(ResolverVisitor resolver, DartType? contextType) { |
| resolver.visitAwaitExpression(this, contextType: contextType); |
| } |
| |
| @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({ |
| required ExpressionImpl leftOperand, |
| required this.operator, |
| required ExpressionImpl rightOperand, |
| }) : _leftOperand = leftOperand, |
| _rightOperand = rightOperand { |
| _becomeParentOf(leftOperand); |
| _becomeParentOf(rightOperand); |
| } |
| |
| @override |
| Token get beginToken => _leftOperand.beginToken; |
| |
| @override |
| Token get endToken => _rightOperand.endToken; |
| |
| @override |
| ExpressionImpl get leftOperand => _leftOperand; |
| |
| set leftOperand(Expression expression) { |
| _leftOperand = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.forTokenType(operator.type); |
| |
| @override |
| ExpressionImpl get rightOperand => _rightOperand; |
| |
| set rightOperand(Expression expression) { |
| _rightOperand = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addNode('leftOperand', leftOperand) |
| ..addToken('operator', operator) |
| ..addNode('rightOperand', rightOperand); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitBinaryExpression(this); |
| |
| @override |
| void resolveExpression(ResolverVisitor resolver, DartType? contextType) { |
| resolver.visitBinaryExpression(this, contextType: contextType); |
| } |
| |
| @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, this._block) { |
| _becomeParentOf(_block); |
| } |
| |
| @override |
| Token get beginToken { |
| if (keyword != null) { |
| return keyword!; |
| } |
| return _block.beginToken; |
| } |
| |
| @override |
| BlockImpl get block => _block; |
| |
| set block(Block block) { |
| _block = _becomeParentOf(block as BlockImpl); |
| } |
| |
| @override |
| Token get endToken => _block.endToken; |
| |
| @override |
| bool get isAsynchronous => keyword?.lexeme == Keyword.ASYNC.lexeme; |
| |
| @override |
| bool get isGenerator => star != null; |
| |
| @override |
| bool get isSynchronous => keyword?.lexeme != Keyword.ASYNC.lexeme; |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('keyword', keyword) |
| ..addToken('star', star) |
| ..addNode('block', block); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitBlockFunctionBody(this); |
| |
| @override |
| DartType resolve(ResolverVisitor resolver, DartType? imposedType) => |
| resolver.visitBlockFunctionBody(this, imposedType: imposedType); |
| |
| @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. |
| final NodeListImpl<Statement> _statements = NodeListImpl._(); |
| |
| /// The right curly bracket. |
| @override |
| Token rightBracket; |
| |
| /// Initialize a newly created block of code. |
| BlockImpl(this.leftBracket, List<Statement> statements, this.rightBracket) { |
| _statements._initialize(this, statements); |
| } |
| |
| @override |
| Token get beginToken => leftBracket; |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| NodeListImpl<Statement> get statements => _statements; |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('leftBracket', leftBracket) |
| ..addNodeList('statements', statements) |
| ..addToken('rightBracket', rightBracket); |
| |
| @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 |
| Token get endToken => literal; |
| |
| @override |
| bool get isSynthetic => literal.isSynthetic; |
| |
| @override |
| ChildEntities get _childEntities => |
| ChildEntities()..addToken('literal', literal); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitBooleanLiteral(this); |
| |
| @override |
| void resolveExpression(ResolverVisitor resolver, DartType? contextType) { |
| resolver.visitBooleanLiteral(this, contextType: contextType); |
| } |
| |
| @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, this._label, this.semicolon) { |
| _becomeParentOf(_label); |
| } |
| |
| @override |
| Token get beginToken => breakKeyword; |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| SimpleIdentifierImpl? get label => _label; |
| |
| set label(SimpleIdentifier? identifier) { |
| _label = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('breakKeyword', breakKeyword) |
| ..addNode('label', label) |
| ..addToken('semicolon', semicolon); |
| |
| @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 |
| with NullShortableExpressionImpl |
| implements CascadeExpression { |
| /// The target of the cascade sections. |
| ExpressionImpl _target; |
| |
| /// The cascade sections sharing the common target. |
| final NodeListImpl<Expression> _cascadeSections = NodeListImpl._(); |
| |
| /// Initialize a newly created cascade expression. The list of |
| /// [cascadeSections] must contain at least one element. |
| CascadeExpressionImpl(this._target, List<Expression> cascadeSections) { |
| _becomeParentOf(_target); |
| _cascadeSections._initialize(this, cascadeSections); |
| } |
| |
| @override |
| Token get beginToken => _target.beginToken; |
| |
| @override |
| NodeListImpl<Expression> get cascadeSections => _cascadeSections; |
| |
| @override |
| Token get endToken => _cascadeSections.endToken!; |
| |
| @override |
| bool get isNullAware { |
| return target.endToken.next!.type == TokenType.QUESTION_PERIOD_PERIOD; |
| } |
| |
| @override |
| Precedence get precedence => Precedence.cascade; |
| |
| @override |
| ExpressionImpl get target => _target; |
| |
| set target(Expression target) { |
| _target = _becomeParentOf(target as ExpressionImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addNode('target', target) |
| ..addNodeList('cascadeSections', cascadeSections); |
| |
| @override |
| AstNode? get _nullShortingExtensionCandidate => null; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitCascadeExpression(this); |
| |
| @override |
| void resolveExpression(ResolverVisitor resolver, DartType? contextType) { |
| resolver.visitCascadeExpression(this, contextType: contextType); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _target.accept(visitor); |
| _cascadeSections.accept(visitor); |
| } |
| |
| @override |
| bool _extendsNullShorting(Expression descendant) { |
| return _cascadeSections.contains(descendant); |
| } |
| } |
| |
| /// 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, |
| this._exceptionType, |
| this.catchKeyword, |
| this.leftParenthesis, |
| this._exceptionParameter, |
| this.comma, |
| this._stackTraceParameter, |
| this.rightParenthesis, |
| this._body) |
| : assert(onKeyword != null || catchKeyword != null) { |
| _becomeParentOf(_exceptionType); |
| _becomeParentOf(_exceptionParameter); |
| _becomeParentOf(_stackTraceParameter); |
| _becomeParentOf(_body); |
| } |
| |
| @override |
| Token get beginToken { |
| if (onKeyword != null) { |
| return onKeyword!; |
| } |
| return catchKeyword!; |
| } |
| |
| @override |
| BlockImpl get body => _body; |
| |
| set body(Block block) { |
| _body = _becomeParentOf(block as BlockImpl); |
| } |
| |
| @override |
| Token get endToken => _body.endToken; |
| |
| @override |
| SimpleIdentifierImpl? get exceptionParameter => _exceptionParameter; |
| |
| set exceptionParameter(SimpleIdentifier? parameter) { |
| _exceptionParameter = _becomeParentOf(parameter as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| TypeAnnotationImpl? get exceptionType => _exceptionType; |
| |
| set exceptionType(TypeAnnotation? exceptionType) { |
| _exceptionType = _becomeParentOf(exceptionType as TypeAnnotationImpl?); |
| } |
| |
| @override |
| SimpleIdentifierImpl? get stackTraceParameter => _stackTraceParameter; |
| |
| set stackTraceParameter(SimpleIdentifier? parameter) { |
| _stackTraceParameter = _becomeParentOf(parameter as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('onKeyword', onKeyword) |
| ..addNode('exceptionType', exceptionType) |
| ..addToken('catchKeyword', catchKeyword) |
| ..addToken('leftParenthesis', leftParenthesis) |
| ..addNode('exceptionParameter', exceptionParameter) |
| ..addToken('comma', comma) |
| ..addNode('stackTraceParameter', stackTraceParameter) |
| ..addToken('rightParenthesis', rightParenthesis) |
| ..addNode('body', body); |
| |
| @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 { |
| /// The list of child entities to be iterated over. |
| final List<ChildEntity> entities = []; |
| |
| List<SyntacticEntity> get syntacticEntities { |
| var result = <SyntacticEntity>[]; |
| for (var entity in entities) { |
| var entityValue = entity.value; |
| if (entityValue is SyntacticEntity) { |
| result.add(entityValue); |
| } else if (entityValue is List<Object>) { |
| for (var element in entityValue) { |
| if (element is SyntacticEntity) { |
| result.add(element); |
| } |
| } |
| } |
| } |
| |
| var needsSorting = false; |
| int? lastOffset; |
| for (var entity in result) { |
| if (lastOffset != null && lastOffset > entity.offset) { |
| needsSorting = true; |
| break; |
| } |
| lastOffset = entity.offset; |
| } |
| |
| if (needsSorting) { |
| result.sort((a, b) => a.offset - b.offset); |
| } |
| |
| return result; |
| } |
| |
| void addAll(ChildEntities other) { |
| entities.addAll(other.entities); |
| } |
| |
| void addNode(String name, AstNode? value) { |
| if (value != null) { |
| entities.add( |
| ChildEntity(name, value), |
| ); |
| } |
| } |
| |
| void addNodeList(String name, List<AstNode> value) { |
| entities.add( |
| ChildEntity(name, value), |
| ); |
| } |
| |
| void addToken(String name, Token? value) { |
| if (value != null) { |
| entities.add( |
| ChildEntity(name, value), |
| ); |
| } |
| } |
| |
| void addTokenList(String name, List<Token> value) { |
| entities.add( |
| ChildEntity(name, value), |
| ); |
| } |
| } |
| |
| /// A named child of an [AstNode], usually a token, node, or a list of nodes. |
| class ChildEntity { |
| final String name; |
| final Object value; |
| |
| ChildEntity(this.name, this.value); |
| } |
| |
| /// 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 'macro' keyword, or `null` if the keyword was absent. |
| Token? macroKeyword; |
| |
| /// The 'augment' keyword, or `null` if the keyword was absent. |
| Token? augmentKeyword; |
| |
| /// 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.macroKeyword, |
| this.augmentKeyword, |
| this.classKeyword, |
| SimpleIdentifierImpl name, |
| TypeParameterListImpl? typeParameters, |
| this._extendsClause, |
| this._withClause, |
| ImplementsClauseImpl? implementsClause, |
| Token leftBracket, |
| List<ClassMember> members, |
| Token rightBracket) |
| : super(comment, metadata, name, typeParameters, implementsClause, |
| leftBracket, members, rightBracket) { |
| _becomeParentOf(_extendsClause); |
| _becomeParentOf(_withClause); |
| } |
| |
| @override |
| ClassElement? get declaredElement => _name.staticElement as ClassElement?; |
| |
| @override |
| ExtendsClauseImpl? get extendsClause => _extendsClause; |
| |
| set extendsClause(ExtendsClause? extendsClause) { |
| _extendsClause = _becomeParentOf(extendsClause as ExtendsClauseImpl?); |
| } |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return abstractKeyword ?? macroKeyword ?? augmentKeyword ?? classKeyword; |
| } |
| |
| @override |
| bool get isAbstract => abstractKeyword != null; |
| |
| @override |
| NativeClauseImpl? get nativeClause => _nativeClause; |
| |
| set nativeClause(NativeClause? nativeClause) { |
| _nativeClause = _becomeParentOf(nativeClause as NativeClauseImpl?); |
| } |
| |
| @override |
| WithClauseImpl? get withClause => _withClause; |
| |
| set withClause(WithClause? withClause) { |
| _withClause = _becomeParentOf(withClause as WithClauseImpl?); |
| } |
| |
| @override |
| ChildEntities get _childEntities => super._childEntities |
| ..addToken('abstractKeyword', abstractKeyword) |
| ..addToken('macroKeyword', macroKeyword) |
| ..addToken('augmentKeyword', augmentKeyword) |
| ..addToken('classKeyword', classKeyword) |
| ..addNode('name', name) |
| ..addNode('typeParameters', typeParameters) |
| ..addNode('extendsClause', extendsClause) |
| ..addNode('withClause', withClause) |
| ..addNode('implementsClause', implementsClause) |
| ..addNode('nativeClause', nativeClause) |
| ..addToken('leftBracket', leftBracket) |
| ..addNodeList('members', members) |
| ..addToken('rightBracket', rightBracket); |
| |
| @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(super.comment, super.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. |
| @override |
| Token leftBracket; |
| |
| /// The members defined by the class or mixin. |
| final NodeListImpl<ClassMember> _members = NodeListImpl._(); |
| |
| /// The right curly bracket. |
| @override |
| Token rightBracket; |
| |
| ClassOrMixinDeclarationImpl( |
| super.comment, |
| super.metadata, |
| super.name, |
| this._typeParameters, |
| this._implementsClause, |
| this.leftBracket, |
| List<ClassMember> members, |
| this.rightBracket) { |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_implementsClause); |
| _members._initialize(this, members); |
| } |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| ImplementsClauseImpl? get implementsClause => _implementsClause; |
| |
| set implementsClause(ImplementsClause? implementsClause) { |
| _implementsClause = |
| _becomeParentOf(implementsClause as ImplementsClauseImpl?); |
| } |
| |
| @override |
| NodeListImpl<ClassMember> get members => _members; |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl?); |
| } |
| |
| @override |
| 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]; |
| if (name == field.name.name) { |
| return field; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| @override |
| 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; |
| if (name == method.name.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 token for the 'macro' keyword, or `null` if this is not defining a |
| /// macro class. |
| Token? macroKeyword; |
| |
| /// The token for the 'augment' keyword, or `null` if this is not defining an |
| /// augmentation class. |
| Token? augmentKeyword; |
| |
| /// The name of the superclass of the class being declared. |
| NamedTypeImpl _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, |
| this._typeParameters, |
| this.equals, |
| this.abstractKeyword, |
| this.macroKeyword, |
| this.augmentKeyword, |
| this._superclass, |
| this._withClause, |
| this._implementsClause, |
| Token semicolon) |
| : super(comment, metadata, keyword, name, semicolon) { |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_superclass); |
| _becomeParentOf(_withClause); |
| _becomeParentOf(_implementsClause); |
| } |
| |
| @override |
| ClassElement? get declaredElement => _name.staticElement as ClassElement?; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return abstractKeyword ?? macroKeyword ?? augmentKeyword ?? typedefKeyword; |
| } |
| |
| @override |
| ImplementsClauseImpl? get implementsClause => _implementsClause; |
| |
| set implementsClause(ImplementsClause? implementsClause) { |
| _implementsClause = |
| _becomeParentOf(implementsClause as ImplementsClauseImpl?); |
| } |
| |
| @override |
| bool get isAbstract => abstractKeyword != null; |
| |
| @override |
| NamedTypeImpl get superclass => _superclass; |
| |
| set superclass(NamedType superclass) { |
| _superclass = _becomeParentOf(superclass as NamedTypeImpl); |
| } |
| |
| @Deprecated('Use superclass instead') |
| @override |
| NamedTypeImpl get superclass2 => _superclass; |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl); |
| } |
| |
| @override |
| WithClauseImpl get withClause => _withClause; |
| |
| set withClause(WithClause withClause) { |
| _withClause = _becomeParentOf(withClause as WithClauseImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => super._childEntities |
| ..addToken('typedefKeyword', typedefKeyword) |
| ..addNode('name', name) |
| ..addNode('typeParameters', typeParameters) |
| ..addToken('equals', equals) |
| ..addToken('abstractKeyword', abstractKeyword) |
| ..addToken('macroKeyword', macroKeyword) |
| ..addToken('augmentKeyword', augmentKeyword) |
| ..addNode('superclass', superclass) |
| ..addNode('withClause', withClause) |
| ..addNode('implementsClause', implementsClause) |
| ..addToken('semicolon', semicolon); |
| |
| @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); |
| } |
| } |
| |
| abstract class CollectionElementImpl extends AstNodeImpl |
| implements CollectionElement { |
| /// Dispatches this collection element to the [resolver], with the given |
| /// [context] information. |
| void resolveElement( |
| ResolverVisitor resolver, CollectionLiteralContext? context); |
| } |
| |
| /// 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* '*/' |
| /// |
| /// documentationComment ::= |
| /// '/ **' (CHARACTER | [CommentReference])* '*/' |
| /// | ('///' (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. |
| final NodeListImpl<CommentReference> _references = NodeListImpl._(); |
| |
| /// 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._initialize(this, references); |
| } |
| |
| @override |
| Token get beginToken => tokens[0]; |
| |
| @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 |
| NodeListImpl<CommentReference> get references => _references; |
| |
| @override |
| ChildEntities get _childEntities => |
| ChildEntities()..addTokenList('tokens', tokens); |
| |
| @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 CommentImpl createBlockComment(List<Token> tokens) => |
| CommentImpl(tokens, CommentType.BLOCK, const <CommentReference>[]); |
| |
| /// Create a documentation comment consisting of the given [tokens]. |
| static CommentImpl createDocumentationComment(List<Token> tokens) => |
| CommentImpl( |
| tokens, CommentType.DOCUMENTATION, const <CommentReference>[]); |
| |
| /// Create a documentation comment consisting of the given [tokens] and having |
| /// the given [references] embedded within it. |
| static CommentImpl createDocumentationCommentWithReferences( |
| List<Token> tokens, List<CommentReference> references) => |
| CommentImpl(tokens, CommentType.DOCUMENTATION, references); |
| |
| /// Create an end-of-line comment consisting of the given [tokens]. |
| static CommentImpl createEndOfLineComment(List<Token> tokens) => |
| CommentImpl(tokens, CommentType.END_OF_LINE, const <CommentReference>[]); |
| } |
| |
| abstract class CommentReferableExpressionImpl extends ExpressionImpl |
| implements CommentReferableExpression {} |
| |
| /// 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 expression being referenced. |
| CommentReferableExpressionImpl _expression; |
| |
| /// 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, this._expression) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken => newKeyword ?? _expression.beginToken; |
| |
| @override |
| Token get endToken => _expression.endToken; |
| |
| @override |
| CommentReferableExpression get expression => _expression; |
| |
| set expression(CommentReferableExpression expression) { |
| _expression = _becomeParentOf(expression as CommentReferableExpressionImpl); |
| } |
| |
| @override |
| @Deprecated('Use expression instead') |
| IdentifierImpl get identifier => _expression as IdentifierImpl; |
| |
| @Deprecated('Use expression= instead') |
| set identifier(Identifier identifier) { |
| _expression = _becomeParentOf(identifier as CommentReferableExpressionImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('newKeyword', newKeyword) |
| ..addNode('expression', expression); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitCommentReference(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// The possible types of comments that are recognized by the parser. |
| class CommentType { |
| /// A block comment. |
| static const CommentType BLOCK = CommentType('BLOCK'); |
| |
| /// A documentation comment. |
| static const CommentType DOCUMENTATION = CommentType('DOCUMENTATION'); |
| |
| /// An end-of-line comment. |
| static const CommentType END_OF_LINE = 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. |
| final NodeListImpl<Directive> _directives = NodeListImpl._(); |
| |
| /// The declarations contained in this compilation unit. |
| final NodeListImpl<CompilationUnitMember> _declarations = NodeListImpl._(); |
| |
| /// 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 |
| final LineInfo lineInfo; |
| |
| /// The language version information. |
| LibraryLanguageVersion? languageVersion; |
| |
| @override |
| final FeatureSet featureSet; |
| |
| /// 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, |
| this._scriptTag, |
| List<Directive>? directives, |
| List<CompilationUnitMember>? declarations, |
| this.endToken, |
| this.featureSet, |
| this.lineInfo) { |
| _becomeParentOf(_scriptTag); |
| _directives._initialize(this, directives); |
| _declarations._initialize(this, declarations); |
| } |
| |
| @override |
| NodeListImpl<CompilationUnitMember> get declarations => _declarations; |
| |
| @override |
| NodeListImpl<Directive> get directives => _directives; |
| |
| set element(CompilationUnitElement? element) { |
| declaredElement = element; |
| } |
| |
| @override |
| LanguageVersionToken? get languageVersionToken { |
| Token? targetToken = beginToken; |
| if (targetToken.type == TokenType.SCRIPT_TAG) { |
| targetToken = targetToken.next; |
| } |
| |
| Token? comment = targetToken?.precedingComments; |
| while (comment != null) { |
| if (comment is LanguageVersionToken) { |
| return comment; |
| } |
| comment = comment.next; |
| } |
| return null; |
| } |
| |
| @override |
| int get length { |
| final endToken = this.endToken; |
| return endToken.offset + endToken.length; |
| } |
| |
| @override |
| int get offset => 0; |
| |
| @override |
| ScriptTag? get scriptTag => _scriptTag; |
| |
| set scriptTag(ScriptTag? scriptTag) { |
| _scriptTag = _becomeParentOf(scriptTag as ScriptTagImpl?); |
| } |
| |
| @override |
| List<AstNode> get sortedDirectivesAndDeclarations { |
| return <AstNode>[ |
| ..._directives, |
| ..._declarations, |
| ]..sort(AstNode.LEXICAL_ORDER); |
| } |
| |
| @override |
| ChildEntities get _childEntities { |
| return ChildEntities() |
| ..addNode('scriptTag', scriptTag) |
| ..addNodeList('directives', directives) |
| ..addNodeList('declarations', declarations); |
| } |
| |
| /// 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] |
| /// | [MixinDeclaration] |
| /// | [ExtensionDeclaration] |
| /// | [EnumDeclaration] |
| /// | [TypeAlias] |
| /// | [FunctionDeclaration] |
| /// | [TopLevelVariableDeclaration] |
| 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(super.comment, super.metadata); |
| } |
| |
| mixin CompoundAssignmentExpressionImpl implements CompoundAssignmentExpression { |
| @override |
| Element? readElement; |
| |
| @override |
| Element? writeElement; |
| |
| @override |
| DartType? readType; |
| |
| @override |
| DartType? writeType; |
| } |
| |
| /// 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(this._condition, this.question, |
| this._thenExpression, this.colon, this._elseExpression) { |
| _becomeParentOf(_condition); |
| _becomeParentOf(_thenExpression); |
| _becomeParentOf(_elseExpression); |
| } |
| |
| @override |
| Token get beginToken => _condition.beginToken; |
| |
| @override |
| ExpressionImpl get condition => _condition; |
| |
| set condition(Expression expression) { |
| _condition = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| ExpressionImpl get elseExpression => _elseExpression; |
| |
| set elseExpression(Expression expression) { |
| _elseExpression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Token get endToken => _elseExpression.endToken; |
| |
| @override |
| Precedence get precedence => Precedence.conditional; |
| |
| @override |
| ExpressionImpl get thenExpression => _thenExpression; |
| |
| set thenExpression(Expression expression) { |
| _thenExpression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addNode('condition', condition) |
| ..addToken('question', question) |
| ..addNode('thenExpression', thenExpression) |
| ..addToken('colon', colon) |
| ..addNode('elseExpression', elseExpression); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitConditionalExpression(this); |
| |
| @override |
| void resolveExpression(ResolverVisitor resolver, DartType? contextType) { |
| resolver.visitConditionalExpression(this, contextType: contextType); |
| } |
| |
| @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, this._name, |
| this.equalToken, this._value, this.rightParenthesis, this._uri) { |
| _becomeParentOf(_name); |
| _becomeParentOf(_value); |
| _becomeParentOf(_uri); |
| } |
| |
| @override |
| Token get beginToken => ifKeyword; |
| |
| @override |
| Token get endToken => _uri.endToken; |
| |
| @override |
| DottedNameImpl get name => _name; |
| |
| set name(DottedName name) { |
| _name = _becomeParentOf(name as DottedNameImpl); |
| } |
| |
| @override |
| StringLiteralImpl get uri => _uri; |
| |
| set uri(StringLiteral uri) { |
| _uri = _becomeParentOf(uri as StringLiteralImpl); |
| } |
| |
| @override |
| StringLiteralImpl? get value => _value; |
| |
| set value(StringLiteral? value) { |
| _value = _becomeParentOf(value as StringLiteralImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('ifKeyword', ifKeyword) |
| ..addToken('leftParenthesis', leftParenthesis) |
| ..addNode('name', name) |
| ..addToken('equalToken', equalToken) |
| ..addNode('value', value) |
| ..addToken('rightParenthesis', rightParenthesis) |
| ..addNode('uri', uri); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitConfiguration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _name.accept(visitor); |
| _value?.accept(visitor); |
| _uri.accept(visitor); |
| } |
| } |
| |
| /// This class is used as a marker of constant context for initializers |
| /// of constant fields and top-level variables read from summaries. |
| class ConstantContextForExpressionImpl extends AstNodeImpl { |
| final ExpressionImpl expression; |
| |
| ConstantContextForExpressionImpl(this.expression) { |
| _becomeParentOf(expression); |
| } |
| |
| @override |
| noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
| } |
| |
| /// 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. |
| final NodeListImpl<ConstructorInitializer> _initializers = NodeListImpl._(); |
| |
| /// 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. |
| 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( |
| super.comment, |
| super.metadata, |
| this.externalKeyword, |
| this.constKeyword, |
| this.factoryKeyword, |
| this._returnType, |
| this.period, |
| this._name, |
| this._parameters, |
| this.separator, |
| List<ConstructorInitializer>? initializers, |
| this._redirectedConstructor, |
| this._body) { |
| _becomeParentOf(_returnType); |
| _becomeParentOf(_name); |
| _becomeParentOf(_parameters); |
| _initializers._initialize(this, initializers); |
| _becomeParentOf(_redirectedConstructor); |
| _becomeParentOf(_body); |
| } |
| |
| @override |
| FunctionBodyImpl get body => _body; |
| |
| set body(FunctionBody functionBody) { |
| _body = _becomeParentOf(functionBody as FunctionBodyImpl); |
| } |
| |
| @override |
| Token get endToken { |
| return _body.endToken; |
| } |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return Token.lexicallyFirst( |
| externalKeyword, constKeyword, factoryKeyword) ?? |
| _returnType.beginToken; |
| } |
| |
| @override |
| NodeListImpl<ConstructorInitializer> get initializers => _initializers; |
| |
| @override |
| SimpleIdentifierImpl? get name => _name; |
| |
| set name(SimpleIdentifier? identifier) { |
| _name = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| FormalParameterListImpl get parameters => _parameters; |
| |
| set parameters(FormalParameterList parameters) { |
| _parameters = _becomeParentOf(parameters as FormalParameterListImpl); |
| } |
| |
| @override |
| ConstructorNameImpl? get redirectedConstructor => _redirectedConstructor; |
| |
| set redirectedConstructor(ConstructorName? redirectedConstructor) { |
| _redirectedConstructor = |
| _becomeParentOf(redirectedConstructor as ConstructorNameImpl); |
| } |
| |
| @override |
| IdentifierImpl get returnType => _returnType; |
| |
| set returnType(Identifier typeName) { |
| _returnType = _becomeParentOf(typeName as IdentifierImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => super._childEntities |
| ..addToken('externalKeyword', externalKeyword) |
| ..addToken('constKeyword', constKeyword) |
| ..addToken('factoryKeyword', factoryKeyword) |
| ..addNode('returnType', returnType) |
| ..addToken('period', period) |
| ..addNode('name', name) |
| ..addNode('parameters', parameters) |
| ..addToken('separator', separator) |
| ..addNodeList('initializers', initializers) |
| ..addNode('redirectedConstructor', redirectedConstructor) |
| ..addNode('body', body); |
| |
| @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, |
| this._fieldName, this.equals, this._expression) { |
| _becomeParentOf(_fieldName); |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken { |
| if (thisKeyword != null) { |
| return thisKeyword!; |
| } |
| return _fieldName.beginToken; |
| } |
| |
| @override |
| Token get endToken => _expression.endToken; |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| SimpleIdentifierImpl get fieldName => _fieldName; |
| |
| set fieldName(SimpleIdentifier identifier) { |
| _fieldName = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('thisKeyword', thisKeyword) |
| ..addToken('period', period) |
| ..addNode('fieldName', fieldName) |
| ..addToken('equals', equals) |
| ..addNode('expression', expression); |
| |
| @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. |
| NamedTypeImpl _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(this._type, this.period, this._name) { |
| _becomeParentOf(_type); |
| _becomeParentOf(_name); |
| } |
| |
| @override |
| Token get beginToken => _type.beginToken; |
| |
| @override |
| Token get endToken { |
| if (_name != null) { |
| return _name!.endToken; |
| } |
| return _type.endToken; |
| } |
| |
| @override |
| SimpleIdentifierImpl? get name => _name; |
| |
| set name(SimpleIdentifier? name) { |
| _name = _becomeParentOf(name as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| NamedTypeImpl get type => _type; |
| |
| set type(NamedType type) { |
| _type = _becomeParentOf(type as NamedTypeImpl); |
| } |
| |
| @Deprecated('Use type instead') |
| @override |
| NamedTypeImpl get type2 => _type; |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addNode('type', type) |
| ..addToken('period', period) |
| ..addNode('name', name); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitConstructorName(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _type.accept(visitor); |
| _name?.accept(visitor); |
| } |
| } |
| |
| /// An expression representing a reference to a constructor, e.g. the expression |
| /// `List.filled` in `var x = List.filled;`. |
| /// |
| /// Objects of this type are not produced directly by the parser (because the |
| /// parser cannot tell whether an identifier refers to a type); they are |
| /// produced at resolution time. |
| class ConstructorReferenceImpl extends CommentReferableExpressionImpl |
| implements ConstructorReference { |
| ConstructorNameImpl _constructorName; |
| |
| ConstructorReferenceImpl(this._constructorName) { |
| _becomeParentOf(_constructorName); |
| } |
| |
| @override |
| Token get beginToken => constructorName.beginToken; |
| |
| @override |
| ConstructorNameImpl get constructorName => _constructorName; |
| |
| set constructorName(ConstructorNameImpl value) { |
| _constructorName = _becomeParentOf(value); |
| } |
| |
| @override |
| Token get endToken => constructorName.endToken; |
| |
| @override |
| Precedence get precedence => Precedence.postfix; |
| |
| @override |
| ChildEntities get _childEntities => |
| ChildEntities()..addNode('constructorName', constructorName); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitConstructorReference(this); |
| |
| @override |
| void resolveExpression(ResolverVisitor resolver, DartType? contextType) { |
| resolver.visitConstructorReference(this, contextType: contextType); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| constructorName.accept(visitor); |
| } |
| } |
| |
| class ConstructorSelectorImpl extends AstNodeImpl |
| implements ConstructorSelector { |
| @override |
| final Token period; |
| |
| @override |
| final SimpleIdentifierImpl name; |
| |
| ConstructorSelectorImpl({ |
| required this.period, |
| required this.name, |
| }) { |
| _becomeParentOf(name); |
| } |
| |
| @override |
| Token get beginToken => period; |
| |
| @override |
| Token get endToken => name.token; |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('period', period) |
| ..addNode('name', name); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) { |
| return visitor.visitConstructorSelector(this); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) {} |
| } |
| |
| /// A continue statement. |
| /// |
| /// continueStatement ::= |
| /// 'continue' [SimpleIdentifier]? ';' |
| class ContinueStatementImpl extends StatementImpl implements ContinueStatement { |
| /// The token representing the 'continue' keyword. |
| @override |
| Token continueKeyword; |
| |
| /// 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 continue statement is continuing to. This will be |
| /// either a Statement (in the case of continuing a loop) or a SwitchMember |
| /// (in the case of continuing from one switch case to another). 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 may be invalid (e.g. |
| /// the target may be in an enclosing function). |
| @override |
| AstNode? target; |
| |
| /// Initialize a newly created continue statement. The [label] can be `null` |
| /// if there is no label associated with the statement. |
| ContinueStatementImpl(this.continueKeyword, this._label, this.semicolon) { |
| _becomeParentOf(_label); |
| } |
| |
| @override |
| Token get beginToken => continueKeyword; |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| SimpleIdentifierImpl? get label => _label; |
| |
| set label(SimpleIdentifier? identifier) { |
| _label = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('continueKeyword', continueKeyword) |
| ..addNode('label', label) |
| ..addToken('semicolon', semicolon); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitContinueStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _label?.accept(visitor); |
| } |
| } |
| |
| /// A node that represents the declaration of one or more names. Each declared |
| /// name is visible within a name scope. |
| abstract class DeclarationImpl extends AnnotatedNodeImpl |
| implements Declaration { |
| /// Initialize a newly created declaration. Either or both of the [comment] |
| /// and [metadata] can be `null` if the declaration does not have the |
| /// corresponding attribute. |
| DeclarationImpl(super.comment, super.metadata); |
| } |
| |
| /// The declaration of a single identifier. |
| /// |
| /// declaredIdentifier ::= |
| /// [Annotation] finalConstVarOrType [SimpleIdentifier] |
| class DeclaredIdentifierImpl extends DeclarationImpl |
| implements DeclaredIdentifier { |
| /// The token representing either the 'final', 'const' or 'var' keyword, or |
| /// `null` if no keyword was used. |
| @override |
| Token? keyword; |
| |
| /// The name of the declared type of the parameter, or `null` if the parameter |
| /// does not have a declared type. |
| TypeAnnotationImpl? _type; |
| |
| /// The name of the variable being declared. |
| SimpleIdentifierImpl _identifier; |
| |
| /// Initialize a newly created formal parameter. Either or both of the |
| /// [comment] and [metadata] can be `null` if the declaration does not have |
| /// the corresponding attribute. The [keyword] can be `null` if a type name is |
| /// given. The [type] must be `null` if the keyword is 'var'. |
| DeclaredIdentifierImpl(super.comment, super.metadata, this.keyword, |
| this._type, this._identifier) { |
| _becomeParentOf(_type); |
| _becomeParentOf(_identifier); |
| } |
| |
| @override |
| LocalVariableElement? get declaredElement { |
| return _identifier.staticElement as LocalVariableElement; |
| } |
| |
| @override |
| Token get endToken => _identifier.endToken; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return keyword ?? _type?.beginToken ?? _identifier.beginToken; |
| } |
| |
| @override |
| SimpleIdentifierImpl get identifier => _identifier; |
| |
| set identifier(SimpleIdentifier identifier) { |
| _identifier = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| |
| @override |
| bool get isConst => keyword?.keyword == Keyword.CONST; |
| |
| @override |
| bool get isFinal => keyword?.keyword == Keyword.FINAL; |
| |
| @override |
| TypeAnnotationImpl? get type => _type; |
| |
| set type(TypeAnnotation? type) { |
| _type = _becomeParentOf(type as TypeAnnotationImpl?); |
| } |
| |
| @override |
| ChildEntities get _childEntities => super._childEntities |
| ..addToken('keyword', keyword) |
| ..addNode('type', type) |
| ..addNode('identifier', identifier); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitDeclaredIdentifier(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _type?.accept(visitor); |
| _identifier.accept(visitor); |
| } |
| } |
| |
| /// A simple identifier that declares a name. |
| // TODO(rnystrom): Consider making this distinct from [SimpleIdentifier] and |
| // get rid of all of the: |
| // |
| // if (node.inDeclarationContext()) { ... } |
| // |
| // code and instead visit this separately. A declaration is semantically pretty |
| // different from a use, so using the same node type doesn't seem to buy us |
| // much. |
| class DeclaredSimpleIdentifier extends SimpleIdentifierImpl { |
| DeclaredSimpleIdentifier(super.token); |
| |
| @override |
| bool inDeclarationContext() => true; |
| } |
| |
| /// A formal parameter with a default value. There are two kinds of parameters |
| /// that are both represented by this class: named formal parameters and |
| /// positional formal parameters. |
| /// |
| /// defaultFormalParameter ::= |
| /// [NormalFormalParameter] ('=' [Expression])? |
| /// |
| /// defaultNamedParameter ::= |
| /// [NormalFormalParameter] (':' [Expression])? |
| class DefaultFormalParameterImpl extends FormalParameterImpl |
| implements DefaultFormalParameter { |
| /// The formal parameter with which the default value is associated. |
| NormalFormalParameterImpl _parameter; |
| |
| /// The kind of this parameter. |
| @override |
| ParameterKind kind; |
| |
| /// The token separating the parameter from the default value, or `null` if |
| /// there is no default value. |
| @override |
| Token? separator; |
| |
| /// The expression computing the default value for the parameter, or `null` if |
| /// there is no default value. |
| ExpressionImpl? _defaultValue; |
| |
| /// Initialize a newly created default formal parameter. The [separator] and |
| /// [defaultValue] can be `null` if there is no default value. |
| DefaultFormalParameterImpl( |
| this._parameter, this.kind, this.separator, this._defaultValue) { |
| _becomeParentOf(_parameter); |
| _becomeParentOf(_defaultValue); |
| } |
| |
| @override |
| Token get beginToken => _parameter.beginToken; |
| |
| @override |
| Token? get covariantKeyword => null; |
| |
| @override |
| ParameterElement? get declaredElement => _parameter.declaredElement; |
| |
| @override |
| ExpressionImpl? get defaultValue => _defaultValue; |
| |
| set defaultValue(Expression? expression) { |
| _defaultValue = _becomeParentOf(expression as ExpressionImpl?); |
| } |
| |
| @override |
| Token get endToken { |
| if (_defaultValue != null) { |
| return _defaultValue!.endToken; |
| } |
| return _parameter.endToken; |
| } |
| |
| @override |
| SimpleIdentifierImpl? get identifier => _parameter.identifier; |
| |
| @override |
| bool get isConst => _parameter.isConst; |
| |
| @override |
| bool get isExplicitlyTyped => _parameter.isExplicitlyTyped; |
| |
| @override |
| bool get isFinal => _parameter.isFinal; |
| |
| @override |
| NodeListImpl<Annotation> get metadata => _parameter.metadata; |
| |
| @override |
| NormalFormalParameterImpl get parameter => _parameter; |
| |
| set parameter(NormalFormalParameter formalParameter) { |
| _parameter = _becomeParentOf(formalParameter as NormalFormalParameterImpl); |
| } |
| |
| @override |
| Token? get requiredKeyword => null; |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addNode('parameter', parameter) |
| ..addToken('separator', separator) |
| ..addNode('defaultValue', defaultValue); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitDefaultFormalParameter(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _parameter.accept(visitor); |
| _defaultValue?.accept(visitor); |
| } |
| } |
| |
| /// A node that represents a directive. |
| /// |
| /// directive ::= |
| /// [AugmentationImportDirective] |
| /// | [ExportDirective] |
| /// | [ImportDirective] |
| /// | [LibraryDirective] |
| /// | [PartDirective] |
| /// | [PartOfDirective] |
| abstract class DirectiveImpl extends AnnotatedNodeImpl implements Directive { |
| /// The element associated with this directive, or `null` if the AST structure |
| /// has not been resolved or if this directive could not be resolved. |
| Element? _element; |
| |
| /// Initialize a newly create directive. Either or both of the [comment] and |
| /// [metadata] can be `null` if the directive does not have the corresponding |
| /// attribute. |
| DirectiveImpl(super.comment, super.metadata); |
| |
| @override |
| Element? get element => _element; |
| |
| /// Set the element associated with this directive to be the given [element]. |
| set element(Element? element) { |
| _element = element; |
| } |
| } |
| |
| /// A do statement. |
| /// |
| /// doStatement ::= |
| /// 'do' [Statement] 'while' '(' [Expression] ')' ';' |
| class DoStatementImpl extends StatementImpl implements DoStatement { |
| /// The token representing the 'do' keyword. |
| @override |
| Token doKeyword; |
| |
| /// The body of the loop. |
| StatementImpl _body; |
| |
| /// The token representing the 'while' keyword. |
| @override |
| Token whileKeyword; |
| |
| /// The left parenthesis. |
| @override |
| Token leftParenthesis; |
| |
| /// The condition that determines when the loop will terminate. |
| ExpressionImpl _condition; |
| |
| /// The right parenthesis. |
| @override |
| Token rightParenthesis; |
| |
| /// The semicolon terminating the statement. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created do loop. |
| DoStatementImpl( |
| this.doKeyword, |
| this._body, |
| this.whileKeyword, |
| this.leftParenthesis, |
| this._condition, |
| this.rightParenthesis, |
| this.semicolon) { |
| _becomeParentOf(_body); |
| _becomeParentOf(_condition); |
| } |
| |
| @override |
| Token get beginToken => doKeyword; |
| |
| @override |
| StatementImpl get body => _body; |
| |
| set body(Statement statement) { |
| _body = _becomeParentOf(statement as StatementImpl); |
| } |
| |
| @override |
| ExpressionImpl get condition => _condition; |
| |
| set condition(Expression expression) { |
| _condition = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| ChildEntities get _childEntities => ChildEntities() |
| ..addToken('doKeyword', doKeyword) |
| ..addNode('body', body) |
| ..addToken('whileKeyword', whileKeyword) |
| ..addToken('leftParenthesis', leftParenthesis) |
| ..addNode('condition', condition) |
| ..addToken('rightParenthesis', rightParenthesis) |
| ..addToken('semicolon', semicolon); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitDoStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _body.accept(visitor); |
| _condition.accept(visitor); |
| } |
| } |
| |
| /// A dotted name, used in a configuration within an import or export directive. |
| /// |
| /// dottedName ::= |
| /// [SimpleIdentifier] ('.' [SimpleIdentifier])* |
| class DottedNameImpl extends AstNodeImpl implements DottedName { |
| /// The components of the identifier. |
| final NodeListImpl<SimpleIdentifier> _components = NodeListImpl._(); |
| |
| /// Initialize a newly created dotted name. |
| DottedNameImpl(List<SimpleIdentifier> components) { |
| _components._initialize(this, components); |
| } |
| |
| @override |
| Token get beginToken => _components.beginToken!; |
| |
| @override |
| NodeListImpl<SimpleIdentifier> get components => _components; |
| |
| @override |
| Token get endToken => _components.endToken!; |
| |
| @override |
| // TODO(paulberry): add "." tokens. |
| ChildEntities get _childEntities => |
| ChildEntities()..addNodeList('components', components); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitDottedName(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _components.accept(visitor); |
| } |
| } |
| |
| /// A floating point literal expression. |
| /// |
| /// doubleLiteral ::= |
| /// decimalDigit+ ('.' decimalDigit*)? exponent? |
| /// | '.' decimalDigit+ exponent? |
| /// |
| /// exponent ::= |
| |