| // 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/type.dart'; |
| import 'package:analyzer/src/dart/ast/to_source_visitor.dart'; |
| import 'package:analyzer/src/dart/ast/token.dart'; |
| import 'package:analyzer/src/fasta/token_utils.dart' as util show findPrevious; |
| import 'package:analyzer/src/generated/java_engine.dart'; |
| import 'package:analyzer/src/generated/source.dart' show LineInfo, Source; |
| import 'package:analyzer/src/generated/utilities_dart.dart'; |
| |
| /// Two or more string literals that are implicitly concatenated because of |
| /// being adjacent (separated only by whitespace). |
| /// |
| /// While the grammar only allows adjacent strings when all of the strings are |
| /// of the same kind (single line or multi-line), this class doesn't enforce |
| /// that restriction. |
| /// |
| /// adjacentStrings ::= |
| /// [StringLiteral] [StringLiteral]+ |
| class AdjacentStringsImpl extends StringLiteralImpl implements AdjacentStrings { |
| /// The strings that are implicitly concatenated. |
| 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(List<StringLiteral> strings) { |
| _strings._initialize(this, strings); |
| } |
| |
| @override |
| Token get beginToken => _strings.beginToken!; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..addAll(_strings); |
| |
| @override |
| Token get endToken => _strings.endToken!; |
| |
| @override |
| NodeListImpl<StringLiteral> get strings => _strings; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitAdjacentStrings(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _strings.accept(visitor); |
| } |
| |
| @override |
| void _appendStringValue(StringBuffer buffer) { |
| int length = strings.length; |
| for (int i = 0; i < length; i++) { |
| 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); |
| } |
| |
| /// Return a holder of child entities that subclasses can add to. |
| ChildEntities get _childEntities { |
| ChildEntities result = ChildEntities(); |
| if (_commentIsBeforeAnnotations()) { |
| result |
| ..add(_comment) |
| ..addAll(_metadata); |
| } else { |
| result.addAll(sortedCommentAndAnnotations); |
| } |
| return result; |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| if (_commentIsBeforeAnnotations()) { |
| _comment?.accept(visitor); |
| _metadata.accept(visitor); |
| } else { |
| List<AstNode> children = sortedCommentAndAnnotations; |
| int length = children.length; |
| for (int i = 0; i < length; i++) { |
| children[i].accept(visitor); |
| } |
| } |
| } |
| |
| /// Return `true` if there are no annotations before the comment. Note that a |
| /// result of `true` does not imply that there is a comment, nor that there |
| /// are annotations associated with this node. |
| bool _commentIsBeforeAnnotations() { |
| if (_comment == null || _metadata.isEmpty) { |
| return true; |
| } |
| Annotation firstAnnotation = _metadata[0]; |
| return _comment!.offset < firstAnnotation.offset; |
| } |
| } |
| |
| /// An annotation that can be associated with an AST node. |
| /// |
| /// metadata ::= |
| /// annotation* |
| /// |
| /// annotation ::= |
| /// '@' [Identifier] ('.' [SimpleIdentifier])? [ArgumentList]? |
| class AnnotationImpl extends AstNodeImpl implements Annotation { |
| /// The at sign that introduced the annotation. |
| @override |
| Token atSign; |
| |
| /// The name of the class defining the constructor that is being invoked or |
| /// the name of the field that is being referenced. |
| IdentifierImpl _name; |
| |
| /// The 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 |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(atSign) |
| ..add(_name) |
| ..add(_typeArguments) |
| ..add(period) |
| ..add(_constructorName) |
| ..add(_arguments); |
| |
| @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 |
| 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( |
| this.leftParenthesis, List<Expression> arguments, this.rightParenthesis) { |
| _arguments._initialize(this, arguments); |
| } |
| |
| @override |
| NodeListImpl<Expression> get arguments => _arguments; |
| |
| @override |
| Token get beginToken => leftParenthesis; |
| |
| @override |
| // TODO(paulberry): Add commas. |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(leftParenthesis) |
| ..addAll(_arguments) |
| ..add(rightParenthesis); |
| |
| 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 |
| 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(this._expression, this.asOperator, this._type) { |
| _becomeParentOf(_expression); |
| _becomeParentOf(_type); |
| } |
| |
| @override |
| Token get beginToken => _expression.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_expression)..add(asOperator)..add(_type); |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitAsExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| _type.accept(visitor); |
| } |
| } |
| |
| /// An assert in the initializer list of a constructor. |
| /// |
| /// assertInitializer ::= |
| /// 'assert' '(' [Expression] (',' [Expression])? ')' |
| class AssertInitializerImpl extends ConstructorInitializerImpl |
| implements AssertInitializer { |
| @override |
| Token assertKeyword; |
| |
| @override |
| Token leftParenthesis; |
| |
| /// The condition that is being asserted to be `true`. |
| ExpressionImpl _condition; |
| |
| @override |
| Token? comma; |
| |
| /// The message to report if the assertion fails, or `null` if no message was |
| /// supplied. |
| ExpressionImpl? _message; |
| |
| @override |
| Token rightParenthesis; |
| |
| /// Initialize a newly created assert initializer. |
| AssertInitializerImpl(this.assertKeyword, this.leftParenthesis, |
| this._condition, this.comma, this._message, this.rightParenthesis) { |
| _becomeParentOf(_condition); |
| _becomeParentOf(_message); |
| } |
| |
| @override |
| Token get beginToken => assertKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(assertKeyword) |
| ..add(leftParenthesis) |
| ..add(_condition) |
| ..add(comma) |
| ..add(_message) |
| ..add(rightParenthesis); |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitAssertInitializer(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _condition.accept(visitor); |
| message?.accept(visitor); |
| } |
| } |
| |
| /// An assert statement. |
| /// |
| /// assertStatement ::= |
| /// 'assert' '(' [Expression] ')' ';' |
| class AssertStatementImpl extends StatementImpl implements AssertStatement { |
| @override |
| Token assertKeyword; |
| |
| @override |
| Token leftParenthesis; |
| |
| /// The condition that is being asserted to be `true`. |
| ExpressionImpl _condition; |
| |
| @override |
| Token? comma; |
| |
| /// The message to report if the assertion fails, or `null` if no message was |
| /// supplied. |
| ExpressionImpl? _message; |
| |
| @override |
| Token rightParenthesis; |
| |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created assert statement. |
| AssertStatementImpl(this.assertKeyword, this.leftParenthesis, this._condition, |
| this.comma, this._message, this.rightParenthesis, this.semicolon) { |
| _becomeParentOf(_condition); |
| _becomeParentOf(_message); |
| } |
| |
| @override |
| Token get beginToken => assertKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(assertKeyword) |
| ..add(leftParenthesis) |
| ..add(_condition) |
| ..add(comma) |
| ..add(_message) |
| ..add(rightParenthesis) |
| ..add(semicolon); |
| |
| @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 |
| 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( |
| this._leftHandSide, this.operator, this._rightHandSide) { |
| _becomeParentOf(_leftHandSide); |
| _becomeParentOf(_rightHandSide); |
| } |
| |
| @override |
| Token get beginToken => _leftHandSide.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_leftHandSide)..add(operator)..add(_rightHandSide); |
| |
| @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 |
| 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 visitChildren(AstVisitor visitor) { |
| _leftHandSide.accept(visitor); |
| _rightHandSide.accept(visitor); |
| } |
| |
| @override |
| bool _extendsNullShorting(Expression child) => |
| identical(child, _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 |
| 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; |
| } |
| |
| @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; |
| } |
| |
| void detachFromParent() { |
| _parent = null; |
| } |
| |
| @override |
| Token? findPrevious(Token target) => |
| util.findPrevious(beginToken, target) ?? parent?.findPrevious(target); |
| |
| @override |
| E? getProperty<E>(String name) { |
| if (_propertyMap == null) { |
| return null; |
| } |
| return _propertyMap![name] as E?; |
| } |
| |
| @override |
| void setProperty(String name, Object? value) { |
| if (value == null) { |
| if (_propertyMap != null) { |
| _propertyMap!.remove(name); |
| if (_propertyMap!.isEmpty) { |
| _propertyMap = null; |
| } |
| } |
| } else { |
| _propertyMap ??= HashMap<String, Object>(); |
| _propertyMap![name] = value; |
| } |
| } |
| |
| @override |
| E? thisOrAncestorMatching<E extends AstNode>(Predicate<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 await expression. |
| /// |
| /// awaitExpression ::= |
| /// 'await' [Expression] |
| class AwaitExpressionImpl extends ExpressionImpl implements AwaitExpression { |
| /// The 'await' keyword. |
| @override |
| Token awaitKeyword; |
| |
| /// The expression whose value is being waited on. |
| ExpressionImpl _expression; |
| |
| /// Initialize a newly created await expression. |
| AwaitExpressionImpl(this.awaitKeyword, this._expression) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken { |
| return awaitKeyword; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(awaitKeyword)..add(_expression); |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitAwaitExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// A binary (infix) expression. |
| /// |
| /// binaryExpression ::= |
| /// [Expression] [Token] [Expression] |
| class BinaryExpressionImpl extends ExpressionImpl implements BinaryExpression { |
| /// The expression used to compute the left operand. |
| ExpressionImpl _leftOperand; |
| |
| /// The binary operator being applied. |
| @override |
| Token operator; |
| |
| /// The expression used to compute the right operand. |
| ExpressionImpl _rightOperand; |
| |
| /// The element associated with the operator based on the static type of the |
| /// left operand, or `null` if the AST structure has not been resolved, if the |
| /// operator is not user definable, or if the operator could not be resolved. |
| @override |
| MethodElement? staticElement; |
| |
| @override |
| FunctionType? staticInvokeType; |
| |
| /// Initialize a newly created binary expression. |
| BinaryExpressionImpl(this._leftOperand, this.operator, this._rightOperand) { |
| _becomeParentOf(_leftOperand); |
| _becomeParentOf(_rightOperand); |
| } |
| |
| @override |
| Token get beginToken => _leftOperand.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_leftOperand)..add(operator)..add(_rightOperand); |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitBinaryExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _leftOperand.accept(visitor); |
| _rightOperand.accept(visitor); |
| } |
| } |
| |
| /// A function body that consists of a block of statements. |
| /// |
| /// blockFunctionBody ::= |
| /// ('async' | 'async' '*' | 'sync' '*')? [Block] |
| class BlockFunctionBodyImpl extends FunctionBodyImpl |
| implements BlockFunctionBody { |
| /// The token representing the 'async' or 'sync' keyword, or `null` if there |
| /// is no such keyword. |
| @override |
| Token? keyword; |
| |
| /// The star optionally following the 'async' or 'sync' keyword, or `null` if |
| /// there is wither no such keyword or no star. |
| @override |
| Token? star; |
| |
| /// The block representing the body of the function. |
| BlockImpl _block; |
| |
| /// Initialize a newly created function body consisting of a block of |
| /// statements. The [keyword] can be `null` if there is no keyword specified |
| /// for the block. The [star] can be `null` if there is no star following the |
| /// keyword (and must be `null` if there is no keyword). |
| BlockFunctionBodyImpl(this.keyword, this.star, 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 |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(keyword)..add(star)..add(_block); |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitBlockFunctionBody(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _block.accept(visitor); |
| } |
| } |
| |
| /// A sequence of statements. |
| /// |
| /// block ::= |
| /// '{' statement* '}' |
| class BlockImpl extends StatementImpl implements Block { |
| /// The left curly bracket. |
| @override |
| Token leftBracket; |
| |
| /// The statements contained in the block. |
| 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 |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(leftBracket) |
| ..addAll(_statements) |
| ..add(rightBracket); |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| NodeListImpl<Statement> get statements => _statements; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitBlock(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _statements.accept(visitor); |
| } |
| } |
| |
| /// A boolean literal expression. |
| /// |
| /// booleanLiteral ::= |
| /// 'false' | 'true' |
| class BooleanLiteralImpl extends LiteralImpl implements BooleanLiteral { |
| /// The token representing the literal. |
| @override |
| Token literal; |
| |
| /// The value of the literal. |
| @override |
| bool value = false; |
| |
| /// Initialize a newly created boolean literal. |
| BooleanLiteralImpl(this.literal, this.value); |
| |
| @override |
| Token get beginToken => literal; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal); |
| |
| @override |
| Token get endToken => literal; |
| |
| @override |
| bool get isSynthetic => literal.isSynthetic; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitBooleanLiteral(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| /// A break statement. |
| /// |
| /// breakStatement ::= |
| /// 'break' [SimpleIdentifier]? ';' |
| class BreakStatementImpl extends StatementImpl implements BreakStatement { |
| /// The token representing the 'break' keyword. |
| @override |
| Token breakKeyword; |
| |
| /// The label associated with the statement, or `null` if there is no label. |
| SimpleIdentifierImpl? _label; |
| |
| /// The semicolon terminating the statement. |
| @override |
| Token semicolon; |
| |
| /// The AstNode which this break statement is breaking from. This will be |
| /// either a [Statement] (in the case of breaking out of a loop), a |
| /// [SwitchMember] (in the case of a labeled break statement whose label |
| /// matches a label on a switch case in an enclosing switch statement), or |
| /// `null` if the AST has not yet been resolved or if the target could not be |
| /// resolved. Note that if the source code has errors, the target might be |
| /// invalid (e.g. trying to break to a switch case). |
| @override |
| AstNode? target; |
| |
| /// Initialize a newly created break statement. The [label] can be `null` if |
| /// there is no label associated with the statement. |
| BreakStatementImpl(this.breakKeyword, this._label, this.semicolon) { |
| _becomeParentOf(_label); |
| } |
| |
| @override |
| Token get beginToken => breakKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(breakKeyword)..add(_label)..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| SimpleIdentifierImpl? get label => _label; |
| |
| set label(SimpleIdentifier? identifier) { |
| _label = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitBreakStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _label?.accept(visitor); |
| } |
| } |
| |
| /// A sequence of cascaded expressions: expressions that share a common target. |
| /// There are three kinds of expressions that can be used in a cascade |
| /// expression: [IndexExpression], [MethodInvocation] and [PropertyAccess]. |
| /// |
| /// cascadeExpression ::= |
| /// [Expression] cascadeSection* |
| /// |
| /// cascadeSection ::= |
| /// '..' (cascadeSelector arguments*) (assignableSelector arguments*)* |
| /// (assignmentOperator expressionWithoutCascade)? |
| /// |
| /// cascadeSelector ::= |
| /// '[ ' expression '] ' |
| /// | identifier |
| class CascadeExpressionImpl extends ExpressionImpl |
| 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 |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_target) |
| ..addAll(_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 |
| AstNode? get _nullShortingExtensionCandidate => null; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitCascadeExpression(this); |
| |
| @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 |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(onKeyword) |
| ..add(_exceptionType) |
| ..add(catchKeyword) |
| ..add(leftParenthesis) |
| ..add(_exceptionParameter) |
| ..add(comma) |
| ..add(_stackTraceParameter) |
| ..add(rightParenthesis) |
| ..add(_body); |
| |
| @override |
| Token get endToken => _body.endToken; |
| |
| @override |
| 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 |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitCatchClause(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _exceptionType?.accept(visitor); |
| _exceptionParameter?.accept(visitor); |
| _stackTraceParameter?.accept(visitor); |
| _body.accept(visitor); |
| } |
| } |
| |
| /// Helper class to allow iteration of child entities of an AST node. |
| class ChildEntities |
| with IterableMixin<SyntacticEntity> |
| implements Iterable<SyntacticEntity> { |
| /// The list of child entities to be iterated over. |
| final List<SyntacticEntity> _entities = []; |
| |
| @override |
| Iterator<SyntacticEntity> get iterator => _entities.iterator; |
| |
| /// Add an AST node or token as the next child entity, if it is not `null`. |
| void add(SyntacticEntity? entity) { |
| if (entity != null) { |
| _entities.add(entity); |
| } |
| } |
| |
| /// Add the given items as the next child entities, if [items] is not `null`. |
| void addAll(Iterable<SyntacticEntity>? items) { |
| if (items != null) { |
| _entities.addAll(items); |
| } |
| } |
| } |
| |
| /// The declaration of a class. |
| /// |
| /// classDeclaration ::= |
| /// 'abstract'? 'class' [SimpleIdentifier] [TypeParameterList]? |
| /// ([ExtendsClause] [WithClause]?)? |
| /// [ImplementsClause]? |
| /// '{' [ClassMember]* '}' |
| class ClassDeclarationImpl extends ClassOrMixinDeclarationImpl |
| implements ClassDeclaration { |
| /// The 'abstract' keyword, or `null` if the keyword was absent. |
| @override |
| Token? abstractKeyword; |
| |
| /// The token representing the 'class' keyword. |
| @override |
| Token classKeyword; |
| |
| /// The extends clause for the class, or `null` if the class does not extend |
| /// any other class. |
| ExtendsClauseImpl? _extendsClause; |
| |
| /// The with clause for the class, or `null` if the class does not have a with |
| /// clause. |
| WithClauseImpl? _withClause; |
| |
| /// The native clause for the class, or `null` if the class does not have a |
| /// native clause. |
| NativeClauseImpl? _nativeClause; |
| |
| /// Initialize a newly created class declaration. Either or both of the |
| /// [comment] and [metadata] can be `null` if the class does not have the |
| /// corresponding attribute. The [abstractKeyword] can be `null` if the class |
| /// is not abstract. The [typeParameters] can be `null` if the class does not |
| /// have any type parameters. Any or all of the [extendsClause], [withClause], |
| /// and [implementsClause] can be `null` if the class does not have the |
| /// corresponding clause. The list of [members] can be `null` if the class |
| /// does not have any members. |
| ClassDeclarationImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.abstractKeyword, |
| this.classKeyword, |
| SimpleIdentifierImpl name, |
| TypeParameterListImpl? typeParameters, |
| 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 |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(abstractKeyword) |
| ..add(classKeyword) |
| ..add(_name) |
| ..add(_typeParameters) |
| ..add(_extendsClause) |
| ..add(_withClause) |
| ..add(_implementsClause) |
| ..add(_nativeClause) |
| ..add(leftBracket) |
| ..addAll(members) |
| ..add(rightBracket); |
| |
| @override |
| ClassElement? get declaredElement => _name.staticElement as ClassElement?; |
| |
| @override |
| ExtendsClauseImpl? get extendsClause => _extendsClause; |
| |
| set extendsClause(ExtendsClause? extendsClause) { |
| _extendsClause = _becomeParentOf(extendsClause as ExtendsClauseImpl?); |
| } |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return abstractKeyword ?? 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 |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitClassDeclaration(this); |
| |
| @override |
| ConstructorDeclaration? getConstructor(String? name) { |
| int length = _members.length; |
| for (int i = 0; i < length; i++) { |
| ClassMember classMember = _members[i]; |
| if (classMember is ConstructorDeclaration) { |
| ConstructorDeclaration constructor = classMember; |
| SimpleIdentifier? constructorName = constructor.name; |
| if (name == null && constructorName == null) { |
| return constructor; |
| } |
| if (constructorName != null && constructorName.name == name) { |
| return constructor; |
| } |
| } |
| } |
| return null; |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _name.accept(visitor); |
| _typeParameters?.accept(visitor); |
| _extendsClause?.accept(visitor); |
| _withClause?.accept(visitor); |
| _implementsClause?.accept(visitor); |
| _nativeClause?.accept(visitor); |
| members.accept(visitor); |
| } |
| } |
| |
| /// A node that declares a name within the scope of a class. |
| abstract class ClassMemberImpl extends DeclarationImpl implements ClassMember { |
| /// Initialize a newly created member of a class. Either or both of the |
| /// [comment] and [metadata] can be `null` if the member does not have the |
| /// corresponding attribute. |
| ClassMemberImpl(CommentImpl? comment, List<Annotation>? metadata) |
| : super(comment, metadata); |
| } |
| |
| abstract class ClassOrMixinDeclarationImpl |
| extends NamedCompilationUnitMemberImpl implements ClassOrMixinDeclaration { |
| /// The type parameters for the class or mixin, |
| /// or `null` if the declaration does not have any type parameters. |
| TypeParameterListImpl? _typeParameters; |
| |
| /// The implements clause for the class or mixin, |
| /// or `null` if the declaration does not implement any interfaces. |
| ImplementsClauseImpl? _implementsClause; |
| |
| /// The left curly bracket. |
| @override |
| Token leftBracket; |
| |
| /// The members defined by the class or mixin. |
| final NodeListImpl<ClassMember> _members = NodeListImpl._(); |
| |
| /// The right curly bracket. |
| @override |
| Token rightBracket; |
| |
| ClassOrMixinDeclarationImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| SimpleIdentifierImpl name, |
| this._typeParameters, |
| this._implementsClause, |
| this.leftBracket, |
| List<ClassMember> members, |
| this.rightBracket) |
| : super(comment, metadata, name) { |
| _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 name of the superclass of the class being declared. |
| TypeNameImpl _superclass; |
| |
| /// The with clause for this class. |
| WithClauseImpl _withClause; |
| |
| /// The implements clause for this class, or `null` if there is no implements |
| /// clause. |
| ImplementsClauseImpl? _implementsClause; |
| |
| /// Initialize a newly created class type alias. Either or both of the |
| /// [comment] and [metadata] can be `null` if the class type alias does not |
| /// have the corresponding attribute. The [typeParameters] can be `null` if |
| /// the class does not have any type parameters. The [abstractKeyword] can be |
| /// `null` if the class is not abstract. The [implementsClause] can be `null` |
| /// if the class does not implement any interfaces. |
| ClassTypeAliasImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| Token keyword, |
| SimpleIdentifierImpl name, |
| this._typeParameters, |
| this.equals, |
| this.abstractKeyword, |
| this._superclass, |
| this._withClause, |
| this._implementsClause, |
| Token semicolon) |
| : super(comment, metadata, keyword, name, semicolon) { |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_superclass); |
| _becomeParentOf(_withClause); |
| _becomeParentOf(_implementsClause); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(typedefKeyword) |
| ..add(_name) |
| ..add(_typeParameters) |
| ..add(equals) |
| ..add(abstractKeyword) |
| ..add(_superclass) |
| ..add(_withClause) |
| ..add(_implementsClause) |
| ..add(semicolon); |
| |
| @override |
| ClassElement? get declaredElement => _name.staticElement as ClassElement?; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return abstractKeyword ?? typedefKeyword; |
| } |
| |
| @override |
| ImplementsClauseImpl? get implementsClause => _implementsClause; |
| |
| set implementsClause(ImplementsClause? implementsClause) { |
| _implementsClause = |
| _becomeParentOf(implementsClause as ImplementsClauseImpl?); |
| } |
| |
| @override |
| bool get isAbstract => abstractKeyword != null; |
| |
| @override |
| TypeNameImpl get superclass => _superclass; |
| |
| set superclass(TypeName superclass) { |
| _superclass = _becomeParentOf(superclass as TypeNameImpl); |
| } |
| |
| @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 |
| 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 {} |
| |
| /// 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 |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..addAll(tokens); |
| |
| @override |
| Token get endToken => tokens[tokens.length - 1]; |
| |
| @override |
| bool get isBlock => _type == CommentType.BLOCK; |
| |
| @override |
| bool get isDocumentation => _type == CommentType.DOCUMENTATION; |
| |
| @override |
| bool get isEndOfLine => _type == CommentType.END_OF_LINE; |
| |
| @override |
| NodeListImpl<CommentReference> get references => _references; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitComment(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _references.accept(visitor); |
| } |
| |
| /// Create a block comment consisting of the given [tokens]. |
| static 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>[]); |
| } |
| |
| /// A reference to a Dart element that is found within a documentation comment. |
| /// |
| /// commentReference ::= |
| /// '[' 'new'? [Identifier] ']' |
| class CommentReferenceImpl extends AstNodeImpl implements CommentReference { |
| /// The token representing the 'new' keyword, or `null` if there was no 'new' |
| /// keyword. |
| @override |
| Token? newKeyword; |
| |
| /// The identifier being referenced. |
| IdentifierImpl _identifier; |
| |
| /// Initialize a newly created reference to a Dart element. The [newKeyword] |
| /// can be `null` if the reference is not to a constructor. |
| CommentReferenceImpl(this.newKeyword, this._identifier) { |
| _becomeParentOf(_identifier); |
| } |
| |
| @override |
| Token get beginToken => newKeyword ?? _identifier.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(newKeyword)..add(_identifier); |
| |
| @override |
| Token get endToken => _identifier.endToken; |
| |
| @override |
| IdentifierImpl get identifier => _identifier; |
| |
| set identifier(Identifier identifier) { |
| _identifier = _becomeParentOf(identifier as IdentifierImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitCommentReference(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _identifier.accept(visitor); |
| } |
| } |
| |
| /// The possible types of comments that are recognized by the parser. |
| class CommentType { |
| /// A block comment. |
| static const CommentType BLOCK = 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 |
| 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) { |
| _becomeParentOf(_scriptTag); |
| _directives._initialize(this, directives); |
| _declarations._initialize(this, declarations); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities { |
| ChildEntities result = ChildEntities()..add(_scriptTag); |
| if (_directivesAreBeforeDeclarations) { |
| result..addAll(_directives)..addAll(_declarations); |
| } else { |
| result.addAll(sortedDirectivesAndDeclarations); |
| } |
| return result; |
| } |
| |
| @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); |
| } |
| |
| /// 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(CommentImpl? comment, List<Annotation>? metadata) |
| : super(comment, 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 |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_condition) |
| ..add(question) |
| ..add(_thenExpression) |
| ..add(colon) |
| ..add(_elseExpression); |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitConditionalExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _condition.accept(visitor); |
| _thenExpression.accept(visitor); |
| _elseExpression.accept(visitor); |
| } |
| } |
| |
| /// A configuration in either an import or export directive. |
| /// |
| /// configuration ::= |
| /// 'if' '(' test ')' uri |
| /// |
| /// test ::= |
| /// dottedName ('==' stringLiteral)? |
| /// |
| /// dottedName ::= |
| /// identifier ('.' identifier)* |
| class ConfigurationImpl extends AstNodeImpl implements Configuration { |
| @override |
| Token ifKeyword; |
| |
| @override |
| Token leftParenthesis; |
| |
| DottedNameImpl _name; |
| |
| @override |
| Token? equalToken; |
| |
| StringLiteralImpl? _value; |
| |
| @override |
| Token rightParenthesis; |
| |
| StringLiteralImpl _uri; |
| |
| @override |
| Source? uriSource; |
| |
| ConfigurationImpl(this.ifKeyword, this.leftParenthesis, this._name, |
| this.equalToken, this._value, this.rightParenthesis, this._uri) { |
| _becomeParentOf(_name); |
| _becomeParentOf(_value); |
| _becomeParentOf(_uri); |
| } |
| |
| @override |
| Token get beginToken => ifKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(ifKeyword) |
| ..add(leftParenthesis) |
| ..add(_name) |
| ..add(equalToken) |
| ..add(_value) |
| ..add(rightParenthesis) |
| ..add(_uri); |
| |
| @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 |
| 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( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.externalKeyword, |
| this.constKeyword, |
| this.factoryKeyword, |
| this._returnType, |
| this.period, |
| this._name, |
| this._parameters, |
| this.separator, |
| List<ConstructorInitializer>? initializers, |
| this._redirectedConstructor, |
| this._body) |
| : super(comment, metadata) { |
| _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 |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(externalKeyword) |
| ..add(constKeyword) |
| ..add(factoryKeyword) |
| ..add(_returnType) |
| ..add(period) |
| ..add(_name) |
| ..add(_parameters) |
| ..add(separator) |
| ..addAll(initializers) |
| ..add(_redirectedConstructor) |
| ..add(_body); |
| |
| @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 |
| 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 |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(thisKeyword) |
| ..add(period) |
| ..add(_fieldName) |
| ..add(equals) |
| ..add(_expression); |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitConstructorFieldInitializer(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _fieldName.accept(visitor); |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// A node that can occur in the initializer list of a constructor declaration. |
| /// |
| /// constructorInitializer ::= |
| /// [SuperConstructorInvocation] |
| /// | [ConstructorFieldInitializer] |
| /// | [RedirectingConstructorInvocation] |
| abstract class ConstructorInitializerImpl extends AstNodeImpl |
| implements ConstructorInitializer {} |
| |
| /// The name of the constructor. |
| /// |
| /// constructorName ::= |
| /// type ('.' identifier)? |
| class ConstructorNameImpl extends AstNodeImpl implements ConstructorName { |
| /// The name of the type defining the constructor. |
| TypeNameImpl _type; |
| |
| /// The token for the period before the constructor name, or `null` if the |
| /// specified constructor is the unnamed constructor. |
| @override |
| Token? period; |
| |
| /// The name of the constructor, or `null` if the specified constructor is the |
| /// unnamed constructor. |
| SimpleIdentifierImpl? _name; |
| |
| /// The element associated with this constructor name based on static type |
| /// information, or `null` if the AST structure has not been resolved or if |
| /// this constructor name could not be resolved. |
| @override |
| ConstructorElement? staticElement; |
| |
| /// Initialize a newly created constructor name. The [period] and [name] can |
| /// be`null` if the constructor being named is the unnamed constructor. |
| ConstructorNameImpl(this._type, this.period, this._name) { |
| _becomeParentOf(_type); |
| _becomeParentOf(_name); |
| } |
| |
| @override |
| Token get beginToken => _type.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_type)..add(period)..add(_name); |
| |
| @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 |
| TypeNameImpl get type => _type; |
| |
| set type(TypeName type) { |
| _type = _becomeParentOf(type as TypeNameImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitConstructorName(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _type.accept(visitor); |
| _name?.accept(visitor); |
| } |
| } |
| |
| /// 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 ExpressionImpl |
| implements ConstructorReference { |
| ConstructorNameImpl _constructorName; |
| |
| ConstructorReferenceImpl(this._constructorName) { |
| _becomeParentOf(_constructorName); |
| } |
| |
| @override |
| Token get beginToken => constructorName.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(constructorName); |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitConstructorReference(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| constructorName.accept(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 |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(continueKeyword)..add(_label)..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| SimpleIdentifierImpl? get label => _label; |
| |
| set label(SimpleIdentifier? identifier) { |
| _label = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @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(CommentImpl? comment, List<Annotation>? metadata) |
| : super(comment, 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(CommentImpl? comment, List<Annotation>? metadata, |
| this.keyword, this._type, this._identifier) |
| : super(comment, metadata) { |
| _becomeParentOf(_type); |
| _becomeParentOf(_identifier); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(keyword)..add(_type)..add(_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 |
| 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(Token token) : 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 |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_parameter)..add(separator)..add(_defaultValue); |
| |
| @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 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 |
| 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 ::= |
| /// [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(CommentImpl? comment, List<Annotation>? metadata) |
| : super(comment, 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 |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(doKeyword) |
| ..add(_body) |
| ..add(whileKeyword) |
| ..add(leftParenthesis) |
| ..add(_condition) |
| ..add(rightParenthesis) |
| ..add(semicolon); |
| |
| @override |
| ExpressionImpl get condition => _condition; |
| |
| set condition(Expression expression) { |
| _condition = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Token get endToken => 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 |
| // TODO(paulberry): add "." tokens. |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..addAll(_components); |
| |
| @override |
| NodeListImpl<SimpleIdentifier> get components => _components; |
| |
| @override |
| Token get endToken => _components.endToken!; |
| |
| @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 ::= |
| /// ('e' | 'E') ('+' | '-')? decimalDigit+ |
| class DoubleLiteralImpl extends LiteralImpl implements DoubleLiteral { |
| /// The token representing the literal. |
| @override |
| Token literal; |
| |
| /// The value of the literal. |
| @override |
| double value; |
| |
| /// Initialize a newly created floating point literal. |
| DoubleLiteralImpl(this.literal, this.value); |
| |
| @override |
| Token get beginToken => literal; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal); |
| |
| @override |
| Token get endToken => literal; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitDoubleLiteral(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| /// An empty function body, which can only appear in constructors or abstract |
| /// methods. |
| /// |
| /// emptyFunctionBody ::= |
| /// ';' |
| class EmptyFunctionBodyImpl extends FunctionBodyImpl |
| implements EmptyFunctionBody { |
| /// The token representing the semicolon that marks the end of the function |
| /// body. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created function body. |
| EmptyFunctionBodyImpl(this.semicolon); |
| |
| @override |
| Token get beginToken => semicolon; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitEmptyFunctionBody(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // Empty function bodies have no children. |
| } |
| } |
| |
| /// An empty statement. |
| /// |
| /// emptyStatement ::= |
| /// ';' |
| class EmptyStatementImpl extends StatementImpl implements EmptyStatement { |
| /// The semicolon terminating the statement. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created empty statement. |
| EmptyStatementImpl(this.semicolon); |
| |
| @override |
| Token get beginToken => semicolon; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| bool get isSynthetic => semicolon.isSynthetic; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitEmptyStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| /// The declaration of an enum constant. |
| class EnumConstantDeclarationImpl extends DeclarationImpl |
| implements EnumConstantDeclaration { |
| /// The name of the constant. |
| SimpleIdentifierImpl _name; |
| |
| /// Initialize a newly created enum constant declaration. Either or both of |
| /// the [comment] and [metadata] can be `null` if the constant does not have |
| /// the corresponding attribute. (Technically, enum constants cannot have |
| /// metadata, but we allow it for consistency.) |
| EnumConstantDeclarationImpl( |
| CommentImpl? comment, List<Annotation>? metadata, this._name) |
| : super(comment, metadata) { |
| _becomeParentOf(_name); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(_name); |
| |
| @override |
| FieldElement get declaredElement => _name.staticElement as FieldElement; |
| |
| @override |
| Token get endToken => _name.endToken; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => _name.beginToken; |
| |
| @override |
| SimpleIdentifierImpl get name => _name; |
| |
| set name(SimpleIdentifier name) { |
| _name = _becomeParentOf(name as SimpleIdentifierImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitEnumConstantDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _name.accept(visitor); |
| } |
| } |
| |
| /// The declaration of an enumeration. |
| /// |
| /// enumType ::= |
| /// metadata 'enum' [SimpleIdentifier] '{' [SimpleIdentifier] |
| /// (',' [SimpleIdentifier])* (',')? '}' |
| class EnumDeclarationImpl extends NamedCompilationUnitMemberImpl |
| implements EnumDeclaration { |
| /// The 'enum' keyword. |
| @override |
| Token enumKeyword; |
| |
| /// The left curly bracket. |
| @override |
| Token leftBracket; |
| |
| /// The enumeration constants being declared. |
| final NodeListImpl<EnumConstantDeclaration> _constants = NodeListImpl._(); |
| |
| /// The right curly bracket. |
| @override |
| Token rightBracket; |
| |
| /// Initialize a newly created enumeration declaration. Either or both of the |
| /// [comment] and [metadata] can be `null` if the declaration does not have |
| /// the corresponding attribute. The list of [constants] must contain at least |
| /// one value. |
| EnumDeclarationImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.enumKeyword, |
| SimpleIdentifierImpl name, |
| this.leftBracket, |
| List<EnumConstantDeclaration> constants, |
| this.rightBracket) |
| : super(comment, metadata, name) { |
| _constants._initialize(this, constants); |
| } |
| |
| @override |
| // TODO(brianwilkerson) Add commas? |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(enumKeyword) |
| ..add(_name) |
| ..add(leftBracket) |
| ..addAll(_constants) |
| ..add(rightBracket); |
| |
| @override |
| NodeListImpl<EnumConstantDeclaration> get constants => _constants; |
| |
| @override |
| ClassElement? get declaredElement => _name.staticElement as ClassElement?; |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => enumKeyword; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitEnumDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _name.accept(visitor); |
| _constants.accept(visitor); |
| } |
| } |
| |
| /// Ephemeral identifiers are created as needed to mimic the presence of an |
| /// empty identifier. |
| class EphemeralIdentifier extends SimpleIdentifierImpl { |
| EphemeralIdentifier(AstNode parent, int location) |
| : super(StringToken(TokenType.IDENTIFIER, "", location)) { |
| (parent as AstNodeImpl)._becomeParentOf(this); |
| } |
| } |
| |
| /// An export directive. |
| /// |
| /// exportDirective ::= |
| /// [Annotation] 'export' [StringLiteral] [Combinator]* ';' |
| class ExportDirectiveImpl extends NamespaceDirectiveImpl |
| implements ExportDirective { |
| /// Initialize a newly created export directive. Either or both of the |
| /// [comment] and [metadata] can be `null` if the directive does not have the |
| /// corresponding attribute. The list of [combinators] can be `null` if there |
| /// are no combinators. |
| ExportDirectiveImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| Token keyword, |
| StringLiteralImpl libraryUri, |
| List<Configuration>? configurations, |
| List<Combinator>? combinators, |
| Token semicolon) |
| : super(comment, metadata, keyword, libraryUri, configurations, |
| combinators, semicolon); |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(keyword) |
| ..add(_uri) |
| ..addAll(combinators) |
| ..add(semicolon); |
| |
| @override |
| ExportElement? get element => super.element as ExportElement?; |
| |
| @override |
| LibraryElement? get uriElement { |
| return element?.exportedLibrary; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitExportDirective(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| configurations.accept(visitor); |
| super.visitChildren(visitor); |
| combinators.accept(visitor); |
| } |
| } |
| |
| /// A function body consisting of a single expression. |
| /// |
| /// expressionFunctionBody ::= |
| /// 'async'? '=>' [Expression] ';' |
| class ExpressionFunctionBodyImpl extends FunctionBodyImpl |
| implements ExpressionFunctionBody { |
| /// The token representing the 'async' keyword, or `null` if there is no such |
| /// keyword. |
| @override |
| Token? keyword; |
| |
| /// The token introducing the expression that represents the body of the |
| /// function. |
| @override |
| Token functionDefinition; |
| |
| /// The expression representing the body of the function. |
| ExpressionImpl _expression; |
| |
| /// The semicolon terminating the statement. |
| @override |
| Token? semicolon; |
| |
| /// Initialize a newly created function body consisting of a block of |
| /// statements. The [keyword] can be `null` if the function body is not an |
| /// async function body. |
| ExpressionFunctionBodyImpl( |
| this.keyword, this.functionDefinition, this._expression, this.semicolon) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken { |
| if (keyword != null) { |
| return keyword!; |
| } |
| return functionDefinition; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(keyword) |
| ..add(functionDefinition) |
| ..add(_expression) |
| ..add(semicolon); |
| |
| @override |
| Token get endToken { |
| if (semicolon != null) { |
| return semicolon!; |
| } |
| return _expression.endToken; |
| } |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| bool get isAsynchronous => keyword != null; |
| |
| @override |
| bool get isSynchronous => keyword == null; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitExpressionFunctionBody(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// A node that represents an expression. |
| /// |
| /// expression ::= |
| /// [AssignmentExpression] |
| /// | [ConditionalExpression] cascadeSection* |
| /// | [ThrowExpression] |
| abstract class ExpressionImpl extends AstNodeImpl |
| implements CollectionElementImpl, Expression { |
| /// The static type of this expression, or `null` if the AST structure has not |
| /// been resolved. |
| @override |
| DartType? staticType; |
| |
| @override |
| bool get inConstantContext { |
| AstNode child = this; |
| while (child is Expression || |
| child is ArgumentList || |
| child is MapLiteralEntry || |
| child is SpreadElement || |
| child is IfElement || |
| child is ForElement) { |
| var parent = child.parent; |
| if (parent is ConstantContextForExpressionImpl) { |
| return true; |
| } else if (parent is TypedLiteralImpl && parent.constKeyword != null) { |
| // Inside an explicitly `const` list or map literal. |
| return true; |
| } else if (parent is InstanceCreationExpression && |
| parent.keyword?.keyword == Keyword.CONST) { |
| // Inside an explicitly `const` instance creation expression. |
| return true; |
| } else if (parent is Annotation) { |
| // Inside an annotation. |
| return true; |
| } else if (parent is VariableDeclaration) { |
| var grandParent = parent.parent; |
| // Inside the initializer for a `const` variable declaration. |
| return grandParent is VariableDeclarationList && |
| grandParent.keyword?.keyword == Keyword.CONST; |
| } else if (parent is SwitchCase) { |
| // Inside a switch case. |
| return true; |
| } else if (parent == null) { |
| break; |
| } |
| child = parent; |
| } |
| return false; |
| } |
| |
| @override |
| bool get isAssignable => false; |
| |
| @override |
| ParameterElement? get staticParameterElement { |
| final parent = this.parent; |
| if (parent is ArgumentListImpl) { |
| return parent._getStaticParameterElementFor(this); |
| } else if (parent is IndexExpressionImpl) { |
| if (identical(parent.index, this)) { |
| return parent._staticParameterElementForIndex; |
| } |
| } else if (parent is BinaryExpressionImpl) { |
| if (identical(parent.rightOperand, this)) { |
| var parameters = parent.staticInvokeType?.parameters; |
| if (parameters != null && parameters.isNotEmpty) { |
| return parameters[0]; |
| } |
| return null; |
| } |
| } else if (parent is AssignmentExpressionImpl) { |
| if (identical(parent.rightHandSide, this)) { |
| return parent._staticParameterElementForRightHandSide; |
| } |
| } else if (parent is PrefixExpressionImpl) { |
| return parent._staticParameterElementForOperand; |
| } else if (parent is PostfixExpressionImpl) { |
| return parent._staticParameterElementForOperand; |
| } |
| return null; |
| } |
| |
| @override |
| ExpressionImpl get unParenthesized => this; |
| } |
| |
| /// An expression used as a statement. |
| /// |
| /// expressionStatement ::= |
| /// [Expression]? ';' |
| class ExpressionStatementImpl extends StatementImpl |
| implements ExpressionStatement { |
| /// The expression that comprises the statement. |
| ExpressionImpl _expression; |
| |
| /// The semicolon terminating the statement, or `null` if the expression is a |
| /// function expression and therefore isn't followed by a semicolon. |
| @override |
| Token? semicolon; |
| |
| /// Initialize a newly created expression statement. |
| ExpressionStatementImpl(this._expression, this.semicolon) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken => _expression.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_expression)..add(semicolon); |
| |
| @override |
| Token get endToken { |
| if (semicolon != null) { |
| return semicolon!; |
| } |
| return _expression.endToken; |
| } |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| bool get isSynthetic => |
| _expression.isSynthetic && (semicolon == null || semicolon!.isSynthetic); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitExpressionStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// The "extends" clause in a class declaration. |
| /// |
| /// extendsClause ::= |
| /// 'extends' [TypeName] |
| class ExtendsClauseImpl extends AstNodeImpl implements ExtendsClause { |
| /// The token representing the 'extends' keyword. |
| @override |
| Token extendsKeyword; |
| |
| /// The name of the class that is being extended. |
| TypeNameImpl _superclass; |
| |
| /// Initialize a newly created extends clause. |
| ExtendsClauseImpl(this.extendsKeyword, this._superclass) { |
| _becomeParentOf(_superclass); |
| } |
| |
| @override |
| Token get beginToken => extendsKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(extendsKeyword)..add(_superclass); |
| |
| @override |
| Token get endToken => _superclass.endToken; |
| |
| @override |
| TypeNameImpl get superclass => _superclass; |
| |
| set superclass(TypeName name) { |
| _superclass = _becomeParentOf(name as TypeNameImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitExtendsClause(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _superclass.accept(visitor); |
| } |
| } |
| |
| /// The declaration of an extension of a type. |
| /// |
| /// extension ::= |
| /// 'extension' [SimpleIdentifier] [TypeParameterList]? |
| /// 'on' [TypeAnnotation] '{' [ClassMember]* '}' |
| /// |
| /// Clients may not extend, implement or mix-in this class. |
| class ExtensionDeclarationImpl extends CompilationUnitMemberImpl |
| implements ExtensionDeclaration { |
| @override |
| Token extensionKeyword; |
| |
| @override |
| Token? typeKeyword; |
| |
| /// The name of the extension, or `null` if the extension does not have a |
| /// name. |
| SimpleIdentifierImpl? _name; |
| |
| /// The type parameters for the extension, or `null` if the extension does not |
| /// have any type parameters. |
| TypeParameterListImpl? _typeParameters; |
| |
| @override |
| Token onKeyword; |
| |
| /// The type that is being extended. |
| TypeAnnotationImpl _extendedType; |
| |
| @override |
| Token leftBracket; |
| |
| /// The members being added to the extended class. |
| final NodeListImpl<ClassMember> _members = NodeListImpl._(); |
| |
| @override |
| Token rightBracket; |
| |
| ExtensionElement? _declaredElement; |
| |
| ExtensionDeclarationImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.extensionKeyword, |
| this.typeKeyword, |
| this._name, |
| this._typeParameters, |
| this.onKeyword, |
| this._extendedType, |
| this.leftBracket, |
| List<ClassMember> members, |
| this.rightBracket) |
| : super(comment, metadata) { |
| _becomeParentOf(_name); |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_extendedType); |
| _members._initialize(this, members); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(extensionKeyword) |
| ..add(name) |
| ..add(typeParameters) |
| ..add(onKeyword) |
| ..add(extendedType) |
| ..add(leftBracket) |
| ..addAll(members) |
| ..add(rightBracket); |
| |
| @override |
| ExtensionElement? get declaredElement => _declaredElement; |
| |
| /// Set the element declared by this declaration to the given [element]. |
| set declaredElement(ExtensionElement? element) { |
| _declaredElement = element; |
| } |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| TypeAnnotationImpl get extendedType => _extendedType; |
| |
| set extendedType(TypeAnnotation extendedClass) { |
| _extendedType = _becomeParentOf(extendedClass as TypeAnnotationImpl); |
| } |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => extensionKeyword; |
| |
| @override |
| NodeListImpl<ClassMember> get members => _members; |
| |
| @override |
| SimpleIdentifierImpl? get name => _name; |
| |
| set name(SimpleIdentifier? identifier) { |
| _name = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitExtensionDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| name?.accept(visitor); |
| _typeParameters?.accept(visitor); |
| _extendedType.accept(visitor); |
| _members.accept(visitor); |
| } |
| } |
| |
| /// An override to force resolution to choose a member from a specific |
| /// extension. |
| /// |
| /// extensionOverride ::= |
| /// [Identifier] [TypeArgumentList]? [ArgumentList] |
| class ExtensionOverrideImpl extends ExpressionImpl |
| implements ExtensionOverride { |
| /// The list of arguments to the override. In valid code this will contain a |
| /// single argument, which evaluates to the object being extended. |
| ArgumentListImpl _argumentList; |
| |
| /// The name of the extension being selected. |
| IdentifierImpl _extensionName; |
| |
| /// The type arguments to be applied to the extension, or `null` if no type |
| /// arguments were provided. |
| TypeArgumentListImpl? _typeArguments; |
| |
| @override |
| List<DartType>? typeArgumentTypes; |
| |
| @override |
| DartType? extendedType; |
| |
| ExtensionOverrideImpl( |
| this._extensionName, this._typeArguments, this._argumentList) { |
| _becomeParentOf(_extensionName); |
| _becomeParentOf(_typeArguments); |
| _becomeParentOf(_argumentList); |
| } |
| |
| @override |
| ArgumentListImpl get argumentList => _argumentList; |
| |
| set argumentList(ArgumentList argumentList) { |
| _argumentList = _becomeParentOf(argumentList as ArgumentListImpl); |
| } |
| |
| @override |
| Token get beginToken => _extensionName.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_extensionName) |
| ..add(_typeArguments) |
| ..add(_argumentList); |
| |
| @override |
| Token get endToken => _argumentList.endToken; |
| |
| @override |
| IdentifierImpl get extensionName => _extensionName; |
| |
| set extensionName(Identifier extensionName) { |
| _extensionName = _becomeParentOf(extensionName as IdentifierImpl); |
| } |
| |
| @override |
| bool get isNullAware { |
| var nextType = argumentList.endToken.next!.type; |
| return nextType == TokenType.QUESTION_PERIOD || |
| nextType == TokenType.QUESTION; |
| } |
| |
| @override |
| Precedence get precedence => Precedence.postfix; |
| |
| @override |
| ExtensionElement? get staticElement { |
| return extensionName.staticElement as ExtensionElement?; |
| } |
| |
| @override |
| TypeArgumentListImpl? get typeArguments => _typeArguments; |
| |
| set typeArguments(TypeArgumentList? typeArguments) { |
| _typeArguments = _becomeParentOf(typeArguments as TypeArgumentListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) { |
| return visitor.visitExtensionOverride(this); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _extensionName.accept(visitor); |
| _typeArguments?.accept(visitor); |
| _argumentList.accept(visitor); |
| } |
| } |
| |
| /// The declaration of one or more fields of the same type. |
| /// |
| /// fieldDeclaration ::= |
| /// 'static'? [VariableDeclarationList] ';' |
| class FieldDeclarationImpl extends ClassMemberImpl implements FieldDeclaration { |
| @override |
| Token? abstractKeyword; |
| |
| /// The 'covariant' keyword, or `null` if the keyword was not used. |
| @override |
| Token? covariantKeyword; |
| |
| @override |
| Token? externalKeyword; |
| |
| /// The token representing the 'static' keyword, or `null` if the fields are |
| /// not static. |
| @override |
| Token? staticKeyword; |
| |
| /// The fields being declared. |
| VariableDeclarationListImpl _fieldList; |
| |
| /// The semicolon terminating the declaration. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created field declaration. Either or both of the |
| /// [comment] and [metadata] can be `null` if the declaration does not have |
| /// the corresponding attribute. The [staticKeyword] can be `null` if the |
| /// field is not a static field. |
| FieldDeclarationImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.abstractKeyword, |
| this.covariantKeyword, |
| this.externalKeyword, |
| this.staticKeyword, |
| this._fieldList, |
| this.semicolon) |
| : super(comment, metadata) { |
| _becomeParentOf(_fieldList); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(staticKeyword)..add(_fieldList)..add(semicolon); |
| |
| @override |
| Element? get declaredElement => null; |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| VariableDeclarationListImpl get fields => _fieldList; |
| |
| set fields(VariableDeclarationList fields) { |
| _fieldList = _becomeParentOf(fields as VariableDeclarationListImpl); |
| } |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return Token.lexicallyFirst(abstractKeyword, externalKeyword, |
| covariantKeyword, staticKeyword) ?? |
| _fieldList.beginToken; |
| } |
| |
| @override |
| bool get isStatic => staticKeyword != null; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitFieldDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _fieldList.accept(visitor); |
| } |
| } |
| |
| /// A field formal parameter. |
| /// |
| /// fieldFormalParameter ::= |
| /// ('final' [TypeName] | 'const' [TypeName] | 'var' | [TypeName])? |
| /// 'this' '.' [SimpleIdentifier] |
| /// ([TypeParameterList]? [FormalParameterList])? |
| class FieldFormalParameterImpl extends NormalFormalParameterImpl |
| implements FieldFormalParameter { |
| /// 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 token representing the 'this' keyword. |
| @override |
| Token thisKeyword; |
| |
| /// The token representing the period. |
| @override |
| Token period; |
| |
| /// The type parameters associated with the method, or `null` if the method is |
| /// not a generic method. |
| TypeParameterListImpl? _typeParameters; |
| |
| /// The parameters of the function-typed parameter, or `null` if this is not a |
| /// function-typed field formal parameter. |
| FormalParameterListImpl? _parameters; |
| |
| @override |
| Token? question; |
| |
| /// Initialize a newly created formal parameter. Either or both of the |
| /// [comment] and [metadata] can be `null` if the parameter does not have the |
| /// corresponding attribute. The [keyword] can be `null` if there is a type. |
| /// The [type] must be `null` if the keyword is 'var'. The [thisKeyword] and |
| /// [period] can be `null` if the keyword 'this' was not provided. The |
| /// [parameters] can be `null` if this is not a function-typed field formal |
| /// parameter. |
| FieldFormalParameterImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| Token? covariantKeyword, |
| Token? requiredKeyword, |
| this.keyword, |
| this._type, |
| this.thisKeyword, |
| this.period, |
| SimpleIdentifierImpl identifier, |
| this._typeParameters, |
| this._parameters, |
| this.question) |
| : super( |
| comment, metadata, covariantKeyword, requiredKeyword, identifier) { |
| _becomeParentOf(_type); |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_parameters); |
| } |
| |
| @override |
| Token get beginToken { |
| final metadata = this.metadata; |
| if (metadata.isNotEmpty) { |
| return metadata.beginToken!; |
| } else if (requiredKeyword != null) { |
| return requiredKeyword!; |
| } else if (covariantKeyword != null) { |
| return covariantKeyword!; |
| } else if (keyword != null) { |
| return keyword!; |
| } else if (_type != null) { |
| return _type!.beginToken; |
| } |
| return thisKeyword; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(keyword) |
| ..add(_type) |
| ..add(thisKeyword) |
| ..add(period) |
| ..add(identifier) |
| ..add(_parameters); |
| |
| @override |
| Token get endToken { |
| return question ?? _parameters?.endToken ?? identifier.endToken; |
| } |
| |
| @override |
| SimpleIdentifierImpl get identifier => super.identifier!; |
| |
| @override |
| bool get isConst => keyword?.keyword == Keyword.CONST; |
| |
| @override |
| bool get isFinal => keyword?.keyword == Keyword.FINAL; |
| |
| @override |
| FormalParameterListImpl? get parameters => _parameters; |
| |
| set parameters(FormalParameterList? parameters) { |
| _parameters = _becomeParentOf(parameters as FormalParameterListImpl?); |
| } |
| |
| @override |
| TypeAnnotationImpl? get type => _type; |
| |
| set type(TypeAnnotation? type) { |
| _type = _becomeParentOf(type as TypeAnnotationImpl); |
| } |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitFieldFormalParameter(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _type?.accept(visitor); |
| identifier.accept(visitor); |
| _typeParameters?.accept(visitor); |
| _parameters?.accept(visitor); |
| } |
| } |
| |
| abstract class ForEachPartsImpl extends ForLoopPartsImpl |
| implements ForEachParts { |
| @override |
| Token inKeyword; |
| |
| /// The expression evaluated to produce the iterator. |
| ExpressionImpl _iterable; |
| |
| /// Initialize a newly created for-each statement whose loop control variable |
| /// is declared internally (in the for-loop part). The [awaitKeyword] can be |
| /// `null` if this is not an asynchronous for loop. |
| ForEachPartsImpl(this.inKeyword, this._iterable) { |
| _becomeParentOf(_iterable); |
| } |
| |
| @override |
| Token get beginToken => inKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(inKeyword)..add(_iterable); |
| |
| @override |
| Token get endToken => _iterable.endToken; |
| |
| @override |
| ExpressionImpl get iterable => _iterable; |
| |
| set iterable(Expression expression) { |
| _iterable = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _iterable.accept(visitor); |
| } |
| } |
| |
| class ForEachPartsWithDeclarationImpl extends ForEachPartsImpl |
| implements ForEachPartsWithDeclaration { |
| /// The declaration of the loop variable. |
| DeclaredIdentifierImpl _loopVariable; |
| |
| /// Initialize a newly created for-each statement whose loop control variable |
| /// is declared internally (inside the for-loop part). |
| ForEachPartsWithDeclarationImpl( |
| this._loopVariable, Token inKeyword, ExpressionImpl iterator) |
| : super(inKeyword, iterator) { |
| _becomeParentOf(_loopVariable); |
| } |
| |
| @override |
| Token get beginToken => _loopVariable.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_loopVariable) |
| ..addAll(super.childEntities); |
| |
| @override |
| DeclaredIdentifierImpl get loopVariable => _loopVariable; |
| |
| set loopVariable(DeclaredIdentifier variable) { |
| _loopVariable = _becomeParentOf(variable as DeclaredIdentifierImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitForEachPartsWithDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _loopVariable.accept(visitor); |
| super.visitChildren(visitor); |
| } |
| } |
| |
| class ForEachPartsWithIdentifierImpl extends ForEachPartsImpl |
| implements ForEachPartsWithIdentifier { |
| /// The loop variable. |
| SimpleIdentifierImpl _identifier; |
| |
| /// Initialize a newly created for-each statement whose loop control variable |
| /// is declared externally (outside the for-loop part). |
| ForEachPartsWithIdentifierImpl( |
| this._identifier, Token inKeyword, ExpressionImpl iterator) |
| : super(inKeyword, iterator) { |
| _becomeParentOf(_identifier); |
| } |
| |
| @override |
| Token get beginToken => _identifier.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_identifier) |
| ..addAll(super.childEntities); |
| |
| @override |
| SimpleIdentifierImpl get identifier => _identifier; |
| |
| set identifier(SimpleIdentifier identifier) { |
| _identifier = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitForEachPartsWithIdentifier(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _identifier.accept(visitor); |
| _iterable.accept(visitor); |
| } |
| } |
| |
| class ForElementImpl extends CollectionElementImpl implements ForElement { |
| @override |
| Token? awaitKeyword; |
| |
| @override |
| Token forKeyword; |
| |
| @override |
| Token leftParenthesis; |
| |
| ForLoopPartsImpl _forLoopParts; |
| |
| @override |
| Token rightParenthesis; |
| |
| /// The body of the loop. |
| CollectionElementImpl _body; |
| |
| /// Initialize a newly created for element. |
| ForElementImpl(this.awaitKeyword, this.forKeyword, this.leftParenthesis, |
| this._forLoopParts, this.rightParenthesis, this._body) { |
| _becomeParentOf(_forLoopParts); |
| _becomeParentOf(_body); |
| } |
| |
| @override |
| Token get beginToken => awaitKeyword ?? forKeyword; |
| |
| @override |
| CollectionElementImpl get body => _body; |
| |
| set body(CollectionElement statement) { |
| _body = _becomeParentOf(statement as CollectionElementImpl); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(awaitKeyword) |
| ..add(forKeyword) |
| ..add(leftParenthesis) |
| ..add(_forLoopParts) |
| ..add(rightParenthesis) |
| ..add(_body); |
| |
| @override |
| Token get endToken => _body.endToken; |
| |
| @override |
| ForLoopPartsImpl get forLoopParts => _forLoopParts; |
| |
| set forLoopParts(ForLoopParts forLoopParts) { |
| _forLoopParts = _becomeParentOf(forLoopParts as ForLoopPartsImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitForElement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _forLoopParts.accept(visitor); |
| _body.accept(visitor); |
| } |
| } |
| |
| abstract class ForLoopPartsImpl extends AstNodeImpl implements ForLoopParts {} |
| |
| /// A node representing a parameter to a function. |
| /// |
| /// formalParameter ::= |
| /// [NormalFormalParameter] |
| /// | [DefaultFormalParameter] |
| abstract class FormalParameterImpl extends AstNodeImpl |
| implements FormalParameter { |
| @override |
| ParameterElement? get declaredElement { |
| final identifier = this.identifier; |
| if (identifier == null) { |
| return null; |
| } |
| return identifier.staticElement as ParameterElement?; |
| } |
| |
| @override |
| SimpleIdentifierImpl? get identifier; |
| |
| @override |
| bool get isNamed => kind.isNamed; |
| |
| @override |
| bool get isOptional => kind.isOptional; |
| |
| @override |
| bool get isOptionalNamed => kind.isOptionalNamed; |
| |
| @override |
| bool get isOptionalPositional => kind.isOptionalPositional; |
| |
| @override |
| bool get isPositional => kind.isPositional; |
| |
| @override |
| bool get isRequired => kind.isRequired; |
| |
| @override |
| bool get isRequiredNamed => kind.isRequiredNamed; |
| |
| @override |
| bool get isRequiredPositional => kind.isRequiredPositional; |
| |
| /// Return the kind of this parameter. |
| ParameterKind get kind; |
| |
| static void setDeclaredElement( |
| FormalParameterImpl node, |
| ParameterElement element, |
| ) { |
| if (node is DefaultFormalParameterImpl) { |
| setDeclaredElement(node.parameter, element); |
| } else if (node is SimpleFormalParameterImpl) { |
| node.declaredElement = element; |
| } else { |
| node.identifier!.staticElement = element; |
| } |
| } |
| } |
| |
| /// The formal parameter list of a method declaration, function declaration, or |
| /// function type alias. |
| /// |
| /// While the grammar requires all optional formal parameters to follow all of |
| /// the normal formal parameters and at most one grouping of optional formal |
| /// parameters, this class does not enforce those constraints. All parameters |
| /// are flattened into a single list, which can have any or all kinds of |
| /// parameters (normal, named, and positional) in any order. |
| /// |
| /// formalParameterList ::= |
| /// '(' ')' |
| /// | '(' normalFormalParameters (',' optionalFormalParameters)? ')' |
| /// | '(' optionalFormalParameters ')' |
| /// |
| /// normalFormalParameters ::= |
| /// [NormalFormalParameter] (',' [NormalFormalParameter])* |
| /// |
| /// optionalFormalParameters ::= |
| /// optionalPositionalFormalParameters |
| /// | namedFormalParameters |
| /// |
| /// optionalPositionalFormalParameters ::= |
| /// '[' [DefaultFormalParameter] (',' [DefaultFormalParameter])* ']' |
| /// |
| /// namedFormalParameters ::= |
| /// '{' [DefaultFormalParameter] (',' [DefaultFormalParameter])* '}' |
| class FormalParameterListImpl extends AstNodeImpl |
| implements FormalParameterList { |
| /// The left parenthesis. |
| @override |
| Token leftParenthesis; |
| |
| /// The parameters associated with the method. |
| final NodeListImpl<FormalParameter> _parameters = NodeListImpl._(); |
| |
| /// The left square bracket ('[') or left curly brace ('{') introducing the |
| /// optional parameters, or `null` if there are no optional parameters. |
| @override |
| Token? leftDelimiter; |
| |
| /// The right square bracket (']') or right curly brace ('}') terminating the |
| /// optional parameters, or `null` if there are no optional parameters. |
| @override |
| Token? rightDelimiter; |
| |
| /// The right parenthesis. |
| @override |
| Token rightParenthesis; |
| |
| /// Initialize a newly created parameter list. The list of [parameters] can be |
| /// `null` if there are no parameters. The [leftDelimiter] and |
| /// [rightDelimiter] can be `null` if there are no optional parameters. |
| FormalParameterListImpl( |
| this.leftParenthesis, |
| List<FormalParameter> parameters, |
| this.leftDelimiter, |
| this.rightDelimiter, |
| this.rightParenthesis) { |
| _parameters._initialize(this, parameters); |
| } |
| |
| @override |
| Token get beginToken => leftParenthesis; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities { |
| // TODO(paulberry): include commas. |
| ChildEntities result = ChildEntities()..add(leftParenthesis); |
| bool leftDelimiterNeeded = leftDelimiter != null; |
| int length = _parameters.length; |
| for (int i = 0; i < length; i++) { |
| FormalParameter parameter = _parameters[i]; |
| if (leftDelimiterNeeded && leftDelimiter!.offset < parameter.offset) { |
| result.add(leftDelimiter); |
| leftDelimiterNeeded = false; |
| } |
| result.add(parameter); |
| } |
| return result..add(rightDelimiter)..add(rightParenthesis); |
| } |
| |
| @override |
| Token get endToken => rightParenthesis; |
| |
| @override |
| List<ParameterElement?> get parameterElements { |
| int count = _parameters.length; |
| var types = <ParameterElement?>[]; |
| for (int i = 0; i < count; i++) { |
| types.add(_parameters[i].declaredElement); |
| } |
| return types; |
| } |
| |
| @override |
| NodeListImpl<FormalParameter> get parameters => _parameters; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitFormalParameterList(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _parameters.accept(visitor); |
| } |
| } |
| |
| abstract class ForPartsImpl extends ForLoopPartsImpl implements ForParts { |
| @override |
| Token leftSeparator; |
| |
| /// The condition used to determine when to terminate the loop, or `null` if |
| /// there is no condition. |
| ExpressionImpl? _condition; |
| |
| @override |
| Token rightSeparator; |
| |
| /// The list of expressions run after each execution of the loop body. |
| final NodeListImpl<Expression> _updaters = NodeListImpl._(); |
| |
| /// Initialize a newly created for statement. Either the [variableList] or the |
| /// [initialization] must be `null`. Either the [condition] and the list of |
| /// [updaters] can be `null` if the loop does not have the corresponding |
| /// attribute. |
| ForPartsImpl(this.leftSeparator, this._condition, this.rightSeparator, |
| List<Expression>? updaters) { |
| _becomeParentOf(_condition); |
| _updaters._initialize(this, updaters); |
| } |
| |
| @override |
| Token get beginToken => leftSeparator; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(leftSeparator) |
| ..add(_condition) |
| ..add(rightSeparator) |
| ..addAll(_updaters); |
| |
| @override |
| ExpressionImpl? get condition => _condition; |
| |
| set condition(Expression? expression) { |
| _condition = _becomeParentOf(expression as ExpressionImpl?); |
| } |
| |
| @override |
| Token get endToken => _updaters.endToken ?? rightSeparator; |
| |
| @override |
| NodeListImpl<Expression> get updaters => _updaters; |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _condition?.accept(visitor); |
| _updaters.accept(visitor); |
| } |
| } |
| |
| class ForPartsWithDeclarationsImpl extends ForPartsImpl |
| implements ForPartsWithDeclarations { |
| /// The declaration of the loop variables, or `null` if there are no |
| /// variables. Note that a for statement cannot have both a variable list and |
| /// an initialization expression, but can validly have neither. |
| VariableDeclarationListImpl _variableList; |
| |
| /// Initialize a newly created for statement. Both the [condition] and the |
| /// list of [updaters] can be `null` if the loop does not have the |
| /// corresponding attribute. |
| ForPartsWithDeclarationsImpl( |
| this._variableList, |
| Token leftSeparator, |
| ExpressionImpl? condition, |
| Token rightSeparator, |
| List<Expression>? updaters) |
| : super(leftSeparator, condition, rightSeparator, updaters) { |
| _becomeParentOf(_variableList); |
| } |
| |
| @override |
| Token get beginToken => _variableList.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_variableList) |
| ..addAll(super.childEntities); |
| |
| @override |
| VariableDeclarationListImpl get variables => _variableList; |
| |
| set variables(VariableDeclarationList? variableList) { |
| _variableList = |
| _becomeParentOf(variableList as VariableDeclarationListImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitForPartsWithDeclarations(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _variableList.accept(visitor); |
| super.visitChildren(visitor); |
| } |
| } |
| |
| class ForPartsWithExpressionImpl extends ForPartsImpl |
| implements ForPartsWithExpression { |
| /// The initialization expression, or `null` if there is no initialization |
| /// expression. Note that a for statement cannot have both a variable list and |
| /// an initialization expression, but can validly have neither. |
| ExpressionImpl? _initialization; |
| |
| /// Initialize a newly created for statement. Both the [condition] and the |
| /// list of [updaters] can be `null` if the loop does not have the |
| /// corresponding attribute. |
| ForPartsWithExpressionImpl( |
| this._initialization, |
| Token leftSeparator, |
| ExpressionImpl? condition, |
| Token rightSeparator, |
| List<Expression>? updaters) |
| : super(leftSeparator, condition, rightSeparator, updaters) { |
| _becomeParentOf(_initialization); |
| } |
| |
| @override |
| Token get beginToken => initialization?.beginToken ?? super.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_initialization) |
| ..addAll(super.childEntities); |
| |
| @override |
| ExpressionImpl? get initialization => _initialization; |
| |
| set initialization(Expression? initialization) { |
| _initialization = _becomeParentOf(initialization as ExpressionImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitForPartsWithExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _initialization?.accept(visitor); |
| super.visitChildren(visitor); |
| } |
| } |
| |
| class ForStatementImpl extends StatementImpl implements ForStatement { |
| @override |
| Token? awaitKeyword; |
| |
| @override |
| Token forKeyword; |
| |
| @override |
| Token leftParenthesis; |
| |
| ForLoopPartsImpl _forLoopParts; |
| |
| @override |
| Token rightParenthesis; |
| |
| /// The body of the loop. |
| StatementImpl _body; |
| |
| /// Initialize a newly created for statement. |
| ForStatementImpl(this.awaitKeyword, this.forKeyword, this.leftParenthesis, |
| this._forLoopParts, this.rightParenthesis, this._body) { |
| _becomeParentOf(_forLoopParts); |
| _becomeParentOf(_body); |
| } |
| |
| @override |
| Token get beginToken => awaitKeyword ?? forKeyword; |
| |
| @override |
| StatementImpl get body => _body; |
| |
| set body(Statement statement) { |
| _body = _becomeParentOf(statement as StatementImpl); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(awaitKeyword) |
| ..add(forKeyword) |
| ..add(leftParenthesis) |
| ..add(_forLoopParts) |
| ..add(rightParenthesis) |
| ..add(_body); |
| |
| @override |
| Token get endToken => _body.endToken; |
| |
| @override |
| ForLoopPartsImpl get forLoopParts => _forLoopParts; |
| |
| set forLoopParts(ForLoopParts forLoopParts) { |
| _forLoopParts = _becomeParentOf(forLoopParts as ForLoopPartsImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitForStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _forLoopParts.accept(visitor); |
| _body.accept(visitor); |
| } |
| } |
| |
| /// A node representing the body of a function or method. |
| /// |
| /// functionBody ::= |
| /// [BlockFunctionBody] |
| /// | [EmptyFunctionBody] |
| /// | [ExpressionFunctionBody] |
| abstract class FunctionBodyImpl extends AstNodeImpl implements FunctionBody { |
| /// Additional information about local variables and parameters that are |
| /// declared within this function body or any enclosing function body. `null` |
| /// if resolution has not yet been performed. |
| LocalVariableInfo? localVariableInfo; |
| |
| /// Return `true` if this function body is asynchronous. |
| @override |
| bool get isAsynchronous => false; |
| |
| /// Return `true` if this function body is a generator. |
| @override |
| bool get isGenerator => false; |
| |
| /// Return `true` if this function body is synchronous. |
| @override |
| bool get isSynchronous => true; |
| |
| /// Return the token representing the 'async' or 'sync' keyword, or `null` if |
| /// there is no such keyword. |
| @override |
| Token? get keyword => null; |
| |
| /// Return the star following the 'async' or 'sync' keyword, or `null` if |
| /// there is no star. |
| @override |
| Token? get star => null; |
| |
| @override |
| bool isPotentiallyMutatedInClosure(VariableElement variable) { |
| if (localVariableInfo == null) { |
| throw StateError('Resolution has not yet been performed'); |
| } |
| return localVariableInfo!.potentiallyMutatedInClosure.contains(variable); |
| } |
| |
| @override |
| bool isPotentiallyMutatedInScope(VariableElement variable) { |
| if (localVariableInfo == null) { |
| throw StateError('Resolution has not yet been performed'); |
| } |
| return localVariableInfo!.potentiallyMutatedInScope.contains(variable); |
| } |
| } |
| |
| /// A top-level declaration. |
| /// |
| /// functionDeclaration ::= |
| /// 'external' functionSignature |
| /// | functionSignature [FunctionBody] |
| /// |
| /// functionSignature ::= |
| /// [Type]? ('get' | 'set')? [SimpleIdentifier] [FormalParameterList] |
| class FunctionDeclarationImpl extends NamedCompilationUnitMemberImpl |
| implements FunctionDeclaration { |
| /// The token representing the 'external' keyword, or `null` if this is not an |
| /// external function. |
| @override |
| Token? externalKeyword; |
| |
| /// The return type of the function, or `null` if no return type was declared. |
| TypeAnnotationImpl? _returnType; |
| |
| /// The token representing the 'get' or 'set' keyword, or `null` if this is a |
| /// function declaration rather than a property declaration. |
| @override |
| Token? propertyKeyword; |
| |
| /// The function expression being wrapped. |
| FunctionExpressionImpl _functionExpression; |
| |
| /// Initialize a newly created function declaration. Either or both of the |
| /// [comment] and [metadata] can be `null` if the function does not have the |
| /// corresponding attribute. The [externalKeyword] can be `null` if the |
| /// function is not an external function. The [returnType] can be `null` if no |
| /// return type was specified. The [propertyKeyword] can be `null` if the |
| /// function is neither a getter or a setter. |
| FunctionDeclarationImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.externalKeyword, |
| this._returnType, |
| this.propertyKeyword, |
| SimpleIdentifierImpl name, |
| this._functionExpression) |
| : super(comment, metadata, name) { |
| _becomeParentOf(_returnType); |
| _becomeParentOf(_functionExpression); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(externalKeyword) |
| ..add(_returnType) |
| ..add(propertyKeyword) |
| ..add(_name) |
| ..add(_functionExpression); |
| |
| @override |
| ExecutableElement? get declaredElement => |
| _name.staticElement as ExecutableElement?; |
| |
| @override |
| Token get endToken => _functionExpression.endToken; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return externalKeyword ?? |
| _returnType?.beginToken ?? |
| propertyKeyword ?? |
| _name.beginToken; |
| } |
| |
| @override |
| FunctionExpressionImpl get functionExpression => _functionExpression; |
| |
| set functionExpression(FunctionExpression functionExpression) { |
| _functionExpression = |
| _becomeParentOf(functionExpression as FunctionExpressionImpl); |
| } |
| |
| @override |
| bool get isGetter => propertyKeyword?.keyword == Keyword.GET; |
| |
| @override |
| bool get isSetter => propertyKeyword?.keyword == Keyword.SET; |
| |
| @override |
| TypeAnnotationImpl? get returnType => _returnType; |
| |
| set returnType(TypeAnnotation? type) { |
| _returnType = _becomeParentOf(type as TypeAnnotationImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _returnType?.accept(visitor); |
| _name.accept(visitor); |
| _functionExpression.accept(visitor); |
| } |
| } |
| |
| /// A [FunctionDeclaration] used as a statement. |
| class FunctionDeclarationStatementImpl extends StatementImpl |
| implements FunctionDeclarationStatement { |
| /// The function declaration being wrapped. |
| FunctionDeclarationImpl _functionDeclaration; |
| |
| /// Initialize a newly created function declaration statement. |
| FunctionDeclarationStatementImpl(this._functionDeclaration) { |
| _becomeParentOf(_functionDeclaration); |
| } |
| |
| @override |
| Token get beginToken => _functionDeclaration.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_functionDeclaration); |
| |
| @override |
| Token get endToken => _functionDeclaration.endToken; |
| |
| @override |
| FunctionDeclarationImpl get functionDeclaration => _functionDeclaration; |
| |
| set functionDeclaration(FunctionDeclaration functionDeclaration) { |
| _functionDeclaration = |
| _becomeParentOf(functionDeclaration as FunctionDeclarationImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitFunctionDeclarationStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _functionDeclaration.accept(visitor); |
| } |
| } |
| |
| /// A function expression. |
| /// |
| /// functionExpression ::= |
| /// [TypeParameterList]? [FormalParameterList] [FunctionBody] |
| class FunctionExpressionImpl extends ExpressionImpl |
| implements FunctionExpression { |
| /// The type parameters associated with the method, or `null` if the method is |
| /// not a generic method. |
| TypeParameterListImpl? _typeParameters; |
| |
| /// The parameters associated with the function, or `null` if the function is |
| /// part of a top-level getter. |
| FormalParameterListImpl? _parameters; |
| |
| /// The body of the function. |
| FunctionBodyImpl _body; |
| |
| @override |
| ExecutableElement? declaredElement; |
| |
| /// Initialize a newly created function declaration. |
| FunctionExpressionImpl(this._typeParameters, this._parameters, this._body) { |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_parameters); |
| _becomeParentOf(_body); |
| } |
| |
| @override |
| Token get beginToken { |
| if (_typeParameters != null) { |
| return _typeParameters!.beginToken; |
| } else if (_parameters != null) { |
| return _parameters!.beginToken; |
| } |
| return _body.beginToken; |
| } |
| |
| @override |
| FunctionBodyImpl get body => _body; |
| |
| set body(FunctionBody functionBody) { |
| _body = _becomeParentOf(functionBody as FunctionBodyImpl); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_typeParameters)..add(_parameters)..add(_body); |
| |
| @override |
| Token get endToken { |
| return _body.endToken; |
| } |
| |
| @override |
| FormalParameterListImpl? get parameters => _parameters; |
| |
| set parameters(FormalParameterList? parameters) { |
| _parameters = _becomeParentOf(parameters as FormalParameterListImpl?); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.primary; |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _typeParameters?.accept(visitor); |
| _parameters?.accept(visitor); |
| _body.accept(visitor); |
| } |
| } |
| |
| /// The invocation of a function resulting from evaluating an expression. |
| /// Invocations of methods and other forms of functions are represented by |
| /// [MethodInvocation] nodes. Invocations of getters and setters are represented |
| /// by either [PrefixedIdentifier] or [PropertyAccess] nodes. |
| /// |
| /// functionExpressionInvocation ::= |
| /// [Expression] [TypeArgumentList]? [ArgumentList] |
| class FunctionExpressionInvocationImpl extends InvocationExpressionImpl |
| with NullShortableExpressionImpl |
| implements FunctionExpressionInvocation { |
| /// The expression producing the function being invoked. |
| ExpressionImpl _function; |
| |
| /// The element associated with the function being invoked based on static |
| /// type information, or `null` if the AST structure has not been resolved or |
| /// the function could not be resolved. |
| @override |
| ExecutableElement? staticElement; |
| |
| /// Initialize a newly created function expression invocation. |
| FunctionExpressionInvocationImpl(this._function, |
| TypeArgumentListImpl? typeArguments, ArgumentListImpl argumentList) |
| : super(typeArguments, argumentList) { |
| _becomeParentOf(_function); |
| } |
| |
| @override |
| Token get beginToken => _function.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_function)..add(_argumentList); |
| |
| @override |
| Token get endToken => _argumentList.endToken; |
| |
| @override |
| ExpressionImpl get function => _function; |
| |
| set function(Expression expression) { |
| _function = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.postfix; |
| |
| @override |
| AstNode? get _nullShortingExtensionCandidate => parent; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitFunctionExpressionInvocation(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _function.accept(visitor); |
| _typeArguments?.accept(visitor); |
| _argumentList.accept(visitor); |
| } |
| |
| @override |
| bool _extendsNullShorting(Expression child) => identical(child, _function); |
| } |
| |
| /// An expression representing a reference to a function, possibly with type |
| /// arguments applied to it, e.g. the expression `print` in `var x = print;`. |
| class FunctionReferenceImpl extends ExpressionImpl |
| implements FunctionReference { |
| ExpressionImpl _function; |
| |
| TypeArgumentListImpl? _typeArguments; |
| |
| @override |
| List<DartType>? typeArgumentTypes; |
| |
| FunctionReferenceImpl(this._function, {TypeArgumentListImpl? typeArguments}) |
| : _typeArguments = typeArguments { |
| _becomeParentOf(_function); |
| _becomeParentOf(_typeArguments); |
| } |
| |
| @override |
| Token get beginToken => function.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(function)..add(typeArguments); |
| |
| @override |
| Token get endToken => typeArguments?.endToken ?? function.endToken; |
| |
| @override |
| ExpressionImpl get function => _function; |
| |
| set function(ExpressionImpl value) { |
| _function = _becomeParentOf(value); |
| } |
| |
| @override |
| Precedence get precedence => |
| typeArguments == null ? function.precedence : Precedence.postfix; |
| |
| @override |
| TypeArgumentListImpl? get typeArguments => _typeArguments; |
| |
| set typeArguments(TypeArgumentListImpl? value) { |
| _typeArguments = _becomeParentOf(value); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionReference(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| function.accept(visitor); |
| typeArguments?.accept(visitor); |
| } |
| } |
| |
| /// A function type alias. |
| /// |
| /// functionTypeAlias ::= |
| /// functionPrefix [TypeParameterList]? [FormalParameterList] ';' |
| /// |
| /// functionPrefix ::= |
| /// [TypeName]? [SimpleIdentifier] |
| class FunctionTypeAliasImpl extends TypeAliasImpl implements FunctionTypeAlias { |
| /// The name of the return type of the function type being defined, or `null` |
| /// if no return type was given. |
| TypeAnnotationImpl? _returnType; |
| |
| /// The type parameters for the function type, or `null` if the function type |
| /// does not have any type parameters. |
| TypeParameterListImpl? _typeParameters; |
| |
| /// The parameters associated with the function type. |
| FormalParameterListImpl _parameters; |
| |
| /// Initialize a newly created function type alias. Either or both of the |
| /// [comment] and [metadata] can be `null` if the function does not have the |
| /// corresponding attribute. The [returnType] can be `null` if no return type |
| /// was specified. The [typeParameters] can be `null` if the function has no |
| /// type parameters. |
| FunctionTypeAliasImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| Token keyword, |
| this._returnType, |
| SimpleIdentifierImpl name, |
| this._typeParameters, |
| this._parameters, |
| Token semicolon) |
| : super(comment, metadata, keyword, name, semicolon) { |
| _becomeParentOf(_returnType); |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_parameters); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(typedefKeyword) |
| ..add(_returnType) |
| ..add(_name) |
| ..add(_typeParameters) |
| ..add(_parameters) |
| ..add(semicolon); |
| |
| @override |
| TypeAliasElement? get declaredElement => |
| _name.staticElement as TypeAliasElement?; |
| |
| @override |
| FormalParameterListImpl get parameters => _parameters; |
| |
| set parameters(FormalParameterList parameters) { |
| _parameters = _becomeParentOf(parameters as FormalParameterListImpl); |
| } |
| |
| @override |
| TypeAnnotationImpl? get returnType => _returnType; |
| |
| set returnType(TypeAnnotation? type) { |
| _returnType = _becomeParentOf(type as TypeAnnotationImpl?); |
| } |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionTypeAlias(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _returnType?.accept(visitor); |
| _name.accept(visitor); |
| _typeParameters?.accept(visitor); |
| _parameters.accept(visitor); |
| } |
| } |
| |
| /// A function-typed formal parameter. |
| /// |
| /// functionSignature ::= |
| /// [TypeName]? [SimpleIdentifier] [TypeParameterList]? |
| /// [FormalParameterList] '?'? |
| class FunctionTypedFormalParameterImpl extends NormalFormalParameterImpl |
| implements FunctionTypedFormalParameter { |
| /// The return type of the function, or `null` if the function does not have a |
| /// return type. |
| TypeAnnotationImpl? _returnType; |
| |
| /// The type parameters associated with the function, or `null` if the |
| /// function is not a generic function. |
| TypeParameterListImpl? _typeParameters; |
| |
| /// The parameters of the function-typed parameter. |
| FormalParameterListImpl _parameters; |
| |
| @override |
| Token? question; |
| |
| /// Initialize a newly created formal parameter. Either or both of the |
| /// [comment] and [metadata] can be `null` if the parameter does not have the |
| /// corresponding attribute. The [returnType] can be `null` if no return type |
| /// was specified. |
| FunctionTypedFormalParameterImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| Token? covariantKeyword, |
| Token? requiredKeyword, |
| this._returnType, |
| SimpleIdentifierImpl identifier, |
| this._typeParameters, |
| this._parameters, |
| this.question) |
| : super( |
| comment, metadata, covariantKeyword, requiredKeyword, identifier) { |
| _becomeParentOf(_returnType); |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_parameters); |
| } |
| |
| @override |
| Token get beginToken { |
| final metadata = this.metadata; |
| if (metadata.isNotEmpty) { |
| return metadata.beginToken!; |
| } else if (requiredKeyword != null) { |
| return requiredKeyword!; |
| } else if (covariantKeyword != null) { |
| return covariantKeyword!; |
| } else if (_returnType != null) { |
| return _returnType!.beginToken; |
| } |
| return identifier.beginToken; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(_returnType)..add(identifier)..add(parameters); |
| |
| @override |
| Token get endToken => question ?? _parameters.endToken; |
| |
| @override |
| SimpleIdentifierImpl get identifier => super.identifier!; |
| |
| @override |
| bool get isConst => false; |
| |
| @override |
| bool get isFinal => false; |
| |
| @override |
| FormalParameterListImpl get parameters => _parameters; |
| |
| set parameters(FormalParameterList parameters) { |
| _parameters = _becomeParentOf(parameters as FormalParameterListImpl); |
| } |
| |
| @override |
| TypeAnnotationImpl? get returnType => _returnType; |
| |
| set returnType(TypeAnnotation? type) { |
| _returnType = _becomeParentOf(type as TypeAnnotationImpl?); |
| } |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitFunctionTypedFormalParameter(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _returnType?.accept(visitor); |
| identifier.accept(visitor); |
| _typeParameters?.accept(visitor); |
| _parameters.accept(visitor); |
| } |
| } |
| |
| /// An anonymous function type. |
| /// |
| /// functionType ::= |
| /// [TypeAnnotation]? 'Function' [TypeParameterList]? |
| /// [FormalParameterList] |
| /// |
| /// where the FormalParameterList is being used to represent the following |
| /// grammar, despite the fact that FormalParameterList can represent a much |
| /// larger grammar than the one below. This is done in order to simplify the |
| /// implementation. |
| /// |
| /// parameterTypeList ::= |
| /// () | |
| /// ( normalParameterTypes ,? ) | |
| /// ( normalParameterTypes , optionalParameterTypes ) | |
| /// ( optionalParameterTypes ) |
| /// namedParameterTypes ::= |
| /// { namedParameterType (, namedParameterType)* ,? } |
| /// namedParameterType ::= |
| /// [TypeAnnotation]? [SimpleIdentifier] |
| /// normalParameterTypes ::= |
| /// normalParameterType (, normalParameterType)* |
| /// normalParameterType ::= |
| /// [TypeAnnotation] [SimpleIdentifier]? |
| /// optionalParameterTypes ::= |
| /// optionalPositionalParameterTypes | namedParameterTypes |
| /// optionalPositionalParameterTypes ::= |
| /// [ normalParameterTypes ,? ] |
| class GenericFunctionTypeImpl extends TypeAnnotationImpl |
| implements GenericFunctionType { |
| /// The name of the return type of the function type being defined, or |
| /// `null` if no return type was given. |
| TypeAnnotationImpl? _returnType; |
| |
| @override |
| Token functionKeyword; |
| |
| /// The type parameters for the function type, or `null` if the function type |
| /// does not have any type parameters. |
| TypeParameterListImpl? _typeParameters; |
| |
| /// The parameters associated with the function type. |
| FormalParameterListImpl _parameters; |
| |
| @override |
| Token? question; |
| |
| @override |
| DartType? type; |
| |
| /// Return the element associated with the function type, or `null` if the |
| /// AST structure has not been resolved. |
| GenericFunctionTypeElement? declaredElement; |
| |
| /// Initialize a newly created generic function type. |
| GenericFunctionTypeImpl(this._returnType, this.functionKeyword, |
| this._typeParameters, this._parameters, |
| {this.question}) { |
| _becomeParentOf(_returnType); |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_parameters); |
| } |
| |
| @override |
| Token get beginToken => _returnType?.beginToken ?? functionKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_returnType) |
| ..add(functionKeyword) |
| ..add(_typeParameters) |
| ..add(_parameters) |
| ..add(question); |
| |
| @override |
| Token get endToken => question ?? _parameters.endToken; |
| |
| @override |
| FormalParameterListImpl get parameters => _parameters; |
| |
| set parameters(FormalParameterList parameters) { |
| _parameters = _becomeParentOf(parameters as FormalParameterListImpl); |
| } |
| |
| @override |
| TypeAnnotationImpl? get returnType => _returnType; |
| |
| set returnType(TypeAnnotation? type) { |
| _returnType = _becomeParentOf(type as TypeAnnotationImpl?); |
| } |
| |
| /// Return the type parameters for the function type, or `null` if the |
| /// function type does not have any type parameters. |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| /// Set the type parameters for the function type to the given list of |
| /// [typeParameters]. |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) { |
| return visitor.visitGenericFunctionType(this); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _returnType?.accept(visitor); |
| _typeParameters?.accept(visitor); |
| _parameters.accept(visitor); |
| } |
| } |
| |
| /// A generic type alias. |
| /// |
| /// functionTypeAlias ::= |
| /// metadata 'typedef' [SimpleIdentifier] [TypeParameterList]? = |
| /// [FunctionType] ';' |
| class GenericTypeAliasImpl extends TypeAliasImpl implements GenericTypeAlias { |
| /// The type being defined by the alias. |
| TypeAnnotationImpl _type; |
| |
| /// The type parameters for the function type, or `null` if the function |
| /// type does not have any type parameters. |
| TypeParameterListImpl? _typeParameters; |
| |
| @override |
| Token equals; |
| |
| /// Returns a newly created generic type alias. Either or both of the |
| /// [comment] and [metadata] can be `null` if the variable list does not have |
| /// the corresponding attribute. The [typeParameters] can be `null` if there |
| /// are no type parameters. |
| GenericTypeAliasImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| Token typedefToken, |
| SimpleIdentifierImpl name, |
| this._typeParameters, |
| this.equals, |
| this._type, |
| Token semicolon) |
| : super(comment, metadata, typedefToken, name, semicolon) { |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_type); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..addAll(metadata) |
| ..add(typedefKeyword) |
| ..add(name) |
| ..add(_typeParameters) |
| ..add(equals) |
| ..add(_type); |
| |
| @override |
| Element? get declaredElement => name.staticElement; |
| |
| /// The type of function being defined by the alias. |
| /// |
| /// If the non-function type aliases feature is enabled, a type alias may have |
| /// a [_type] which is not a [GenericFunctionTypeImpl]. In that case `null` |
| /// is returned. |
| @override |
| GenericFunctionType? get functionType { |
| var type = _type; |
| return type is GenericFunctionTypeImpl ? type : null; |
| } |
| |
| set functionType(GenericFunctionType? functionType) { |
| _type = _becomeParentOf(functionType as GenericFunctionTypeImpl?)!; |
| } |
| |
| @override |
| TypeAnnotationImpl get type => _type; |
| |
| /// Set the type being defined by the alias to the given [TypeAnnotation]. |
| set type(TypeAnnotation typeAnnotation) { |
| _type = _becomeParentOf(typeAnnotation as TypeAnnotationImpl); |
| } |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) { |
| return visitor.visitGenericTypeAlias(this); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| name.accept(visitor); |
| _typeParameters?.accept(visitor); |
| _type.accept(visitor); |
| } |
| } |
| |
| /// A combinator that restricts the names being imported to those that are not |
| /// in a given list. |
| /// |
| /// hideCombinator ::= |
| /// 'hide' [SimpleIdentifier] (',' [SimpleIdentifier])* |
| class HideCombinatorImpl extends CombinatorImpl implements HideCombinator { |
| /// The list of names from the library that are hidden by this combinator. |
| final NodeListImpl<SimpleIdentifier> _hiddenNames = NodeListImpl._(); |
| |
| /// Initialize a newly created import show combinator. |
| HideCombinatorImpl(Token keyword, List<SimpleIdentifier> hiddenNames) |
| : super(keyword) { |
| _hiddenNames._initialize(this, hiddenNames); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(keyword) |
| ..addAll(_hiddenNames); |
| |
| @override |
| Token get endToken => _hiddenNames.endToken!; |
| |
| @override |
| NodeListImpl<SimpleIdentifier> get hiddenNames => _hiddenNames; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitHideCombinator(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _hiddenNames.accept(visitor); |
| } |
| } |
| |
| /// A node that represents an identifier. |
| /// |
| /// identifier ::= |
| /// [SimpleIdentifier] |
| /// | [PrefixedIdentifier] |
| abstract class IdentifierImpl extends ExpressionImpl implements Identifier { |
| @override |
| bool get isAssignable => true; |
| } |
| |
| class IfElementImpl extends CollectionElementImpl implements IfElement { |
| @override |
| Token ifKeyword; |
| |
| @override |
| Token leftParenthesis; |
| |
| /// The condition used to determine which of the branches is executed next. |
| ExpressionImpl _condition; |
| |
| @override |
| Token rightParenthesis; |
| |
| @override |
| Token? elseKeyword; |
| |
| /// The element to be executed if the condition is `true`. |
| CollectionElementImpl _thenElement; |
| |
| /// The element to be executed if the condition is `false`, or `null` if there |
| /// is no such element. |
| CollectionElementImpl? _elseElement; |
| |
| /// Initialize a newly created for element. |
| IfElementImpl( |
| this.ifKeyword, |
| this.leftParenthesis, |
| this._condition, |
| this.rightParenthesis, |
| this._thenElement, |
| this.elseKeyword, |
| this._elseElement) { |
| _becomeParentOf(_condition); |
| _becomeParentOf(_thenElement); |
| _becomeParentOf(_elseElement); |
| } |
| |
| @override |
| Token get beginToken => ifKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(ifKeyword) |
| ..add(leftParenthesis) |
| ..add(_condition) |
| ..add(rightParenthesis) |
| ..add(_thenElement) |
| ..add(elseKeyword) |
| ..add(_elseElement); |
| |
| @override |
| ExpressionImpl get condition => _condition; |
| |
| set condition(Expression condition) { |
| _condition = _becomeParentOf(condition as ExpressionImpl); |
| } |
| |
| @override |
| CollectionElement? get elseElement => _elseElement; |
| |
| set elseElement(CollectionElement? element) { |
| _elseElement = _becomeParentOf(element as CollectionElementImpl?); |
| } |
| |
| @override |
| Token get endToken => _elseElement?.endToken ?? _thenElement.endToken; |
| |
| @override |
| CollectionElementImpl get thenElement => _thenElement; |
| |
| set thenElement(CollectionElement element) { |
| _thenElement = _becomeParentOf(element as CollectionElementImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitIfElement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _condition.accept(visitor); |
| _thenElement.accept(visitor); |
| _elseElement?.accept(visitor); |
| } |
| } |
| |
| /// An if statement. |
| /// |
| /// ifStatement ::= |
| /// 'if' '(' [Expression] ')' [Statement] ('else' [Statement])? |
| class IfStatementImpl extends StatementImpl implements IfStatement { |
| @override |
| Token ifKeyword; |
| |
| @override |
| Token leftParenthesis; |
| |
| /// The condition used to determine which of the branches is executed next. |
| ExpressionImpl _condition; |
| |
| @override |
| Token rightParenthesis; |
| |
| @override |
| Token? elseKeyword; |
| |
| /// The statement that is executed if the condition evaluates to `true`. |
| StatementImpl _thenStatement; |
| |
| /// The statement that is executed if the condition evaluates to `false`, or |
| /// `null` if there is no else statement. |
| StatementImpl? _elseStatement; |
| |
| /// Initialize a newly created if statement. The [elseKeyword] and |
| /// [elseStatement] can be `null` if there is no else clause. |
| IfStatementImpl( |
| this.ifKeyword, |
| this.leftParenthesis, |
| this._condition, |
| this.rightParenthesis, |
| this._thenStatement, |
| this.elseKeyword, |
| this._elseStatement) { |
| _becomeParentOf(_condition); |
| _becomeParentOf(_thenStatement); |
| _becomeParentOf(_elseStatement); |
| } |
| |
| @override |
| Token get beginToken => ifKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(ifKeyword) |
| ..add(leftParenthesis) |
| ..add(_condition) |
| ..add(rightParenthesis) |
| ..add(_thenStatement) |
| ..add(elseKeyword) |
| ..add(_elseStatement); |
| |
| @override |
| ExpressionImpl get condition => _condition; |
| |
| set condition(Expression condition) { |
| _condition = _becomeParentOf(condition as ExpressionImpl); |
| } |
| |
| @override |
| StatementImpl? get elseStatement => _elseStatement; |
| |
| set elseStatement(Statement? statement) { |
| _elseStatement = _becomeParentOf(statement as StatementImpl?); |
| } |
| |
| @override |
| Token get endToken { |
| if (_elseStatement != null) { |
| return _elseStatement!.endToken; |
| } |
| return _thenStatement.endToken; |
| } |
| |
| @override |
| StatementImpl get thenStatement => _thenStatement; |
| |
| set thenStatement(Statement statement) { |
| _thenStatement = _becomeParentOf(statement as StatementImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitIfStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _condition.accept(visitor); |
| _thenStatement.accept(visitor); |
| _elseStatement?.accept(visitor); |
| } |
| } |
| |
| /// The "implements" clause in an class declaration. |
| /// |
| /// implementsClause ::= |
| /// 'implements' [TypeName] (',' [TypeName])* |
| class ImplementsClauseImpl extends AstNodeImpl implements ImplementsClause { |
| /// The token representing the 'implements' keyword. |
| @override |
| Token implementsKeyword; |
| |
| /// The interfaces that are being implemented. |
| final NodeListImpl<TypeName> _interfaces = NodeListImpl._(); |
| |
| /// Initialize a newly created implements clause. |
| ImplementsClauseImpl(this.implementsKeyword, List<TypeName> interfaces) { |
| _interfaces._initialize(this, interfaces); |
| } |
| |
| @override |
| Token get beginToken => implementsKeyword; |
| |
| @override |
| // TODO(paulberry): add commas. |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(implementsKeyword) |
| ..addAll(interfaces); |
| |
| @override |
| Token get endToken => _interfaces.endToken!; |
| |
| @override |
| NodeListImpl<TypeName> get interfaces => _interfaces; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitImplementsClause(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _interfaces.accept(visitor); |
| } |
| } |
| |
| /// An import directive. |
| /// |
| /// importDirective ::= |
| /// [Annotation] 'import' [StringLiteral] ('as' identifier)? |
| // [Combinator]* ';' |
| /// | [Annotation] 'import' [StringLiteral] 'deferred' 'as' identifier |
| // [Combinator]* ';' |
| class ImportDirectiveImpl extends NamespaceDirectiveImpl |
| implements ImportDirective { |
| /// The token representing the 'deferred' keyword, or `null` if the imported |
| /// is not deferred. |
| @override |
| Token? deferredKeyword; |
| |
| /// The token representing the 'as' keyword, or `null` if the imported names |
| /// are not prefixed. |
| @override |
| Token? asKeyword; |
| |
| /// The prefix to be used with the imported names, or `null` if the imported |
| /// names are not prefixed. |
| SimpleIdentifierImpl? _prefix; |
| |
| /// Initialize a newly created import directive. Either or both of the |
| /// [comment] and [metadata] can be `null` if the function does not have the |
| /// corresponding attribute. The [deferredKeyword] can be `null` if the import |
| /// is not deferred. The [asKeyword] and [prefix] can be `null` if the import |
| /// does not specify a prefix. The list of [combinators] can be `null` if |
| /// there are no combinators. |
| ImportDirectiveImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| Token keyword, |
| StringLiteralImpl libraryUri, |
| List<Configuration>? configurations, |
| this.deferredKeyword, |
| this.asKeyword, |
| this._prefix, |
| List<Combinator>? combinators, |
| Token semicolon) |
| : super(comment, metadata, keyword, libraryUri, configurations, |
| combinators, semicolon) { |
| _becomeParentOf(_prefix); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(keyword) |
| ..add(_uri) |
| ..add(deferredKeyword) |
| ..add(asKeyword) |
| ..add(_prefix) |
| ..addAll(combinators) |
| ..add(semicolon); |
| |
| @override |
| ImportElement? get element => super.element as ImportElement?; |
| |
| @override |
| SimpleIdentifierImpl? get prefix => _prefix; |
| |
| set prefix(SimpleIdentifier? identifier) { |
| _prefix = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| LibraryElement? get uriElement { |
| return element?.importedLibrary; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitImportDirective(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| configurations.accept(visitor); |
| _prefix?.accept(visitor); |
| combinators.accept(visitor); |
| } |
| } |
| |
| /// An index expression. |
| /// |
| /// indexExpression ::= |
| /// [Expression] '[' [Expression] ']' |
| class IndexExpressionImpl extends ExpressionImpl |
| with NullShortableExpressionImpl |
| implements IndexExpression { |
| @override |
| Token? period; |
| |
| /// The expression used to compute the object being indexed, or `null` if this |
| /// index expression is part of a cascade expression. |
| ExpressionImpl? _target; |
| |
| @override |
| Token? question; |
| |
| @override |
| Token leftBracket; |
| |
| /// The expression used to compute the index. |
| ExpressionImpl _index; |
| |
| @override |
| Token rightBracket; |
| |
| /// The element associated with the operator based on the static type of the |
| /// target, or `null` if the AST structure has not been resolved or if the |
| /// operator could not be resolved. |
| @override |
| MethodElement? staticElement; |
| |
| /// Initialize a newly created index expression that is a child of a cascade |
| /// expression. |
| IndexExpressionImpl.forCascade(this.period, this.question, this.leftBracket, |
| this._index, this.rightBracket) { |
| _becomeParentOf(_index); |
| } |
| |
| /// Initialize a newly created index expression that is not a child of a |
| /// cascade expression. |
| IndexExpressionImpl.forTarget(this._target, this.question, this.leftBracket, |
| this._index, this.rightBracket) { |
| _becomeParentOf(_target); |
| _becomeParentOf(_index); |
| } |
| |
| @override |
| Token get beginToken { |
| if (_target != null) { |
| return _target!.beginToken; |
| } |
| return period!; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_target) |
| ..add(period) |
| ..add(leftBracket) |
| ..add(_index) |
| ..add(rightBracket); |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| ExpressionImpl get index => _index; |
| |
| set index(Expression expression) { |
| _index = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| bool get isAssignable => true; |
| |
| @override |
| bool get isCascaded => period != null; |
| |
| @override |
| bool get isNullAware { |
| if (isCascaded) { |
| return _ancestorCascade.isNullAware; |
| } |
| return question != null || |
| (leftBracket.type == TokenType.OPEN_SQUARE_BRACKET && |
| period != null && |
| period!.type == TokenType.QUESTION_PERIOD_PERIOD); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.postfix; |
| |
| @override |
| ExpressionImpl get realTarget { |
| if (isCascaded) { |
| return _ancestorCascade.target; |
| } |
| return _target!; |
| } |
| |
| @override |
| ExpressionImpl? get target => _target; |
| |
| set target(Expression? expression) { |
| _target = _becomeParentOf(expression as ExpressionImpl?); |
| } |
| |
| /// Return the cascade that contains this [IndexExpression]. |
| /// |
| /// We expect that [isCascaded] is `true`. |
| CascadeExpressionImpl get _ancestorCascade { |
| assert(isCascaded); |
| for (var ancestor = parent!;; ancestor = ancestor.parent!) { |
| if (ancestor is CascadeExpressionImpl) { |
| return ancestor; |
| } |
| } |
| } |
| |
| @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 index expression will |
| /// be bound. Otherwise, return `null`. |
| ParameterElement? get _staticParameterElementForIndex { |
| Element? element = staticElement; |
| |
| final parent = this.parent; |
| if (parent is CompoundAssignmentExpression) { |
| element = parent.writeElement ?? parent.readElement; |
| } |
| |
| if (element is ExecutableElement) { |
| List<ParameterElement> parameters = element.parameters; |
| if (parameters.isEmpty) { |
| return null; |
| } |
| return parameters[0]; |
| } |
| return null; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitIndexExpression(this); |
| |
| @override |
| bool inGetterContext() { |
| // TODO(brianwilkerson) Convert this to a getter. |
| final parent = this.parent!; |
| if (parent is AssignmentExpression) { |
| AssignmentExpression assignment = parent; |
| if (identical(assignment.leftHandSide, this) && |
| assignment.operator.type == TokenType.EQ) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @override |
| bool inSetterContext() { |
| // TODO(brianwilkerson) Convert this to a getter. |
| final parent = this.parent!; |
| if (parent is PrefixExpression) { |
| return parent.operator.type.isIncrementOperator; |
| } else if (parent is PostfixExpression) { |
| return parent.operator.type.isIncrementOperator; |
| } else if (parent is AssignmentExpression) { |
| return identical(parent.leftHandSide, this); |
| } |
| return false; |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _target?.accept(visitor); |
| _index.accept(visitor); |
| } |
| |
| @override |
| bool _extendsNullShorting(Expression child) => identical(child, _target); |
| } |
| |
| /// An instance creation expression. |
| /// |
| /// newExpression ::= |
| /// ('new' | 'const')? [TypeName] ('.' [SimpleIdentifier])? |
| /// [ArgumentList] |
| class InstanceCreationExpressionImpl extends ExpressionImpl |
| implements InstanceCreationExpression { |
| // TODO(brianwilkerson) Consider making InstanceCreationExpressionImpl extend |
| // InvocationExpressionImpl. This would probably be a breaking change, but is |
| // also probably worth it. |
| |
| /// The 'new' or 'const' keyword used to indicate how an object should be |
| /// created, or `null` if the keyword is implicit. |
| @override |
| Token? keyword; |
| |
| /// The name of the constructor to be invoked. |
| ConstructorNameImpl _constructorName; |
| |
| /// The type arguments associated with the constructor, rather than with the |
| /// class in which the constructor is defined. It is always an error if there |
| /// are type arguments because Dart doesn't currently support generic |
| /// constructors, but we capture them in the AST in order to recover better. |
| TypeArgumentListImpl? _typeArguments; |
| |
| /// The list of arguments to the constructor. |
| ArgumentListImpl _argumentList; |
| |
| /// Initialize a newly created instance creation expression. |
| InstanceCreationExpressionImpl( |
| this.keyword, this._constructorName, this._argumentList, |
| {TypeArgumentListImpl? typeArguments}) |
| : _typeArguments = typeArguments { |
| _becomeParentOf(_constructorName); |
| _becomeParentOf(_typeArguments); |
| _becomeParentOf(_argumentList); |
| } |
| |
| @override |
| ArgumentListImpl get argumentList => _argumentList; |
| |
| set argumentList(ArgumentList argumentList) { |
| _argumentList = _becomeParentOf(argumentList as ArgumentListImpl); |
| } |
| |
| @override |
| Token get beginToken => keyword ?? _constructorName.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(keyword) |
| ..add(_constructorName) |
| ..add(_typeArguments) |
| ..add(_argumentList); |
| |
| @override |
| ConstructorNameImpl get constructorName => _constructorName; |
| |
| set constructorName(ConstructorName name) { |
| _constructorName = _becomeParentOf(name as ConstructorNameImpl); |
| } |
| |
| @override |
| Token get endToken => _argumentList.endToken; |
| |
| @override |
| bool get isConst { |
| if (!isImplicit) { |
| return keyword!.keyword == Keyword.CONST; |
| } else { |
| return inConstantContext; |
| } |
| } |
| |
| /// Return `true` if this is an implicit constructor invocations. |
| bool get isImplicit => keyword == null; |
| |
| @override |
| Precedence get precedence => Precedence.primary; |
| |
| /// Return the type arguments associated with the constructor, rather than |
| /// with the class in which the constructor is defined. It is always an error |
| /// if there are type arguments because Dart doesn't currently support generic |
| /// constructors, but we capture them in the AST in order to recover better. |
| TypeArgumentListImpl? get typeArguments => _typeArguments; |
| |
| /// Return the type arguments associated with the constructor, rather than |
| /// with the class in which the constructor is defined. It is always an error |
| /// if there are type arguments because Dart doesn't currently support generic |
| /// constructors, but we capture them in the AST in order to recover better. |
| set typeArguments(TypeArgumentList? typeArguments) { |
| _typeArguments = _becomeParentOf(typeArguments as TypeArgumentListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitInstanceCreationExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _constructorName.accept(visitor); |
| _typeArguments?.accept(visitor); |
| _argumentList.accept(visitor); |
| } |
| } |
| |
| /// An integer literal expression. |
| /// |
| /// integerLiteral ::= |
| /// decimalIntegerLiteral |
| /// | hexadecimalIntegerLiteral |
| /// |
| /// decimalIntegerLiteral ::= |
| /// decimalDigit+ |
| /// |
| /// hexadecimalIntegerLiteral ::= |
| /// '0x' hexadecimalDigit+ |
| /// | '0X' hexadecimalDigit+ |
| class IntegerLiteralImpl extends LiteralImpl implements IntegerLiteral { |
| /// The token representing the literal. |
| @override |
| Token literal; |
| |
| /// The value of the literal. |
| @override |
| int? value = 0; |
| |
| /// Initialize a newly created integer literal. |
| IntegerLiteralImpl(this.literal, this.value); |
| |
| @override |
| Token get beginToken => literal; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal); |
| |
| @override |
| Token get endToken => literal; |
| |
| /// Returns whether this literal's [parent] is a [PrefixExpression] of unary |
| /// negation. |
| /// |
| /// Note: this does *not* indicate that the value itself is negated, just that |
| /// the literal is the child of a negation operation. The literal value itself |
| /// will always be positive. |
| bool get immediatelyNegated { |
| final parent = this.parent!; |
| return parent is PrefixExpression && |
| parent.operator.type == TokenType.MINUS; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitIntegerLiteral(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| |
| static bool isValidAsDouble(String lexeme) { |
| // Less than 16 characters must be a valid double since it will be less than |
| // 9007199254740992, 0x10000000000000, both 16 characters and 53 bits. |
| if (lexeme.length < 16) { |
| return true; |
| } |
| |
| var fullPrecision = BigInt.tryParse(lexeme); |
| if (fullPrecision == null) { |
| return false; |
| } |
| |
| // Usually handled by the length check, however, we must check this before |
| // constructing a mask later, or we'd get a negative-shift runtime error. |
| int bitLengthAsInt = fullPrecision.bitLength; |
| if (bitLengthAsInt <= 53) { |
| return true; |
| } |
| |
| // This would overflow the exponent (larger than maximum double). |
| if (fullPrecision > BigInt.from(double.maxFinite)) { |
| return false; |
| } |
| |
| // Say [lexeme] uses 100 bits as an integer. The bottom 47 must be 0s -- so |
| // construct a mask of 47 ones, via of 2^n - 1 where n is 47. |
| BigInt bottomMask = (BigInt.one << (bitLengthAsInt - 53)) - BigInt.one; |
| |
| return fullPrecision & bottomMask == BigInt.zero; |
| } |
| |
| /// Return `true` if the given [lexeme] is a valid lexeme for an integer |
| /// literal. The flag [isNegative] should be `true` if the lexeme is preceded |
| /// by a unary negation operator. |
| static bool isValidAsInteger(String lexeme, bool isNegative) { |
| // TODO(jmesserly): this depends on the platform int implementation, and |
| // may not be accurate if run on dart4web. |
| // |
| // (Prior to https://dart-review.googlesource.com/c/sdk/+/63023 there was |
| // a partial implementation here which may be a good starting point. |
| // _isValidDecimalLiteral relied on int.parse so that would need some fixes. |
| // _isValidHexadecimalLiteral worked except for negative int64 max.) |
| if (isNegative) lexeme = '-$lexeme'; |
| return int.tryParse(lexeme) != null; |
| } |
| |
| /// Suggest the nearest valid double to a user. If the integer they wrote |
| /// requires more than a 53 bit mantissa, or more than 10 exponent bits, do |
| /// them the favor of suggesting the nearest integer that would work for them. |
| static double nearestValidDouble(String lexeme) => |
| math.min(double.maxFinite, BigInt.parse(lexeme).toDouble()); |
| } |
| |
| /// A node within a [StringInterpolation]. |
| /// |
| /// interpolationElement ::= |
| /// [InterpolationExpression] |
| /// | [InterpolationString] |
| abstract class InterpolationElementImpl extends AstNodeImpl |
| implements InterpolationElement {} |
| |
| /// An expression embedded in a string interpolation. |
| /// |
| /// interpolationExpression ::= |
| /// '$' [SimpleIdentifier] |
| /// | '$' '{' [Expression] '}' |
| class InterpolationExpressionImpl extends InterpolationElementImpl |
| implements InterpolationExpression { |
| /// The token used to introduce the interpolation expression; either '$' if |
| /// the expression is a simple identifier or '${' if the expression is a full |
| /// expression. |
| @override |
| Token leftBracket; |
| |
| /// The expression to be evaluated for the value to be converted into a |
| /// string. |
| ExpressionImpl _expression; |
| |
| /// The right curly bracket, or `null` if the expression is an identifier |
| /// without brackets. |
| @override |
| Token? rightBracket; |
| |
| /// Initialize a newly created interpolation expression. |
| InterpolationExpressionImpl( |
| this.leftBracket, this._expression, this.rightBracket) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken => leftBracket; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(leftBracket)..add(_expression)..add(rightBracket); |
| |
| @override |
| Token get endToken => rightBracket ?? _expression.endToken; |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitInterpolationExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// A non-empty substring of an interpolated string. |
| /// |
| /// interpolationString ::= |
| /// characters |
| class InterpolationStringImpl extends InterpolationElementImpl |
| implements InterpolationString { |
| /// The characters that will be added to the string. |
| @override |
| Token contents; |
| |
| /// The value of the literal. |
| @override |
| String value; |
| |
| /// Initialize a newly created string of characters that are part of a string |
| /// interpolation. |
| InterpolationStringImpl(this.contents, this.value); |
| |
| @override |
| Token get beginToken => contents; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(contents); |
| |
| @override |
| int get contentsEnd => offset + _lexemeHelper.end; |
| |
| @override |
| int get contentsOffset => contents.offset + _lexemeHelper.start; |
| |
| @override |
| Token get endToken => contents; |
| |
| @override |
| StringInterpolation get parent => super.parent as StringInterpolation; |
| |
| StringLexemeHelper get _lexemeHelper { |
| String lexeme = contents.lexeme; |
| return StringLexemeHelper(lexeme, identical(this, parent.elements.first), |
| identical(this, parent.elements.last)); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitInterpolationString(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) {} |
| } |
| |
| /// Common base class for [FunctionExpressionInvocationImpl] and |
| /// [MethodInvocationImpl]. |
| abstract class InvocationExpressionImpl extends ExpressionImpl |
| implements InvocationExpression { |
| /// The list of arguments to the function. |
| ArgumentListImpl _argumentList; |
| |
| /// The type arguments to be applied to the method being invoked, or `null` if |
| /// no type arguments were provided. |
| TypeArgumentListImpl? _typeArguments; |
| |
| @override |
| List<DartType>? typeArgumentTypes; |
| |
| @override |
| DartType? staticInvokeType; |
| |
| /// Initialize a newly created invocation. |
| InvocationExpressionImpl(this._typeArguments, this._argumentList) { |
| _becomeParentOf(_typeArguments); |
| _becomeParentOf(_argumentList); |
| } |
| |
| @override |
| ArgumentListImpl get argumentList => _argumentList; |
| |
| set argumentList(ArgumentList argumentList) { |
| _argumentList = _becomeParentOf(argumentList as ArgumentListImpl); |
| } |
| |
| @override |
| TypeArgumentListImpl? get typeArguments => _typeArguments; |
| |
| set typeArguments(TypeArgumentList? typeArguments) { |
| _typeArguments = _becomeParentOf(typeArguments as TypeArgumentListImpl?); |
| } |
| } |
| |
| /// An is expression. |
| /// |
| /// isExpression ::= |
| /// [Expression] 'is' '!'? [TypeName] |
| class IsExpressionImpl extends ExpressionImpl implements IsExpression { |
| /// The expression used to compute the value whose type is being tested. |
| ExpressionImpl _expression; |
| |
| /// The is operator. |
| @override |
| Token isOperator; |
| |
| /// The not operator, or `null` if the sense of the test is not negated. |
| @override |
| Token? notOperator; |
| |
| /// The name of the type being tested for. |
| TypeAnnotationImpl _type; |
| |
| /// Initialize a newly created is expression. The [notOperator] can be `null` |
| /// if the sense of the test is not negated. |
| IsExpressionImpl( |
| this._expression, this.isOperator, this.notOperator, this._type) { |
| _becomeParentOf(_expression); |
| _becomeParentOf(_type); |
| } |
| |
| @override |
| Token get beginToken => _expression.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_expression) |
| ..add(isOperator) |
| ..add(notOperator) |
| ..add(_type); |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitIsExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| _type.accept(visitor); |
| } |
| } |
| |
| /// A statement that has a label associated with them. |
| /// |
| /// labeledStatement ::= |
| /// [Label]+ [Statement] |
| class LabeledStatementImpl extends StatementImpl implements LabeledStatement { |
| /// The labels being associated with the statement. |
| final NodeListImpl<Label> _labels = NodeListImpl._(); |
| |
| /// The statement with which the labels are being associated. |
| StatementImpl _statement; |
| |
| /// Initialize a newly created labeled statement. |
| LabeledStatementImpl(List<Label> labels, this._statement) { |
| _labels._initialize(this, labels); |
| _becomeParentOf(_statement); |
| } |
| |
| @override |
| Token get beginToken { |
| if (_labels.isNotEmpty) { |
| return _labels.beginToken!; |
| } |
| return _statement.beginToken; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..addAll(_labels) |
| ..add(_statement); |
| |
| @override |
| Token get endToken => _statement.endToken; |
| |
| @override |
| NodeListImpl<Label> get labels => _labels; |
| |
| @override |
| StatementImpl get statement => _statement; |
| |
| set statement(Statement statement) { |
| _statement = _becomeParentOf(statement as StatementImpl); |
| } |
| |
| @override |
| StatementImpl get unlabeled => _statement.unlabeled; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitLabeledStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _labels.accept(visitor); |
| _statement.accept(visitor); |
| } |
| } |
| |
| /// A label on either a [LabeledStatement] or a [NamedExpression]. |
| /// |
| /// label ::= |
| /// [SimpleIdentifier] ':' |
| class LabelImpl extends AstNodeImpl implements Label { |
| /// The label being associated with the statement. |
| SimpleIdentifierImpl _label; |
| |
| /// The colon that separates the label from the statement. |
| @override |
| Token colon; |
| |
| /// Initialize a newly created label. |
| LabelImpl(this._label, this.colon) { |
| _becomeParentOf(_label); |
| } |
| |
| @override |
| Token get beginToken => _label.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_label)..add(colon); |
| |
| @override |
| Token get endToken => colon; |
| |
| @override |
| SimpleIdentifierImpl get label => _label; |
| |
| set label(SimpleIdentifier label) { |
| _label = _becomeParentOf(label as SimpleIdentifierImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitLabel(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _label.accept(visitor); |
| } |
| } |
| |
| /// A library directive. |
| /// |
| /// libraryDirective ::= |
| /// [Annotation] 'library' [Identifier] ';' |
| class LibraryDirectiveImpl extends DirectiveImpl implements LibraryDirective { |
| /// The token representing the 'library' keyword. |
| @override |
| Token libraryKeyword; |
| |
| /// The name of the library being defined. |
| LibraryIdentifierImpl _name; |
| |
| /// The semicolon terminating the directive. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created library directive. Either or both of the |
| /// [comment] and [metadata] can be `null` if the directive does not have the |
| /// corresponding attribute. |
| LibraryDirectiveImpl(CommentImpl? comment, List<Annotation>? metadata, |
| this.libraryKeyword, this._name, this.semicolon) |
| : super(comment, metadata) { |
| _becomeParentOf(_name); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(libraryKeyword)..add(_name)..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => libraryKeyword; |
| |
| @override |
| Token get keyword => libraryKeyword; |
| |
| @override |
| LibraryIdentifierImpl get name => _name; |
| |
| set name(LibraryIdentifier name) { |
| _name = _becomeParentOf(name as LibraryIdentifierImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitLibraryDirective(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _name.accept(visitor); |
| } |
| } |
| |
| /// The identifier for a library. |
| /// |
| /// libraryIdentifier ::= |
| /// [SimpleIdentifier] ('.' [SimpleIdentifier])* |
| class LibraryIdentifierImpl extends IdentifierImpl |
| implements LibraryIdentifier { |
| /// The components of the identifier. |
| final NodeListImpl<SimpleIdentifier> _components = NodeListImpl._(); |
| |
| /// Initialize a newly created prefixed identifier. |
| LibraryIdentifierImpl(List<SimpleIdentifier> components) { |
| _components._initialize(this, components); |
| } |
| |
| @override |
| Token get beginToken => _components.beginToken!; |
| |
| @override |
| // TODO(paulberry): add "." tokens. |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..addAll(_components); |
| |
| @override |
| NodeListImpl<SimpleIdentifier> get components => _components; |
| |
| @override |
| Token get endToken => _components.endToken!; |
| |
| @override |
| String get name { |
| StringBuffer buffer = StringBuffer(); |
| bool needsPeriod = false; |
| int length = _components.length; |
| for (int i = 0; i < length; i++) { |
| SimpleIdentifier identifier = _components[i]; |
| if (needsPeriod) { |
| buffer.write("."); |
| } else { |
| needsPeriod = true; |
| } |
| buffer.write(identifier.name); |
| } |
| return buffer.toString(); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.postfix; |
| |
| @override |
| Element? get staticElement => null; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitLibraryIdentifier(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _components.accept(visitor); |
| } |
| } |
| |
| class ListLiteralImpl extends TypedLiteralImpl implements ListLiteral { |
| /// The left square bracket. |
| @override |
| Token leftBracket; |
| |
| /// The expressions used to compute the elements of the list. |
| final NodeListImpl<CollectionElement> _elements = NodeListImpl._(); |
| |
| /// The right square bracket. |
| @override |
| Token rightBracket; |
| |
| /// Initialize a newly created list literal. The [constKeyword] can be `null` |
| /// if the literal is not a constant. The [typeArguments] can be `null` if no |
| /// type arguments were declared. The list of [elements] can be `null` if the |
| /// list is empty. |
| ListLiteralImpl(Token? constKeyword, TypeArgumentListImpl? typeArguments, |
| this.leftBracket, List<Expression> elements, this.rightBracket) |
| : super(constKeyword, typeArguments) { |
| _elements._initialize(this, elements); |
| } |
| |
| /// Initialize a newly created list literal. |
| /// |
| /// The [constKeyword] can be `null` if the literal is not a constant. The |
| /// [typeArguments] can be `null` if no type arguments were declared. The list |
| /// of [elements] can be `null` if the list is empty. |
| ListLiteralImpl.experimental( |
| Token? constKeyword, |
| TypeArgumentListImpl? typeArguments, |
| this.leftBracket, |
| List<CollectionElement> elements, |
| this.rightBracket) |
| : super(constKeyword, typeArguments) { |
| _elements._initialize(this, elements); |
| } |
| |
| @override |
| Token get beginToken { |
| if (constKeyword != null) { |
| return constKeyword!; |
| } |
| final typeArguments = this.typeArguments; |
| if (typeArguments != null) { |
| return typeArguments.beginToken; |
| } |
| return leftBracket; |
| } |
| |
| @override |
| // TODO(paulberry): add commas. |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(leftBracket) |
| ..addAll(_elements) |
| ..add(rightBracket); |
| |
| @override |
| NodeListImpl<CollectionElement> get elements => _elements; |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitListLiteral(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _elements.accept(visitor); |
| } |
| } |
| |
| /// A node that represents a literal expression. |
| /// |
| /// literal ::= |
| /// [BooleanLiteral] |
| /// | [DoubleLiteral] |
| /// | [IntegerLiteral] |
| /// | [ListLiteral] |
| /// | [MapLiteral] |
| /// | [NullLiteral] |
| /// | [StringLiteral] |
| abstract class LiteralImpl extends ExpressionImpl implements Literal { |
| @override |
| Precedence get precedence => Precedence.primary; |
| } |
| |
| /// Additional information about local variables within a function or method |
| /// produced at resolution time. |
| class LocalVariableInfo { |
| /// The set of local variables and parameters that are potentially mutated |
| /// within a local function other than the function in which they are |
| /// declared. |
| final Set<VariableElement> potentiallyMutatedInClosure = <VariableElement>{}; |
| |
| /// The set of local variables and parameters that are potentially mutated |
| /// within the scope of their declarations. |
| final Set<VariableElement> potentiallyMutatedInScope = <VariableElement>{}; |
| } |
| |
| /// A single key/value pair in a map literal. |
| /// |
| /// mapLiteralEntry ::= |
| /// [Expression] ':' [Expression] |
| class MapLiteralEntryImpl extends CollectionElementImpl |
| implements MapLiteralEntry { |
| /// The expression computing the key with which the value will be associated. |
| ExpressionImpl _key; |
| |
| /// The colon that separates the key from the value. |
| @override |
| Token separator; |
| |
| /// The expression computing the value that will be associated with the key. |
| ExpressionImpl _value; |
| |
| /// Initialize a newly created map literal entry. |
| MapLiteralEntryImpl(this._key, this.separator, this._value) { |
| _becomeParentOf(_key); |
| _becomeParentOf(_value); |
| } |
| |
| @override |
| Token get beginToken => _key.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_key)..add(separator)..add(_value); |
| |
| @override |
| Token get endToken => _value.endToken; |
| |
| @override |
| ExpressionImpl get key => _key; |
| |
| set key(Expression string) { |
| _key = _becomeParentOf(string as ExpressionImpl); |
| } |
| |
| @override |
| ExpressionImpl get value => _value; |
| |
| set value(Expression expression) { |
| _value = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitMapLiteralEntry(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _key.accept(visitor); |
| _value.accept(visitor); |
| } |
| } |
| |
| /// A method declaration. |
| /// |
| /// methodDeclaration ::= |
| /// methodSignature [FunctionBody] |
| /// |
| /// methodSignature ::= |
| /// 'external'? ('abstract' | 'static')? [Type]? ('get' | 'set')? |
| /// methodName [TypeParameterList] [FormalParameterList] |
| /// |
| /// methodName ::= |
| /// [SimpleIdentifier] |
| /// | 'operator' [SimpleIdentifier] |
| class MethodDeclarationImpl extends ClassMemberImpl |
| implements MethodDeclaration { |
| /// The token for the 'external' keyword, or `null` if the constructor is not |
| /// external. |
| @override |
| Token? externalKeyword; |
| |
| /// The token representing the 'abstract' or 'static' keyword, or `null` if |
| /// neither modifier was specified. |
| @override |
| Token? modifierKeyword; |
| |
| /// The return type of the method, or `null` if no return type was declared. |
| TypeAnnotationImpl? _returnType; |
| |
| /// The token representing the 'get' or 'set' keyword, or `null` if this is a |
| /// method declaration rather than a property declaration. |
| @override |
| Token? propertyKeyword; |
| |
| /// The token representing the 'operator' keyword, or `null` if this method |
| /// does not declare an operator. |
| @override |
| Token? operatorKeyword; |
| |
| /// The name of the method. |
| SimpleIdentifierImpl _name; |
| |
| /// The type parameters associated with the method, or `null` if the method is |
| /// not a generic method. |
| TypeParameterListImpl? _typeParameters; |
| |
| /// The parameters associated with the method, or `null` if this method |
| /// declares a getter. |
| FormalParameterListImpl? _parameters; |
| |
| /// The body of the method. |
| FunctionBodyImpl _body; |
| |
| /// Initialize a newly created method declaration. Either or both of the |
| /// [comment] and [metadata] can be `null` if the declaration does not have |
| /// the corresponding attribute. The [externalKeyword] can be `null` if the |
| /// method is not external. The [modifierKeyword] can be `null` if the method |
| /// is neither abstract nor static. The [returnType] can be `null` if no |
| /// return type was specified. The [propertyKeyword] can be `null` if the |
| /// method is neither a getter or a setter. The [operatorKeyword] can be |
| /// `null` if the method does not implement an operator. The [parameters] must |
| /// be `null` if this method declares a getter. |
| MethodDeclarationImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.externalKeyword, |
| this.modifierKeyword, |
| this._returnType, |
| this.propertyKeyword, |
| this.operatorKeyword, |
| this._name, |
| this._typeParameters, |
| this._parameters, |
| this._body) |
| : super(comment, metadata) { |
| _becomeParentOf(_returnType); |
| _becomeParentOf(_name); |
| _becomeParentOf(_typeParameters); |
| _becomeParentOf(_parameters); |
| _becomeParentOf(_body); |
| } |
| |
| @override |
| FunctionBodyImpl get body => _body; |
| |
| set body(FunctionBody functionBody) { |
| _body = _becomeParentOf(functionBody as FunctionBodyImpl); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(externalKeyword) |
| ..add(modifierKeyword) |
| ..add(_returnType) |
| ..add(propertyKeyword) |
| ..add(operatorKeyword) |
| ..add(_name) |
| ..add(_parameters) |
| ..add(_body); |
| |
| /// Return the element associated with this method, or `null` if the AST |
| /// structure has not been resolved. The element can either be a |
| /// [MethodElement], if this represents the declaration of a normal method, or |
| /// a [PropertyAccessorElement] if this represents the declaration of either a |
| /// getter or a setter. |
| @override |
| ExecutableElement? get declaredElement => |
| _name.staticElement as ExecutableElement?; |
| |
| @override |
| Token get endToken => _body.endToken; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return Token.lexicallyFirst(externalKeyword, modifierKeyword) ?? |
| _returnType?.beginToken ?? |
| Token.lexicallyFirst(propertyKeyword, operatorKeyword) ?? |
| _name.beginToken; |
| } |
| |
| @override |
| bool get isAbstract { |
| FunctionBody body = _body; |
| return externalKeyword == null && |
| (body is EmptyFunctionBody && !body.semicolon.isSynthetic); |
| } |
| |
| @override |
| bool get isGetter => propertyKeyword?.keyword == Keyword.GET; |
| |
| @override |
| bool get isOperator => operatorKeyword != null; |
| |
| @override |
| bool get isSetter => propertyKeyword?.keyword == Keyword.SET; |
| |
| @override |
| bool get isStatic => modifierKeyword?.keyword == Keyword.STATIC; |
| |
| @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 |
| TypeAnnotationImpl? get returnType => _returnType; |
| |
| set returnType(TypeAnnotation? type) { |
| _returnType = _becomeParentOf(type as TypeAnnotationImpl?); |
| } |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| set typeParameters(TypeParameterList? typeParameters) { |
| _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitMethodDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _returnType?.accept(visitor); |
| _name.accept(visitor); |
| _typeParameters?.accept(visitor); |
| _parameters?.accept(visitor); |
| _body.accept(visitor); |
| } |
| } |
| |
| /// The invocation of either a function or a method. Invocations of functions |
| /// resulting from evaluating an expression are represented by |
| /// [FunctionExpressionInvocation] nodes. Invocations of getters and setters are |
| /// represented by either [PrefixedIdentifier] or [PropertyAccess] nodes. |
| /// |
| /// methodInvocation ::= |
| /// ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? |
| /// [ArgumentList] |
| class MethodInvocationImpl extends InvocationExpressionImpl |
| with NullShortableExpressionImpl |
| implements MethodInvocation { |
| /// The expression producing the object on which the method is defined, or |
| /// `null` if there is no target (that is, the target is implicitly `this`). |
| ExpressionImpl? _target; |
| |
| /// The operator that separates the target from the method name, or `null` |
| /// if there is no target. In an ordinary method invocation this will be a |
| /// period ('.'). In a cascade section this will be the cascade operator |
| /// ('..' | '?..'). |
| @override |
| Token? operator; |
| |
| /// The name of the method being invoked. |
| SimpleIdentifierImpl _methodName; |
| |
| /// The invoke type of the [methodName] if the target element is a getter, |
| /// or `null` otherwise. |
| DartType? _methodNameType; |
| |
| /// Initialize a newly created method invocation. The [target] and [operator] |
| /// can be `null` if there is no target. |
| MethodInvocationImpl(this._target, this.operator, this._methodName, |
| TypeArgumentListImpl? typeArguments, ArgumentListImpl argumentList) |
| : super(typeArguments, argumentList) { |
| _becomeParentOf(_target); |
| _becomeParentOf(_methodName); |
| } |
| |
| @override |
| Token get beginToken { |
| if (_target != null) { |
| return _target!.beginToken; |
| } else if (operator != null) { |
| return operator!; |
| } |
| return _methodName.beginToken; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(_target) |
| ..add(operator) |
| ..add(_methodName) |
| ..add(_argumentList); |
| |
| @override |
| Token get endToken => _argumentList.endToken; |
| |
| @override |
| ExpressionImpl get function => methodName; |
| |
| @override |
| bool get isCascaded => |
| operator != null && |
| (operator!.type == TokenType.PERIOD_PERIOD || |
| operator!.type == TokenType.QUESTION_PERIOD_PERIOD); |
| |
| @override |
| bool get isNullAware { |
| if (isCascaded) { |
| return _ancestorCascade.isNullAware; |
| } |
| return operator != null && |
| (operator!.type == TokenType.QUESTION_PERIOD || |
| operator!.type == TokenType.QUESTION_PERIOD_PERIOD); |
| } |
| |
| @override |
| SimpleIdentifierImpl get methodName => _methodName; |
| |
| set methodName(SimpleIdentifier identifier) { |
| _methodName = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| |
| /// The invoke type of the [methodName]. |
| /// |
| /// If the target element is a [MethodElement], this is the same as the |
| /// [staticInvokeType]. If the target element is a getter, presumably |
| /// returning an [ExecutableElement] so that it can be invoked in this |
| /// [MethodInvocation], then this type is the type of the getter, and the |
| /// [staticInvokeType] is the invoked type of the returned element. |
| DartType? get methodNameType => _methodNameType ?? staticInvokeType; |
| |
| /// Set the [methodName] invoke type, only if the target element is a getter. |
| /// Otherwise, the target element itself is invoked, [_methodNameType] is |
| /// `null`, and the getter will return [staticInvokeType]. |
| set methodNameType(DartType? methodNameType) { |
| _methodNameType = methodNameType; |
| } |
| |
| @override |
| Precedence get precedence => Precedence.postfix; |
| |
| @override |
| ExpressionImpl? get realTarget { |
| if (isCascaded) { |
| return _ancestorCascade.target; |
| } |
| return _target; |
| } |
| |
| @override |
| ExpressionImpl? get target => _target; |
| |
| set target(Expression? expression) { |
| _target = _becomeParentOf(expression as ExpressionImpl?); |
| } |
| |
| /// Return the cascade that contains this [IndexExpression]. |
| /// |
| /// We expect that [isCascaded] is `true`. |
| CascadeExpressionImpl get _ancestorCascade { |
| assert(isCascaded); |
| for (var ancestor = parent!;; ancestor = ancestor.parent!) { |
| if (ancestor is CascadeExpressionImpl) { |
| return ancestor; |
| } |
| } |
| } |
| |
| @override |
| AstNode? get _nullShortingExtensionCandidate => parent; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitMethodInvocation(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _target?.accept(visitor); |
| _methodName.accept(visitor); |
| _typeArguments?.accept(visitor); |
| _argumentList.accept(visitor); |
| } |
| |
| @override |
| bool _extendsNullShorting(Expression child) => identical(child, _target); |
| } |
| |
| /// The declaration of a mixin. |
| /// |
| /// mixinDeclaration ::= |
| /// metadata? 'mixin' [SimpleIdentifier] [TypeParameterList]? |
| /// [RequiresClause]? [ImplementsClause]? '{' [ClassMember]* '}' |
| class MixinDeclarationImpl extends ClassOrMixinDeclarationImpl |
| implements MixinDeclaration { |
| @override |
| Token mixinKeyword; |
| |
| /// The on clause for the mixin, or `null` if the mixin does not have any |
| /// super-class constraints. |
| OnClauseImpl? _onClause; |
| |
| /// Initialize a newly created mixin declaration. Either or both of the |
| /// [comment] and [metadata] can be `null` if the mixin does not have the |
| /// corresponding attribute. The [typeParameters] can be `null` if the mixin |
| /// does not have any type parameters. Either or both of the [onClause], |
| /// and [implementsClause] can be `null` if the mixin does not have the |
| /// corresponding clause. The list of [members] can be `null` if the mixin |
| /// does not have any members. |
| MixinDeclarationImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.mixinKeyword, |
| SimpleIdentifierImpl name, |
| TypeParameterListImpl? typeParameters, |
| this._onClause, |
| ImplementsClauseImpl? implementsClause, |
| Token leftBracket, |
| List<ClassMember> members, |
| Token rightBracket) |
| : super(comment, metadata, name, typeParameters, implementsClause, |
| leftBracket, members, rightBracket) { |
| _becomeParentOf(_onClause); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(mixinKeyword) |
| ..add(_name) |
| ..add(_typeParameters) |
| ..add(_onClause) |
| ..add(_implementsClause) |
| ..add(leftBracket) |
| ..addAll(members) |
| ..add(rightBracket); |
| |
| @override |
| ClassElement? get declaredElement => _name.staticElement as ClassElement?; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return mixinKeyword; |
| } |
| |
| @override |
| ImplementsClauseImpl? get implementsClause => _implementsClause; |
| |
| @override |
| NodeListImpl<ClassMember> get members => _members; |
| |
| @override |
| OnClause? get onClause => _onClause; |
| |
| set onClause(OnClause? onClause) { |
| _onClause = _becomeParentOf(onClause as OnClauseImpl?); |
| } |
| |
| @override |
| TypeParameterListImpl? get typeParameters => _typeParameters; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitMixinDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _name.accept(visitor); |
| _typeParameters?.accept(visitor); |
| _onClause?.accept(visitor); |
| _implementsClause?.accept(visitor); |
| members.accept(visitor); |
| } |
| } |
| |
| /// A node that declares a single name within the scope of a compilation unit. |
| abstract class NamedCompilationUnitMemberImpl extends CompilationUnitMemberImpl |
| implements NamedCompilationUnitMember { |
| /// The name of the member being declared. |
| SimpleIdentifierImpl _name; |
| |
| /// Initialize a newly created compilation unit member with the given [name]. |
| /// Either or both of the [comment] and [metadata] can be `null` if the member |
| /// does not have the corresponding attribute. |
| NamedCompilationUnitMemberImpl( |
| CommentImpl? comment, List<Annotation>? metadata, this._name) |
| : super(comment, metadata) { |
| _becomeParentOf(_name); |
| } |
| |
| @override |
| SimpleIdentifierImpl get name => _name; |
| |
| set name(SimpleIdentifier identifier) { |
| _name = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| } |
| |
| /// An expression that has a name associated with it. They are used in method |
| /// invocations when there are named parameters. |
| /// |
| /// namedExpression ::= |
| /// [Label] [Expression] |
| class NamedExpressionImpl extends ExpressionImpl implements NamedExpression { |
| /// The name associated with the expression. |
| LabelImpl _name; |
| |
| /// The expression with which the name is associated. |
| ExpressionImpl _expression; |
| |
| /// Initialize a newly created named expression.. |
| NamedExpressionImpl(this._name, this._expression) { |
| _becomeParentOf(_name); |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken => _name.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_name)..add(_expression); |
| |
| @override |
| ParameterElement? get element { |
| var element = _name.label.staticElement; |
| if (element is ParameterElement) { |
| return element; |
| } |
| return null; |
| } |
| |
| @override |
| Token get endToken => _expression.endToken; |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| LabelImpl get name => _name; |
| |
| set name(Label identifier) { |
| _name = _becomeParentOf(identifier as LabelImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.none; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitNamedExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _name.accept(visitor); |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// A node that represents a directive that impacts the namespace of a library. |
| /// |
| /// directive ::= |
| /// [ExportDirective] |
| /// | [ImportDirective] |
| abstract class NamespaceDirectiveImpl extends UriBasedDirectiveImpl |
| implements NamespaceDirective { |
| /// The token representing the 'import' or 'export' keyword. |
| @override |
| Token keyword; |
| |
| /// The configurations used to control which library will actually be loaded |
| /// at run-time. |
| final NodeListImpl<Configuration> _configurations = NodeListImpl._(); |
| |
| /// The combinators used to control which names are imported or exported. |
| final NodeListImpl<Combinator> _combinators = NodeListImpl._(); |
| |
| /// The semicolon terminating the directive. |
| @override |
| Token semicolon; |
| |
| @override |
| String? selectedUriContent; |
| |
| @override |
| Source? selectedSource; |
| |
| /// Initialize a newly created namespace directive. Either or both of the |
| /// [comment] and [metadata] can be `null` if the directive does not have the |
| /// corresponding attribute. The list of [combinators] can be `null` if there |
| /// are no combinators. |
| NamespaceDirectiveImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.keyword, |
| StringLiteralImpl libraryUri, |
| List<Configuration>? configurations, |
| List<Combinator>? combinators, |
| this.semicolon) |
| : super(comment, metadata, libraryUri) { |
| _configurations._initialize(this, configurations); |
| _combinators._initialize(this, combinators); |
| } |
| |
| @override |
| NodeListImpl<Combinator> get combinators => _combinators; |
| |
| @override |
| NodeListImpl<Configuration> get configurations => _configurations; |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => keyword; |
| |
| @override |
| LibraryElement? get uriElement; |
| } |
| |
| /// The "native" clause in an class declaration. |
| /// |
| /// nativeClause ::= |
| /// 'native' [StringLiteral] |
| class NativeClauseImpl extends AstNodeImpl implements NativeClause { |
| /// The token representing the 'native' keyword. |
| @override |
| Token nativeKeyword; |
| |
| /// The name of the native object that implements the class. |
| StringLiteralImpl? _name; |
| |
| /// Initialize a newly created native clause. |
| NativeClauseImpl(this.nativeKeyword, this._name) { |
| _becomeParentOf(_name); |
| } |
| |
| @override |
| Token get beginToken => nativeKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(nativeKeyword)..add(_name); |
| |
| @override |
| Token get endToken { |
| return _name?.endToken ?? nativeKeyword; |
| } |
| |
| @override |
| StringLiteralImpl? get name => _name; |
| |
| set name(StringLiteral? name) { |
| _name = _becomeParentOf(name as StringLiteralImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitNativeClause(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _name?.accept(visitor); |
| } |
| } |
| |
| /// A function body that consists of a native keyword followed by a string |
| /// literal. |
| /// |
| /// nativeFunctionBody ::= |
| /// 'native' [SimpleStringLiteral] ';' |
| class NativeFunctionBodyImpl extends FunctionBodyImpl |
| implements NativeFunctionBody { |
| /// The token representing 'native' that marks the start of the function body. |
| @override |
| Token nativeKeyword; |
| |
| /// The string literal, after the 'native' token. |
| StringLiteralImpl? _stringLiteral; |
| |
| /// The token representing the semicolon that marks the end of the function |
| /// body. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created function body consisting of the 'native' token, |
| /// a string literal, and a semicolon. |
| NativeFunctionBodyImpl( |
| this.nativeKeyword, this._stringLiteral, this.semicolon) { |
| _becomeParentOf(_stringLiteral); |
| } |
| |
| @override |
| Token get beginToken => nativeKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(nativeKeyword)..add(_stringLiteral)..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| StringLiteralImpl? get stringLiteral => _stringLiteral; |
| |
| set stringLiteral(StringLiteral? stringLiteral) { |
| _stringLiteral = _becomeParentOf(stringLiteral as StringLiteralImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitNativeFunctionBody(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _stringLiteral?.accept(visitor); |
| } |
| } |
| |
| /// A list of AST nodes that have a common parent. |
| class NodeListImpl<E extends AstNode> with ListMixin<E> implements NodeList<E> { |
| /// The node that is the parent of each of the elements in the list. |
| late final AstNodeImpl _owner; |
| |
| /// The elements contained in the list. |
| List<E> _elements = <E>[]; |
| |
| /// Initialize a newly created list of nodes such that all of the nodes that |
| /// are added to the list will have their parent set to the given [owner]. |
| NodeListImpl(AstNodeImpl owner) : _owner = owner; |
| |
| /// Create a partially initialized instance, [_initialize] must be called. |
| NodeListImpl._(); |
| |
| @override |
| Token? get beginToken { |
| if (_elements.isEmpty) { |
| return null; |
| } |
| return _elements[0].beginToken; |
| } |
| |
| @override |
| Token? get endToken { |
| int length = _elements.length; |
| if (length == 0) { |
| return null; |
| } |
| return _elements[length - 1].endToken; |
| } |
| |
| @override |
| int get length => _elements.length; |
| |
| @override |
| set length(int newLength) { |
| throw UnsupportedError("Cannot resize NodeList."); |
| } |
| |
| @override |
| AstNodeImpl get owner => _owner; |
| |
| @override |
| E operator [](int index) { |
| if (index < 0 || index >= _elements.length) { |
| throw RangeError("Index: $index, Size: ${_elements.length}"); |
| } |
| return _elements[index]; |
| } |
| |
| @override |
| void operator []=(int index, E node) { |
| if (index < 0 || index >= _elements.length) { |
| throw RangeError("Index: $index, Size: ${_elements.length}"); |
| } |
| _elements[index] = node; |
| _owner._becomeParentOf(node as AstNodeImpl); |
| } |
| |
| @override |
| void accept(AstVisitor visitor) { |
| int length = _elements.length; |
| for (var i = 0; i < length; i++) { |
| _elements[i].accept(visitor); |
| } |
| } |
| |
| @override |
| void add(E node) { |
| insert(length, node); |
| } |
| |
| @override |
| void addAll(Iterable<E> nodes) { |
| for (E node in nodes) { |
| _elements.add(node); |
| _owner._becomeParentOf(node as AstNodeImpl); |
| } |
| } |
| |
| @override |
| void clear() { |
| _elements = <E>[]; |
| } |
| |
| @override |
| void insert(int index, E node) { |
| _elements.insert(index, node); |
| _owner._becomeParentOf(node as AstNodeImpl); |
| } |
| |
| @override |
| E removeAt(int index) { |
| if (index < 0 || index >= _elements.length) { |
| throw RangeError("Index: $index, Size: ${_elements.length}"); |
| } |
| return _elements.removeAt(index); |
| } |
| |
| /// Set the [owner] of this container, and populate it with [elements]. |
| void _initialize(AstNodeImpl owner, List<E>? elements) { |
| _owner = owner; |
| if (elements != null) { |
| var length = elements.length; |
| for (var i = 0; i < length; i++) { |
| var node = elements[i]; |
| _elements.add(node); |
| owner._becomeParentOf(node as AstNodeImpl); |
| } |
| } |
| } |
| } |
| |
| /// A formal parameter that is required (is not optional). |
| /// |
| /// normalFormalParameter ::= |
| /// [FunctionTypedFormalParameter] |
| /// | [FieldFormalParameter] |
| /// | [SimpleFormalParameter] |
| abstract class NormalFormalParameterImpl extends FormalParameterImpl |
| implements NormalFormalParameter { |
| /// The documentation comment associated with this parameter, or `null` if |
| /// this parameter does not have a documentation comment associated with it. |
| CommentImpl? _comment; |
| |
| /// The annotations associated with this parameter. |
| final NodeListImpl<Annotation> _metadata = NodeListImpl._(); |
| |
| /// The 'covariant' keyword, or `null` if the keyword was not used. |
| @override |
| Token? covariantKeyword; |
| |
| /// The 'required' keyword, or `null` if the keyword was not used. |
| @override |
| Token? requiredKeyword; |
| |
| /// The name of the parameter being declared. |
| SimpleIdentifierImpl? _identifier; |
| |
| /// Initialize a newly created formal parameter. Either or both of the |
| /// [comment] and [metadata] can be `null` if the parameter does not have the |
| /// corresponding attribute. |
| NormalFormalParameterImpl(this._comment, List<Annotation>? metadata, |
| this.covariantKeyword, this.requiredKeyword, this._identifier) { |
| _becomeParentOf(_comment); |
| _metadata._initialize(this, metadata); |
| _becomeParentOf(_identifier); |
| } |
| |
| @override |
| CommentImpl? get documentationComment => _comment; |
| |
| set documentationComment(Comment? comment) { |
| _comment = _becomeParentOf(comment as CommentImpl?); |
| } |
| |
| @override |
| SimpleIdentifierImpl? get identifier => _identifier; |
| |
| set identifier(SimpleIdentifier? identifier) { |
| _identifier = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| ParameterKind get kind { |
| final parent = this.parent; |
| if (parent is DefaultFormalParameterImpl) { |
| return parent.kind; |
| } |
| return ParameterKind.REQUIRED; |
| } |
| |
| @override |
| NodeListImpl<Annotation> get metadata => _metadata; |
| |
| set metadata(List<Annotation> metadata) { |
| _metadata.clear(); |
| _metadata.addAll(metadata); |
| } |
| |
| @override |
| List<AstNode> get sortedCommentAndAnnotations { |
| var comment = _comment; |
| return <AstNode>[ |
| if (comment != null) comment, |
| ..._metadata, |
| ]..sort(AstNode.LEXICAL_ORDER); |
| } |
| |
| ChildEntities get _childEntities { |
| ChildEntities result = ChildEntities(); |
| if (_commentIsBeforeAnnotations()) { |
| result |
| ..add(_comment) |
| ..addAll(_metadata); |
| } else { |
| result.addAll(sortedCommentAndAnnotations); |
| } |
| result..add(requiredKeyword)..add(covariantKeyword); |
| return result; |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // |
| // Note that subclasses are responsible for visiting the identifier because |
| // they often need to visit other nodes before visiting the identifier. |
| // |
| 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 the comment is lexically before any annotations. |
| bool _commentIsBeforeAnnotations() { |
| if (_comment == null || _metadata.isEmpty) { |
| return true; |
| } |
| Annotation firstAnnotation = _metadata[0]; |
| return _comment!.offset < firstAnnotation.offset; |
| } |
| } |
| |
| /// A null literal expression. |
| /// |
| /// nullLiteral ::= |
| /// 'null' |
| class NullLiteralImpl extends LiteralImpl implements NullLiteral { |
| /// The token representing the literal. |
| @override |
| Token literal; |
| |
| /// Initialize a newly created null literal. |
| NullLiteralImpl(this.literal); |
| |
| @override |
| Token get beginToken => literal; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal); |
| |
| @override |
| Token get endToken => literal; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitNullLiteral(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| /// Mixin that can be used to implement [NullShortableExpression]. |
| mixin NullShortableExpressionImpl implements NullShortableExpression { |
| @override |
| Expression get nullShortingTermination { |
| var result = this; |
| while (true) { |
| var parent = result._nullShortingExtensionCandidate; |
| if (parent is NullShortableExpressionImpl && |
| parent._extendsNullShorting(result)) { |
| result = parent; |
| } else { |
| return result; |
| } |
| } |
| } |
| |
| /// Gets the ancestor of this node to which null-shorting might be extended. |
| /// Usually this is just the node's parent, however if `this` is the base of |
| /// a cascade section, it will be the cascade expression itself, which may be |
| /// a more distant ancestor. |
| AstNode? get _nullShortingExtensionCandidate; |
| |
| /// Indicates whether the effect of any null-shorting within [descendant] |
| /// (which should be a descendant of `this`) should extend to include `this`. |
| bool _extendsNullShorting(Expression descendant); |
| } |
| |
| /// The "on" clause in a mixin declaration. |
| /// |
| /// onClause ::= |
| /// 'on' [TypeName] (',' [TypeName])* |
| class OnClauseImpl extends AstNodeImpl implements OnClause { |
| @override |
| Token onKeyword; |
| |
| /// The classes are super-class constraints for the mixin. |
| final NodeListImpl<TypeName> _superclassConstraints = NodeListImpl._(); |
| |
| /// Initialize a newly created on clause. |
| OnClauseImpl(this.onKeyword, List<TypeName> superclassConstraints) { |
| _superclassConstraints._initialize(this, superclassConstraints); |
| } |
| |
| @override |
| Token get beginToken => onKeyword; |
| |
| @override |
| // TODO(paulberry): add commas. |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(onKeyword) |
| ..addAll(superclassConstraints); |
| |
| @override |
| Token get endToken => _superclassConstraints.endToken!; |
| |
| @override |
| NodeListImpl<TypeName> get superclassConstraints => _superclassConstraints; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitOnClause(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _superclassConstraints.accept(visitor); |
| } |
| } |
| |
| /// A parenthesized expression. |
| /// |
| /// parenthesizedExpression ::= |
| /// '(' [Expression] ')' |
| class ParenthesizedExpressionImpl extends ExpressionImpl |
| implements ParenthesizedExpression { |
| /// The left parenthesis. |
| @override |
| Token leftParenthesis; |
| |
| /// The expression within the parentheses. |
| ExpressionImpl _expression; |
| |
| /// The right parenthesis. |
| @override |
| Token rightParenthesis; |
| |
| /// Initialize a newly created parenthesized expression. |
| ParenthesizedExpressionImpl( |
| this.leftParenthesis, this._expression, this.rightParenthesis) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken => leftParenthesis; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(leftParenthesis) |
| ..add(_expression) |
| ..add(rightParenthesis); |
| |
| @override |
| Token get endToken => rightParenthesis; |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.primary; |
| |
| @override |
| ExpressionImpl get unParenthesized { |
| // This is somewhat inefficient, but it avoids a stack overflow in the |
| // degenerate case. |
| var expression = _expression; |
| while (expression is ParenthesizedExpressionImpl) { |
| expression = expression._expression; |
| } |
| return expression; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitParenthesizedExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// A part directive. |
| /// |
| /// partDirective ::= |
| /// [Annotation] 'part' [StringLiteral] ';' |
| class PartDirectiveImpl extends UriBasedDirectiveImpl implements PartDirective { |
| /// The token representing the 'part' keyword. |
| @override |
| Token partKeyword; |
| |
| /// The semicolon terminating the directive. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created part directive. Either or both of the [comment] |
| /// and [metadata] can be `null` if the directive does not have the |
| /// corresponding attribute. |
| PartDirectiveImpl(CommentImpl? comment, List<Annotation>? metadata, |
| this.partKeyword, StringLiteralImpl partUri, this.semicolon) |
| : super(comment, metadata, partUri); |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(partKeyword)..add(_uri)..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => partKeyword; |
| |
| @override |
| Token get keyword => partKeyword; |
| |
| @override |
| CompilationUnitElement? get uriElement => element as CompilationUnitElement?; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitPartDirective(this); |
| } |
| |
| /// A part-of directive. |
| /// |
| /// partOfDirective ::= |
| /// [Annotation] 'part' 'of' [Identifier] ';' |
| class PartOfDirectiveImpl extends DirectiveImpl implements PartOfDirective { |
| /// The token representing the 'part' keyword. |
| @override |
| Token partKeyword; |
| |
| /// The token representing the 'of' keyword. |
| @override |
| Token ofKeyword; |
| |
| /// The URI of the library that the containing compilation unit is part of. |
| StringLiteralImpl? _uri; |
| |
| /// The name of the library that the containing compilation unit is part of, |
| /// or `null` if no name was given (typically because a library URI was |
| /// provided). |
| LibraryIdentifierImpl? _libraryName; |
| |
| /// The semicolon terminating the directive. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created part-of directive. Either or both of the |
| /// [comment] and [metadata] can be `null` if the directive does not have the |
| /// corresponding attribute. |
| PartOfDirectiveImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.partKeyword, |
| this.ofKeyword, |
| this._uri, |
| this._libraryName, |
| this.semicolon) |
| : super(comment, metadata) { |
| _becomeParentOf(_uri); |
| _becomeParentOf(_libraryName); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(partKeyword) |
| ..add(ofKeyword) |
| ..add(_uri) |
| ..add(_libraryName) |
| ..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => partKeyword; |
| |
| @override |
| Token get keyword => partKeyword; |
| |
| @override |
| LibraryIdentifierImpl? get libraryName => _libraryName; |
| |
| set libraryName(LibraryIdentifier? libraryName) { |
| _libraryName = _becomeParentOf(libraryName as LibraryIdentifierImpl?); |
| } |
| |
| @override |
| StringLiteralImpl? get uri => _uri; |
| |
| set uri(StringLiteral? uri) { |
| _uri = _becomeParentOf(uri as StringLiteralImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitPartOfDirective(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _libraryName?.accept(visitor); |
| _uri?.accept(visitor); |
| } |
| } |
| |
| /// A postfix unary expression. |
| /// |
| /// postfixExpression ::= |
| /// [Expression] [Token] |
| class PostfixExpressionImpl extends ExpressionImpl |
| with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl |
| implements PostfixExpression { |
| /// The expression computing the operand for the operator. |
| ExpressionImpl _operand; |
| |
| /// The postfix operator being applied to the operand. |
| @override |
| Token operator; |
| |
| /// The element associated with the operator based on the static type of the |
| /// 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; |
| |
| /// Initialize a newly created postfix expression. |
| PostfixExpressionImpl(this._operand, this.operator) { |
| _becomeParentOf(_operand); |
| } |
| |
| @override |
| Token get beginToken => _operand.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_operand)..add(operator); |
| |
| @override |
| Token get endToken => operator; |
| |
| @override |
| ExpressionImpl get operand => _operand; |
| |
| set operand(Expression expression) { |
| _operand = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.postfix; |
| |
| @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 operand will be |
| /// bound. Otherwise, return `null`. |
| ParameterElement? get _staticParameterElementForOperand { |
| if (staticElement == null) { |
| return null; |
| } |
| List<ParameterElement> parameters = staticElement!.parameters; |
| if (parameters.isEmpty) { |
| return null; |
| } |
| return parameters[0]; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitPostfixExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _operand.accept(visitor); |
| } |
| |
| @override |
| bool _extendsNullShorting(Expression child) => identical(child, operand); |
| } |
| |
| /// An identifier that is prefixed or an access to an object property where the |
| /// target of the property access is a simple identifier. |
| /// |
| /// prefixedIdentifier ::= |
| /// [SimpleIdentifier] '.' [SimpleIdentifier] |
| class PrefixedIdentifierImpl extends IdentifierImpl |
| implements PrefixedIdentifier { |
| /// The prefix associated with the library in which the identifier is defined. |
| SimpleIdentifierImpl _prefix; |
| |
| /// The period used to separate the prefix from the identifier. |
| @override |
| Token period; |
| |
| /// The identifier being prefixed. |
| SimpleIdentifierImpl _identifier; |
| |
| /// Initialize a newly created prefixed identifier. |
| PrefixedIdentifierImpl(this._prefix, this.period, this._identifier) { |
| _becomeParentOf(_prefix); |
| _becomeParentOf(_identifier); |
| } |
| |
| @override |
| Token get beginToken => _prefix.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_prefix)..add(period)..add(_identifier); |
| |
| @override |
| Token get endToken => _identifier.endToken; |
| |
| @override |
| SimpleIdentifierImpl get identifier => _identifier; |
| |
| set identifier(SimpleIdentifier identifier) { |
| _identifier = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| |
| @override |
| bool get isDeferred { |
| Element? element = _prefix.staticElement; |
| if (element is PrefixElement) { |
| List<ImportElement> imports = |
| element.enclosingElement.getImportsWithPrefix(element); |
| if (imports.length != 1) { |
| return false; |
| } |
| return imports[0].isDeferred; |
| } |
| return false; |
| } |
| |
| @override |
| String get name => "${_prefix.name}.${_identifier.name}"; |
| |
| @override |
| Precedence get precedence => Precedence.postfix; |
| |
| @override |
| SimpleIdentifierImpl get prefix => _prefix; |
| |
| set prefix(SimpleIdentifier identifier) { |
| _prefix = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| |
| @override |
| Element? get staticElement { |
| return _identifier.staticElement; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitPrefixedIdentifier(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _prefix.accept(visitor); |
| _identifier.accept(visitor); |
| } |
| } |
| |
| /// A prefix unary expression. |
| /// |
| /// prefixExpression ::= |
| /// [Token] [Expression] |
| class PrefixExpressionImpl extends ExpressionImpl |
| with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl |
| implements PrefixExpression { |
| /// The prefix operator being applied to the operand. |
| @override |
| Token operator; |
| |
| /// The expression computing the operand for the operator. |
| ExpressionImpl _operand; |
| |
| /// The element associated with the operator based on the static type of the |
| /// 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; |
| |
| /// Initialize a newly created prefix expression. |
| PrefixExpressionImpl(this.operator, this._operand) { |
| _becomeParentOf(_operand); |
| } |
| |
| @override |
| Token get beginToken => operator; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(operator)..add(_operand); |
| |
| @override |
| Token get endToken => _operand.endToken; |
| |
| @override |
| ExpressionImpl get operand => _operand; |
| |
| set operand(Expression expression) { |
| _operand = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.prefix; |
| |
| @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 operand will be |
| /// bound. Otherwise, return `null`. |
| ParameterElement? get _staticParameterElementForOperand { |
| if (staticElement == null) { |
| return null; |
| } |
| List<ParameterElement> parameters = staticElement!.parameters; |
| if (parameters.isEmpty) { |
| return null; |
| } |
| return parameters[0]; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitPrefixExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _operand.accept(visitor); |
| } |
| |
| @override |
| bool _extendsNullShorting(Expression child) => |
| identical(child, operand) && operator.type.isIncrementOperator; |
| } |
| |
| /// The access of a property of an object. |
| /// |
| /// Note, however, that accesses to properties of objects can also be |
| /// represented as [PrefixedIdentifier] nodes in cases where the target is also |
| /// a simple identifier. |
| /// |
| /// propertyAccess ::= |
| /// [Expression] '.' [SimpleIdentifier] |
| class PropertyAccessImpl extends ExpressionImpl |
| with NullShortableExpressionImpl |
| implements PropertyAccess { |
| /// The expression computing the object defining the property being accessed. |
| ExpressionImpl? _target; |
| |
| /// The property access operator. |
| @override |
| Token operator; |
| |
| /// The name of the property being accessed. |
| SimpleIdentifierImpl _propertyName; |
| |
| /// Initialize a newly created property access expression. |
| PropertyAccessImpl(this._target, this.operator, this._propertyName) { |
| _becomeParentOf(_target); |
| _becomeParentOf(_propertyName); |
| } |
| |
| @override |
| Token get beginToken { |
| if (_target != null) { |
| return _target!.beginToken; |
| } |
| return operator; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_target)..add(operator)..add(_propertyName); |
| |
| @override |
| Token get endToken => _propertyName.endToken; |
| |
| @override |
| bool get isAssignable => true; |
| |
| @override |
| bool get isCascaded => |
| operator.type == TokenType.PERIOD_PERIOD || |
| operator.type == TokenType.QUESTION_PERIOD_PERIOD; |
| |
| @override |
| bool get isNullAware { |
| if (isCascaded) { |
| return _ancestorCascade.isNullAware; |
| } |
| return operator.type == TokenType.QUESTION_PERIOD || |
| operator.type == TokenType.QUESTION_PERIOD_PERIOD; |
| } |
| |
| @override |
| Precedence get precedence => Precedence.postfix; |
| |
| @override |
| SimpleIdentifierImpl get propertyName => _propertyName; |
| |
| set propertyName(SimpleIdentifier identifier) { |
| _propertyName = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| |
| @override |
| ExpressionImpl get realTarget { |
| if (isCascaded) { |
| return _ancestorCascade.target; |
| } |
| return _target!; |
| } |
| |
| @override |
| ExpressionImpl? get target => _target; |
| |
| set target(Expression? expression) { |
| _target = _becomeParentOf(expression as ExpressionImpl?); |
| } |
| |
| /// Return the cascade that contains this [IndexExpression]. |
| /// |
| /// We expect that [isCascaded] is `true`. |
| CascadeExpressionImpl get _ancestorCascade { |
| assert(isCascaded); |
| for (var ancestor = parent!;; ancestor = ancestor.parent!) { |
| if (ancestor is CascadeExpressionImpl) { |
| return ancestor; |
| } |
| } |
| } |
| |
| @override |
| AstNode? get _nullShortingExtensionCandidate => parent; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitPropertyAccess(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _target?.accept(visitor); |
| _propertyName.accept(visitor); |
| } |
| |
| @override |
| bool _extendsNullShorting(Expression child) => identical(child, _target); |
| } |
| |
| /// The invocation of a constructor in the same class from within a |
| /// constructor's initialization list. |
| /// |
| /// redirectingConstructorInvocation ::= |
| /// 'this' ('.' identifier)? arguments |
| class RedirectingConstructorInvocationImpl extends ConstructorInitializerImpl |
| implements RedirectingConstructorInvocation { |
| /// The token for the 'this' keyword. |
| @override |
| Token thisKeyword; |
| |
| /// The token for the period before the name of the constructor that is being |
| /// invoked, or `null` if the unnamed constructor is being invoked. |
| @override |
| Token? period; |
| |
| /// The name of the constructor that is being invoked, or `null` if the |
| /// unnamed constructor is being invoked. |
| SimpleIdentifierImpl? _constructorName; |
| |
| /// The list of arguments to the constructor. |
| ArgumentListImpl _argumentList; |
| |
| /// The element associated with the constructor based on static type |
| /// information, or `null` if the AST structure has not been resolved or if |
| /// the constructor could not be resolved. |
| @override |
| ConstructorElement? staticElement; |
| |
| /// Initialize a newly created redirecting invocation to invoke the |
| /// constructor with the given name with the given arguments. The |
| /// [constructorName] can be `null` if the constructor being invoked is the |
| /// unnamed constructor. |
| RedirectingConstructorInvocationImpl(this.thisKeyword, this.period, |
| this._constructorName, this._argumentList) { |
| _becomeParentOf(_constructorName); |
| _becomeParentOf(_argumentList); |
| } |
| |
| @override |
| ArgumentListImpl get argumentList => _argumentList; |
| |
| set argumentList(ArgumentList argumentList) { |
| _argumentList = _becomeParentOf(argumentList as ArgumentListImpl); |
| } |
| |
| @override |
| Token get beginToken => thisKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(thisKeyword) |
| ..add(period) |
| ..add(_constructorName) |
| ..add(_argumentList); |
| |
| @override |
| SimpleIdentifierImpl? get constructorName => _constructorName; |
| |
| set constructorName(SimpleIdentifier? identifier) { |
| _constructorName = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| Token get endToken => _argumentList.endToken; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitRedirectingConstructorInvocation(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _constructorName?.accept(visitor); |
| _argumentList.accept(visitor); |
| } |
| } |
| |
| /// A rethrow expression. |
| /// |
| /// rethrowExpression ::= |
| /// 'rethrow' |
| class RethrowExpressionImpl extends ExpressionImpl |
| implements RethrowExpression { |
| /// The token representing the 'rethrow' keyword. |
| @override |
| Token rethrowKeyword; |
| |
| /// Initialize a newly created rethrow expression. |
| RethrowExpressionImpl(this.rethrowKeyword); |
| |
| @override |
| Token get beginToken => rethrowKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(rethrowKeyword); |
| |
| @override |
| Token get endToken => rethrowKeyword; |
| |
| @override |
| Precedence get precedence => Precedence.assignment; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitRethrowExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| /// A return statement. |
| /// |
| /// returnStatement ::= |
| /// 'return' [Expression]? ';' |
| class ReturnStatementImpl extends StatementImpl implements ReturnStatement { |
| /// The token representing the 'return' keyword. |
| @override |
| Token returnKeyword; |
| |
| /// The expression computing the value to be returned, or `null` if no |
| /// explicit value was provided. |
| ExpressionImpl? _expression; |
| |
| /// The semicolon terminating the statement. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created return statement. The [expression] can be |
| /// `null` if no explicit value was provided. |
| ReturnStatementImpl(this.returnKeyword, this._expression, this.semicolon) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken => returnKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(returnKeyword)..add(_expression)..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| ExpressionImpl? get expression => _expression; |
| |
| set expression(Expression? expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitReturnStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression?.accept(visitor); |
| } |
| } |
| |
| /// A script tag that can optionally occur at the beginning of a compilation |
| /// unit. |
| /// |
| /// scriptTag ::= |
| /// '#!' (~NEWLINE)* NEWLINE |
| class ScriptTagImpl extends AstNodeImpl implements ScriptTag { |
| /// The token representing this script tag. |
| @override |
| Token scriptTag; |
| |
| /// Initialize a newly created script tag. |
| ScriptTagImpl(this.scriptTag); |
| |
| @override |
| Token get beginToken => scriptTag; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(scriptTag); |
| |
| @override |
| Token get endToken => scriptTag; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitScriptTag(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| class SetOrMapLiteralImpl extends TypedLiteralImpl implements SetOrMapLiteral { |
| @override |
| Token leftBracket; |
| |
| /// The syntactic elements in the set. |
| final NodeListImpl<CollectionElement> _elements = NodeListImpl._(); |
| |
| @override |
| Token rightBracket; |
| |
| /// A representation of whether this literal represents a map or a set, or |
| /// whether the kind has not or cannot be determined. |
| _SetOrMapKind _resolvedKind = _SetOrMapKind.unresolved; |
| |
| /// The context type computed by |
| /// [ResolverVisitor._computeSetOrMapContextType]. |
| /// |
| /// Note that this is not the same as the context pushed down by type |
| /// inference (which can be obtained via [InferenceContext.getContext]). For |
| /// example, in the following code: |
| /// |
| /// var m = {}; |
| /// |
| /// The context pushed down by type inference is null, whereas the |
| /// `contextType` is `Map<dynamic, dynamic>`. |
| InterfaceType? contextType; |
| |
| /// Initialize a newly created set or map literal. The [constKeyword] can be |
| /// `null` if the literal is not a constant. The [typeArguments] can be `null` |
| /// if no type arguments were declared. The [elements] can be `null` if the |
| /// set is empty. |
| SetOrMapLiteralImpl(Token? constKeyword, TypeArgumentListImpl? typeArguments, |
| this.leftBracket, List<CollectionElement> elements, this.rightBracket) |
| : super(constKeyword, typeArguments) { |
| _elements._initialize(this, elements); |
| } |
| |
| @override |
| Token get beginToken { |
| if (constKeyword != null) { |
| return constKeyword!; |
| } |
| final typeArguments = this.typeArguments; |
| if (typeArguments != null) { |
| return typeArguments.beginToken; |
| } |
| return leftBracket; |
| } |
| |
| @override |
| // TODO(paulberry): add commas. |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(leftBracket) |
| ..addAll(elements) |
| ..add(rightBracket); |
| |
| @override |
| NodeListImpl<CollectionElement> get elements => _elements; |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| bool get isMap => _resolvedKind == _SetOrMapKind.map; |
| |
| @override |
| bool get isSet => _resolvedKind == _SetOrMapKind.set; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitSetOrMapLiteral(this); |
| |
| void becomeMap() { |
| assert(_resolvedKind == _SetOrMapKind.unresolved || |
| _resolvedKind == _SetOrMapKind.map); |
| _resolvedKind = _SetOrMapKind.map; |
| } |
| |
| void becomeSet() { |
| assert(_resolvedKind == _SetOrMapKind.unresolved || |
| _resolvedKind == _SetOrMapKind.set); |
| _resolvedKind = _SetOrMapKind.set; |
| } |
| |
| void becomeUnresolved() { |
| _resolvedKind = _SetOrMapKind.unresolved; |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _elements.accept(visitor); |
| } |
| } |
| |
| /// A combinator that restricts the names being imported to those in a given |
| /// list. |
| /// |
| /// showCombinator ::= |
| /// 'show' [SimpleIdentifier] (',' [SimpleIdentifier])* |
| class ShowCombinatorImpl extends CombinatorImpl implements ShowCombinator { |
| /// The list of names from the library that are made visible by this |
| /// combinator. |
| final NodeListImpl<SimpleIdentifier> _shownNames = NodeListImpl._(); |
| |
| /// Initialize a newly created import show combinator. |
| ShowCombinatorImpl(Token keyword, List<SimpleIdentifier> shownNames) |
| : super(keyword) { |
| _shownNames._initialize(this, shownNames); |
| } |
| |
| @override |
| // TODO(paulberry): add commas. |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(keyword) |
| ..addAll(_shownNames); |
| |
| @override |
| Token get endToken => _shownNames.endToken!; |
| |
| @override |
| NodeListImpl<SimpleIdentifier> get shownNames => _shownNames; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitShowCombinator(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _shownNames.accept(visitor); |
| } |
| } |
| |
| /// A simple formal parameter. |
| /// |
| /// simpleFormalParameter ::= |
| /// ('final' [TypeName] | 'var' | [TypeName])? [SimpleIdentifier] |
| class SimpleFormalParameterImpl extends NormalFormalParameterImpl |
| implements SimpleFormalParameter { |
| /// 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; |
| |
| @override |
| // TODO(brianwilkerson) This overrides a concrete implementation in which the |
| // element is assumed to be stored in the `identifier`, but there is no |
| // corresponding inherited setter. This seems inconsistent and error prone. |
| ParameterElement? declaredElement; |
| |
| /// Initialize a newly created formal parameter. Either or both of the |
| /// [comment] and [metadata] can be `null` if the parameter does not have the |
| /// corresponding attribute. The [keyword] can be `null` if a type was |
| /// specified. The [type] must be `null` if the keyword is 'var'. |
| SimpleFormalParameterImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| Token? covariantKeyword, |
| Token? requiredKeyword, |
| this.keyword, |
| this._type, |
| SimpleIdentifierImpl? identifier) |
| : super( |
| comment, metadata, covariantKeyword, requiredKeyword, identifier) { |
| _becomeParentOf(_type); |
| } |
| |
| @override |
| Token get beginToken { |
| final metadata = this.metadata; |
| if (metadata.isNotEmpty) { |
| return metadata.beginToken!; |
| } else if (requiredKeyword != null) { |
| return requiredKeyword!; |
| } else if (covariantKeyword != null) { |
| return covariantKeyword!; |
| } else if (keyword != null) { |
| return keyword!; |
| } else if (_type != null) { |
| return _type!.beginToken; |
| } |
| return identifier!.beginToken; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(keyword)..add(_type)..add(identifier); |
| |
| @override |
| Token get endToken => identifier?.endToken ?? type!.endToken; |
| |
| @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 |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitSimpleFormalParameter(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _type?.accept(visitor); |
| identifier?.accept(visitor); |
| } |
| } |
| |
| /// A simple identifier. |
| /// |
| /// simpleIdentifier ::= |
| /// initialCharacter internalCharacter* |
| /// |
| /// initialCharacter ::= '_' | '$' | letter |
| /// |
| /// internalCharacter ::= '_' | '$' | letter | digit |
| class SimpleIdentifierImpl extends IdentifierImpl implements SimpleIdentifier { |
| /// The token representing the identifier. |
| @override |
| Token token; |
| |
| /// The element associated with this identifier based on static type |
| /// information, or `null` if the AST structure has not been resolved or if |
| /// this identifier could not be resolved. |
| Element? _staticElement; |
| |
| @override |
| List<DartType>? tearOffTypeArgumentTypes; |
| |
| /// Initialize a newly created identifier. |
| SimpleIdentifierImpl(this.token); |
| |
| @override |
| Token get beginToken => token; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(token); |
| |
| @override |
| Token get endToken => token; |
| |
| @override |
| bool get isQualified { |
| final parent = this.parent!; |
| if (parent is PrefixedIdentifier) { |
| return identical(parent.identifier, this); |
| } else if (parent is PropertyAccess) { |
| return identical(parent.propertyName, this); |
| } else if (parent is ConstructorName) { |
| return identical(parent.name, this); |
| } else if (parent is MethodInvocation) { |
| MethodInvocation invocation = parent; |
| return identical(invocation.methodName, this) && |
| invocation.realTarget != null; |
| } |
| return false; |
| } |
| |
| @override |
| bool get isSynthetic => token.isSynthetic; |
| |
| @override |
| String get name => token.lexeme; |
| |
| @override |
| Precedence get precedence => Precedence.primary; |
| |
| /// This element is set when this identifier is used not as an expression, |
| /// but just to reference some element. |
| /// |
| /// Examples are the name of the type in a [TypeName], the name of the method |
| /// in a [MethodInvocation], the name of the constructor in a |
| /// [ConstructorName], the name of the property in a [PropertyAccess], the |
| /// prefix and the identifier in a [PrefixedIdentifier] (which then can be |
| /// used to read or write a value). |
| /// |
| /// In invalid code, for recovery, any element could be used, e.g. a |
| /// setter as a type name `set mySetter(_) {} mySetter topVar;`. We do this |
| /// to help the user to navigate to this element, and maybe change its name, |
| /// add a new declaration, etc. |
| /// |
| /// Return `null` if this identifier is used to either read or write a value, |
| /// or the AST structure has not been resolved, or if this identifier could |
| /// not be resolved. |
| /// |
| /// If either [readElement] or [writeElement] are not `null`, the |
| /// [referenceElement] is `null`, because the identifier is being used to |
| /// read or write a value. |
| /// |
| /// All three [readElement], [writeElement], and [referenceElement] can be |
| /// `null` when the AST structure has not been resolved, or this identifier |
| /// could not be resolved. |
| Element? get referenceElement => null; |
| |
| @override |
| Element? get staticElement => _staticElement; |
| |
| set staticElement(Element? element) { |
| _staticElement = element; |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitSimpleIdentifier(this); |
| |
| @override |
| bool inDeclarationContext() => false; |
| |
| @override |
| bool inGetterContext() { |
| // TODO(brianwilkerson) Convert this to a getter. |
| AstNode initialParent = this.parent!; |
| AstNode parent = initialParent; |
| AstNode target = this; |
| // skip prefix |
| if (initialParent is PrefixedIdentifier) { |
| if (identical(initialParent.prefix, this)) { |
| return true; |
| } |
| parent = initialParent.parent!; |
| target = initialParent; |
| } else if (initialParent is PropertyAccess) { |
| if (identical(initialParent.target, this)) { |
| return true; |
| } |
| parent = initialParent.parent!; |
| target = initialParent; |
| } |
| // skip label |
| if (parent is Label) { |
| return false; |
| } |
| // analyze usage |
| if (parent is AssignmentExpression) { |
| if (identical(parent.leftHandSide, target) && |
| parent.operator.type == TokenType.EQ) { |
| return false; |
| } |
| } |
| if (parent is ConstructorFieldInitializer && |
| identical(parent.fieldName, target)) { |
| return false; |
| } |
| if (parent is ForEachPartsWithIdentifier) { |
| if (identical(parent.identifier, target)) { |
| return false; |
| } |
| } |
| if (parent is FieldFormalParameter) { |
| if (identical(parent.identifier, target)) { |
| return false; |
| } |
| } |
| if (parent is VariableDeclaration) { |
| if (identical(parent.name, target)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @override |
| bool inSetterContext() { |
| // TODO(brianwilkerson) Convert this to a getter. |
| AstNode initialParent = this.parent!; |
| AstNode parent = initialParent; |
| AstNode target = this; |
| // skip prefix |
| if (initialParent is PrefixedIdentifier) { |
| // if this is the prefix, then return false |
| if (identical(initialParent.prefix, this)) { |
| return false; |
| } |
| parent = initialParent.parent!; |
| target = initialParent; |
| } else if (initialParent is PropertyAccess) { |
| if (identical(initialParent.target, this)) { |
| return false; |
| } |
| parent = initialParent.parent!; |
| target = initialParent; |
| } |
| // analyze usage |
| if (parent is PrefixExpression) { |
| return parent.operator.type.isIncrementOperator; |
| } else if (parent is PostfixExpression) { |
| return parent.operator.type.isIncrementOperator; |
| } else if (parent is AssignmentExpression) { |
| return identical(parent.leftHandSide, target); |
| } else if (parent is ForEachPartsWithIdentifier) { |
| return identical(parent.identifier, target); |
| } |
| return false; |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| /// A string literal expression that does not contain any interpolations. |
| /// |
| /// simpleStringLiteral ::= |
| /// rawStringLiteral |
| /// | basicStringLiteral |
| /// |
| /// rawStringLiteral ::= |
| /// 'r' basicStringLiteral |
| /// |
| /// simpleStringLiteral ::= |
| /// multiLineStringLiteral |
| /// | singleLineStringLiteral |
| /// |
| /// multiLineStringLiteral ::= |
| /// "'''" characters "'''" |
| /// | '"""' characters '"""' |
| /// |
| /// singleLineStringLiteral ::= |
| /// "'" characters "'" |
| /// | '"' characters '"' |
| class SimpleStringLiteralImpl extends SingleStringLiteralImpl |
| implements SimpleStringLiteral { |
| /// The token representing the literal. |
| @override |
| Token literal; |
| |
| /// The value of the literal. |
| String _value; |
| |
| /// Initialize a newly created simple string literal. |
| SimpleStringLiteralImpl(this.literal, this._value) { |
| _value = StringUtilities.intern(value); |
| } |
| |
| @override |
| Token get beginToken => literal; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(literal); |
| |
| @override |
| int get contentsEnd => offset + _helper.end; |
| |
| @override |
| int get contentsOffset => offset + _helper.start; |
| |
| @override |
| Token get endToken => literal; |
| |
| @override |
| bool get isMultiline => _helper.isMultiline; |
| |
| @override |
| bool get isRaw => _helper.isRaw; |
| |
| @override |
| bool get isSingleQuoted => _helper.isSingleQuoted; |
| |
| @override |
| bool get isSynthetic => literal.isSynthetic; |
| |
| @override |
| String get value => _value; |
| |
| set value(String string) { |
| _value = StringUtilities.intern(_value); |
| } |
| |
| StringLexemeHelper get _helper { |
| return StringLexemeHelper(literal.lexeme, true, true); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitSimpleStringLiteral(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| |
| @override |
| void _appendStringValue(StringBuffer buffer) { |
| buffer.write(value); |
| } |
| } |
| |
| /// A single string literal expression. |
| /// |
| /// singleStringLiteral ::= |
| /// [SimpleStringLiteral] |
| /// | [StringInterpolation] |
| abstract class SingleStringLiteralImpl extends StringLiteralImpl |
| implements SingleStringLiteral {} |
| |
| class SpreadElementImpl extends AstNodeImpl |
| implements CollectionElementImpl, SpreadElement { |
| @override |
| Token spreadOperator; |
| |
| ExpressionImpl _expression; |
| |
| SpreadElementImpl(this.spreadOperator, this._expression) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken => spreadOperator; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(spreadOperator)..add(_expression); |
| |
| @override |
| Token get endToken => _expression.endToken; |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| bool get isNullAware => |
| spreadOperator.type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) { |
| return visitor.visitSpreadElement(this); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// A node that represents a statement. |
| /// |
| /// statement ::= |
| /// [Block] |
| /// | [VariableDeclarationStatement] |
| /// | [ForStatement] |
| /// | [ForEachStatement] |
| /// | [WhileStatement] |
| /// | [DoStatement] |
| /// | [SwitchStatement] |
| /// | [IfStatement] |
| /// | [TryStatement] |
| /// | [BreakStatement] |
| /// | [ContinueStatement] |
| /// | [ReturnStatement] |
| /// | [ExpressionStatement] |
| /// | [FunctionDeclarationStatement] |
| abstract class StatementImpl extends AstNodeImpl implements Statement { |
| @override |
| StatementImpl get unlabeled => this; |
| } |
| |
| /// A string interpolation literal. |
| /// |
| /// stringInterpolation ::= |
| /// ''' [InterpolationElement]* ''' |
| /// | '"' [InterpolationElement]* '"' |
| class StringInterpolationImpl extends SingleStringLiteralImpl |
| implements StringInterpolation { |
| /// The elements that will be composed to produce the resulting string. |
| final NodeListImpl<InterpolationElement> _elements = NodeListImpl._(); |
| |
| /// Initialize a newly created string interpolation expression. |
| StringInterpolationImpl(List<InterpolationElement> elements) { |
| // TODO(scheglov) Replace asserts with appropriately typed parameters. |
| assert(elements.length > 2, 'Expected at last three elements.'); |
| assert( |
| elements.first is InterpolationStringImpl, |
| 'The first element must be a string.', |
| ); |
| assert( |
| elements[1] is InterpolationExpressionImpl, |
| 'The second element must be an expression.', |
| ); |
| assert( |
| elements.last is InterpolationStringImpl, |
| 'The last element must be a string.', |
| ); |
| _elements._initialize(this, elements); |
| } |
| |
| @override |
| Token get beginToken => _elements.beginToken!; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..addAll(_elements); |
| |
| @override |
| int get contentsEnd { |
| var element = _elements.last as InterpolationString; |
| return element.contentsEnd; |
| } |
| |
| @override |
| int get contentsOffset { |
| var element = _elements.first as InterpolationString; |
| return element.contentsOffset; |
| } |
| |
| /// Return the elements that will be composed to produce the resulting string. |
| @override |
| NodeListImpl<InterpolationElement> get elements => _elements; |
| |
| @override |
| Token get endToken => _elements.endToken!; |
| |
| @override |
| InterpolationStringImpl get firstString => |
| elements.first as InterpolationStringImpl; |
| |
| @override |
| bool get isMultiline => _firstHelper.isMultiline; |
| |
| @override |
| bool get isRaw => false; |
| |
| @override |
| bool get isSingleQuoted => _firstHelper.isSingleQuoted; |
| |
| @override |
| InterpolationStringImpl get lastString => |
| elements.last as InterpolationStringImpl; |
| |
| StringLexemeHelper get _firstHelper { |
| var lastString = _elements.first as InterpolationString; |
| String lexeme = lastString.contents.lexeme; |
| return StringLexemeHelper(lexeme, true, false); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitStringInterpolation(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _elements.accept(visitor); |
| } |
| |
| @override |
| void _appendStringValue(StringBuffer buffer) { |
| throw ArgumentError(); |
| } |
| } |
| |
| /// A helper for analyzing string lexemes. |
| class StringLexemeHelper { |
| final String lexeme; |
| final bool isFirst; |
| final bool isLast; |
| |
| bool isRaw = false; |
| bool isSingleQuoted = false; |
| bool isMultiline = false; |
| int start = 0; |
| int end = 0; |
| |
| StringLexemeHelper(this.lexeme, this.isFirst, this.isLast) { |
| if (isFirst) { |
| isRaw = lexeme.startsWith('r'); |
| if (isRaw) { |
| start++; |
| } |
| if (StringUtilities.startsWith3(lexeme, start, 0x27, 0x27, 0x27)) { |
| isSingleQuoted = true; |
| isMultiline = true; |
| start += 3; |
| start = _trimInitialWhitespace(start); |
| } else if (StringUtilities.startsWith3(lexeme, start, 0x22, 0x22, 0x22)) { |
| isSingleQuoted = false; |
| isMultiline = true; |
| start += 3; |
| start = _trimInitialWhitespace(start); |
| } else if (start < lexeme.length && lexeme.codeUnitAt(start) == 0x27) { |
| isSingleQuoted = true; |
| isMultiline = false; |
| start++; |
| } else if (start < lexeme.length && lexeme.codeUnitAt(start) == 0x22) { |
| isSingleQuoted = false; |
| isMultiline = false; |
| start++; |
| } |
| } |
| end = lexeme.length; |
| if (isLast) { |
| if (start + 3 <= end && |
| (StringUtilities.endsWith3(lexeme, 0x22, 0x22, 0x22) || |
| StringUtilities.endsWith3(lexeme, 0x27, 0x27, 0x27))) { |
| end -= 3; |
| } else if (start + 1 <= end && |
| (StringUtilities.endsWithChar(lexeme, 0x22) || |
| StringUtilities.endsWithChar(lexeme, 0x27))) { |
| end -= 1; |
| } |
| } |
| } |
| |
| /// Given the [lexeme] for a multi-line string whose content begins at the |
| /// given [start] index, return the index of the first character that is |
| /// included in the value of the string. According to the specification: |
| /// |
| /// If the first line of a multiline string consists solely of the whitespace |
| /// characters defined by the production WHITESPACE 20.1), possibly prefixed |
| /// by \, then that line is ignored, including the new line at its end. |
| int _trimInitialWhitespace(int start) { |
| int length = lexeme.length; |
| int index = start; |
| while (index < length) { |
| int currentChar = lexeme.codeUnitAt(index); |
| if (currentChar == 0x0D) { |
| if (index + 1 < length && lexeme.codeUnitAt(index + 1) == 0x0A) { |
| return index + 2; |
| } |
| return index + 1; |
| } else if (currentChar == 0x0A) { |
| return index + 1; |
| } else if (currentChar == 0x5C) { |
| if (index + 1 >= length) { |
| return start; |
| } |
| currentChar = lexeme.codeUnitAt(index + 1); |
| if (currentChar != 0x0D && |
| currentChar != 0x0A && |
| currentChar != 0x09 && |
| currentChar != 0x20) { |
| return start; |
| } |
| } else if (currentChar != 0x09 && currentChar != 0x20) { |
| return start; |
| } |
| index++; |
| } |
| return start; |
| } |
| } |
| |
| /// A string literal expression. |
| /// |
| /// stringLiteral ::= |
| /// [SimpleStringLiteral] |
| /// | [AdjacentStrings] |
| /// | [StringInterpolation] |
| abstract class StringLiteralImpl extends LiteralImpl implements StringLiteral { |
| @override |
| String? get stringValue { |
| StringBuffer buffer = StringBuffer(); |
| try { |
| _appendStringValue(buffer); |
| } on ArgumentError { |
| return null; |
| } |
| return buffer.toString(); |
| } |
| |
| /// Append the value of this string literal to the given [buffer]. Throw an |
| /// [ArgumentError] if the string is not a constant string without any |
| /// string interpolation. |
| void _appendStringValue(StringBuffer buffer); |
| } |
| |
| /// The invocation of a superclass' constructor from within a constructor's |
| /// initialization list. |
| /// |
| /// superInvocation ::= |
| /// 'super' ('.' [SimpleIdentifier])? [ArgumentList] |
| class SuperConstructorInvocationImpl extends ConstructorInitializerImpl |
| implements SuperConstructorInvocation { |
| /// The token for the 'super' keyword. |
| @override |
| Token superKeyword; |
| |
| /// The token for the period before the name of the constructor that is being |
| /// invoked, or `null` if the unnamed constructor is being invoked. |
| @override |
| Token? period; |
| |
| /// The name of the constructor that is being invoked, or `null` if the |
| /// unnamed constructor is being invoked. |
| SimpleIdentifierImpl? _constructorName; |
| |
| /// The list of arguments to the constructor. |
| ArgumentListImpl _argumentList; |
| |
| /// The element associated with the constructor based on static type |
| /// information, or `null` if the AST structure has not been resolved or if |
| /// the constructor could not be resolved. |
| @override |
| ConstructorElement? staticElement; |
| |
| /// Initialize a newly created super invocation to invoke the inherited |
| /// constructor with the given name with the given arguments. The [period] and |
| /// [constructorName] can be `null` if the constructor being invoked is the |
| /// unnamed constructor. |
| SuperConstructorInvocationImpl(this.superKeyword, this.period, |
| this._constructorName, this._argumentList) { |
| _becomeParentOf(_constructorName); |
| _becomeParentOf(_argumentList); |
| } |
| |
| @override |
| ArgumentListImpl get argumentList => _argumentList; |
| |
| set argumentList(ArgumentList argumentList) { |
| _argumentList = _becomeParentOf(argumentList as ArgumentListImpl); |
| } |
| |
| @override |
| Token get beginToken => superKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(superKeyword) |
| ..add(period) |
| ..add(_constructorName) |
| ..add(_argumentList); |
| |
| @override |
| SimpleIdentifierImpl? get constructorName => _constructorName; |
| |
| set constructorName(SimpleIdentifier? identifier) { |
| _constructorName = _becomeParentOf(identifier as SimpleIdentifierImpl?); |
| } |
| |
| @override |
| Token get endToken => _argumentList.endToken; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitSuperConstructorInvocation(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _constructorName?.accept(visitor); |
| _argumentList.accept(visitor); |
| } |
| } |
| |
| /// A super expression. |
| /// |
| /// superExpression ::= |
| /// 'super' |
| class SuperExpressionImpl extends ExpressionImpl implements SuperExpression { |
| /// The token representing the 'super' keyword. |
| @override |
| Token superKeyword; |
| |
| /// Initialize a newly created super expression. |
| SuperExpressionImpl(this.superKeyword); |
| |
| @override |
| Token get beginToken => superKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(superKeyword); |
| |
| @override |
| Token get endToken => superKeyword; |
| |
| @override |
| Precedence get precedence => Precedence.primary; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitSuperExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| /// A case in a switch statement. |
| /// |
| /// switchCase ::= |
| /// [SimpleIdentifier]* 'case' [Expression] ':' [Statement]* |
| class SwitchCaseImpl extends SwitchMemberImpl implements SwitchCase { |
| /// The expression controlling whether the statements will be executed. |
| ExpressionImpl _expression; |
| |
| /// Initialize a newly created switch case. The list of [labels] can be `null` |
| /// if there are no labels. |
| SwitchCaseImpl(List<Label> labels, Token keyword, this._expression, |
| Token colon, List<Statement> statements) |
| : super(labels, keyword, colon, statements) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..addAll(labels) |
| ..add(keyword) |
| ..add(_expression) |
| ..add(colon) |
| ..addAll(statements); |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchCase(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| labels.accept(visitor); |
| _expression.accept(visitor); |
| statements.accept(visitor); |
| } |
| } |
| |
| /// The default case in a switch statement. |
| /// |
| /// switchDefault ::= |
| /// [SimpleIdentifier]* 'default' ':' [Statement]* |
| class SwitchDefaultImpl extends SwitchMemberImpl implements SwitchDefault { |
| /// Initialize a newly created switch default. The list of [labels] can be |
| /// `null` if there are no labels. |
| SwitchDefaultImpl(List<Label> labels, Token keyword, Token colon, |
| List<Statement> statements) |
| : super(labels, keyword, colon, statements); |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..addAll(labels) |
| ..add(keyword) |
| ..add(colon) |
| ..addAll(statements); |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchDefault(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| labels.accept(visitor); |
| statements.accept(visitor); |
| } |
| } |
| |
| /// An element within a switch statement. |
| /// |
| /// switchMember ::= |
| /// switchCase |
| /// | switchDefault |
| abstract class SwitchMemberImpl extends AstNodeImpl implements SwitchMember { |
| /// The labels associated with the switch member. |
| final NodeListImpl<Label> _labels = NodeListImpl._(); |
| |
| /// The token representing the 'case' or 'default' keyword. |
| @override |
| Token keyword; |
| |
| /// The colon separating the keyword or the expression from the statements. |
| @override |
| Token colon; |
| |
| /// The statements that will be executed if this switch member is selected. |
| final NodeListImpl<Statement> _statements = NodeListImpl._(); |
| |
| /// Initialize a newly created switch member. The list of [labels] can be |
| /// `null` if there are no labels. |
| SwitchMemberImpl(List<Label> labels, this.keyword, this.colon, |
| List<Statement> statements) { |
| _labels._initialize(this, labels); |
| _statements._initialize(this, statements); |
| } |
| |
| @override |
| Token get beginToken { |
| if (_labels.isNotEmpty) { |
| return _labels.beginToken!; |
| } |
| return keyword; |
| } |
| |
| @override |
| Token get endToken { |
| if (_statements.isNotEmpty) { |
| return _statements.endToken!; |
| } |
| return colon; |
| } |
| |
| @override |
| NodeListImpl<Label> get labels => _labels; |
| |
| @override |
| NodeListImpl<Statement> get statements => _statements; |
| } |
| |
| /// A switch statement. |
| /// |
| /// switchStatement ::= |
| /// 'switch' '(' [Expression] ')' '{' [SwitchCase]* [SwitchDefault]? '}' |
| class SwitchStatementImpl extends StatementImpl implements SwitchStatement { |
| /// The token representing the 'switch' keyword. |
| @override |
| Token switchKeyword; |
| |
| /// The left parenthesis. |
| @override |
| Token leftParenthesis; |
| |
| /// The expression used to determine which of the switch members will be |
| /// selected. |
| ExpressionImpl _expression; |
| |
| /// The right parenthesis. |
| @override |
| Token rightParenthesis; |
| |
| /// The left curly bracket. |
| @override |
| Token leftBracket; |
| |
| /// The switch members that can be selected by the expression. |
| final NodeListImpl<SwitchMember> _members = NodeListImpl._(); |
| |
| /// The right curly bracket. |
| @override |
| Token rightBracket; |
| |
| /// Initialize a newly created switch statement. The list of [members] can be |
| /// `null` if there are no switch members. |
| SwitchStatementImpl( |
| this.switchKeyword, |
| this.leftParenthesis, |
| this._expression, |
| this.rightParenthesis, |
| this.leftBracket, |
| List<SwitchMember> members, |
| this.rightBracket) { |
| _becomeParentOf(_expression); |
| _members._initialize(this, members); |
| } |
| |
| @override |
| Token get beginToken => switchKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(switchKeyword) |
| ..add(leftParenthesis) |
| ..add(_expression) |
| ..add(rightParenthesis) |
| ..add(leftBracket) |
| ..addAll(_members) |
| ..add(rightBracket); |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| NodeListImpl<SwitchMember> get members => _members; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| _members.accept(visitor); |
| } |
| } |
| |
| /// A symbol literal expression. |
| /// |
| /// symbolLiteral ::= |
| /// '#' (operator | (identifier ('.' identifier)*)) |
| class SymbolLiteralImpl extends LiteralImpl implements SymbolLiteral { |
| /// The token introducing the literal. |
| @override |
| Token poundSign; |
| |
| /// The components of the literal. |
| @override |
| final List<Token> components; |
| |
| /// Initialize a newly created symbol literal. |
| SymbolLiteralImpl(this.poundSign, this.components); |
| |
| @override |
| Token get beginToken => poundSign; |
| |
| @override |
| // TODO(paulberry): add "." tokens. |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(poundSign) |
| ..addAll(components); |
| |
| @override |
| Token get endToken => components[components.length - 1]; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitSymbolLiteral(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| /// A this expression. |
| /// |
| /// thisExpression ::= |
| /// 'this' |
| class ThisExpressionImpl extends ExpressionImpl implements ThisExpression { |
| /// The token representing the 'this' keyword. |
| @override |
| Token thisKeyword; |
| |
| /// Initialize a newly created this expression. |
| ThisExpressionImpl(this.thisKeyword); |
| |
| @override |
| Token get beginToken => thisKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(thisKeyword); |
| |
| @override |
| Token get endToken => thisKeyword; |
| |
| @override |
| Precedence get precedence => Precedence.primary; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitThisExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| // There are no children to visit. |
| } |
| } |
| |
| /// A throw expression. |
| /// |
| /// throwExpression ::= |
| /// 'throw' [Expression] |
| class ThrowExpressionImpl extends ExpressionImpl implements ThrowExpression { |
| /// The token representing the 'throw' keyword. |
| @override |
| Token throwKeyword; |
| |
| /// The expression computing the exception to be thrown. |
| ExpressionImpl _expression; |
| |
| /// Initialize a newly created throw expression. |
| ThrowExpressionImpl(this.throwKeyword, this._expression) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken => throwKeyword; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(throwKeyword)..add(_expression); |
| |
| @override |
| Token get endToken { |
| return _expression.endToken; |
| } |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Precedence get precedence => Precedence.assignment; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitThrowExpression(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// The declaration of one or more top-level variables of the same type. |
| /// |
| /// topLevelVariableDeclaration ::= |
| /// ('final' | 'const') type? staticFinalDeclarationList ';' |
| /// | variableDeclaration ';' |
| class TopLevelVariableDeclarationImpl extends CompilationUnitMemberImpl |
| implements TopLevelVariableDeclaration { |
| /// The top-level variables being declared. |
| VariableDeclarationListImpl _variableList; |
| |
| @override |
| Token? externalKeyword; |
| |
| /// The semicolon terminating the declaration. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created top-level variable declaration. Either or both |
| /// of the [comment] and [metadata] can be `null` if the variable does not |
| /// have the corresponding attribute. |
| TopLevelVariableDeclarationImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.externalKeyword, |
| this._variableList, |
| this.semicolon) |
| : super(comment, metadata) { |
| _becomeParentOf(_variableList); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(_variableList)..add(semicolon); |
| |
| @override |
| Element? get declaredElement => null; |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => |
| externalKeyword ?? _variableList.beginToken; |
| |
| @override |
| VariableDeclarationListImpl get variables => _variableList; |
| |
| set variables(VariableDeclarationList variables) { |
| _variableList = _becomeParentOf(variables as VariableDeclarationListImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitTopLevelVariableDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _variableList.accept(visitor); |
| } |
| } |
| |
| /// A try statement. |
| /// |
| /// tryStatement ::= |
| /// 'try' [Block] ([CatchClause]+ finallyClause? | finallyClause) |
| /// |
| /// finallyClause ::= |
| /// 'finally' [Block] |
| class TryStatementImpl extends StatementImpl implements TryStatement { |
| /// The token representing the 'try' keyword. |
| @override |
| Token tryKeyword; |
| |
| /// The body of the statement. |
| BlockImpl _body; |
| |
| /// The catch clauses contained in the try statement. |
| final NodeListImpl<CatchClause> _catchClauses = NodeListImpl._(); |
| |
| /// The token representing the 'finally' keyword, or `null` if the statement |
| /// does not contain a finally clause. |
| @override |
| Token? finallyKeyword; |
| |
| /// The finally block contained in the try statement, or `null` if the |
| /// statement does not contain a finally clause. |
| BlockImpl? _finallyBlock; |
| |
| /// Initialize a newly created try statement. The list of [catchClauses] can |
| /// be`null` if there are no catch clauses. The [finallyKeyword] and |
| /// [finallyBlock] can be `null` if there is no finally clause. |
| TryStatementImpl(this.tryKeyword, this._body, List<CatchClause> catchClauses, |
| this.finallyKeyword, this._finallyBlock) { |
| _becomeParentOf(_body); |
| _catchClauses._initialize(this, catchClauses); |
| _becomeParentOf(_finallyBlock); |
| } |
| |
| @override |
| Token get beginToken => tryKeyword; |
| |
| @override |
| BlockImpl get body => _body; |
| |
| set body(Block block) { |
| _body = _becomeParentOf(block as BlockImpl); |
| } |
| |
| @override |
| NodeListImpl<CatchClause> get catchClauses => _catchClauses; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(tryKeyword) |
| ..add(_body) |
| ..addAll(_catchClauses) |
| ..add(finallyKeyword) |
| ..add(_finallyBlock); |
| |
| @override |
| Token get endToken { |
| if (_finallyBlock != null) { |
| return _finallyBlock!.endToken; |
| } else if (finallyKeyword != null) { |
| return finallyKeyword!; |
| } else if (_catchClauses.isNotEmpty) { |
| return _catchClauses.endToken!; |
| } |
| return _body.endToken; |
| } |
| |
| @override |
| Block? get finallyBlock => _finallyBlock; |
| |
| set finallyBlock(Block? block) { |
| _finallyBlock = _becomeParentOf(block as BlockImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitTryStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _body.accept(visitor); |
| _catchClauses.accept(visitor); |
| _finallyBlock?.accept(visitor); |
| } |
| } |
| |
| /// The declaration of a type alias. |
| /// |
| /// typeAlias ::= |
| /// 'typedef' typeAliasBody |
| /// |
| /// typeAliasBody ::= |
| /// classTypeAlias |
| /// | functionTypeAlias |
| abstract class TypeAliasImpl extends NamedCompilationUnitMemberImpl |
| implements TypeAlias { |
| /// The token representing the 'typedef' keyword. |
| @override |
| Token typedefKeyword; |
| |
| /// The semicolon terminating the declaration. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created type alias. Either or both of the [comment] and |
| /// [metadata] can be `null` if the declaration does not have the |
| /// corresponding attribute. |
| TypeAliasImpl(CommentImpl? comment, List<Annotation>? metadata, |
| this.typedefKeyword, SimpleIdentifierImpl name, this.semicolon) |
| : super(comment, metadata, name); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => typedefKeyword; |
| } |
| |
| /// A type annotation. |
| /// |
| /// type ::= |
| /// [NamedType] |
| /// | [GenericFunctionType] |
| abstract class TypeAnnotationImpl extends AstNodeImpl |
| implements TypeAnnotation {} |
| |
| /// A list of type arguments. |
| /// |
| /// typeArguments ::= |
| /// '<' typeName (',' typeName)* '>' |
| class TypeArgumentListImpl extends AstNodeImpl implements TypeArgumentList { |
| /// The left bracket. |
| @override |
| Token leftBracket; |
| |
| /// The type arguments associated with the type. |
| final NodeListImpl<TypeAnnotation> _arguments = NodeListImpl._(); |
| |
| /// The right bracket. |
| @override |
| Token rightBracket; |
| |
| /// Initialize a newly created list of type arguments. |
| TypeArgumentListImpl( |
| this.leftBracket, List<TypeAnnotation> arguments, this.rightBracket) { |
| _arguments._initialize(this, arguments); |
| } |
| |
| @override |
| NodeListImpl<TypeAnnotation> get arguments => _arguments; |
| |
| @override |
| Token get beginToken => leftBracket; |
| |
| @override |
| // TODO(paulberry): Add commas. |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(leftBracket) |
| ..addAll(_arguments) |
| ..add(rightBracket); |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeArgumentList(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _arguments.accept(visitor); |
| } |
| } |
| |
| /// A literal that has a type associated with it. |
| /// |
| /// typedLiteral ::= |
| /// [ListLiteral] |
| /// | [MapLiteral] |
| abstract class TypedLiteralImpl extends LiteralImpl implements TypedLiteral { |
| /// The token representing the 'const' keyword, or `null` if the literal is |
| /// not a constant. |
| @override |
| Token? constKeyword; |
| |
| /// The type argument associated with this literal, or `null` if no type |
| /// arguments were declared. |
| TypeArgumentListImpl? _typeArguments; |
| |
| /// Initialize a newly created typed literal. The [constKeyword] can be |
| /// `null` if the literal is not a constant. The [typeArguments] can be `null` |
| /// if no type arguments were declared. |
| TypedLiteralImpl(this.constKeyword, this._typeArguments) { |
| _becomeParentOf(_typeArguments); |
| } |
| |
| @override |
| bool get isConst { |
| return constKeyword != null || inConstantContext; |
| } |
| |
| @override |
| TypeArgumentListImpl? get typeArguments => _typeArguments; |
| |
| set typeArguments(TypeArgumentList? typeArguments) { |
| _typeArguments = _becomeParentOf(typeArguments as TypeArgumentListImpl?); |
| } |
| |
| ChildEntities get _childEntities => |
| ChildEntities()..add(constKeyword)..add(_typeArguments); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _typeArguments?.accept(visitor); |
| } |
| } |
| |
| /// An expression representing a type, e.g. the expression `int` in |
| /// `var x = int;`. |
| /// |
| /// 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. |
| /// |
| /// The `.staticType` getter returns the type of the expression (which will |
| /// always be the type `Type`). To see the type represented by the type literal |
| /// use `.typeName.type`. |
| class TypeLiteralImpl extends ExpressionImpl implements TypeLiteral { |
| TypeNameImpl _typeName; |
| |
| TypeLiteralImpl(this._typeName) { |
| _becomeParentOf(_typeName); |
| } |
| |
| @override |
| Token get beginToken => typeName.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities()..add(typeName); |
| |
| @override |
| Token get endToken => typeName.endToken; |
| |
| @override |
| Precedence get precedence => typeName.typeArguments == null |
| ? typeName.name.precedence |
| : Precedence.postfix; |
| |
| @override |
| TypeNameImpl get typeName => _typeName; |
| |
| set typeName(TypeNameImpl value) { |
| _typeName = _becomeParentOf(value); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeLiteral(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| typeName.accept(visitor); |
| } |
| } |
| |
| /// The name of a type, which can optionally include type arguments. |
| /// |
| /// typeName ::= |
| /// [Identifier] typeArguments? '?'? |
| class TypeNameImpl extends TypeAnnotationImpl implements TypeName { |
| /// The name of the type. |
| IdentifierImpl _name; |
| |
| /// The type arguments associated with the type, or `null` if there are no |
| /// type arguments. |
| TypeArgumentListImpl? _typeArguments; |
| |
| @override |
| Token? question; |
| |
| /// The type being named, or `null` if the AST structure has not been |
| /// resolved. |
| @override |
| DartType? type; |
| |
| /// Initialize a newly created type name. The [typeArguments] can be `null` if |
| /// there are no type arguments. |
| TypeNameImpl(this._name, this._typeArguments, {this.question}) { |
| _becomeParentOf(_name); |
| _becomeParentOf(_typeArguments); |
| } |
| |
| @override |
| Token get beginToken => _name.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_name)..add(_typeArguments)..add(question); |
| |
| @override |
| Token get endToken => question ?? _typeArguments?.endToken ?? _name.endToken; |
| |
| @override |
| bool get isDeferred { |
| Identifier identifier = name; |
| if (identifier is! PrefixedIdentifier) { |
| return false; |
| } |
| return identifier.isDeferred; |
| } |
| |
| @override |
| bool get isSynthetic => _name.isSynthetic && _typeArguments == null; |
| |
| @override |
| IdentifierImpl get name => _name; |
| |
| set name(Identifier identifier) { |
| _name = _becomeParentOf(identifier as IdentifierImpl); |
| } |
| |
| @override |
| TypeArgumentListImpl? get typeArguments => _typeArguments; |
| |
| set typeArguments(TypeArgumentList? typeArguments) { |
| _typeArguments = _becomeParentOf(typeArguments as TypeArgumentListImpl?); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeName(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _name.accept(visitor); |
| _typeArguments?.accept(visitor); |
| } |
| } |
| |
| /// A type parameter. |
| /// |
| /// typeParameter ::= |
| /// typeParameterVariance? [SimpleIdentifier] ('extends' [TypeName])? |
| /// |
| /// typeParameterVariance ::= 'out' | 'inout' | 'in' |
| class TypeParameterImpl extends DeclarationImpl implements TypeParameter { |
| /// The name of the type parameter. |
| SimpleIdentifierImpl _name; |
| |
| /// The token representing the variance modifier keyword, or `null` if |
| /// there is no explicit variance modifier, meaning legacy covariance. |
| Token? varianceKeyword; |
| |
| /// The token representing the 'extends' keyword, or `null` if there is no |
| /// explicit upper bound. |
| @override |
| Token? extendsKeyword; |
| |
| /// The name of the upper bound for legal arguments, or `null` if there is no |
| /// explicit upper bound. |
| TypeAnnotationImpl? _bound; |
| |
| /// Initialize a newly created type parameter. Either or both of the [comment] |
| /// and [metadata] can be `null` if the parameter does not have the |
| /// corresponding attribute. The [extendsKeyword] and [bound] can be `null` if |
| /// the parameter does not have an upper bound. |
| TypeParameterImpl(CommentImpl? comment, List<Annotation>? metadata, |
| this._name, this.extendsKeyword, this._bound) |
| : super(comment, metadata) { |
| _becomeParentOf(_name); |
| _becomeParentOf(_bound); |
| } |
| |
| @override |
| TypeAnnotationImpl? get bound => _bound; |
| |
| set bound(TypeAnnotation? type) { |
| _bound = _becomeParentOf(type as TypeAnnotationImpl?); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(_name)..add(extendsKeyword)..add(_bound); |
| |
| @override |
| TypeParameterElement? get declaredElement => |
| _name.staticElement as TypeParameterElement?; |
| |
| @override |
| Token get endToken { |
| if (_bound == null) { |
| return _name.endToken; |
| } |
| return _bound!.endToken; |
| } |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => _name.beginToken; |
| |
| @override |
| SimpleIdentifierImpl get name => _name; |
| |
| set name(SimpleIdentifier identifier) { |
| _name = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeParameter(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _name.accept(visitor); |
| _bound?.accept(visitor); |
| } |
| } |
| |
| /// Type parameters within a declaration. |
| /// |
| /// typeParameterList ::= |
| /// '<' [TypeParameter] (',' [TypeParameter])* '>' |
| class TypeParameterListImpl extends AstNodeImpl implements TypeParameterList { |
| /// The left angle bracket. |
| @override |
| final Token leftBracket; |
| |
| /// The type parameters in the list. |
| final NodeListImpl<TypeParameter> _typeParameters = NodeListImpl._(); |
| |
| /// The right angle bracket. |
| @override |
| final Token rightBracket; |
| |
| /// Initialize a newly created list of type parameters. |
| TypeParameterListImpl( |
| this.leftBracket, List<TypeParameter> typeParameters, this.rightBracket) { |
| _typeParameters._initialize(this, typeParameters); |
| } |
| |
| @override |
| Token get beginToken => leftBracket; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(leftBracket) |
| ..addAll(_typeParameters) |
| ..add(rightBracket); |
| |
| @override |
| Token get endToken => rightBracket; |
| |
| @override |
| NodeListImpl<TypeParameter> get typeParameters => _typeParameters; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeParameterList(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _typeParameters.accept(visitor); |
| } |
| } |
| |
| /// A directive that references a URI. |
| /// |
| /// uriBasedDirective ::= |
| /// [ExportDirective] |
| /// | [ImportDirective] |
| /// | [PartDirective] |
| abstract class UriBasedDirectiveImpl extends DirectiveImpl |
| implements UriBasedDirective { |
| /// The prefix of a URI using the `dart-ext` scheme to reference a native code |
| /// library. |
| static const String _DART_EXT_SCHEME = "dart-ext:"; |
| |
| /// The URI referenced by this directive. |
| StringLiteralImpl _uri; |
| |
| @override |
| String? uriContent; |
| |
| @override |
| Source? uriSource; |
| |
| /// Initialize a newly create URI-based directive. Either or both of the |
| /// [comment] and [metadata] can be `null` if the directive does not have the |
| /// corresponding attribute. |
| UriBasedDirectiveImpl( |
| CommentImpl? comment, List<Annotation>? metadata, this._uri) |
| : super(comment, metadata) { |
| _becomeParentOf(_uri); |
| } |
| |
| @override |
| StringLiteralImpl get uri => _uri; |
| |
| set uri(StringLiteral uri) { |
| _uri = _becomeParentOf(uri as StringLiteralImpl); |
| } |
| |
| UriValidationCode? validate() { |
| return validateUri(this is ImportDirective, uri, uriContent); |
| } |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _uri.accept(visitor); |
| } |
| |
| /// Validate this directive, but do not check for existence. Return a code |
| /// indicating the problem if there is one, or `null` no problem. |
| static UriValidationCode? validateUri( |
| bool isImport, StringLiteral uriLiteral, String? uriContent) { |
| if (uriLiteral is StringInterpolation) { |
| return UriValidationCode.URI_WITH_INTERPOLATION; |
| } |
| if (uriContent == null) { |
| return UriValidationCode.INVALID_URI; |
| } |
| if (uriContent.isEmpty) { |
| return null; |
| } |
| if (isImport && uriContent.startsWith(_DART_EXT_SCHEME)) { |
| return UriValidationCode.URI_WITH_DART_EXT_SCHEME; |
| } |
| Uri uri; |
| try { |
| uri = Uri.parse(Uri.encodeFull(uriContent)); |
| } on FormatException { |
| return UriValidationCode.INVALID_URI; |
| } |
| if (uri.path.isEmpty) { |
| return UriValidationCode.INVALID_URI; |
| } |
| return null; |
| } |
| } |
| |
| /// Validation codes returned by [UriBasedDirective.validate]. |
| class UriValidationCode { |
| static const UriValidationCode INVALID_URI = UriValidationCode('INVALID_URI'); |
| |
| static const UriValidationCode URI_WITH_INTERPOLATION = |
| UriValidationCode('URI_WITH_INTERPOLATION'); |
| |
| static const UriValidationCode URI_WITH_DART_EXT_SCHEME = |
| UriValidationCode('URI_WITH_DART_EXT_SCHEME'); |
| |
| /// The name of the validation code. |
| final String name; |
| |
| /// Initialize a newly created validation code to have the given [name]. |
| const UriValidationCode(this.name); |
| |
| @override |
| String toString() => name; |
| } |
| |
| /// An identifier that has an initial value associated with it. Instances of |
| /// this class are always children of the class [VariableDeclarationList]. |
| /// |
| /// variableDeclaration ::= |
| /// [SimpleIdentifier] ('=' [Expression])? |
| /// |
| /// TODO(paulberry): the grammar does not allow metadata to be associated with |
| /// a VariableDeclaration, and currently we don't record comments for it either. |
| /// Consider changing the class hierarchy so that [VariableDeclaration] does not |
| /// extend [Declaration]. |
| class VariableDeclarationImpl extends DeclarationImpl |
| implements VariableDeclaration { |
| /// The name of the variable being declared. |
| SimpleIdentifierImpl _name; |
| |
| /// The equal sign separating the variable name from the initial value, or |
| /// `null` if the initial value was not specified. |
| @override |
| Token? equals; |
| |
| /// The expression used to compute the initial value for the variable, or |
| /// `null` if the initial value was not specified. |
| ExpressionImpl? _initializer; |
| |
| /// When this node is read as a part of summaries, we usually don't want |
| /// to read the [initializer], but we need to know if there is one in |
| /// the code. So, this flag might be set to `true` even though |
| /// [initializer] is `null`. |
| bool hasInitializer = false; |
| |
| /// Initialize a newly created variable declaration. The [equals] and |
| /// [initializer] can be `null` if there is no initializer. |
| VariableDeclarationImpl(this._name, this.equals, this._initializer) |
| : super(null, null) { |
| _becomeParentOf(_name); |
| _becomeParentOf(_initializer); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| super._childEntities..add(_name)..add(equals)..add(_initializer); |
| |
| @override |
| VariableElement? get declaredElement => |
| _name.staticElement as VariableElement?; |
| |
| /// This overridden implementation of [documentationComment] looks in the |
| /// grandparent node for Dartdoc comments if no documentation is specifically |
| /// available on the node. |
| @override |
| CommentImpl? get documentationComment { |
| var comment = super.documentationComment; |
| if (comment == null) { |
| var node = parent?.parent; |
| if (node is AnnotatedNodeImpl) { |
| return node.documentationComment; |
| } |
| } |
| return comment; |
| } |
| |
| @override |
| Token get endToken { |
| if (_initializer != null) { |
| return _initializer!.endToken; |
| } |
| return _name.endToken; |
| } |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata => _name.beginToken; |
| |
| @override |
| ExpressionImpl? get initializer => _initializer; |
| |
| set initializer(Expression? expression) { |
| _initializer = _becomeParentOf(expression as ExpressionImpl?); |
| } |
| |
| @override |
| bool get isConst { |
| final parent = this.parent; |
| return parent is VariableDeclarationList && parent.isConst; |
| } |
| |
| @override |
| bool get isFinal { |
| final parent = this.parent; |
| return parent is VariableDeclarationList && parent.isFinal; |
| } |
| |
| @override |
| bool get isLate { |
| final parent = this.parent; |
| return parent is VariableDeclarationList && parent.isLate; |
| } |
| |
| @override |
| SimpleIdentifierImpl get name => _name; |
| |
| set name(SimpleIdentifier identifier) { |
| _name = _becomeParentOf(identifier as SimpleIdentifierImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitVariableDeclaration(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _name.accept(visitor); |
| _initializer?.accept(visitor); |
| } |
| } |
| |
| /// The declaration of one or more variables of the same type. |
| /// |
| /// variableDeclarationList ::= |
| /// finalConstVarOrType [VariableDeclaration] |
| /// (',' [VariableDeclaration])* |
| /// |
| /// finalConstVarOrType ::= |
| /// 'final' 'late'? [TypeAnnotation]? |
| /// | 'const' [TypeAnnotation]? |
| /// | 'var' |
| /// | 'late'? [TypeAnnotation] |
| class VariableDeclarationListImpl extends AnnotatedNodeImpl |
| implements VariableDeclarationList { |
| /// The token representing the 'final', 'const' or 'var' keyword, or `null` if |
| /// no keyword was included. |
| @override |
| Token? keyword; |
| |
| /// The token representing the 'late' keyword, or `null` if the late modifier |
| /// was not included. |
| @override |
| Token? lateKeyword; |
| |
| /// The type of the variables being declared, or `null` if no type was |
| /// provided. |
| TypeAnnotationImpl? _type; |
| |
| /// A list containing the individual variables being declared. |
| final NodeListImpl<VariableDeclaration> _variables = NodeListImpl._(); |
| |
| /// Initialize a newly created variable declaration list. Either or both of |
| /// the [comment] and [metadata] can be `null` if the variable list does not |
| /// have the corresponding attribute. The [keyword] can be `null` if a type |
| /// was specified. The [type] must be `null` if the keyword is 'var'. |
| VariableDeclarationListImpl( |
| CommentImpl? comment, |
| List<Annotation>? metadata, |
| this.lateKeyword, |
| this.keyword, |
| this._type, |
| List<VariableDeclaration> variables) |
| : super(comment, metadata) { |
| _becomeParentOf(_type); |
| _variables._initialize(this, variables); |
| } |
| |
| @override |
| // TODO(paulberry): include commas. |
| Iterable<SyntacticEntity> get childEntities => super._childEntities |
| ..add(keyword) |
| ..add(_type) |
| ..addAll(_variables); |
| |
| @override |
| Token get endToken => _variables.endToken!; |
| |
| @override |
| Token get firstTokenAfterCommentAndMetadata { |
| return Token.lexicallyFirst(lateKeyword, keyword) ?? |
| _type?.beginToken ?? |
| _variables.beginToken!; |
| } |
| |
| @override |
| bool get isConst => keyword?.keyword == Keyword.CONST; |
| |
| @override |
| bool get isFinal => keyword?.keyword == Keyword.FINAL; |
| |
| @override |
| bool get isLate => lateKeyword != null; |
| |
| @override |
| TypeAnnotationImpl? get type => _type; |
| |
| set type(TypeAnnotation? type) { |
| _type = _becomeParentOf(type as TypeAnnotationImpl?); |
| } |
| |
| @override |
| NodeListImpl<VariableDeclaration> get variables => _variables; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitVariableDeclarationList(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| super.visitChildren(visitor); |
| _type?.accept(visitor); |
| _variables.accept(visitor); |
| } |
| } |
| |
| /// A list of variables that are being declared in a context where a statement |
| /// is required. |
| /// |
| /// variableDeclarationStatement ::= |
| /// [VariableDeclarationList] ';' |
| class VariableDeclarationStatementImpl extends StatementImpl |
| implements VariableDeclarationStatement { |
| /// The variables being declared. |
| VariableDeclarationListImpl _variableList; |
| |
| /// The semicolon terminating the statement. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created variable declaration statement. |
| VariableDeclarationStatementImpl(this._variableList, this.semicolon) { |
| _becomeParentOf(_variableList); |
| } |
| |
| @override |
| Token get beginToken => _variableList.beginToken; |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => |
| ChildEntities()..add(_variableList)..add(semicolon); |
| |
| @override |
| Token get endToken => semicolon; |
| |
| @override |
| VariableDeclarationListImpl get variables => _variableList; |
| |
| set variables(VariableDeclarationList variables) { |
| _variableList = _becomeParentOf(variables as VariableDeclarationListImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => |
| visitor.visitVariableDeclarationStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _variableList.accept(visitor); |
| } |
| } |
| |
| /// A while statement. |
| /// |
| /// whileStatement ::= |
| /// 'while' '(' [Expression] ')' [Statement] |
| class WhileStatementImpl extends StatementImpl implements WhileStatement { |
| /// The token representing the 'while' keyword. |
| @override |
| Token whileKeyword; |
| |
| /// The left parenthesis. |
| @override |
| Token leftParenthesis; |
| |
| /// The expression used to determine whether to execute the body of the loop. |
| ExpressionImpl _condition; |
| |
| /// The right parenthesis. |
| @override |
| Token rightParenthesis; |
| |
| /// The body of the loop. |
| StatementImpl _body; |
| |
| /// Initialize a newly created while statement. |
| WhileStatementImpl(this.whileKeyword, this.leftParenthesis, this._condition, |
| this.rightParenthesis, this._body) { |
| _becomeParentOf(_condition); |
| _becomeParentOf(_body); |
| } |
| |
| @override |
| Token get beginToken => whileKeyword; |
| |
| @override |
| StatementImpl get body => _body; |
| |
| set body(Statement statement) { |
| _body = _becomeParentOf(statement as StatementImpl); |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(whileKeyword) |
| ..add(leftParenthesis) |
| ..add(_condition) |
| ..add(rightParenthesis) |
| ..add(_body); |
| |
| @override |
| ExpressionImpl get condition => _condition; |
| |
| set condition(Expression expression) { |
| _condition = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| Token get endToken => _body.endToken; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitWhileStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _condition.accept(visitor); |
| _body.accept(visitor); |
| } |
| } |
| |
| /// The with clause in a class declaration. |
| /// |
| /// withClause ::= |
| /// 'with' [TypeName] (',' [TypeName])* |
| class WithClauseImpl extends AstNodeImpl implements WithClause { |
| /// The token representing the 'with' keyword. |
| @override |
| Token withKeyword; |
| |
| /// The names of the mixins that were specified. |
| final NodeListImpl<TypeName> _mixinTypes = NodeListImpl._(); |
| |
| /// Initialize a newly created with clause. |
| WithClauseImpl(this.withKeyword, List<TypeName> mixinTypes) { |
| _mixinTypes._initialize(this, mixinTypes); |
| } |
| |
| @override |
| Token get beginToken => withKeyword; |
| |
| @override |
| // TODO(paulberry): add commas. |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(withKeyword) |
| ..addAll(_mixinTypes); |
| |
| @override |
| Token get endToken => _mixinTypes.endToken!; |
| |
| @override |
| NodeListImpl<TypeName> get mixinTypes => _mixinTypes; |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitWithClause(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _mixinTypes.accept(visitor); |
| } |
| } |
| |
| /// A yield statement. |
| /// |
| /// yieldStatement ::= |
| /// 'yield' '*'? [Expression] ‘;’ |
| class YieldStatementImpl extends StatementImpl implements YieldStatement { |
| /// The 'yield' keyword. |
| @override |
| Token yieldKeyword; |
| |
| /// The star optionally following the 'yield' keyword. |
| @override |
| Token? star; |
| |
| /// The expression whose value will be yielded. |
| ExpressionImpl _expression; |
| |
| /// The semicolon following the expression. |
| @override |
| Token semicolon; |
| |
| /// Initialize a newly created yield expression. The [star] can be `null` if |
| /// no star was provided. |
| YieldStatementImpl( |
| this.yieldKeyword, this.star, this._expression, this.semicolon) { |
| _becomeParentOf(_expression); |
| } |
| |
| @override |
| Token get beginToken { |
| return yieldKeyword; |
| } |
| |
| @override |
| Iterable<SyntacticEntity> get childEntities => ChildEntities() |
| ..add(yieldKeyword) |
| ..add(star) |
| ..add(_expression) |
| ..add(semicolon); |
| |
| @override |
| Token get endToken { |
| return semicolon; |
| } |
| |
| @override |
| ExpressionImpl get expression => _expression; |
| |
| set expression(Expression expression) { |
| _expression = _becomeParentOf(expression as ExpressionImpl); |
| } |
| |
| @override |
| E? accept<E>(AstVisitor<E> visitor) => visitor.visitYieldStatement(this); |
| |
| @override |
| void visitChildren(AstVisitor visitor) { |
| _expression.accept(visitor); |
| } |
| } |
| |
| /// An indication of the resolved kind of a [SetOrMapLiteral]. |
| enum _SetOrMapKind { |
| /// Indicates that the literal represents a map. |
| map, |
| |
| /// Indicates that the literal represents a set. |
| set, |
| |
| /// Indicates that either |
| /// - the literal is syntactically ambiguous and resolution has not yet been |
| /// performed, or |
| /// - the literal is invalid because resolution was not able to resolve the |
| /// ambiguity. |
| unresolved |
| } |