// 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:_fe_analyzer_shared/src/base/analyzer_public_api.dart';
import 'package:_fe_analyzer_shared/src/scanner/string_canonicalizer.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_analysis_result.dart';
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/doc_comment.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/element2.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/ast/to_source_visitor.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_schema.dart';
import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
import 'package:analyzer/src/fasta/token_utils.dart' as util show findPrevious;
import 'package:analyzer/src/generated/inference_log.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/utilities/extensions/object.dart';
import 'package:collection/collection.dart';
import 'package:meta/meta.dart';

/// Two or more string literals that are implicitly concatenated because of
/// being adjacent (separated only by whitespace).
///
/// For example
/// ```dart
/// 'Hello ' 'World'
/// ```
///
/// While the grammar only allows adjacent strings where all of the strings are
/// of the same kind (single line or multi-line), this class doesn't enforce
/// that restriction.
///
///    adjacentStrings ::=
///        [StringLiteral] [StringLiteral]+
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AdjacentStrings implements StringLiteral {
  /// The strings that are implicitly concatenated.
  NodeList<StringLiteral> get strings;
}

final class AdjacentStringsImpl extends StringLiteralImpl
    implements AdjacentStrings {
  final NodeListImpl<StringLiteralImpl> _strings = NodeListImpl._();

  /// Initializes a newly created list of adjacent strings.
  ///
  /// To be syntactically valid, the list of [strings] must contain at least two
  /// elements.
  AdjacentStringsImpl({required List<StringLiteralImpl> strings}) {
    _strings._initialize(this, strings);
  }

  @override
  Token get beginToken => _strings.beginToken!;

  @override
  Token get endToken => _strings.endToken!;

  @override
  NodeListImpl<StringLiteralImpl> get strings => _strings;

  @override
  ChildEntities get _childEntities {
    return ChildEntities()..addNodeList('strings', strings);
  }

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitAdjacentStrings(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitAdjacentStrings(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _strings.accept(visitor);
  }

  @override
  void _appendStringValue(StringBuffer buffer) {
    int length = strings.length;
    for (int i = 0; i < length; i++) {
      strings[i]._appendStringValue(buffer);
    }
  }
}

/// An AST node that can be annotated with either a documentation comment, a
/// list of annotations (metadata), or both.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AnnotatedNode implements AstNode {
  /// The documentation comment associated with this node, or `null` if this
  /// node doesn't have a documentation comment associated with it.
  Comment? get documentationComment;

  /// The first token following the comment and metadata.
  Token get firstTokenAfterCommentAndMetadata;

  /// The annotations associated with this node.
  ///
  /// If there are no annotations, then the returned list is empty.
  NodeList<Annotation> get metadata;

  /// A list containing the comment and annotations associated with this node,
  /// sorted in lexical order.
  ///
  /// If there are neither annotations nor a comment, then the returned list is
  /// empty.
  List<AstNode> get sortedCommentAndAnnotations;
}

sealed class AnnotatedNodeImpl extends AstNodeImpl with _AnnotatedNodeMixin {
  /// Initializes a newly created annotated node.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the node
  /// doesn't have the corresponding attribute.
  AnnotatedNodeImpl({
    required CommentImpl? comment,
    required List<AnnotationImpl>? metadata,
  }) {
    _initializeCommentAndAnnotations(comment, 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
  void visitChildren(AstVisitor visitor) {
    _visitCommentAndAnnotations(visitor);
  }
}

/// An annotation that can be associated with a declaration.
///
/// For example
/// ```dart
/// @override
/// ```
///
/// or
/// ```dart
/// @Deprecated('1.3.2')
/// ```
///
///    metadata ::=
///        annotation*
///
///    annotation ::=
///        '@' metadatum
///
///    metadatum ::=
///        [Identifier]
///      | qualifiedName
///      | constructorDesignation argumentPart
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Annotation implements AstNode {
  /// The arguments to the constructor being invoked, or `null` if this
  /// annotation isn't the invocation of a constructor.
  ArgumentList? get arguments;

  /// The at sign (`@`) that introduces the annotation.
  Token get atSign;

  /// The name of the constructor being invoked, or `null` if this annotation
  /// isn't the invocation of a named constructor.
  SimpleIdentifier? get constructorName;

  /// The element associated with this annotation.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if this
  /// annotation couldn't be resolved.
  @experimental
  Element2? get element2;

  /// The element annotation representing this annotation in the element model,
  /// or `null` if the AST hasn't been resolved.
  ElementAnnotation? get elementAnnotation;

  /// The name of either the class defining the constructor that is being
  /// invoked or the field that is being referenced.
  ///
  /// If a named constructor is being referenced, then the name of the
  /// constructor is available using [constructorName].
  Identifier get name;

  @override
  AstNode get parent;

  /// The period before the constructor name, or `null` if this annotation isn't
  /// the invocation of a named constructor.
  Token? get period;

  /// The type arguments to the constructor being invoked, or `null` if either
  /// this annotation isn't the invocation of a constructor or this annotation
  /// doesn't specify type arguments explicitly.
  ///
  /// Note that type arguments are only valid if [Feature.generic_metadata] is
  /// enabled.
  TypeArgumentList? get typeArguments;
}

final class AnnotationImpl extends AstNodeImpl implements Annotation {
  @override
  final Token atSign;

  IdentifierImpl _name;

  TypeArgumentListImpl? _typeArguments;

  @override
  final Token? period;

  SimpleIdentifierImpl? _constructorName;

  ArgumentListImpl? _arguments;

  Element2? _element2;

  @override
  ElementAnnotationImpl? elementAnnotation;

  /// Initializes a newly created annotation.
  ///
  /// Both the [period] and the [constructorName] can be `null` if the
  /// annotation isn't referencing a named constructor.
  ///
  /// The [arguments] can be `null` if the annotation isn't referencing a
  /// constructor.
  ///
  /// Note that type arguments are only valid if [Feature.generic_metadata] is
  /// enabled.
  AnnotationImpl({
    required this.atSign,
    required IdentifierImpl name,
    required TypeArgumentListImpl? typeArguments,
    required this.period,
    required SimpleIdentifierImpl? constructorName,
    required ArgumentListImpl? arguments,
  }) : _name = name,
       _typeArguments = typeArguments,
       _constructorName = constructorName,
       _arguments = arguments {
    _becomeParentOf(_name);
    _becomeParentOf(_typeArguments);
    _becomeParentOf(_constructorName);
    _becomeParentOf(_arguments);
  }

  @override
  ArgumentListImpl? get arguments => _arguments;

  set arguments(ArgumentListImpl? arguments) {
    _arguments = _becomeParentOf(arguments);
  }

  @override
  Token get beginToken => atSign;

  @override
  SimpleIdentifierImpl? get constructorName => _constructorName;

  set constructorName(SimpleIdentifierImpl? name) {
    _constructorName = _becomeParentOf(name);
  }

  @override
  Element2? get element2 {
    if (_element2 case var element?) {
      return element;
    } else if (_constructorName == null) {
      return _name.element;
    }
    return null;
  }

  set element2(Element2? value) {
    _element2 = value;
  }

  @override
  Token get endToken {
    if (arguments case var arguments?) {
      return arguments.endToken;
    } else if (constructorName case var constructorName?) {
      return constructorName.endToken;
    }
    return _name.endToken;
  }

  @override
  IdentifierImpl get name => _name;

  set name(IdentifierImpl name) {
    _name = _becomeParentOf(name)!;
  }

  @override
  AstNode get parent => super.parent!;

  @override
  TypeArgumentListImpl? get typeArguments => _typeArguments;

  set typeArguments(TypeArgumentListImpl? typeArguments) {
    _typeArguments = _becomeParentOf(typeArguments);
  }

  @override
  ChildEntities get _childEntities {
    return ChildEntities()
      ..addToken('atSign', atSign)
      ..addNode('name', name)
      ..addNode('typeArguments', typeArguments)
      ..addToken('period', period)
      ..addNode('constructorName', constructorName)
      ..addNode('arguments', arguments);
  }

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitAnnotation(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _name.accept(visitor);
    _typeArguments?.accept(visitor);
    _constructorName?.accept(visitor);
    _arguments?.accept(visitor);
  }
}

/// A list of arguments in the invocation of an executable element (that is, a
/// function, method, or constructor).
///
///    argumentList ::=
///        '(' arguments? ')'
///
///    arguments ::=
///        [NamedExpression] (',' [NamedExpression])*
///      | [Expression] (',' [Expression])* (',' [NamedExpression])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ArgumentList implements AstNode {
  /// The expressions producing the values of the arguments.
  ///
  /// If there are no arguments the list will be empty.
  ///
  /// Although the language requires that positional arguments appear before
  /// named arguments unless the [Feature.named_arguments_anywhere] is enabled,
  /// this class allows them to be intermixed.
  NodeList<Expression> get arguments;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;
}

final class ArgumentListImpl extends AstNodeImpl implements ArgumentList {
  @override
  final Token leftParenthesis;

  final NodeListImpl<ExpressionImpl> _arguments = NodeListImpl._();

  @override
  final Token rightParenthesis;

  /// A list containing the elements representing the parameters corresponding
  /// to each of the arguments in this list, or `null` if the AST hasn't been
  /// resolved or if the function or method being invoked couldn't 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 doesn't correspond to a formal
  /// parameter.
  List<FormalParameterElementMixin?>? _correspondingStaticParameters;

  /// Initializes a newly created list of arguments.
  ArgumentListImpl({
    required this.leftParenthesis,
    required List<ExpressionImpl> arguments,
    required this.rightParenthesis,
  }) {
    _arguments._initialize(this, arguments);
  }

  @override
  NodeListImpl<ExpressionImpl> get arguments => _arguments;

  @override
  Token get beginToken => leftParenthesis;

  List<FormalParameterElementMixin?>? get correspondingStaticParameters2 =>
      _correspondingStaticParameters;

  set correspondingStaticParameters2(
    List<FormalParameterElementMixin?>? parameters,
  ) {
    if (parameters != null && parameters.length != _arguments.length) {
      throw ArgumentError(
        "Expected ${_arguments.length} parameters, not ${parameters.length}",
      );
    }
    _correspondingStaticParameters = parameters;
  }

  @override
  Token get endToken => rightParenthesis;

  @override
  // TODO(paulberry): Add commas.
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNodeList('arguments', arguments)
        ..addToken('rightParenthesis', rightParenthesis);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitArgumentList(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _arguments.accept(visitor);
  }

  /// Returns the parameter element representing the parameter to which the
  /// value of the given expression is bound, or `null` if any of the following
  /// are not true
  /// - the given [expression] is a child of this list
  /// - the AST structure is resolved
  /// - the function being invoked is known based on static type information
  /// - the expression corresponds to one of the parameters of the function
  ///   being invoked
  FormalParameterElementMixin? _getStaticParameterElementFor(
    Expression expression,
  ) {
    if (_correspondingStaticParameters == null ||
        _correspondingStaticParameters!.length != _arguments.length) {
      // Either the AST structure hasn't been resolved, the invocation of which
      // this list is a part couldn't 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' [TypeAnnotation]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AsExpression implements Expression {
  /// The `as` operator.
  Token get asOperator;

  /// The expression used to compute the value being cast.
  Expression get expression;

  /// The type being cast to.
  TypeAnnotation get type;
}

final class AsExpressionImpl extends ExpressionImpl implements AsExpression {
  ExpressionImpl _expression;

  @override
  final Token asOperator;

  TypeAnnotationImpl _type;

  /// Initializes a newly created as expression.
  AsExpressionImpl({
    required ExpressionImpl expression,
    required this.asOperator,
    required TypeAnnotationImpl type,
  }) : _expression = expression,
       _type = type {
    _becomeParentOf(_expression);
    _becomeParentOf(_type);
  }

  @override
  Token get beginToken => _expression.beginToken;

  @override
  Token get endToken => _type.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.relational;

  @override
  TypeAnnotationImpl get type => _type;

  set type(TypeAnnotationImpl type) {
    _type = _becomeParentOf(type);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('expression', expression)
        ..addToken('asOperator', asOperator)
        ..addNode('type', type);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitAsExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitAsExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _expression.accept(visitor);
    _type.accept(visitor);
  }
}

/// An assert in the initializer list of a constructor.
///
///    assertInitializer ::=
///        'assert' '(' [Expression] (',' [Expression])? ')'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AssertInitializer
    implements Assertion, ConstructorInitializer {}

final class AssertInitializerImpl extends ConstructorInitializerImpl
    implements AssertInitializer {
  @override
  final Token assertKeyword;

  @override
  final Token leftParenthesis;

  ExpressionImpl _condition;

  @override
  final Token? comma;

  ExpressionImpl? _message;

  @override
  final Token rightParenthesis;

  /// Initializes a newly created assert initializer.
  AssertInitializerImpl({
    required this.assertKeyword,
    required this.leftParenthesis,
    required ExpressionImpl condition,
    required this.comma,
    required ExpressionImpl? message,
    required this.rightParenthesis,
  }) : _condition = condition,
       _message = message {
    _becomeParentOf(_condition);
    _becomeParentOf(_message);
  }

  @override
  Token get beginToken => assertKeyword;

  @override
  ExpressionImpl get condition => _condition;

  set condition(ExpressionImpl condition) {
    _condition = _becomeParentOf(condition);
  }

  @override
  Token get endToken => rightParenthesis;

  @override
  ExpressionImpl? get message => _message;

  set message(ExpressionImpl? expression) {
    _message = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('assertKeyword', assertKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('condition', condition)
        ..addToken('comma', comma)
        ..addNode('message', message)
        ..addToken('rightParenthesis', rightParenthesis);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitAssertInitializer(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _condition.accept(visitor);
    message?.accept(visitor);
  }
}

/// An assertion, either in a block or in the initializer list of a constructor.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Assertion implements AstNode {
  /// The token representing the `assert` keyword.
  Token get assertKeyword;

  /// The comma between the [condition] and the [message], or `null` if no
  /// message was supplied.
  Token? get comma;

  /// The condition that is being asserted to be `true`.
  Expression get condition;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The message to report if the assertion fails, or `null` if no message was
  /// supplied.
  Expression? get message;

  /// The right parenthesis.
  Token get rightParenthesis;
}

/// An assert statement.
///
///    assertStatement ::=
///        'assert' '(' [Expression] (',' [Expression])? ')' ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AssertStatement implements Assertion, Statement {
  /// The semicolon terminating the statement.
  Token get semicolon;
}

final class AssertStatementImpl extends StatementImpl
    implements AssertStatement {
  @override
  final Token assertKeyword;

  @override
  final Token leftParenthesis;

  ExpressionImpl _condition;

  @override
  final Token? comma;

  ExpressionImpl? _message;

  @override
  final Token rightParenthesis;

  @override
  final Token semicolon;

  /// Initializes a newly created assert statement.
  AssertStatementImpl({
    required this.assertKeyword,
    required this.leftParenthesis,
    required ExpressionImpl condition,
    required this.comma,
    required ExpressionImpl? message,
    required this.rightParenthesis,
    required this.semicolon,
  }) : _condition = condition,
       _message = message {
    _becomeParentOf(_condition);
    _becomeParentOf(_message);
  }

  @override
  Token get beginToken => assertKeyword;

  @override
  ExpressionImpl get condition => _condition;

  set condition(ExpressionImpl condition) {
    _condition = _becomeParentOf(condition);
  }

  @override
  Token get endToken => semicolon;

  @override
  ExpressionImpl? get message => _message;

  set message(ExpressionImpl? expression) {
    _message = _becomeParentOf(expression as ExpressionImpl);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('assertKeyword', assertKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('condition', condition)
        ..addToken('comma', comma)
        ..addNode('message', message)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitAssertStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _condition.accept(visitor);
    message?.accept(visitor);
  }
}

/// A variable pattern in [PatternAssignment].
///
///    variablePattern ::= identifier
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AssignedVariablePattern implements VariablePattern {
  /// The element referenced by this pattern.
  ///
  /// Returns `null` if either [name] doesn't resolve to an element or the AST
  /// structure hasn't been resolved.
  ///
  /// In valid code this is either a [LocalVariableElement2] or a
  /// [FormalParameterElement].
  @experimental
  Element2? get element2;
}

final class AssignedVariablePatternImpl extends VariablePatternImpl
    implements AssignedVariablePattern {
  @override
  Element2? element2;

  AssignedVariablePatternImpl({required super.name});

  @override
  Token get beginToken => name;

  @override
  Token get endToken => name;

  @override
  PatternPrecedence get precedence => PatternPrecedence.primary;

  @override
  ChildEntities get _childEntities => ChildEntities()..addToken('name', name);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitAssignedVariablePattern(this);
  }

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    var element = element2;
    if (element is PromotableElementImpl2) {
      return resolverVisitor
          .analyzeAssignedVariablePatternSchema(element)
          .unwrapTypeSchemaView();
    }
    return resolverVisitor.operations.unknownType.unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    return resolverVisitor.resolveAssignedVariablePattern(
      node: this,
      context: context,
    );
  }

  @override
  void visitChildren(AstVisitor visitor) {}
}

/// An assignment expression.
///
///    assignmentExpression ::=
///        [Expression] operator [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AssignmentExpression
    implements
        NullShortableExpression,
        MethodReferenceExpression,
        CompoundAssignmentExpression {
  /// The expression used to compute the left hand side.
  Expression get leftHandSide;

  /// The assignment operator being applied.
  Token get operator;

  /// The expression used to compute the right-hand side.
  Expression get rightHandSide;
}

final class AssignmentExpressionImpl extends ExpressionImpl
    with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl
    implements AssignmentExpression {
  ExpressionImpl _leftHandSide;

  @override
  final Token operator;

  ExpressionImpl _rightHandSide;

  @override
  MethodElement2OrMember? element;

  /// Initializes a newly created assignment expression.
  AssignmentExpressionImpl({
    required ExpressionImpl leftHandSide,
    required this.operator,
    required ExpressionImpl rightHandSide,
  }) : _leftHandSide = leftHandSide,
       _rightHandSide = rightHandSide {
    _becomeParentOf(_leftHandSide);
    _becomeParentOf(_rightHandSide);
  }

  @override
  Token get beginToken => _leftHandSide.beginToken;

  @override
  Token get endToken => _rightHandSide.endToken;

  @override
  ExpressionImpl get leftHandSide => _leftHandSide;

  set leftHandSide(ExpressionImpl expression) {
    _leftHandSide = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.assignment;

  @override
  ExpressionImpl get rightHandSide => _rightHandSide;

  set rightHandSide(ExpressionImpl expression) {
    _rightHandSide = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('leftHandSide', leftHandSide)
        ..addToken('operator', operator)
        ..addNode('rightHandSide', rightHandSide);

  @override
  AstNode? get _nullShortingExtensionCandidate => parent;

  /// The parameter element representing the parameter to which the value of the
  /// right operand is bound, or `null` if the AST structure is not resolved or
  /// the function being invoked is not known based on static type information.
  FormalParameterElementMixin? get _staticParameterElementForRightHandSide {
    Element2? executableElement;
    if (operator.type != TokenType.EQ) {
      executableElement = element;
    } else {
      executableElement = writeElement2;
    }

    if (executableElement is ExecutableElement2) {
      var formalParameters = executableElement.formalParameters;
      if (formalParameters.isEmpty) {
        return null;
      }
      if (operator.type == TokenType.EQ && leftHandSide is IndexExpression) {
        return formalParameters.length == 2
            ? (formalParameters[1] as FormalParameterElementMixin)
            : null;
      }
      return formalParameters[0] as FormalParameterElementMixin;
    }

    return null;
  }

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitAssignmentExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitAssignmentExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _leftHandSide.accept(visitor);
    _rightHandSide.accept(visitor);
  }

  @override
  bool _extendsNullShorting(Expression descendant) =>
      identical(descendant, _leftHandSide);
}

/// A node in the AST structure for a Dart program.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AstNode implements SyntacticEntity {
  /// A comparator that can be used to sort AST nodes in lexical order.
  ///
  /// In other words, `compare` returns a negative value if the offset of the
  /// first node is less than the offset of the second node, zero (0) if the
  /// nodes have the same offset, and a positive value if the offset of the
  /// first node is greater than the offset of the second node.
  static Comparator<AstNode> LEXICAL_ORDER =
      (AstNode first, AstNode second) => first.offset - second.offset;

  /// The first token included in this node's source range.
  Token get beginToken;

  /// An iterator that can be used to iterate through all the entities (either
  /// AST nodes or tokens) that make up the contents of this node, including doc
  /// comments but excluding other comments.
  Iterable<SyntacticEntity> get childEntities;

  /// The offset of the character immediately following the last character of
  /// this node's source range.
  ///
  /// This is equivalent to `node.offset + node.length`. For a compilation unit
  /// this is equal to the length of the unit's source. For synthetic nodes this
  /// is equivalent to the node's offset (because the length is zero (`0`) by
  /// definition).
  @override
  int get end;

  /// The last token included in this node's source range.
  Token get endToken;

  /// Whether this node is a synthetic node.
  ///
  /// A synthetic node is a node that was introduced by the parser in order to
  /// recover from an error in the code. Synthetic nodes always have a length
  /// of zero (`0`).
  bool get isSynthetic;

  @override
  int get length;

  @override
  int get offset;

  /// Returns this node's parent node, or `null` if this node is the root of an
  /// AST structure.
  ///
  /// Note that the relationship between an AST node and its parent node may
  /// change over the lifetime of a node.
  AstNode? get parent;

  /// The node at the root of this node's AST structure.
  ///
  /// Note that this method's performance is linear with respect to the depth
  /// of the node in the AST structure (O(depth)).
  AstNode get root;

  /// Use the given [visitor] to visit this node.
  ///
  /// Returns the value returned by the visitor as a result of visiting this
  /// node.
  E? accept<E>(AstVisitor<E> visitor);

  /// Returns the token before [target], or `null` if it can't be found.
  Token? findPrevious(Token target);

  /// Returns either this node or the most immediate ancestor of this node for
  /// which the [predicate] returns `true`, or `null` if there's no such node.
  E? thisOrAncestorMatching<E extends AstNode>(
    bool Function(AstNode) predicate,
  );

  /// Returns either this node or the most immediate ancestor of this node that
  /// has the given type, or `null` if there's no such node.
  E? thisOrAncestorOfType<E extends AstNode>();

  /// Returns a textual description of this node in a form approximating valid
  /// source.
  ///
  /// The returned string isn't valid source code primarily in the case where
  /// the node itself isn't well-formed.
  ///
  /// Clients should never depend on the returned value being valid code, nor
  /// being consistent from one version of the package to the next. As a result,
  /// clients should never display the returned string to users.
  String toSource();

  /// Returns a textual description of this node.
  ///
  /// The returned string is intended to be useful only for debugging.
  ///
  /// Clients should never depend on the returned value being useful for any
  /// purpose, nor being consistent from one version of the package to the next.
  /// As a result, clients should never display the returned string to users.
  @override
  String toString();

  /// Use the given [visitor] to visit all of the children of this node.
  ///
  /// The children are visited in lexical order.
  void visitChildren(AstVisitor visitor);
}

sealed class AstNodeImpl implements AstNode {
  AstNode? _parent;

  @override
  Iterable<SyntacticEntity> get childEntities =>
      _childEntities.syntacticEntities;

  @override
  int get end => offset + length;

  @override
  bool get isSynthetic => false;

  @override
  int get length {
    var beginToken = this.beginToken;
    var endToken = this.endToken;
    return endToken.offset + endToken.length - beginToken.offset;
  }

  /// The properties (tokens and nodes) of this node, with names, in the order
  /// in which these entities should normally appear, not necessarily in the
  /// order they really are (because of recovery).
  Iterable<ChildEntity> get namedChildEntities => _childEntities.entities;

  @override
  int get offset {
    var beginToken = this.beginToken;
    return beginToken.offset;
  }

  @override
  AstNode? get parent => _parent;

  @override
  AstNode get root {
    AstNode root = this;
    var rootParent = parent;
    while (rootParent != null) {
      root = rootParent;
      rootParent = root.parent;
    }
    return root;
  }

  ChildEntities get _childEntities => ChildEntities();

  void detachFromParent() {
    _parent = null;
  }

  @override
  Token? findPrevious(Token target) =>
      util.findPrevious(beginToken, target) ?? parent?.findPrevious(target);

  @override
  E? thisOrAncestorMatching<E extends AstNode>(
    bool Function(AstNode) predicate,
  ) {
    AstNode? node = this;
    while (node != null && !predicate(node)) {
      node = node.parent;
    }
    return node as E?;
  }

  @override
  E? thisOrAncestorOfType<E extends AstNode>() {
    AstNode? node = this;
    while (node != null && node is! E) {
      node = node.parent;
    }
    return node as E?;
  }

  @override
  String toSource() {
    StringBuffer buffer = StringBuffer();
    accept(ToSourceVisitor(buffer));
    return buffer.toString();
  }

  @override
  String toString() => toSource();

  /// Returns the [child] node after making this node the parent of the [child]
  /// node.
  T _becomeParentOf<T extends AstNodeImpl?>(T child) {
    child?._parent = this;
    return child;
  }
}

/// Mixin for any [AstNodeImpl] that can potentially introduce a new scope.
base mixin AstNodeWithNameScopeMixin on AstNodeImpl {
  /// The [Scope] that was used while resolving `this`, or `null` if resolution
  /// has not been performed yet.
  Scope? nameScope;
}

/// An object that can be used to visit an AST structure.
///
/// Clients may not extend, implement or mix-in this class. There are classes
/// that implement this interface that provide useful default behaviors in
/// `package:analyzer/dart/ast/visitor.dart`. A couple of the most useful
/// include
/// - SimpleAstVisitor which implements every visit method by doing nothing,
/// - RecursiveAstVisitor which causes every node in a structure to be visited,
///   and
/// - ThrowingAstVisitor which implements every visit method by throwing an
///   exception.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract class AstVisitor<R> {
  R? visitAdjacentStrings(AdjacentStrings node);

  R? visitAnnotation(Annotation node);

  R? visitArgumentList(ArgumentList node);

  R? visitAsExpression(AsExpression node);

  R? visitAssertInitializer(AssertInitializer node);

  R? visitAssertStatement(AssertStatement assertStatement);

  R? visitAssignedVariablePattern(AssignedVariablePattern node);

  R? visitAssignmentExpression(AssignmentExpression node);

  R? visitAugmentedExpression(AugmentedExpression node);

  R? visitAugmentedInvocation(AugmentedInvocation node);

  R? visitAwaitExpression(AwaitExpression node);

  R? visitBinaryExpression(BinaryExpression node);

  R? visitBlock(Block node);

  R? visitBlockFunctionBody(BlockFunctionBody node);

  R? visitBooleanLiteral(BooleanLiteral node);

  R? visitBreakStatement(BreakStatement node);

  R? visitCascadeExpression(CascadeExpression node);

  R? visitCaseClause(CaseClause node);

  R? visitCastPattern(CastPattern node);

  R? visitCatchClause(CatchClause node);

  R? visitCatchClauseParameter(CatchClauseParameter node);

  R? visitClassDeclaration(ClassDeclaration node);

  R? visitClassTypeAlias(ClassTypeAlias node);

  R? visitComment(Comment node);

  R? visitCommentReference(CommentReference node);

  R? visitCompilationUnit(CompilationUnit node);

  R? visitConditionalExpression(ConditionalExpression node);

  R? visitConfiguration(Configuration node);

  R? visitConstantPattern(ConstantPattern node);

  R? visitConstructorDeclaration(ConstructorDeclaration node);

  R? visitConstructorFieldInitializer(ConstructorFieldInitializer node);

  R? visitConstructorName(ConstructorName node);

  R? visitConstructorReference(ConstructorReference node);

  R? visitConstructorSelector(ConstructorSelector node);

  R? visitContinueStatement(ContinueStatement node);

  R? visitDeclaredIdentifier(DeclaredIdentifier node);

  R? visitDeclaredVariablePattern(DeclaredVariablePattern node);

  R? visitDefaultFormalParameter(DefaultFormalParameter node);

  R? visitDoStatement(DoStatement node);

  R? visitDotShorthandConstructorInvocation(
    DotShorthandConstructorInvocation node,
  );

  R? visitDotShorthandInvocation(DotShorthandInvocation node);

  R? visitDotShorthandPropertyAccess(DotShorthandPropertyAccess node);

  R? visitDottedName(DottedName node);

  R? visitDoubleLiteral(DoubleLiteral node);

  R? visitEmptyFunctionBody(EmptyFunctionBody node);

  R? visitEmptyStatement(EmptyStatement node);

  R? visitEnumConstantArguments(EnumConstantArguments node);

  R? visitEnumConstantDeclaration(EnumConstantDeclaration node);

  R? visitEnumDeclaration(EnumDeclaration node);

  R? visitExportDirective(ExportDirective node);

  R? visitExpressionFunctionBody(ExpressionFunctionBody node);

  R? visitExpressionStatement(ExpressionStatement node);

  R? visitExtendsClause(ExtendsClause node);

  R? visitExtensionDeclaration(ExtensionDeclaration node);

  R? visitExtensionOnClause(ExtensionOnClause node);

  R? visitExtensionOverride(ExtensionOverride node);

  R? visitExtensionTypeDeclaration(ExtensionTypeDeclaration node);

  R? visitFieldDeclaration(FieldDeclaration node);

  R? visitFieldFormalParameter(FieldFormalParameter node);

  R? visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node);

  R? visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node);

  R? visitForEachPartsWithPattern(ForEachPartsWithPattern node);

  R? visitForElement(ForElement node);

  R? visitFormalParameterList(FormalParameterList node);

  R? visitForPartsWithDeclarations(ForPartsWithDeclarations node);

  R? visitForPartsWithExpression(ForPartsWithExpression node);

  R? visitForPartsWithPattern(ForPartsWithPattern node);

  R? visitForStatement(ForStatement node);

  R? visitFunctionDeclaration(FunctionDeclaration node);

  R? visitFunctionDeclarationStatement(FunctionDeclarationStatement node);

  R? visitFunctionExpression(FunctionExpression node);

  R? visitFunctionExpressionInvocation(FunctionExpressionInvocation node);

  R? visitFunctionReference(FunctionReference node);

  R? visitFunctionTypeAlias(FunctionTypeAlias functionTypeAlias);

  R? visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node);

  R? visitGenericFunctionType(GenericFunctionType node);

  R? visitGenericTypeAlias(GenericTypeAlias node);

  R? visitGuardedPattern(GuardedPattern node);

  R? visitHideCombinator(HideCombinator node);

  R? visitIfElement(IfElement node);

  R? visitIfStatement(IfStatement node);

  R? visitImplementsClause(ImplementsClause node);

  R? visitImplicitCallReference(ImplicitCallReference node);

  R? visitImportDirective(ImportDirective node);

  R? visitImportPrefixReference(ImportPrefixReference node);

  R? visitIndexExpression(IndexExpression node);

  R? visitInstanceCreationExpression(InstanceCreationExpression node);

  R? visitIntegerLiteral(IntegerLiteral node);

  R? visitInterpolationExpression(InterpolationExpression node);

  R? visitInterpolationString(InterpolationString node);

  R? visitIsExpression(IsExpression node);

  R? visitLabel(Label node);

  R? visitLabeledStatement(LabeledStatement node);

  R? visitLibraryDirective(LibraryDirective node);

  R? visitLibraryIdentifier(LibraryIdentifier node);

  R? visitListLiteral(ListLiteral node);

  R? visitListPattern(ListPattern node);

  R? visitLogicalAndPattern(LogicalAndPattern node);

  R? visitLogicalOrPattern(LogicalOrPattern node);

  R? visitMapLiteralEntry(MapLiteralEntry node);

  R? visitMapPattern(MapPattern node);

  R? visitMapPatternEntry(MapPatternEntry node);

  R? visitMethodDeclaration(MethodDeclaration node);

  R? visitMethodInvocation(MethodInvocation node);

  R? visitMixinDeclaration(MixinDeclaration node);

  R? visitMixinOnClause(MixinOnClause node);

  R? visitNamedExpression(NamedExpression node);

  R? visitNamedType(NamedType node);

  R? visitNativeClause(NativeClause node);

  R? visitNativeFunctionBody(NativeFunctionBody node);

  R? visitNullAssertPattern(NullAssertPattern node);

  R? visitNullAwareElement(NullAwareElement node);

  R? visitNullCheckPattern(NullCheckPattern node);

  R? visitNullLiteral(NullLiteral node);

  R? visitObjectPattern(ObjectPattern node);

  R? visitParenthesizedExpression(ParenthesizedExpression node);

  R? visitParenthesizedPattern(ParenthesizedPattern node);

  R? visitPartDirective(PartDirective node);

  R? visitPartOfDirective(PartOfDirective node);

  R? visitPatternAssignment(PatternAssignment node);

  R? visitPatternField(PatternField node);

  R? visitPatternFieldName(PatternFieldName node);

  R? visitPatternVariableDeclaration(PatternVariableDeclaration node);

  R? visitPatternVariableDeclarationStatement(
    PatternVariableDeclarationStatement node,
  );

  R? visitPostfixExpression(PostfixExpression node);

  R? visitPrefixedIdentifier(PrefixedIdentifier node);

  R? visitPrefixExpression(PrefixExpression node);

  R? visitPropertyAccess(PropertyAccess node);

  R? visitRecordLiteral(RecordLiteral node);

  R? visitRecordPattern(RecordPattern node);

  R? visitRecordTypeAnnotation(RecordTypeAnnotation node);

  R? visitRecordTypeAnnotationNamedField(RecordTypeAnnotationNamedField node);

  R? visitRecordTypeAnnotationNamedFields(RecordTypeAnnotationNamedFields node);

  R? visitRecordTypeAnnotationPositionalField(
    RecordTypeAnnotationPositionalField node,
  );

  R? visitRedirectingConstructorInvocation(
    RedirectingConstructorInvocation node,
  );

  R? visitRelationalPattern(RelationalPattern node);

  R? visitRepresentationConstructorName(RepresentationConstructorName node);

  R? visitRepresentationDeclaration(RepresentationDeclaration node);

  R? visitRestPatternElement(RestPatternElement node);

  R? visitRethrowExpression(RethrowExpression node);

  R? visitReturnStatement(ReturnStatement node);

  R? visitScriptTag(ScriptTag node);

  R? visitSetOrMapLiteral(SetOrMapLiteral node);

  R? visitShowCombinator(ShowCombinator node);

  R? visitSimpleFormalParameter(SimpleFormalParameter node);

  R? visitSimpleIdentifier(SimpleIdentifier node);

  R? visitSimpleStringLiteral(SimpleStringLiteral node);

  R? visitSpreadElement(SpreadElement node);

  R? visitStringInterpolation(StringInterpolation node);

  R? visitSuperConstructorInvocation(SuperConstructorInvocation node);

  R? visitSuperExpression(SuperExpression node);

  R? visitSuperFormalParameter(SuperFormalParameter node);

  R? visitSwitchCase(SwitchCase node);

  R? visitSwitchDefault(SwitchDefault node);

  R? visitSwitchExpression(SwitchExpression node);

  R? visitSwitchExpressionCase(SwitchExpressionCase node);

  R? visitSwitchPatternCase(SwitchPatternCase node);

  R? visitSwitchStatement(SwitchStatement node);

  R? visitSymbolLiteral(SymbolLiteral node);

  R? visitThisExpression(ThisExpression node);

  R? visitThrowExpression(ThrowExpression node);

  R? visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node);

  R? visitTryStatement(TryStatement node);

  R? visitTypeArgumentList(TypeArgumentList node);

  R? visitTypeLiteral(TypeLiteral node);

  R? visitTypeParameter(TypeParameter node);

  R? visitTypeParameterList(TypeParameterList node);

  R? visitVariableDeclaration(VariableDeclaration node);

  R? visitVariableDeclarationList(VariableDeclarationList node);

  R? visitVariableDeclarationStatement(VariableDeclarationStatement node);

  R? visitWhenClause(WhenClause node);

  R? visitWhileStatement(WhileStatement node);

  R? visitWildcardPattern(WildcardPattern node);

  R? visitWithClause(WithClause node);

  R? visitYieldStatement(YieldStatement node);
}

/// The augmented expression.
///
/// It is created only inside an augmentation.
/// The exact meaning depends on what is augmented, and where it is used.
///
/// Augmenting getters: `augmented` invokes the getter and evaluates to the
/// return value.
/// The [fragment] is the augmented getter.
/// The [staticType] is the return type of the getter.
///
/// Augmenting setters: `augmented` must be followed by an `=`, and will
/// directly invoke the augmented setter.
/// The [fragment] is the augmented setter.
/// The [staticType] is meaningless, and set to `null`.
///
/// Augmenting fields: `augmented` can only be used in an initializer
/// expression, and refers to the original field's initializer expression.
/// The [fragment] is the augmented field.
/// The [staticType] is the type of the field.
///
/// Augmenting binary operators: `augmented` must be the LHS, and followed by
/// the argument, e.g. `augmented + 1`.
/// The [fragment] is the augmented [MethodFragment].
/// The [staticType] is the type of `this`.
///
/// Augmenting index operators: `augmented` must be the index target,
/// e.g. `augmented[0]`.
/// The [fragment] is the augmented [MethodFragment].
/// The [staticType] is the type of `this`.
///
/// Augmenting prefix operators: `augmented` must be the target, e.g.
/// `~augmented`.
/// The [fragment] is the augmented [MethodFragment].
/// The [staticType] is the type of `this`.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AugmentedExpression implements Expression {
  /// The 'augmented' keyword.
  Token get augmentedKeyword;

  /// The referenced augmented fragment: getter, setter, variable.
  @experimental
  Fragment? get fragment;
}

final class AugmentedExpressionImpl extends ExpressionImpl
    implements AugmentedExpression {
  @override
  final Token augmentedKeyword;

  @override
  Fragment? fragment;

  AugmentedExpressionImpl({required this.augmentedKeyword});

  @override
  Token get beginToken => augmentedKeyword;

  @override
  Token get endToken => augmentedKeyword;

  @override
  bool get isAssignable => true;

  @override
  Precedence get precedence => Precedence.primary;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('augmentedKeyword', augmentedKeyword);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitAugmentedExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitAugmentedExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// Invocation of the augmented function, constructor, or method.
///
///    augmentedInvocation ::=
///        'augmented' [TypeArgumentList]? [ArgumentList]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AugmentedInvocation implements Expression {
  /// The list of value arguments.
  ArgumentList get arguments;

  /// The 'augmented' keyword.
  Token get augmentedKeyword;

  /// The referenced augmented element: function, constructor, or method.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if this
  /// fragment is the first fragment in the chain.
  @experimental
  ExecutableFragment? get fragment;

  /// The list of type arguments.
  ///
  /// In valid code cannot be provided for augmented constructor invocation.
  TypeArgumentList? get typeArguments;
}

final class AugmentedInvocationImpl extends ExpressionImpl
    implements AugmentedInvocation {
  @override
  final Token augmentedKeyword;

  @override
  ExecutableFragment? fragment;

  @override
  final TypeArgumentListImpl? typeArguments;

  @override
  final ArgumentListImpl arguments;

  AugmentedInvocationImpl({
    required this.augmentedKeyword,
    required this.typeArguments,
    required this.arguments,
  }) {
    _becomeParentOf(typeArguments);
    _becomeParentOf(arguments);
  }

  @override
  Token get beginToken => augmentedKeyword;

  @override
  Token get endToken => arguments.endToken;

  @override
  Precedence get precedence => Precedence.postfix;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('augmentedKeyword', augmentedKeyword)
        ..addNode('typeArguments', typeArguments)
        ..addNode('arguments', arguments);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitAugmentedInvocation(this);
  }

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitAugmentedInvocation(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    typeArguments?.accept(visitor);
    arguments.accept(visitor);
  }
}

/// An await expression.
///
///    awaitExpression ::=
///        'await' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class AwaitExpression implements Expression {
  /// The `await` keyword.
  Token get awaitKeyword;

  /// The expression whose value is being waited on.
  Expression get expression;
}

final class AwaitExpressionImpl extends ExpressionImpl
    implements AwaitExpression {
  @override
  final Token awaitKeyword;

  ExpressionImpl _expression;

  /// Initializes a newly created await expression.
  AwaitExpressionImpl({
    required this.awaitKeyword,
    required ExpressionImpl expression,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken {
    return awaitKeyword;
  }

  @override
  Token get endToken => _expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.prefix;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('awaitKeyword', awaitKeyword)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitAwaitExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitAwaitExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _expression.accept(visitor);
  }
}

/// A binary (infix) expression.
///
///    binaryExpression ::=
///        [Expression] [Token] [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class BinaryExpression
    implements Expression, MethodReferenceExpression {
  /// The expression used to compute the left operand.
  Expression get leftOperand;

  /// The binary operator being applied.
  Token get operator;

  /// The expression used to compute the right operand.
  Expression get rightOperand;

  /// The function type of the invocation, or `null` if the AST structure hasn't
  /// been resolved or if the invocation couldn't be resolved.
  FunctionType? get staticInvokeType;
}

final class BinaryExpressionImpl extends ExpressionImpl
    implements BinaryExpression {
  ExpressionImpl _leftOperand;

  @override
  final Token operator;

  ExpressionImpl _rightOperand;

  @override
  MethodElement2? element;

  @override
  FunctionTypeImpl? staticInvokeType;

  /// Initializes a newly created binary expression.
  BinaryExpressionImpl({
    required ExpressionImpl leftOperand,
    required this.operator,
    required ExpressionImpl rightOperand,
  }) : _leftOperand = leftOperand,
       _rightOperand = rightOperand {
    _becomeParentOf(leftOperand);
    _becomeParentOf(rightOperand);
  }

  @override
  Token get beginToken => _leftOperand.beginToken;

  @override
  Token get endToken => _rightOperand.endToken;

  @override
  ExpressionImpl get leftOperand => _leftOperand;

  set leftOperand(ExpressionImpl expression) {
    _leftOperand = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.forTokenType(operator.type);

  @override
  ExpressionImpl get rightOperand => _rightOperand;

  set rightOperand(ExpressionImpl expression) {
    _rightOperand = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('leftOperand', leftOperand)
        ..addToken('operator', operator)
        ..addNode('rightOperand', rightOperand);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitBinaryExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitBinaryExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _leftOperand.accept(visitor);
    _rightOperand.accept(visitor);
  }
}

/// A sequence of statements.
///
///    block ::=
///        '{' statement* '}'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Block implements Statement {
  /// The left curly bracket.
  Token get leftBracket;

  /// The right curly bracket.
  Token get rightBracket;

  /// The statements contained in the block.
  NodeList<Statement> get statements;
}

/// A function body that consists of a block of statements.
///
///    blockFunctionBody ::=
///        ('async' | 'async' '*' | 'sync' '*')? [Block]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class BlockFunctionBody implements FunctionBody {
  /// The block representing the body of the function.
  Block get block;
}

final class BlockFunctionBodyImpl extends FunctionBodyImpl
    implements BlockFunctionBody {
  @override
  final Token? keyword;

  @override
  final Token? star;

  BlockImpl _block;

  /// Initializes a newly created function body consisting of a block of
  /// statements.
  ///
  /// The [keyword] can be `null` if there's no keyword specified for the block.
  ///
  /// The [star] can be `null` if there's no star following the keyword (and
  /// must be `null` if there's no keyword).
  BlockFunctionBodyImpl({
    required this.keyword,
    required this.star,
    required BlockImpl block,
  }) : _block = block {
    _becomeParentOf(_block);
  }

  @override
  Token get beginToken {
    if (keyword case var keyword?) {
      return keyword;
    }
    return _block.beginToken;
  }

  @override
  BlockImpl get block => _block;

  set block(BlockImpl block) {
    _block = _becomeParentOf(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
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('keyword', keyword)
        ..addToken('star', star)
        ..addNode('block', block);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitBlockFunctionBody(this);

  @override
  TypeImpl resolve(ResolverVisitor resolver, TypeImpl? imposedType) =>
      resolver.visitBlockFunctionBody(this, imposedType: imposedType);

  @override
  void visitChildren(AstVisitor visitor) {
    _block.accept(visitor);
  }
}

final class BlockImpl extends StatementImpl
    with AstNodeWithNameScopeMixin
    implements Block {
  @override
  final Token leftBracket;

  final NodeListImpl<StatementImpl> _statements = NodeListImpl._();

  @override
  final Token rightBracket;

  /// Initializes a newly created block of code.
  BlockImpl({
    required this.leftBracket,
    required List<StatementImpl> statements,
    required this.rightBracket,
  }) {
    _statements._initialize(this, statements);
  }

  @override
  Token get beginToken => leftBracket;

  @override
  Token get endToken => rightBracket;

  @override
  NodeListImpl<StatementImpl> get statements => _statements;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('statements', statements)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitBlock(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _statements.accept(visitor);
  }
}

/// A boolean literal expression.
///
///    booleanLiteral ::=
///        'false' | 'true'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class BooleanLiteral implements Literal {
  /// The token representing the literal.
  Token get literal;

  /// The value of the literal.
  bool get value;
}

final class BooleanLiteralImpl extends LiteralImpl implements BooleanLiteral {
  @override
  final Token literal;

  @override
  final bool value;

  /// Initializes a newly created boolean literal.
  BooleanLiteralImpl({required this.literal, required this.value});

  @override
  Token get beginToken => literal;

  @override
  Token get endToken => literal;

  @override
  bool get isSynthetic => literal.isSynthetic;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('literal', literal);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitBooleanLiteral(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitBooleanLiteral(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// A break statement.
///
///    breakStatement ::=
///        'break' [SimpleIdentifier]? ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class BreakStatement implements Statement {
  /// The token representing the `break` keyword.
  Token get breakKeyword;

  /// The label associated with the statement, or `null` if there's no label.
  SimpleIdentifier? get label;

  /// The semicolon terminating the statement.
  Token get semicolon;

  /// The node from which this break statement is breaking, or `null` if the AST
  /// hasn't yet been resolved or if the target couldn't be resolved.
  ///
  /// This is 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).
  ///
  /// Note that if the source code has errors, the target might be invalid.
  /// For example, if the break statement is trying to break to a switch case
  /// the target will be the switch case even though breaking to a switch case
  /// isn't valid.
  AstNode? get target;
}

final class BreakStatementImpl extends StatementImpl implements BreakStatement {
  @override
  final Token breakKeyword;

  SimpleIdentifierImpl? _label;

  @override
  final Token semicolon;

  @override
  AstNode? target;

  /// Initializes a newly created break statement.
  ///
  /// The [label] can be `null` if there's no label associated with the
  /// statement.
  BreakStatementImpl({
    required this.breakKeyword,
    required SimpleIdentifierImpl? label,
    required this.semicolon,
  }) : _label = label {
    _becomeParentOf(_label);
  }

  @override
  Token get beginToken => breakKeyword;

  @override
  Token get endToken => semicolon;

  @override
  SimpleIdentifierImpl? get label => _label;

  set label(SimpleIdentifierImpl? identifier) {
    _label = _becomeParentOf(identifier);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('breakKeyword', breakKeyword)
        ..addNode('label', label)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitBreakStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _label?.accept(visitor);
  }
}

/// A sequence of cascaded expressions: expressions that share a common target.
///
/// There are three kinds of expressions that can be used in a cascade
/// expression: [IndexExpression], [MethodInvocation] and [PropertyAccess].
///
///    cascadeExpression ::=
///        [Expression] cascadeSection*
///
///    cascadeSection ::=
///        ('..' | '?..') (cascadeSelector arguments*)
///        (assignableSelector arguments*)*
///        (assignmentOperator expressionWithoutCascade)?
///
///    cascadeSelector ::=
///        '[ ' expression '] '
///      | identifier
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CascadeExpression
    implements Expression, NullShortableExpression {
  /// The cascade sections sharing the common target.
  NodeList<Expression> get cascadeSections;

  /// Whether this cascade is null aware (as opposed to non-null).
  bool get isNullAware;

  /// The target of the cascade sections.
  Expression get target;
}

final class CascadeExpressionImpl extends ExpressionImpl
    with NullShortableExpressionImpl
    implements CascadeExpression {
  ExpressionImpl _target;

  final NodeListImpl<ExpressionImpl> _cascadeSections = NodeListImpl._();

  /// Initializes a newly created cascade expression.
  ///
  /// The list of [cascadeSections] must contain at least one element.
  CascadeExpressionImpl({
    required ExpressionImpl target,
    required List<ExpressionImpl> cascadeSections,
  }) : _target = target {
    _becomeParentOf(_target);
    _cascadeSections._initialize(this, cascadeSections);
  }

  @override
  Token get beginToken => _target.beginToken;

  @override
  NodeListImpl<ExpressionImpl> get cascadeSections => _cascadeSections;

  @override
  Token get endToken => _cascadeSections.endToken!;

  @override
  bool get isNullAware {
    return target.endToken.next!.type == TokenType.QUESTION_PERIOD_PERIOD;
  }

  @override
  Precedence get precedence => Precedence.cascade;

  @override
  ExpressionImpl get target => _target;

  set target(ExpressionImpl target) {
    _target = _becomeParentOf(target);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('target', target)
        ..addNodeList('cascadeSections', cascadeSections);

  @override
  AstNode? get _nullShortingExtensionCandidate => null;

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitCascadeExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitCascadeExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _target.accept(visitor);
    _cascadeSections.accept(visitor);
  }

  @override
  bool _extendsNullShorting(Expression descendant) {
    // Null shorting that occurs in a cascade section does not extend to the
    // full cascade expression.
    return false;
  }
}

/// The `case` clause that can optionally appear in an `if` statement.
///
///    caseClause ::=
///        'case' [GuardedPattern]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CaseClause implements AstNode {
  /// The token representing the `case` keyword.
  Token get caseKeyword;

  /// The pattern controlling whether the statements are executed.
  GuardedPattern get guardedPattern;
}

final class CaseClauseImpl extends AstNodeImpl
    with AstNodeWithNameScopeMixin
    implements CaseClause {
  @override
  final Token caseKeyword;

  @override
  final GuardedPatternImpl guardedPattern;

  CaseClauseImpl({required this.caseKeyword, required this.guardedPattern}) {
    _becomeParentOf(guardedPattern);
  }

  @override
  Token get beginToken => caseKeyword;

  @override
  Token get endToken => guardedPattern.endToken;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('caseKeyword', caseKeyword)
        ..addNode('guardedPattern', guardedPattern);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitCaseClause(this);

  @override
  void visitChildren(AstVisitor visitor) {
    guardedPattern.accept(visitor);
  }
}

sealed class CaseNodeImpl implements AstNode {
  GuardedPatternImpl get guardedPattern;
}

/// A cast pattern.
///
///    castPattern ::=
///        [DartPattern] 'as' [TypeAnnotation]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CastPattern implements DartPattern {
  /// The `as` token.
  Token get asToken;

  /// The pattern used to match the value being cast.
  DartPattern get pattern;

  /// The type that the value being matched is cast to.
  TypeAnnotation get type;
}

final class CastPatternImpl extends DartPatternImpl implements CastPattern {
  @override
  final Token asToken;

  @override
  final DartPatternImpl pattern;

  @override
  final TypeAnnotationImpl type;

  CastPatternImpl({
    required this.pattern,
    required this.asToken,
    required this.type,
  }) {
    _becomeParentOf(pattern);
    _becomeParentOf(type);
  }

  @override
  Token get beginToken => pattern.beginToken;

  @override
  Token get endToken => type.endToken;

  @override
  PatternPrecedence get precedence => PatternPrecedence.postfix;

  @override
  VariablePatternImpl? get variablePattern => pattern.variablePattern;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('pattern', pattern)
        ..addToken('asToken', asToken)
        ..addNode('type', type);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitCastPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor.analyzeCastPatternSchema().unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    type.accept(resolverVisitor);
    var requiredType = type.typeOrThrow;

    var analysisResult = resolverVisitor.analyzeCastPattern(
      context: context,
      pattern: this,
      innerPattern: pattern,
      requiredType: SharedTypeView(requiredType),
    );

    resolverVisitor.checkPatternNeverMatchesValueType(
      context: context,
      pattern: this,
      requiredType: requiredType,
      matchedValueType: analysisResult.matchedValueType.unwrapTypeView(),
    );
    inferenceLogWriter?.exitPattern(this);

    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    pattern.accept(visitor);
    type.accept(visitor);
  }
}

/// A catch clause within a try statement.
///
///    onPart ::=
///        catchPart [Block]
///      | 'on' type catchPart? [Block]
///
///    catchPart ::=
///        'catch' '(' [CatchClauseParameter] (',' [CatchClauseParameter])? ')'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CatchClause implements AstNode {
  /// The body of the catch block.
  Block get body;

  /// The token representing the `catch` keyword, or `null` if there's no
  /// `catch` keyword.
  Token? get catchKeyword;

  /// The comma separating the exception parameter from the stack trace
  /// parameter, or `null` if there's no stack trace parameter.
  Token? get comma;

  /// The parameter whose value is the exception that was thrown, or `null` if
  /// there's no `catch` keyword.
  CatchClauseParameter? get exceptionParameter;

  /// The type of exceptions caught by this catch clause, or `null` if this
  /// catch clause catches every type of exception.
  TypeAnnotation? get exceptionType;

  /// The left parenthesis, or `null` if there's no `catch` keyword.
  Token? get leftParenthesis;

  /// The token representing the `on` keyword, or `null` if there's no `on`
  /// keyword.
  Token? get onKeyword;

  /// The right parenthesis, or `null` if there's no `catch` keyword.
  Token? get rightParenthesis;

  /// The parameter whose value is the stack trace associated with the
  /// exception, or `null` if there's no stack trace parameter.
  CatchClauseParameter? get stackTraceParameter;
}

final class CatchClauseImpl extends AstNodeImpl implements CatchClause {
  @override
  final Token? onKeyword;

  TypeAnnotationImpl? _exceptionType;

  @override
  final Token? catchKeyword;

  @override
  final Token? leftParenthesis;

  CatchClauseParameterImpl? _exceptionParameter;

  @override
  final Token? comma;

  CatchClauseParameterImpl? _stackTraceParameter;

  @override
  final Token? rightParenthesis;

  BlockImpl _body;

  /// Initializes a newly created catch clause.
  ///
  /// The [onKeyword] and [exceptionType] can be `null` if the clause is to
  /// catch all exceptions.
  ///
  /// The [comma] and [_stackTraceParameter] can be `null` if the stack trace
  /// parameter isn't defined.
  CatchClauseImpl({
    required this.onKeyword,
    required TypeAnnotationImpl? exceptionType,
    required this.catchKeyword,
    required this.leftParenthesis,
    required CatchClauseParameterImpl? exceptionParameter,
    required this.comma,
    required CatchClauseParameterImpl? stackTraceParameter,
    required this.rightParenthesis,
    required BlockImpl body,
  }) : assert(onKeyword != null || catchKeyword != null),
       _exceptionType = exceptionType,
       _exceptionParameter = exceptionParameter,
       _stackTraceParameter = stackTraceParameter,
       _body = body {
    _becomeParentOf(_exceptionType);
    _becomeParentOf(_exceptionParameter);
    _becomeParentOf(_stackTraceParameter);
    _becomeParentOf(_body);
  }

  @override
  Token get beginToken {
    if (onKeyword case var onKeyword?) {
      return onKeyword;
    }
    return catchKeyword!;
  }

  @override
  BlockImpl get body => _body;

  set body(BlockImpl block) {
    _body = _becomeParentOf(block);
  }

  @override
  Token get endToken => _body.endToken;

  @override
  CatchClauseParameterImpl? get exceptionParameter {
    return _exceptionParameter;
  }

  set exceptionParameter(CatchClauseParameterImpl? parameter) {
    _exceptionParameter = parameter;
    _becomeParentOf(parameter);
  }

  @override
  TypeAnnotationImpl? get exceptionType => _exceptionType;

  set exceptionType(TypeAnnotationImpl? exceptionType) {
    _exceptionType = _becomeParentOf(exceptionType);
  }

  @override
  CatchClauseParameterImpl? get stackTraceParameter {
    return _stackTraceParameter;
  }

  set stackTraceParameter(CatchClauseParameterImpl? parameter) {
    _stackTraceParameter = parameter;
    _becomeParentOf(parameter);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('onKeyword', onKeyword)
        ..addNode('exceptionType', exceptionType)
        ..addToken('catchKeyword', catchKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('exceptionParameter', exceptionParameter)
        ..addToken('comma', comma)
        ..addNode('stackTraceParameter', stackTraceParameter)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addNode('body', body);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitCatchClause(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _exceptionType?.accept(visitor);
    _exceptionParameter?.accept(visitor);
    _stackTraceParameter?.accept(visitor);
    _body.accept(visitor);
  }
}

/// An 'exception' or 'stackTrace' parameter in [CatchClause].
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CatchClauseParameter extends AstNode {
  /// The declared element.
  ///
  /// Returns `null` if the AST hasn't been resolved.
  @experimental
  LocalVariableElement2? get declaredElement2;

  /// The declared fragment.
  ///
  /// Returns `null` if the AST hasn't been resolved.
  @experimental
  LocalVariableFragment? get declaredFragment;

  /// The name of the parameter.
  Token get name;
}

final class CatchClauseParameterImpl extends AstNodeImpl
    implements CatchClauseParameter {
  @override
  final Token name;

  @override
  LocalVariableElementImpl? declaredFragment;

  CatchClauseParameterImpl({required this.name});

  @override
  Token get beginToken => name;

  @override
  LocalVariableElementImpl2? get declaredElement2 {
    return declaredFragment?.element;
  }

  @override
  Token get endToken => name;

  @override
  ChildEntities get _childEntities =>
      super._childEntities..addToken('name', name);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitCatchClauseParameter(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {}
}

/// A helper class to allow iteration of child entities of an AST node.
class ChildEntities {
  /// The list of child entities to be iterated over.
  final List<ChildEntity> entities = [];

  List<SyntacticEntity> get syntacticEntities {
    var result = <SyntacticEntity>[];
    for (var entity in entities) {
      var entityValue = entity.value;
      if (entityValue is SyntacticEntity) {
        result.add(entityValue);
      } else if (entityValue is List<Object>) {
        for (var element in entityValue) {
          if (element is SyntacticEntity) {
            result.add(element);
          }
        }
      }
    }

    var needsSorting = false;
    int? lastOffset;
    for (var entity in result) {
      if (lastOffset != null && lastOffset > entity.offset) {
        needsSorting = true;
        break;
      }
      lastOffset = entity.offset;
    }

    if (needsSorting) {
      result.sort((a, b) => a.offset - b.offset);
    }

    return result;
  }

  void addAll(ChildEntities other) {
    entities.addAll(other.entities);
  }

  void addNode(String name, AstNode? value) {
    if (value != null) {
      entities.add(ChildEntity(name, value));
    }
  }

  void addNodeList(String name, List<AstNode> value) {
    entities.add(ChildEntity(name, value));
  }

  void addToken(String name, Token? value) {
    if (value != null) {
      entities.add(ChildEntity(name, value));
    }
  }

  void addTokenList(String name, List<Token> value) {
    entities.add(ChildEntity(name, value));
  }
}

/// A named child of an [AstNode], usually a token, node, or a list of nodes.
class ChildEntity {
  final String name;
  final Object value;

  ChildEntity(this.name, this.value);
}

/// The declaration of a class.
///
///    classDeclaration ::=
///        classModifiers 'class' name [TypeParameterList]?
///        [ExtendsClause]? [WithClause]? [ImplementsClause]?
///        '{' [ClassMember]* '}'
///
///    classModifiers ::= 'sealed'
///      | 'abstract'? ('base' | 'interface' | 'final')?
///      | 'abstract'? 'base'? 'mixin'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ClassDeclaration implements NamedCompilationUnitMember {
  /// The `abstract` keyword, or `null` if the keyword was absent.
  Token? get abstractKeyword;

  /// The `augment` keyword, or `null` if the keyword was absent.
  @experimental
  Token? get augmentKeyword;

  /// The `base` keyword, or `null` if the keyword was absent.
  Token? get baseKeyword;

  /// The token representing the `class` keyword.
  Token get classKeyword;

  @experimental
  @override
  ClassFragment? get declaredFragment;

  /// The `extends` clause for this class, or `null` if the class doesn't extend
  /// any other class.
  ExtendsClause? get extendsClause;

  /// The `final` keyword, or `null` if the keyword was absent.
  Token? get finalKeyword;

  /// The `implements` clause for the class, or `null` if the class doesn't
  /// implement any interfaces.
  ImplementsClause? get implementsClause;

  /// The `interface` keyword, or `null` if the keyword was absent.
  Token? get interfaceKeyword;

  /// The left curly bracket.
  Token get leftBracket;

  /// The `macro` keyword, or `null` if the keyword was absent.
  @Deprecated('Support for macros was removed')
  Token? get macroKeyword;

  /// The members defined by the class.
  NodeList<ClassMember> get members;

  /// The `mixin` keyword, or `null` if the keyword was absent.
  Token? get mixinKeyword;

  /// The native clause for this class, or `null` if the class doesn't have a
  /// native clause.
  NativeClause? get nativeClause;

  /// The right curly bracket.
  Token get rightBracket;

  /// The `sealed` keyword, or `null` if the keyword was absent.
  Token? get sealedKeyword;

  /// The type parameters for the class, or `null` if the class doesn't have any
  /// type parameters.
  TypeParameterList? get typeParameters;

  /// The `with` clause for the class, or `null` if the class doesn't have a
  /// `with` clause.
  WithClause? get withClause;
}

final class ClassDeclarationImpl extends NamedCompilationUnitMemberImpl
    with AstNodeWithNameScopeMixin
    implements ClassDeclaration {
  @override
  final Token? augmentKeyword;

  @override
  final Token? abstractKeyword;

  @override
  final Token? macroKeyword;

  @override
  final Token? sealedKeyword;

  @override
  final Token? baseKeyword;

  @override
  final Token? interfaceKeyword;

  @override
  final Token? finalKeyword;

  @override
  final Token? mixinKeyword;

  @override
  final Token classKeyword;

  @override
  TypeParameterListImpl? typeParameters;

  @override
  ExtendsClauseImpl? extendsClause;

  @override
  WithClauseImpl? withClause;

  @override
  ImplementsClauseImpl? implementsClause;

  @override
  final NativeClauseImpl? nativeClause;

  @override
  final Token leftBracket;

  @override
  final NodeListImpl<ClassMemberImpl> members = NodeListImpl._();

  @override
  final Token rightBracket;

  @override
  ClassElementImpl? declaredFragment;

  ClassDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.abstractKeyword,
    required this.macroKeyword,
    required this.sealedKeyword,
    required this.baseKeyword,
    required this.interfaceKeyword,
    required this.finalKeyword,
    required this.mixinKeyword,
    required this.classKeyword,
    required super.name,
    required this.typeParameters,
    required this.extendsClause,
    required this.withClause,
    required this.implementsClause,
    required this.nativeClause,
    required this.leftBracket,
    required List<ClassMemberImpl> members,
    required this.rightBracket,
  }) {
    _becomeParentOf(typeParameters);
    _becomeParentOf(extendsClause);
    _becomeParentOf(withClause);
    _becomeParentOf(implementsClause);
    _becomeParentOf(nativeClause);
    this.members._initialize(this, members);
  }

  @override
  Token get endToken => rightBracket;

  @override
  Token get firstTokenAfterCommentAndMetadata {
    return abstractKeyword ??
        macroKeyword ??
        sealedKeyword ??
        baseKeyword ??
        interfaceKeyword ??
        finalKeyword ??
        augmentKeyword ??
        mixinKeyword ??
        classKeyword;
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('abstractKeyword', abstractKeyword)
        ..addToken('macroKeyword', macroKeyword)
        ..addToken('sealedKeyword', sealedKeyword)
        ..addToken('baseKeyword', baseKeyword)
        ..addToken('interfaceKeyword', interfaceKeyword)
        ..addToken('finalKeyword', finalKeyword)
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('mixinKeyword', mixinKeyword)
        ..addToken('classKeyword', classKeyword)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addNode('extendsClause', extendsClause)
        ..addNode('withClause', withClause)
        ..addNode('implementsClause', implementsClause)
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('members', members)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitClassDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(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, enum, extension,
/// extension type, or mixin declaration.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class ClassMember implements Declaration {}

sealed class ClassMemberImpl extends DeclarationImpl implements ClassMember {
  /// Initializes a newly created member of a class.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the member
  /// doesn't have the corresponding attribute.
  ClassMemberImpl({required super.comment, required super.metadata});
}

/// A class type alias.
///
///    classTypeAlias ::=
///        classModifiers 'class' [SimpleIdentifier] [TypeParameterList]? '='
///        mixinApplication
///
///    classModifiers ::= 'sealed'
///      | 'abstract'? ('base' | 'interface' | 'final')?
///      | 'abstract'? 'base'? 'mixin'
///
///    mixinApplication ::=
///        [NamedType] [WithClause] [ImplementsClause]? ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ClassTypeAlias implements TypeAlias {
  /// The token for the `abstract` keyword, or `null` if this isn't defining an
  /// abstract class.
  Token? get abstractKeyword;

  /// The `base` keyword, or `null` if the keyword was absent.
  Token? get baseKeyword;

  @experimental
  @override
  ClassFragment? get declaredFragment;

  /// The token for the '=' separating the name from the definition.
  Token get equals;

  /// The `final` keyword, or `null` if the keyword was absent.
  Token? get finalKeyword;

  /// The implements clause for this class, or `null` if there's no implements
  /// clause.
  ImplementsClause? get implementsClause;

  /// The `interface` keyword, or `null` if the keyword was absent.
  Token? get interfaceKeyword;

  /// The `mixin` keyword, or `null` if the keyword was absent.
  Token? get mixinKeyword;

  /// The `sealed` keyword, or `null` if the keyword was absent.
  Token? get sealedKeyword;

  /// The name of the superclass of the class being declared.
  NamedType get superclass;

  /// The type parameters for the class, or `null` if the class doesn't have any
  /// type parameters.
  TypeParameterList? get typeParameters;

  /// The with clause for this class.
  WithClause get withClause;
}

final class ClassTypeAliasImpl extends TypeAliasImpl implements ClassTypeAlias {
  TypeParameterListImpl? _typeParameters;

  @override
  final Token equals;

  @override
  final Token? abstractKeyword;

  @override
  final Token? sealedKeyword;

  @override
  final Token? baseKeyword;

  @override
  final Token? interfaceKeyword;

  @override
  final Token? finalKeyword;

  @override
  final Token? mixinKeyword;

  NamedTypeImpl _superclass;

  WithClauseImpl _withClause;

  ImplementsClauseImpl? _implementsClause;

  @override
  ClassElementImpl? declaredFragment;

  /// Initializes a newly created class type alias.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the class
  /// type alias doesn't have the corresponding attribute.
  ///
  /// The [typeParameters] can be `null` if the class doesn't have any type
  /// parameters.
  ///
  /// The [abstractKeyword] can be `null` if the class isn't abstract.
  ///
  /// The [implementsClause] can be `null` if the class doesn't implement any
  /// interfaces.
  ClassTypeAliasImpl({
    required super.comment,
    required super.metadata,
    required super.typedefKeyword,
    required super.name,
    required TypeParameterListImpl? typeParameters,
    required this.equals,
    required this.abstractKeyword,
    required this.sealedKeyword,
    required this.baseKeyword,
    required this.interfaceKeyword,
    required this.finalKeyword,
    required super.augmentKeyword,
    required this.mixinKeyword,
    required NamedTypeImpl superclass,
    required WithClauseImpl withClause,
    required ImplementsClauseImpl? implementsClause,
    required super.semicolon,
  }) : _typeParameters = typeParameters,
       _superclass = superclass,
       _withClause = withClause,
       _implementsClause = implementsClause {
    _becomeParentOf(_typeParameters);
    _becomeParentOf(_superclass);
    _becomeParentOf(_withClause);
    _becomeParentOf(_implementsClause);
  }

  @override
  Token get firstTokenAfterCommentAndMetadata {
    return abstractKeyword ??
        sealedKeyword ??
        baseKeyword ??
        interfaceKeyword ??
        finalKeyword ??
        augmentKeyword ??
        mixinKeyword ??
        typedefKeyword;
  }

  @override
  ImplementsClauseImpl? get implementsClause => _implementsClause;

  set implementsClause(ImplementsClauseImpl? implementsClause) {
    _implementsClause = _becomeParentOf(implementsClause);
  }

  @override
  NamedTypeImpl get superclass => _superclass;

  set superclass(NamedTypeImpl superclass) {
    _superclass = _becomeParentOf(superclass);
  }

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl);
  }

  @override
  WithClauseImpl get withClause => _withClause;

  set withClause(WithClauseImpl withClause) {
    _withClause = _becomeParentOf(withClause);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('typedefKeyword', typedefKeyword)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addToken('equals', equals)
        ..addToken('abstractKeyword', abstractKeyword)
        ..addToken('sealedKeyword', sealedKeyword)
        ..addToken('baseKeyword', baseKeyword)
        ..addToken('interfaceKeyword', interfaceKeyword)
        ..addToken('finalKeyword', finalKeyword)
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('mixinKeyword', mixinKeyword)
        ..addNode('superclass', superclass)
        ..addNode('withClause', withClause)
        ..addNode('implementsClause', implementsClause)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitClassTypeAlias(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _typeParameters?.accept(visitor);
    _superclass.accept(visitor);
    _withClause.accept(visitor);
    _implementsClause?.accept(visitor);
  }
}

@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class CollectionElement implements AstNode {}

sealed class CollectionElementImpl extends AstNodeImpl
    implements CollectionElement {
  /// Dispatches this collection element to the [resolver], with the given
  /// [context] information.
  void resolveElement(
    ResolverVisitor resolver,
    CollectionLiteralContext? context,
  );
}

/// A combinator associated with an import or export directive.
///
///    combinator ::=
///        [HideCombinator]
///      | [ShowCombinator]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class Combinator implements AstNode {
  /// The `hide` or `show` keyword specifying what kind of processing is to be
  /// done on the names.
  Token get keyword;
}

sealed class CombinatorImpl extends AstNodeImpl implements Combinator {
  @override
  final Token keyword;

  /// Initializes a newly created combinator.
  CombinatorImpl({required this.keyword});

  @override
  Token get beginToken => keyword;
}

/// A comment within the source code.
///
///    comment ::=
///        endOfLineComment
///      | blockComment
///      | documentationComment
///
///    endOfLineComment ::=
///        '//' (CHARACTER - EOL)* EOL
///
///    blockComment ::=
///        '/ *' CHARACTER* '&#42;/'
///
///    documentationComment ::=
///        '/ **' (CHARACTER | [CommentReference])* '&#42;/'
///      | ('///' (CHARACTER - EOL)* EOL)+
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Comment implements AstNode {
  /// The markdown code blocks (both fenced and indented) contained in this
  /// comment.
  @experimental
  List<MdCodeBlock> get codeBlocks;

  @experimental
  List<DocDirective> get docDirectives;

  @experimental
  List<DocImport> get docImports;

  /// Whether this comment has a line beginning with '@nodoc', indicating its
  /// contents aren't intended for publishing.
  @experimental
  bool get hasNodoc;

  /// The references embedded within the documentation comment.
  ///
  /// If there are no references in the comment then the list will be empty.
  NodeList<CommentReference> get references;

  /// The tokens representing the comment.
  List<Token> get tokens;
}

final class CommentImpl extends AstNodeImpl
    with AstNodeWithNameScopeMixin
    implements Comment {
  @override
  final List<Token> tokens;

  final NodeListImpl<CommentReferenceImpl> _references = NodeListImpl._();

  @override
  final List<MdCodeBlock> codeBlocks;

  @override
  final List<DocImport> docImports;

  @override
  final List<DocDirective> docDirectives;

  @override
  final bool hasNodoc;

  /// Initializes a newly created comment.
  ///
  /// The list of [tokens] must contain at least one token.
  ///
  /// The list of [references] can be empty if the comment doesn't contain any
  /// embedded references.
  CommentImpl({
    required this.tokens,
    required List<CommentReferenceImpl> references,
    required this.codeBlocks,
    required this.docImports,
    required this.docDirectives,
    required this.hasNodoc,
  }) {
    _references._initialize(this, references);
  }

  @override
  Token get beginToken => tokens[0];

  @override
  Token get endToken => tokens[tokens.length - 1];

  @override
  NodeListImpl<CommentReferenceImpl> get references => _references;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNodeList('references', references)
        ..addTokenList('tokens', tokens);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitComment(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _references.accept(visitor);
  }
}

/// An interface for an [Expression] which can make up a [CommentReference].
///
///    commentReferableExpression ::=
///        [ConstructorReference]
///      | [FunctionReference]
///      | [PrefixedIdentifier]
///      | [PropertyAccess]
///      | [SimpleIdentifier]
///      | [TypeLiteral]
///
/// This interface should align closely with dartdoc's notion of
/// comment-referable expressions at:
/// https://github.com/dart-lang/dartdoc/blob/master/lib/src/comment_references/parser.dart
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CommentReferableExpression implements Expression {}

sealed class CommentReferableExpressionImpl extends ExpressionImpl
    implements CommentReferableExpression {}

/// A reference to a Dart element that is found within a documentation comment.
///
///    commentReference ::=
///        '[' 'new'? [CommentReferableExpression] ']'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CommentReference implements AstNode {
  /// The comment-referable expression being referenced.
  CommentReferableExpression get expression;

  /// The token representing the `new` keyword, or `null` if there was no `new`
  /// keyword.
  Token? get newKeyword;
}

final class CommentReferenceImpl extends AstNodeImpl
    implements CommentReference {
  @override
  final Token? newKeyword;

  CommentReferableExpressionImpl _expression;

  @override
  final bool isSynthetic;

  /// Initializes a newly created reference to a Dart element.
  ///
  /// The [newKeyword] can be `null` if the reference isn't to a constructor.
  CommentReferenceImpl({
    required this.newKeyword,
    required CommentReferableExpressionImpl expression,
    required this.isSynthetic,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => newKeyword ?? _expression.beginToken;

  @override
  Token get endToken => _expression.endToken;

  @override
  CommentReferableExpressionImpl get expression => _expression;

  set expression(CommentReferableExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('newKeyword', newKeyword)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitCommentReference(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _expression.accept(visitor);
  }
}

/// A compilation unit.
///
/// While the grammar restricts the order of the directives and declarations
/// within a compilation unit, this class doesn't enforce those restrictions.
/// In particular, the children of a compilation unit are visited in lexical
/// order even if lexical order doesn't conform to the restrictions of the
/// grammar.
///
///    compilationUnit ::=
///        directives declarations
///
///    directives ::=
///        [ScriptTag]? [LibraryDirective]? namespaceDirective* [PartDirective]*
///      | [PartOfDirective]
///
///    namespaceDirective ::=
///        [ImportDirective]
///      | [ExportDirective]
///
///    declarations ::=
///        [CompilationUnitMember]*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CompilationUnit implements AstNode {
  /// The first (non-EOF) token in the token stream that was parsed to form this
  /// compilation unit.
  @override
  Token get beginToken;

  /// The declarations contained in this compilation unit.
  NodeList<CompilationUnitMember> get declarations;

  /// The fragment associated with this compilation unit.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  @experimental
  LibraryFragment? get declaredFragment;

  /// The directives contained in this compilation unit.
  NodeList<Directive> get directives;

  /// 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 get endToken;

  /// The set of features available to this compilation unit.
  ///
  /// Determined by some combination of the `package_config.json` file, the
  /// enclosing package's SDK version constraint, and/or the presence of a
  /// `@dart` directive in a comment at the top of the file.
  FeatureSet get featureSet;

  /// The language version information.
  LibraryLanguageVersion get languageVersion;

  /// The language version override specified for this compilation unit using a
  /// token like '// @dart = 2.7', or `null` if no override is specified.
  LanguageVersionToken? get languageVersionToken;

  /// The line information for this compilation unit.
  LineInfo get lineInfo;

  /// The script tag at the beginning of the compilation unit, or `null` if
  /// there's no script tag in this compilation unit.
  ScriptTag? get scriptTag;

  /// A list containing all of the directives and declarations in this
  /// compilation unit, sorted in lexical order.
  List<AstNode> get sortedDirectivesAndDeclarations;
}

final class CompilationUnitImpl extends AstNodeImpl
    with AstNodeWithNameScopeMixin
    implements CompilationUnit {
  @override
  final Token beginToken;

  ScriptTagImpl? _scriptTag;

  final NodeListImpl<DirectiveImpl> _directives = NodeListImpl._();

  final NodeListImpl<CompilationUnitMemberImpl> _declarations =
      NodeListImpl._();

  @override
  final Token endToken;

  @override
  CompilationUnitElementImpl? declaredFragment;

  @override
  final LineInfo lineInfo;

  @override
  final LibraryLanguageVersion languageVersion;

  @override
  final FeatureSet featureSet;

  /// Nodes that were parsed, but happened at locations where they aren't
  /// allowed.
  ///
  /// Instead of dropping them, we remember them here. Quick fixes can look
  /// here to determine which source range to remove.
  final List<AstNodeImpl> invalidNodes;

  /// Initializes a newly created compilation unit to have the given directives
  /// and declarations.
  ///
  /// The [scriptTag] can be `null` if there's 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({
    required this.beginToken,
    required ScriptTagImpl? scriptTag,
    required List<DirectiveImpl>? directives,
    required List<CompilationUnitMemberImpl>? declarations,
    required this.endToken,
    required this.featureSet,
    required this.lineInfo,
    required this.invalidNodes,
    required this.languageVersion,
  }) : _scriptTag = scriptTag {
    _becomeParentOf(_scriptTag);
    _directives._initialize(this, directives);
    _declarations._initialize(this, declarations);
  }

  @override
  NodeListImpl<CompilationUnitMemberImpl> get declarations => _declarations;

  @override
  NodeListImpl<DirectiveImpl> get directives => _directives;

  @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 {
    var endToken = this.endToken;
    return endToken.offset + endToken.length;
  }

  @override
  int get offset => 0;

  @override
  ScriptTagImpl? get scriptTag => _scriptTag;

  set scriptTag(ScriptTagImpl? scriptTag) {
    _scriptTag = _becomeParentOf(scriptTag);
  }

  @override
  List<AstNode> get sortedDirectivesAndDeclarations {
    return <AstNode>[..._directives, ..._declarations]
      ..sort(AstNode.LEXICAL_ORDER);
  }

  @override
  ChildEntities get _childEntities {
    return ChildEntities()
      ..addNode('scriptTag', scriptTag)
      ..addNodeList('directives', directives)
      ..addNodeList('declarations', declarations);
  }

  /// Whether 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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CompilationUnitMember implements Declaration {}

sealed class CompilationUnitMemberImpl extends DeclarationImpl
    implements CompilationUnitMember {
  /// Initializes a newly created compilation unit member.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the member
  /// doesn't have the corresponding attribute.
  CompilationUnitMemberImpl({required super.comment, required super.metadata});
}

/// A potentially compound assignment.
///
/// A compound assignment is any node in which a single expression is used to
/// specify both where to access a value to be operated on (the "read") and to
/// specify where to store the result of the operation (the "write"). This
/// happens in an [AssignmentExpression] when the assignment operator is a
/// compound assignment operator, and in a [PrefixExpression] or
/// [PostfixExpression] when the operator is an increment operator.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class CompoundAssignmentExpression implements Expression {
  /// The element that is used to read the value.
  ///
  /// Returns `null` if this node isn't a compound assignment, if the AST
  /// structure hasn't been resolved, or if the target couldn't be resolved.
  ///
  /// In valid code this element can be a [LocalVariableElement2], a
  /// [FormalParameterElement], or a [GetterElement].
  ///
  /// In invalid code this element is `null`. For example, in `int += 2`. In
  /// such cases, for recovery purposes, [writeElement2] is filled, and can be
  /// used for navigation.
  @experimental
  Element2? get readElement2;

  /// The type of the value read with the [readElement2], or `null` if this node
  /// isn't a compound assignment.
  ///
  /// Returns the type `dynamic` if the code is invalid, if the AST structure
  /// hasn't been resolved, or if the target couldn't be resolved.
  DartType? get readType;

  /// The element that is used to write the result.
  ///
  /// Returns `null` if the AST structure hasn't been resolved, or if the target
  /// couldn't be resolved.
  ///
  /// In valid code this is a [LocalVariableElement2], [FormalParameterElement],
  /// or a [SetterElement].
  ///
  /// In invalid code, for recovery, we might use other elements, for example a
  /// [GetterElement] `myGetter = 0` even though the getter can't be used to set
  /// a value. We do this to help the user to navigate to the getter, and maybe
  /// add the corresponding setter.
  ///
  /// If this node is a compound assignment, such as `x += y`, both
  /// [readElement2] and [writeElement2] could be non-`null`.
  @experimental
  Element2? get writeElement2;

  /// The type of the target of the assignment.
  ///
  /// The types of assigned values must be subtypes of this type.
  ///
  /// If the target couldn't be resolved, this type is `dynamic`.
  DartType? get writeType;
}

base mixin CompoundAssignmentExpressionImpl
    implements CompoundAssignmentExpression {
  @override
  Element2? readElement2;

  @override
  Element2? writeElement2;

  @override
  TypeImpl? readType;

  @override
  TypeImpl? writeType;
}

/// A conditional expression.
///
///    conditionalExpression ::=
///        [Expression] '?' [Expression] ':' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ConditionalExpression implements Expression {
  /// The token used to separate the then expression from the else expression.
  Token get colon;

  /// The condition used to determine which of the expressions is executed next.
  Expression get condition;

  /// The expression that is executed if the condition evaluates to `false`.
  Expression get elseExpression;

  /// The token used to separate the condition from the then expression.
  Token get question;

  /// The expression that is executed if the condition evaluates to `true`.
  Expression get thenExpression;
}

final class ConditionalExpressionImpl extends ExpressionImpl
    implements ConditionalExpression {
  ExpressionImpl _condition;

  @override
  final Token question;

  ExpressionImpl _thenExpression;

  @override
  final Token colon;

  ExpressionImpl _elseExpression;

  /// Initializes a newly created conditional expression.
  ConditionalExpressionImpl({
    required ExpressionImpl condition,
    required this.question,
    required ExpressionImpl thenExpression,
    required this.colon,
    required ExpressionImpl elseExpression,
  }) : _condition = condition,
       _thenExpression = thenExpression,
       _elseExpression = elseExpression {
    _becomeParentOf(_condition);
    _becomeParentOf(_thenExpression);
    _becomeParentOf(_elseExpression);
  }

  @override
  Token get beginToken => _condition.beginToken;

  @override
  ExpressionImpl get condition => _condition;

  set condition(ExpressionImpl expression) {
    _condition = _becomeParentOf(expression);
  }

  @override
  ExpressionImpl get elseExpression => _elseExpression;

  set elseExpression(ExpressionImpl expression) {
    _elseExpression = _becomeParentOf(expression);
  }

  @override
  Token get endToken => _elseExpression.endToken;

  @override
  Precedence get precedence => Precedence.conditional;

  @override
  ExpressionImpl get thenExpression => _thenExpression;

  set thenExpression(ExpressionImpl expression) {
    _thenExpression = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('condition', condition)
        ..addToken('question', question)
        ..addNode('thenExpression', thenExpression)
        ..addToken('colon', colon)
        ..addNode('elseExpression', elseExpression);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitConditionalExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitConditionalExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _condition.accept(visitor);
    _thenExpression.accept(visitor);
    _elseExpression.accept(visitor);
  }
}

/// A configuration in either an import or export directive.
///
///    configuration ::=
///        'if' '(' test ')' uri
///
///    test ::=
///        dottedName ('==' stringLiteral)?
///
///    dottedName ::=
///        identifier ('.' identifier)*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Configuration implements AstNode {
  /// The token for the equal operator, or `null` if the condition doesn't
  /// include an equality test.
  Token? get equalToken;

  /// The token for the `if` keyword.
  Token get ifKeyword;

  /// The token for the left parenthesis.
  Token get leftParenthesis;

  /// The name of the declared variable whose value is being used in the
  /// condition.
  DottedName get name;

  /// The result of resolving [uri].
  DirectiveUri? get resolvedUri;

  /// The token for the right parenthesis.
  Token get rightParenthesis;

  /// The URI of the implementation library to be used if the condition is
  /// `true`.
  StringLiteral get uri;

  /// The value to which the value of the declared variable is compared, or
  /// `null` if the condition doesn't include an equality test.
  StringLiteral? get value;
}

final class ConfigurationImpl extends AstNodeImpl implements Configuration {
  @override
  final Token ifKeyword;

  @override
  final Token leftParenthesis;

  DottedNameImpl _name;

  @override
  final Token? equalToken;

  StringLiteralImpl? _value;

  @override
  final Token rightParenthesis;

  StringLiteralImpl _uri;

  @override
  DirectiveUri? resolvedUri;

  ConfigurationImpl({
    required this.ifKeyword,
    required this.leftParenthesis,
    required DottedNameImpl name,
    required this.equalToken,
    required StringLiteralImpl? value,
    required this.rightParenthesis,
    required StringLiteralImpl uri,
  }) : _name = name,
       _value = value,
       _uri = uri {
    _becomeParentOf(_name);
    _becomeParentOf(_value);
    _becomeParentOf(_uri);
  }

  @override
  Token get beginToken => ifKeyword;

  @override
  Token get endToken => _uri.endToken;

  @override
  DottedNameImpl get name => _name;

  set name(DottedNameImpl name) {
    _name = _becomeParentOf(name);
  }

  @override
  StringLiteralImpl get uri => _uri;

  set uri(StringLiteralImpl uri) {
    _uri = _becomeParentOf(uri);
  }

  @override
  StringLiteralImpl? get value => _value;

  set value(StringLiteralImpl? value) {
    _value = _becomeParentOf(value as StringLiteralImpl);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('ifKeyword', ifKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('name', name)
        ..addToken('equalToken', equalToken)
        ..addNode('value', value)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addNode('uri', uri);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitConfiguration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _name.accept(visitor);
    _value?.accept(visitor);
    _uri.accept(visitor);
  }
}

final class ConstantContextForExpressionImpl extends AstNodeImpl {
  final Fragment variable;
  final ExpressionImpl expression;

  ConstantContextForExpressionImpl(this.variable, this.expression) {
    _becomeParentOf(expression);
  }

  @override
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

/// A constant expression being used as a pattern.
///
/// The only expressions that can be validly used as a pattern are
/// - `bool` literals
/// - `double` literals
/// - `int` literals
/// - `null` literals
/// - `String` literals
/// - references to constant variables
/// - constant constructor invocations
/// - constant list literals
/// - constant set or map literals
/// - constant expressions wrapped in parentheses and preceded by the `const`
///   keyword
///
/// This node is also used to recover from cases where a different kind of
/// expression is used as a pattern, so clients need to handle the case where
/// the expression isn't one of the valid alternatives.
///
///    constantPattern ::=
///        'const'? [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ConstantPattern implements DartPattern {
  /// The `const` keyword, or `null` if the expression isn't preceded by the
  /// keyword `const`.
  Token? get constKeyword;

  /// The constant expression being used as a pattern.
  Expression get expression;
}

final class ConstantPatternImpl extends DartPatternImpl
    implements ConstantPattern {
  @override
  final Token? constKeyword;

  ExpressionImpl _expression;

  ConstantPatternImpl({
    required this.constKeyword,
    required ExpressionImpl expression,
  }) : _expression = expression {
    _becomeParentOf(expression);
  }

  @override
  Token get beginToken => constKeyword ?? expression.beginToken;

  @override
  Token get endToken => expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  PatternPrecedence get precedence => PatternPrecedence.primary;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('const', constKeyword)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitConstantPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeConstantPatternSchema()
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var analysisResult = resolverVisitor.analyzeConstantPattern(
      context,
      this,
      expression,
    );
    expression = resolverVisitor.popRewrite()!;
    inferenceLogWriter?.exitPattern(this);
    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    expression.accept(visitor);
  }
}

/// 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] ('.' name)?
///
///    factoryName ::=
///        [Identifier] ('.' [SimpleIdentifier])?
///
///    initializerList ::=
///        ':' [ConstructorInitializer] (',' [ConstructorInitializer])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ConstructorDeclaration implements ClassMember {
  /// The `augment` keyword, or `null` if the keyword was absent.
  Token? get augmentKeyword;

  /// The body of the constructor.
  FunctionBody get body;

  /// The token for the `const` keyword, or `null` if the constructor isn't a
  /// const constructor.
  Token? get constKeyword;

  @experimental
  @override
  ConstructorFragment? get declaredFragment;

  /// The token for the `external` keyword to this constructor declaration.
  Token? get externalKeyword;

  /// The token for the `factory` keyword, or `null` if the constructor isn't a
  /// factory constructor.
  Token? get factoryKeyword;

  /// The initializers associated with the constructor.
  NodeList<ConstructorInitializer> get initializers;

  /// The name of the constructor, or `null` if the constructor being declared
  /// is unnamed.
  Token? get name;

  /// The parameters associated with the constructor.
  FormalParameterList get parameters;

  /// The token for the period before the constructor name, or `null` if the
  /// constructor being declared is unnamed.
  Token? get period;

  /// The name of the constructor to which this constructor is redirected, or
  /// `null` if this isn't a redirecting factory constructor.
  ConstructorName? get redirectedConstructor;

  /// The type of object being created.
  Identifier get returnType;

  /// The token for the separator (colon or equals) before the initializer list
  /// or redirection, or `null` if there are neither initializers nor a
  /// redirection.
  Token? get separator;
}

final class ConstructorDeclarationImpl extends ClassMemberImpl
    implements ConstructorDeclaration {
  @override
  final Token? augmentKeyword;

  @override
  final Token? externalKeyword;

  @override
  Token? constKeyword;

  @override
  final Token? factoryKeyword;

  IdentifierImpl _returnType;

  @override
  final Token? period;

  @override
  final Token? name;

  FormalParameterListImpl _parameters;

  @override
  Token? separator;

  final NodeListImpl<ConstructorInitializerImpl> _initializers =
      NodeListImpl._();

  ConstructorNameImpl? _redirectedConstructor;

  FunctionBodyImpl _body;

  @override
  ConstructorElementImpl? declaredFragment;

  /// Initializes a newly created constructor declaration.
  ///
  /// The [externalKeyword] can be `null` if the constructor isn't external.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// constructor doesn't have the corresponding attribute.
  ///
  /// The [constKeyword] can be `null` if the constructor can't be used to
  /// create a constant.
  ///
  /// The [factoryKeyword] can be `null` if the constructor isn't a factory.
  ///
  /// The [period] and [name] can both be `null` if the constructor isn't a
  /// named constructor.
  ///
  /// The [separator] can be `null` if the constructor doesn't have any
  /// initializers and doesn't redirect to a different constructor.
  ///
  /// The list of [initializers] can be `null` if the constructor doesn't have
  /// any initializers.
  ///
  /// The [redirectedConstructor] can be `null` if the constructor doesn't
  /// redirect to a different constructor.
  ///
  /// The [body] can be `null` if the constructor doesn't have a body.
  ConstructorDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.externalKeyword,
    required this.constKeyword,
    required this.factoryKeyword,
    required IdentifierImpl returnType,
    required this.period,
    required this.name,
    required FormalParameterListImpl parameters,
    required this.separator,
    required List<ConstructorInitializerImpl>? initializers,
    required ConstructorNameImpl? redirectedConstructor,
    required FunctionBodyImpl body,
  }) : _returnType = returnType,
       _parameters = parameters,
       _redirectedConstructor = redirectedConstructor,
       _body = body {
    _becomeParentOf(_returnType);
    _becomeParentOf(_parameters);
    _initializers._initialize(this, initializers);
    _becomeParentOf(_redirectedConstructor);
    _becomeParentOf(_body);
  }

  @override
  FunctionBodyImpl get body => _body;

  set body(FunctionBodyImpl functionBody) {
    _body = _becomeParentOf(functionBody);
  }

  @override
  Token get endToken {
    return _body.endToken;
  }

  @override
  Token get firstTokenAfterCommentAndMetadata {
    return Token.lexicallyFirst(
          externalKeyword,
          constKeyword,
          factoryKeyword,
          augmentKeyword,
        ) ??
        _returnType.beginToken;
  }

  @override
  NodeListImpl<ConstructorInitializerImpl> get initializers => _initializers;

  /// Whether this is a trivial constructor.
  ///
  /// A trivial constructor is a generative constructor that isn't a redirecting
  /// constructor, declares no parameters, has no initializer list, has no body,
  /// and isn't external.
  bool get isTrivial =>
      redirectedConstructor == null &&
      parameters.parameters.isEmpty &&
      initializers.isEmpty &&
      body is EmptyFunctionBody &&
      externalKeyword == null;

  @override
  FormalParameterListImpl get parameters => _parameters;

  set parameters(FormalParameterListImpl parameters) {
    _parameters = _becomeParentOf(parameters);
  }

  @override
  ConstructorNameImpl? get redirectedConstructor => _redirectedConstructor;

  set redirectedConstructor(ConstructorNameImpl? redirectedConstructor) {
    _redirectedConstructor = _becomeParentOf(
      redirectedConstructor as ConstructorNameImpl,
    );
  }

  @override
  IdentifierImpl get returnType => _returnType;

  set returnType(IdentifierImpl typeName) {
    _returnType = _becomeParentOf(typeName);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('externalKeyword', externalKeyword)
        ..addToken('constKeyword', constKeyword)
        ..addToken('factoryKeyword', factoryKeyword)
        ..addNode('returnType', returnType)
        ..addToken('period', period)
        ..addToken('name', name)
        ..addNode('parameters', parameters)
        ..addToken('separator', separator)
        ..addNodeList('initializers', initializers)
        ..addNode('redirectedConstructor', redirectedConstructor)
        ..addNode('body', body);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitConstructorDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _returnType.accept(visitor);
    _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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ConstructorFieldInitializer
    implements ConstructorInitializer {
  /// The token for the equal sign between the field name and the expression.
  Token get equals;

  /// The expression computing the value to which the field is initialized.
  Expression get expression;

  /// The name of the field being initialized.
  SimpleIdentifier get fieldName;

  /// The token for the period after the `this` keyword, or `null` if there's no
  /// `this` keyword.
  Token? get period;

  /// The token for the `this` keyword, or `null` if there's no `this` keyword.
  Token? get thisKeyword;
}

final class ConstructorFieldInitializerImpl extends ConstructorInitializerImpl
    implements ConstructorFieldInitializer {
  @override
  final Token? thisKeyword;

  @override
  final Token? period;

  SimpleIdentifierImpl _fieldName;

  @override
  final Token equals;

  ExpressionImpl _expression;

  /// Initializes 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 isn't
  /// specified.
  ConstructorFieldInitializerImpl({
    required this.thisKeyword,
    required this.period,
    required SimpleIdentifierImpl fieldName,
    required this.equals,
    required ExpressionImpl expression,
  }) : _fieldName = fieldName,
       _expression = expression {
    _becomeParentOf(_fieldName);
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken {
    if (thisKeyword case var thisKeyword?) {
      return thisKeyword;
    }
    return _fieldName.beginToken;
  }

  @override
  Token get endToken => _expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  SimpleIdentifierImpl get fieldName => _fieldName;

  set fieldName(SimpleIdentifierImpl identifier) {
    _fieldName = _becomeParentOf(identifier);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('thisKeyword', thisKeyword)
        ..addToken('period', period)
        ..addNode('fieldName', fieldName)
        ..addToken('equals', equals)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitConstructorFieldInitializer(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _fieldName.accept(visitor);
    _expression.accept(visitor);
  }
}

/// A node that can occur in the initializer list of a constructor declaration.
///
///    constructorInitializer ::=
///        [SuperConstructorInvocation]
///      | [ConstructorFieldInitializer]
///      | [RedirectingConstructorInvocation]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class ConstructorInitializer implements AstNode {}

sealed class ConstructorInitializerImpl extends AstNodeImpl
    implements ConstructorInitializer {}

/// The name of a constructor.
///
///    constructorName ::=
///        type ('.' identifier)?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ConstructorName
    implements AstNode, ConstructorReferenceNode {
  /// The name of the constructor, or `null` if the specified constructor is the
  /// unnamed constructor and the name `new` wasn't explicitly used.
  SimpleIdentifier? get name;

  /// The token for the period before the constructor name, or `null` if the
  /// specified constructor is the unnamed constructor.
  Token? get period;

  /// The name of the type defining the constructor.
  NamedType get type;
}

final class ConstructorNameImpl extends AstNodeImpl implements ConstructorName {
  NamedTypeImpl _type;

  @override
  Token? period;

  SimpleIdentifierImpl? _name;

  @override
  ConstructorElementMixin2? element;

  /// Initializes a newly created constructor name.
  ///
  /// The [period] and [name] can be `null` if the constructor being named is
  /// the unnamed constructor.
  ConstructorNameImpl({
    required NamedTypeImpl type,
    required this.period,
    required SimpleIdentifierImpl? name,
  }) : _type = type,
       _name = name {
    _becomeParentOf(_type);
    _becomeParentOf(_name);
  }

  @override
  Token get beginToken => _type.beginToken;

  @override
  Token get endToken {
    if (name case var name?) {
      return name.endToken;
    }
    return _type.endToken;
  }

  @override
  SimpleIdentifierImpl? get name => _name;

  set name(SimpleIdentifierImpl? name) {
    _name = _becomeParentOf(name);
  }

  @override
  NamedTypeImpl get type => _type;

  set type(NamedTypeImpl type) {
    _type = _becomeParentOf(type);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('type', type)
        ..addToken('period', period)
        ..addNode('name', name);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitConstructorName(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _type.accept(visitor);
    _name?.accept(visitor);
  }
}

/// An expression representing a reference to a constructor.
///
/// For example, the expression `List.filled` in `var x = List.filled;`.
///
/// Objects of this type aren't produced directly by the parser (because the
/// parser can't tell whether an identifier refers to a type); they are
/// produced at resolution time.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ConstructorReference
    implements Expression, CommentReferableExpression {
  /// The constructor being referenced.
  ConstructorName get constructorName;
}

final class ConstructorReferenceImpl extends CommentReferableExpressionImpl
    implements ConstructorReference {
  ConstructorNameImpl _constructorName;

  ConstructorReferenceImpl({required ConstructorNameImpl constructorName})
    : _constructorName = constructorName {
    _becomeParentOf(_constructorName);
  }

  @override
  Token get beginToken => constructorName.beginToken;

  @override
  ConstructorNameImpl get constructorName => _constructorName;

  set constructorName(ConstructorNameImpl value) {
    _constructorName = _becomeParentOf(value);
  }

  @override
  Token get endToken => constructorName.endToken;

  @override
  Precedence get precedence => Precedence.postfix;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addNode('constructorName', constructorName);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitConstructorReference(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitConstructorReference(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    constructorName.accept(visitor);
  }
}

/// An AST node that makes reference to a constructor.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ConstructorReferenceNode implements AstNode {
  /// The element associated with the referenced constructor based on static
  /// type information.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if the
  /// constructor couldn't be resolved.
  @experimental
  ConstructorElement2? get element;
}

/// The name of a constructor being invoked.
///
///    constructorSelector ::=
///        '.' identifier
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ConstructorSelector implements AstNode {
  /// The constructor name.
  SimpleIdentifier get name;

  /// The period before the constructor name.
  Token get period;
}

final class ConstructorSelectorImpl extends AstNodeImpl
    implements ConstructorSelector {
  @override
  final Token period;

  @override
  final SimpleIdentifierImpl name;

  ConstructorSelectorImpl({required this.period, required this.name}) {
    _becomeParentOf(name);
  }

  @override
  Token get beginToken => period;

  @override
  Token get endToken => name.token;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('period', period)
        ..addNode('name', name);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitConstructorSelector(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {}
}

/// A continue statement.
///
///    continueStatement ::=
///        'continue' [SimpleIdentifier]? ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ContinueStatement implements Statement {
  /// The token representing the `continue` keyword.
  Token get continueKeyword;

  /// The label associated with the statement, or `null` if there's no label.
  SimpleIdentifier? get label;

  /// The semicolon terminating the statement.
  Token get semicolon;

  /// The node to which this continue statement is continuing, or `null` if the
  /// AST hasn't yet been resolved or if the target couldn't be resolved.
  ///
  /// This is either a [Statement] (in the case of continuing a loop), or a
  /// [SwitchMember] (in the case of continuing from one switch case to
  /// another).
  ///
  /// Note that if the source code has errors, the target might be invalid.
  /// For example, the target might be in an enclosing function.
  AstNode? get target;
}

final class ContinueStatementImpl extends StatementImpl
    implements ContinueStatement {
  @override
  final Token continueKeyword;

  SimpleIdentifierImpl? _label;

  @override
  final Token semicolon;

  @override
  AstNode? target;

  /// Initializes a newly created continue statement.
  ///
  /// The [label] can be `null` if there's no label associated with the
  /// statement.
  ContinueStatementImpl({
    required this.continueKeyword,
    required SimpleIdentifierImpl? label,
    required this.semicolon,
  }) : _label = label {
    _becomeParentOf(_label);
  }

  @override
  Token get beginToken => continueKeyword;

  @override
  Token get endToken => semicolon;

  @override
  SimpleIdentifierImpl? get label => _label;

  set label(SimpleIdentifierImpl? identifier) {
    _label = _becomeParentOf(identifier);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('continueKeyword', continueKeyword)
        ..addNode('label', label)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitContinueStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _label?.accept(visitor);
  }
}

/// A pattern.
///
///    pattern ::=
///        [AssignedVariablePattern]
///      | [DeclaredVariablePattern]
///      | [CastPattern]
///      | [ConstantPattern]
///      | [ListPattern]
///      | [LogicalAndPattern]
///      | [LogicalOrPattern]
///      | [MapPattern]
///      | [NullAssertPattern]
///      | [NullCheckPattern]
///      | [ObjectPattern]
///      | [ParenthesizedPattern]
///      | [RecordPattern]
///      | [RelationalPattern]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class DartPattern implements AstNode, ListPatternElement {
  /// The matched value type, or `null` if the node isn't resolved yet.
  DartType? get matchedValueType;

  /// The precedence of this pattern.
  ///
  /// The precedence is a positive integer value that defines how the source
  /// code is parsed into an AST. For example `a | b & c` is parsed as `a | (b
  /// & c)` because the precedence of `&` is greater than the precedence of `|`.
  PatternPrecedence get precedence;

  /// If this pattern is a parenthesized pattern, the result of unwrapping the
  /// pattern inside the parentheses. Otherwise, this pattern.
  DartPattern get unParenthesized;
}

sealed class DartPatternImpl extends AstNodeImpl
    implements DartPattern, ListPatternElementImpl {
  @override
  TypeImpl? matchedValueType;

  /// The context for this pattern.
  ///
  /// The possible contexts are
  /// - Declaration context:
  ///     [ForEachPartsWithPatternImpl]
  ///     [PatternVariableDeclarationImpl]
  /// - Assignment context: [PatternAssignmentImpl]
  /// - Matching context: [GuardedPatternImpl]
  AstNodeImpl? get patternContext {
    for (DartPatternImpl current = this; ;) {
      var parent = current.parent;
      if (parent is MapPatternEntry) {
        parent = parent.parent;
      } else if (parent is PatternFieldImpl) {
        parent = parent.parent;
      } else if (parent is RestPatternElementImpl) {
        parent = parent.parent;
      }
      if (parent is ForEachPartsWithPatternImpl) {
        return parent;
      } else if (parent is PatternVariableDeclarationImpl) {
        return parent;
      } else if (parent is PatternAssignmentImpl) {
        return parent;
      } else if (parent is GuardedPatternImpl) {
        return parent;
      } else if (parent is DartPatternImpl) {
        current = parent;
      } else {
        return null;
      }
    }
  }

  @override
  DartPattern get unParenthesized => this;

  /// The variable pattern, itself, or wrapped in a unary pattern.
  VariablePatternImpl? get variablePattern => null;

  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor);

  /// Dispatches this pattern to the [resolverVisitor], with the given [context]
  /// information.
  ///
  /// Note: most code shouldn't call this method directly, but should instead
  /// call [ResolverVisitor.dispatchPattern], which has some special logic for
  /// handling dynamic contexts.
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  );
}

/// A node that represents the declaration of one or more names.
///
/// Each declared name is visible within a name scope.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Declaration implements AnnotatedNode {
  /// The fragment declared by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  @experimental
  Fragment? get declaredFragment;
}

sealed class DeclarationImpl extends AnnotatedNodeImpl implements Declaration {
  /// Initializes a newly created declaration.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// declaration doesn't have the corresponding attribute.
  DeclarationImpl({required super.comment, required super.metadata});
}

/// The declaration of a single identifier.
///
///    declaredIdentifier ::=
///        [Annotation] finalConstVarOrType [SimpleIdentifier]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class DeclaredIdentifier implements Declaration {
  /// The element associated with this declaration.
  ///
  /// Returns `null` if either this node corresponds to a list of declarations
  /// or if the AST structure hasn't been resolved.
  @experimental
  LocalVariableElement2? get declaredElement2;

  @override
  LocalVariableFragment? get declaredFragment;

  /// Whether this variable was declared with the 'const' modifier.
  bool get isConst;

  /// Whether this variable was declared with the 'final' modifier.
  ///
  /// Returns `false` for variables that are declared with the 'const' modifier
  /// even though they are implicitly final.
  bool get isFinal;

  /// The token representing either the `final`, `const` or `var` keyword, or
  /// `null` if no keyword was used.
  Token? get keyword;

  /// The name of the variable being declared.
  Token get name;

  /// The name of the declared type of the parameter, or `null` if the parameter
  /// doesn't have a declared type.
  TypeAnnotation? get type;
}

final class DeclaredIdentifierImpl extends DeclarationImpl
    implements DeclaredIdentifier {
  @override
  final Token? keyword;

  TypeAnnotationImpl? _type;

  @override
  final Token name;

  @override
  LocalVariableElementImpl? declaredFragment;

  /// Initializes a newly created formal parameter.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// declaration doesn't 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({
    required super.comment,
    required super.metadata,
    required this.keyword,
    required TypeAnnotationImpl? type,
    required this.name,
  }) : _type = type {
    _becomeParentOf(_type);
  }

  @experimental
  @override
  LocalVariableElementImpl2? get declaredElement2 {
    return declaredFragment?.element;
  }

  @override
  Token get endToken => name;

  @override
  Token get firstTokenAfterCommentAndMetadata {
    return keyword ?? _type?.beginToken ?? name;
  }

  @override
  bool get isConst => keyword?.keyword == Keyword.CONST;

  @override
  bool get isFinal => keyword?.keyword == Keyword.FINAL;

  @override
  TypeAnnotationImpl? get type => _type;

  set type(TypeAnnotationImpl? type) {
    _type = _becomeParentOf(type);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('keyword', keyword)
        ..addNode('type', type)
        ..addToken('name', name);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitDeclaredIdentifier(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _type?.accept(visitor);
  }
}

/// A variable pattern that declares a variable.
///
///    variablePattern ::=
///        ( 'var' | 'final' | 'final'? [TypeAnnotation])? [Identifier]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class DeclaredVariablePattern implements VariablePattern {
  /// The element declared by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  @experimental
  BindPatternVariableElement2? get declaredElement2;

  /// The fragment declared by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  BindPatternVariableFragment? get declaredFragment;

  /// The `var` or `final` keyword.
  Token? get keyword;

  /// The type that the variable is required to match, or `null` if any type is
  /// matched.
  TypeAnnotation? get type;
}

final class DeclaredVariablePatternImpl extends VariablePatternImpl
    implements DeclaredVariablePattern {
  @override
  BindPatternVariableElementImpl? declaredFragment;

  @override
  final Token? keyword;

  @override
  final TypeAnnotationImpl? type;

  DeclaredVariablePatternImpl({
    required this.keyword,
    required this.type,
    required super.name,
  }) {
    _becomeParentOf(type);
  }

  @override
  Token get beginToken => keyword ?? type?.beginToken ?? name;

  @experimental
  @override
  BindPatternVariableElementImpl2? get declaredElement2 {
    return declaredFragment?.element;
  }

  @override
  Token get endToken => name;

  /// The `final` keyword, or `null` if the `final` keyword isn't used.
  Token? get finalKeyword {
    var keyword = this.keyword;
    if (keyword != null && keyword.keyword == Keyword.FINAL) {
      return keyword;
    }
    return null;
  }

  @override
  PatternPrecedence get precedence => PatternPrecedence.primary;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('keyword', keyword)
        ..addNode('type', type)
        ..addToken('name', name);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitDeclaredVariablePattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeDeclaredVariablePatternSchema(
          type?.typeOrThrow.wrapSharedTypeView(),
        )
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var result = resolverVisitor.analyzeDeclaredVariablePattern(
      context,
      this,
      declaredElement2!,
      declaredFragment!.name,
      type?.typeOrThrow.wrapSharedTypeView(),
    );
    declaredElement2!.type = result.staticType.unwrapTypeView();

    resolverVisitor.checkPatternNeverMatchesValueType(
      context: context,
      pattern: this,
      requiredType: result.staticType.unwrapTypeView(),
      matchedValueType: result.matchedValueType.unwrapTypeView(),
    );
    inferenceLogWriter?.exitPattern(this);

    return result;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    type?.accept(visitor);
  }
}

/// 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])?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class DefaultFormalParameter implements FormalParameter {
  /// The expression computing the default value for the parameter, or `null` if
  /// there's no default value.
  Expression? get defaultValue;

  /// The formal parameter with which the default value is associated.
  NormalFormalParameter get parameter;

  /// The token separating the parameter from the default value, or `null` if
  /// there's no default value.
  Token? get separator;
}

final class DefaultFormalParameterImpl extends FormalParameterImpl
    implements DefaultFormalParameter {
  NormalFormalParameterImpl _parameter;

  @override
  ParameterKind kind;

  @override
  final Token? separator;

  ExpressionImpl? _defaultValue;

  /// Initializes a newly created default formal parameter.
  ///
  /// The [separator] and [defaultValue] can be `null` if there's no default
  /// value.
  DefaultFormalParameterImpl({
    required NormalFormalParameterImpl parameter,
    required this.kind,
    required this.separator,
    required ExpressionImpl? defaultValue,
  }) : _parameter = parameter,
       _defaultValue = defaultValue {
    _becomeParentOf(_parameter);
    _becomeParentOf(_defaultValue);
  }

  @override
  Token get beginToken => _parameter.beginToken;

  @override
  Token? get covariantKeyword => null;

  @experimental
  @override
  ParameterElementImpl? get declaredFragment => _parameter.declaredFragment;

  @override
  ExpressionImpl? get defaultValue => _defaultValue;

  set defaultValue(ExpressionImpl? expression) {
    _defaultValue = _becomeParentOf(expression);
  }

  @override
  Token get endToken {
    if (defaultValue case var defaultValue?) {
      return defaultValue.endToken;
    }
    return _parameter.endToken;
  }

  @override
  bool get isConst => _parameter.isConst;

  @override
  bool get isExplicitlyTyped => _parameter.isExplicitlyTyped;

  @override
  bool get isFinal => _parameter.isFinal;

  @override
  NodeListImpl<AnnotationImpl> get metadata => _parameter.metadata;

  @override
  Token? get name => _parameter.name;

  @override
  NormalFormalParameterImpl get parameter => _parameter;

  set parameter(NormalFormalParameterImpl formalParameter) {
    _parameter = _becomeParentOf(formalParameter);
  }

  @override
  Token? get requiredKeyword => null;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('parameter', parameter)
        ..addToken('separator', separator)
        ..addNode('defaultValue', defaultValue);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitDefaultFormalParameter(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _parameter.accept(visitor);
    _defaultValue?.accept(visitor);
  }
}

/// A node that represents a directive.
///
///    directive ::=
///        [ExportDirective]
///      | [ImportDirective]
///      | [LibraryDirective]
///      | [PartDirective]
///      | [PartOfDirective]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class Directive implements AnnotatedNode {}

sealed class DirectiveImpl extends AnnotatedNodeImpl implements Directive {
  ElementImpl? element;

  /// Initializes a newly create directive.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// directive doesn't have the corresponding attribute.
  DirectiveImpl({required super.comment, required super.metadata});
}

/// A do statement.
///
///    doStatement ::=
///        'do' [Statement] 'while' '(' [Expression] ')' ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class DoStatement implements Statement {
  /// The body of the loop.
  Statement get body;

  /// The condition that determines when the loop terminates.
  Expression get condition;

  /// The token representing the `do` keyword.
  Token get doKeyword;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;

  /// The semicolon terminating the statement.
  Token get semicolon;

  /// The token representing the `while` keyword.
  Token get whileKeyword;
}

final class DoStatementImpl extends StatementImpl implements DoStatement {
  @override
  final Token doKeyword;

  StatementImpl _body;

  @override
  final Token whileKeyword;

  @override
  final Token leftParenthesis;

  ExpressionImpl _condition;

  @override
  final Token rightParenthesis;

  @override
  final Token semicolon;

  /// Initializes a newly created do loop.
  DoStatementImpl({
    required this.doKeyword,
    required StatementImpl body,
    required this.whileKeyword,
    required this.leftParenthesis,
    required ExpressionImpl condition,
    required this.rightParenthesis,
    required this.semicolon,
  }) : _body = body,
       _condition = condition {
    _becomeParentOf(_body);
    _becomeParentOf(_condition);
  }

  @override
  Token get beginToken => doKeyword;

  @override
  StatementImpl get body => _body;

  set body(StatementImpl statement) {
    _body = _becomeParentOf(statement);
  }

  @override
  ExpressionImpl get condition => _condition;

  set condition(ExpressionImpl expression) {
    _condition = _becomeParentOf(expression);
  }

  @override
  Token get endToken => semicolon;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('doKeyword', doKeyword)
        ..addNode('body', body)
        ..addToken('whileKeyword', whileKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('condition', condition)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitDoStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _body.accept(visitor);
    _condition.accept(visitor);
  }
}

/// A node that represents a dot shorthand constructor invocation.
///
/// For example, `.fromCharCode(42)`.
///
///    dotShorthandHead ::=
///        '.' [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
@experimental
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class DotShorthandConstructorInvocation
    extends InvocationExpression
    implements ConstructorReferenceNode {
  /// The name of the constructor invocation.
  SimpleIdentifier get constructorName;

  /// The token representing the period.
  Token get period;
}

final class DotShorthandConstructorInvocationImpl
    extends InvocationExpressionImpl
    implements
        DotShorthandConstructorInvocation,
        RewrittenMethodInvocationImpl {
  @override
  final Token period;

  SimpleIdentifierImpl _constructorName;

  @override
  ConstructorElementImpl2? element;

  /// Initializes a newly created dot shorthand constructor invocation.
  DotShorthandConstructorInvocationImpl({
    required this.period,
    required SimpleIdentifierImpl constructorName,
    required super.typeArguments,
    required super.argumentList,
  }) : _constructorName = constructorName {
    _becomeParentOf(_constructorName);
  }

  @override
  Token get beginToken => period;

  @override
  SimpleIdentifierImpl get constructorName => _constructorName;

  set constructorName(SimpleIdentifierImpl identifier) {
    _constructorName = _becomeParentOf(identifier);
  }

  @override
  Token get endToken => argumentList.endToken;

  @override
  ExpressionImpl get function => constructorName;

  @override
  Precedence get precedence => Precedence.postfix;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('period', period)
        ..addNode('constructorName', constructorName)
        ..addNode('typeArguments', typeArguments)
        ..addNode('argumentList', argumentList);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitDotShorthandConstructorInvocation(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    throw StateError(
      'DotShorthandConstructorInvocationImpl should only appear in fully'
      ' resolved ASTs',
    );
  }

  @override
  void visitChildren(AstVisitor visitor) {
    constructorName.accept(visitor);
    typeArguments?.accept(visitor);
    argumentList.accept(visitor);
  }
}

/// A node that represents a dot shorthand static method or constructor
/// invocation.
///
/// For example, `.parse('42')`.
///
///    dotShorthandHead ::=
///        '.' [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
@experimental
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class DotShorthandInvocation extends InvocationExpression {
  /// The name of the constructor or static method invocation.
  SimpleIdentifier get memberName;

  /// The token representing the period.
  Token get period;
}

final class DotShorthandInvocationImpl extends InvocationExpressionImpl
    with DotShorthandMixin
    implements DotShorthandInvocation {
  @override
  final Token period;

  SimpleIdentifierImpl _memberName;

  /// Initializes a newly created dot shorthand invocation.
  DotShorthandInvocationImpl({
    required this.period,
    required SimpleIdentifierImpl memberName,
    required super.typeArguments,
    required super.argumentList,
  }) : _memberName = memberName {
    _becomeParentOf(_memberName);
  }

  @override
  Token get beginToken => period;

  @override
  Token get endToken => argumentList.endToken;

  @override
  ExpressionImpl get function => memberName;

  @override
  SimpleIdentifierImpl get memberName => _memberName;

  set memberName(SimpleIdentifierImpl identifier) {
    _memberName = _becomeParentOf(identifier);
  }

  @override
  Precedence get precedence => Precedence.postfix;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('period', period)
        ..addNode('memberName', memberName)
        ..addNode('typeArguments', typeArguments)
        ..addNode('argumentList', argumentList);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitDotShorthandInvocation(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitDotShorthandInvocation(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    memberName.accept(visitor);
    typeArguments?.accept(visitor);
    argumentList.accept(visitor);
  }
}

base mixin DotShorthandMixin on ExpressionImpl {
  /// Whether the AST node is a dot shorthand and has a dot shorthand head
  /// ([DotShorthandInvocation] or [DotShorthandPropertyAccess]) as its
  /// inner-most target.
  bool isDotShorthand = false;
}

/// A node that represents a dot shorthand property access of a field or a
/// static getter.
///
/// For example, `.zero`.
///
///    dotShorthandHead ::= '.' [SimpleIdentifier]
@experimental
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class DotShorthandPropertyAccess extends Expression {
  /// The token representing the period.
  Token get period;

  /// The name of the property being accessed.
  SimpleIdentifier get propertyName;
}

final class DotShorthandPropertyAccessImpl extends ExpressionImpl
    with DotShorthandMixin
    implements DotShorthandPropertyAccess {
  @override
  final Token period;

  SimpleIdentifierImpl _propertyName;

  /// Initializes a newly created dot shorthand property access.
  DotShorthandPropertyAccessImpl({
    required this.period,
    required SimpleIdentifierImpl propertyName,
  }) : _propertyName = propertyName {
    _becomeParentOf(_propertyName);
  }

  @override
  Token get beginToken => period;

  @override
  Token get endToken => propertyName.endToken;

  @override
  Precedence get precedence => Precedence.postfix;

  @override
  SimpleIdentifierImpl get propertyName => _propertyName;

  set propertyName(SimpleIdentifierImpl identifier) {
    _propertyName = _becomeParentOf(identifier);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('period', period)
        ..addNode('propertyName', propertyName);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitDotShorthandPropertyAccess(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitDotShorthandPropertyAccess(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    propertyName.accept(visitor);
  }
}

/// A dotted name, used in a configuration within an import or export directive.
///
///    dottedName ::=
///        [SimpleIdentifier] ('.' [SimpleIdentifier])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class DottedName implements AstNode {
  /// The components of the identifier.
  NodeList<SimpleIdentifier> get components;
}

final class DottedNameImpl extends AstNodeImpl implements DottedName {
  final NodeListImpl<SimpleIdentifierImpl> _components = NodeListImpl._();

  /// Initializes a newly created dotted name.
  ///
  /// The list of [components] must contain at least one element.
  DottedNameImpl({required List<SimpleIdentifierImpl> components}) {
    _components._initialize(this, components);
  }

  @override
  Token get beginToken => _components.beginToken!;

  @override
  NodeListImpl<SimpleIdentifierImpl> get components => _components;

  @override
  Token get endToken => _components.endToken!;

  @override
  // TODO(paulberry): add "." tokens.
  ChildEntities get _childEntities =>
      ChildEntities()..addNodeList('components', components);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitDottedName(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _components.accept(visitor);
  }
}

/// A floating point literal expression.
///
///    doubleLiteral ::=
///        decimalDigit+ ('.' decimalDigit*)? exponent?
///      | '.' decimalDigit+ exponent?
///
///    exponent ::=
///        ('e' | 'E') ('+' | '-')? decimalDigit+
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class DoubleLiteral implements Literal {
  /// The token representing the literal.
  Token get literal;

  /// The value of the literal.
  double get value;
}

final class DoubleLiteralImpl extends LiteralImpl implements DoubleLiteral {
  @override
  final Token literal;

  @override
  double value;

  /// Initializes a newly created floating point literal.
  DoubleLiteralImpl({required this.literal, required this.value});

  @override
  Token get beginToken => literal;

  @override
  Token get endToken => literal;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('literal', literal);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitDoubleLiteral(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitDoubleLiteral(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// An empty function body.
///
/// An empty function body can only appear in constructors or abstract methods.
///
///    emptyFunctionBody ::=
///        ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class EmptyFunctionBody implements FunctionBody {
  /// The token representing the semicolon that marks the end of the function
  /// body.
  Token get semicolon;
}

final class EmptyFunctionBodyImpl extends FunctionBodyImpl
    implements EmptyFunctionBody {
  @override
  final Token semicolon;

  /// Initializes a newly created function body.
  EmptyFunctionBodyImpl({required this.semicolon});

  @override
  Token get beginToken => semicolon;

  @override
  Token get endToken => semicolon;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitEmptyFunctionBody(this);

  @override
  TypeImpl resolve(ResolverVisitor resolver, TypeImpl? imposedType) =>
      resolver.visitEmptyFunctionBody(this, imposedType: imposedType);

  @override
  void visitChildren(AstVisitor visitor) {
    // Empty function bodies have no children.
  }
}

/// An empty statement.
///
///    emptyStatement ::=
///        ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class EmptyStatement implements Statement {
  /// The semicolon terminating the statement.
  Token get semicolon;
}

final class EmptyStatementImpl extends StatementImpl implements EmptyStatement {
  @override
  final Token semicolon;

  /// Initializes a newly created empty statement.
  EmptyStatementImpl({required this.semicolon});

  @override
  Token get beginToken => semicolon;

  @override
  Token get endToken => semicolon;

  @override
  bool get isSynthetic => semicolon.isSynthetic;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitEmptyStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// The arguments part of an enum constant.
///
///    enumConstantArguments ::=
///        [TypeArgumentList]? [ConstructorSelector]? [ArgumentList]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class EnumConstantArguments implements AstNode {
  /// The explicit arguments (there are always implicit `index` and `name`
  /// leading arguments) to the invoked constructor.
  ArgumentList get argumentList;

  /// The selector of the constructor that is invoked by this enum constant, or
  /// `null` if the default constructor is invoked.
  ConstructorSelector? get constructorSelector;

  /// The type arguments applied to the enclosing enum declaration when invoking
  /// the constructor, or `null` if no type arguments were provided.
  TypeArgumentList? get typeArguments;
}

final class EnumConstantArgumentsImpl extends AstNodeImpl
    implements EnumConstantArguments {
  @override
  final TypeArgumentListImpl? typeArguments;

  @override
  final ConstructorSelectorImpl? constructorSelector;

  @override
  final ArgumentListImpl argumentList;

  EnumConstantArgumentsImpl({
    required this.typeArguments,
    required this.constructorSelector,
    required this.argumentList,
  }) {
    _becomeParentOf(typeArguments);
    _becomeParentOf(constructorSelector);
    _becomeParentOf(argumentList);
  }

  @override
  Token get beginToken =>
      (typeArguments ?? constructorSelector ?? argumentList).beginToken;

  @override
  Token get endToken => argumentList.endToken;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('typeArguments', typeArguments)
        ..addNode('constructorSelector', constructorSelector)
        ..addNode('argumentList', argumentList);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitEnumConstantArguments(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    typeArguments?.accept(visitor);
    constructorSelector?.accept(visitor);
    argumentList.accept(visitor);
  }
}

/// The declaration of an enum constant.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class EnumConstantDeclaration implements Declaration {
  /// The explicit arguments (there are always implicit `index` and `name`
  /// leading arguments) to the invoked constructor, or `null` if this constant
  /// doesn't provide any explicit arguments.
  EnumConstantArguments? get arguments;

  /// The `augment` keyword, or `null` if the keyword was absent.
  @experimental
  Token? get augmentKeyword;

  /// The constructor that's invoked by this enum constant.
  ///
  /// Returns `null` if the AST structure hasn't been resolved, or if the
  /// constructor couldn't be resolved.
  @experimental
  ConstructorElement2? get constructorElement2;

  @experimental
  @override
  FieldFragment? get declaredFragment;

  /// The name of the constant.
  Token get name;
}

final class EnumConstantDeclarationImpl extends DeclarationImpl
    implements EnumConstantDeclaration {
  @override
  final Token? augmentKeyword;

  @override
  final Token name;

  @override
  FieldElementImpl? declaredFragment;

  @override
  final EnumConstantArgumentsImpl? arguments;

  @override
  ConstructorElementMixin2? constructorElement2;

  /// Initializes a newly created enum constant declaration.
  ///
  /// Either or both of the [documentationComment] and [metadata] can be `null`
  /// if the constant doesn't have the corresponding attributes.
  EnumConstantDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.name,
    required this.arguments,
  }) {
    _becomeParentOf(arguments);
  }

  @override
  Token get endToken => arguments?.endToken ?? name;

  @override
  Token get firstTokenAfterCommentAndMetadata => augmentKeyword ?? name;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('name', name)
        ..addNode('arguments', arguments);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitEnumConstantDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    arguments?.accept(visitor);
  }
}

/// The declaration of an enumeration.
///
///    enumType ::=
///        metadata 'enum' name [TypeParameterList]?
///        [WithClause]? [ImplementsClause]? '{' [SimpleIdentifier]
///        (',' [SimpleIdentifier])* (';' [ClassMember]+)? '}'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class EnumDeclaration implements NamedCompilationUnitMember {
  /// The `augment` keyword, or `null` if the keyword was absent.
  @experimental
  Token? get augmentKeyword;

  /// The enumeration constants being declared.
  NodeList<EnumConstantDeclaration> get constants;

  @experimental
  @override
  EnumFragment? get declaredFragment;

  /// The `enum` keyword.
  Token get enumKeyword;

  /// The `implements` clause for the enumeration, or `null` if the enumeration
  /// doesn't implement any interfaces.
  ImplementsClause? get implementsClause;

  /// The left curly bracket.
  Token get leftBracket;

  /// The members declared by the enumeration.
  NodeList<ClassMember> get members;

  /// The right curly bracket.
  Token get rightBracket;

  /// The optional semicolon after the last constant.
  Token? get semicolon;

  /// The type parameters for the enumeration, or `null` if the enumeration
  /// doesn't have any type parameters.
  TypeParameterList? get typeParameters;

  /// The `with` clause for the enumeration, or `null` if the enumeration
  /// doesn't have a `with` clause.
  WithClause? get withClause;
}

final class EnumDeclarationImpl extends NamedCompilationUnitMemberImpl
    with AstNodeWithNameScopeMixin
    implements EnumDeclaration {
  @override
  final Token? augmentKeyword;

  @override
  final Token enumKeyword;

  TypeParameterListImpl? _typeParameters;

  WithClauseImpl? _withClause;

  ImplementsClauseImpl? _implementsClause;

  @override
  final Token leftBracket;

  final NodeListImpl<EnumConstantDeclarationImpl> _constants = NodeListImpl._();

  @override
  final Token? semicolon;

  final NodeListImpl<ClassMemberImpl> _members = NodeListImpl._();

  @override
  final Token rightBracket;

  @override
  EnumElementImpl? declaredFragment;

  /// Initializes a newly created enumeration declaration.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// declaration doesn't have the corresponding attribute.
  ///
  /// The list of [constants] must contain at least one value.
  EnumDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.enumKeyword,
    required super.name,
    required TypeParameterListImpl? typeParameters,
    required WithClauseImpl? withClause,
    required ImplementsClauseImpl? implementsClause,
    required this.leftBracket,
    required List<EnumConstantDeclarationImpl> constants,
    required this.semicolon,
    required List<ClassMemberImpl> members,
    required this.rightBracket,
  }) : _typeParameters = typeParameters,
       _withClause = withClause,
       _implementsClause = implementsClause {
    _becomeParentOf(_typeParameters);
    _becomeParentOf(_withClause);
    _becomeParentOf(_implementsClause);
    _constants._initialize(this, constants);
    _members._initialize(this, members);
  }

  @override
  NodeListImpl<EnumConstantDeclarationImpl> get constants => _constants;

  @override
  Token get endToken => rightBracket;

  @override
  Token get firstTokenAfterCommentAndMetadata => augmentKeyword ?? enumKeyword;

  @override
  ImplementsClauseImpl? get implementsClause => _implementsClause;

  set implementsClause(ImplementsClauseImpl? implementsClause) {
    _implementsClause = _becomeParentOf(implementsClause);
  }

  @override
  NodeListImpl<ClassMemberImpl> get members => _members;

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters);
  }

  @override
  WithClauseImpl? get withClause => _withClause;

  set withClause(WithClauseImpl? withClause) {
    _withClause = _becomeParentOf(withClause);
  }

  @override
  // TODO(brianwilkerson): Add commas?
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('enumKeyword', enumKeyword)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addNode('withClause', withClause)
        ..addNode('implementsClause', implementsClause)
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('constants', constants)
        ..addToken('semicolon', semicolon)
        ..addNodeList('members', members)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitEnumDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _typeParameters?.accept(visitor);
    _withClause?.accept(visitor);
    _implementsClause?.accept(visitor);
    _constants.accept(visitor);
    _members.accept(visitor);
  }
}

/// An export directive.
///
///    exportDirective ::=
///        [Annotation] 'export' [StringLiteral] [Combinator]* ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ExportDirective implements NamespaceDirective {
  /// The token representing the `export` keyword.
  Token get exportKeyword;

  /// Information about this export directive.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  @experimental
  LibraryExport? get libraryExport;
}

final class ExportDirectiveImpl extends NamespaceDirectiveImpl
    implements ExportDirective {
  @override
  final Token exportKeyword;

  /// Initializes a newly created export directive.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// directive doesn't have the corresponding attribute.
  ///
  /// The list of [combinators] can be `null` if there are no combinators.
  ExportDirectiveImpl({
    required super.comment,
    required super.metadata,
    required this.exportKeyword,
    required super.uri,
    required super.configurations,
    required super.combinators,
    required super.semicolon,
  });

  @override
  Token get firstTokenAfterCommentAndMetadata => exportKeyword;

  @experimental
  @override
  LibraryExportElementImpl? get libraryExport {
    return element as LibraryExportElementImpl?;
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('exportKeyword', exportKeyword)
        ..addNode('uri', uri)
        ..addNodeList('combinators', combinators)
        ..addNodeList('configurations', configurations)
        ..addToken('semicolon', semicolon);

  @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 node that represents an expression.
///
///    expression ::=
///        [AssignmentExpression]
///      | [ConditionalExpression] cascadeSection*
///      | [ThrowExpression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Expression implements CollectionElement {
  /// The parameter element representing the parameter to which the value of
  /// this expression is bound.
  ///
  /// Returns `null` if any of these conditions are false:
  /// - this expression is an argument to an invocation
  /// - the AST structure has been resolved
  /// - the function being invoked is known based on static type information
  /// - this expression corresponds to one of the parameters of the function
  ///   being invoked
  @experimental
  FormalParameterElement? get correspondingParameter;

  /// Whether this expression is in a constant context.
  ///
  /// An expression _e_ is said to _occur in a constant context_,
  /// - if _e_ is an element of a constant list literal, or a key or value of an
  ///   entry of a constant map literal.
  /// - if _e_ is an actual argument of a constant object expression or of a
  ///   metadata annotation.
  /// - if _e_ is the initializing expression of a constant variable
  ///   declaration.
  /// - if _e_ is a switch case expression.
  /// - if _e_ is an immediate subexpression of an expression _e1_ which occurs
  ///   in a constant context, unless _e1_ is a `throw` expression or a function
  ///   literal.
  ///
  /// This roughly means that everything which is inside a syntactically
  /// constant expression is in a constant context. A `throw` expression is
  /// currently not allowed in a constant expression, but extensions affecting
  /// that status might be considered. A similar situation arises for function
  /// literals.
  ///
  /// Note that the default value of an optional formal parameter is _not_ a
  /// constant context. This choice reserves some freedom to modify the
  /// semantics of default values.
  bool get inConstantContext;

  /// Whether this expression is syntactically valid for the LHS of an
  /// [AssignmentExpression].
  bool get isAssignable;

  /// The precedence of this expression.
  ///
  /// The precedence is a positive integer value that defines how the source
  /// code is parsed into an AST. For example `a * b + c` is parsed as
  /// `(a * b) + c` because the precedence of `*` is greater than the precedence
  /// of `+`.
  Precedence get precedence;

  /// The static type of this expression, or `null` if the AST structure hasn't
  /// been resolved.
  DartType? get staticType;

  /// If this expression is a parenthesized expression, returns the result of
  /// unwrapping the expression inside the parentheses. Otherwise, returns this
  /// expression.
  Expression get unParenthesized;
}

/// A function body consisting of a single expression.
///
///    expressionFunctionBody ::=
///        'async'? '=>' [Expression] ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ExpressionFunctionBody implements FunctionBody {
  /// The expression representing the body of the function.
  Expression get expression;

  /// The token introducing the expression that represents the body of the
  /// function.
  Token get functionDefinition;

  /// The token representing the `async` keyword, or `null` if there's no such
  /// keyword.
  @override
  Token? get keyword;

  /// The semicolon terminating the statement.
  Token? get semicolon;

  /// The star following the `async` keyword, or `null` if there's no star.
  ///
  /// It's an error for an expression function body to feature the star, but
  /// the parser accepts it.
  @override
  Token? get star;
}

final class ExpressionFunctionBodyImpl extends FunctionBodyImpl
    with AstNodeWithNameScopeMixin
    implements ExpressionFunctionBody {
  @override
  final Token? keyword;

  @override
  final Token? star;

  @override
  final Token functionDefinition;

  ExpressionImpl _expression;

  @override
  final Token? semicolon;

  /// Initializes a newly created function body consisting of a block of
  /// statements.
  ///
  /// The [keyword] can be `null` if the function body isn't an async function
  /// body.
  ExpressionFunctionBodyImpl({
    required this.keyword,
    required this.star,
    required this.functionDefinition,
    required ExpressionImpl expression,
    required this.semicolon,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken {
    if (keyword case var keyword?) {
      return keyword;
    }
    return functionDefinition;
  }

  @override
  Token get endToken {
    if (semicolon case var semicolon?) {
      return semicolon;
    }
    return _expression.endToken;
  }

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  bool get isAsynchronous => keyword?.lexeme == Keyword.ASYNC.lexeme;

  @override
  bool get isGenerator => star != null;

  @override
  bool get isSynchronous => keyword?.lexeme != Keyword.ASYNC.lexeme;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('keyword', keyword)
        ..addToken('star', star)
        ..addToken('functionDefinition', functionDefinition)
        ..addNode('expression', expression)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitExpressionFunctionBody(this);

  @override
  TypeImpl resolve(ResolverVisitor resolver, TypeImpl? imposedType) =>
      resolver.visitExpressionFunctionBody(this, imposedType: imposedType);

  @override
  void visitChildren(AstVisitor visitor) {
    _expression.accept(visitor);
  }
}

sealed class ExpressionImpl extends AstNodeImpl
    implements CollectionElementImpl, Expression {
  TypeImpl? _staticType;

  @experimental
  @override
  FormalParameterElementMixin? get correspondingParameter {
    var 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) {
      // TODO(scheglov): https://github.com/dart-lang/sdk/issues/49102
      if (identical(parent.rightOperand, this)) {
        var parameters = parent.staticInvokeType?.formalParameters;
        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) {
      // TODO(scheglov): This doesn't look right, there's no element for
      // the operand, for `a++` we invoke `a = a + 1`, so the parameter
      // is for `1`, not for `a`.
      return parent._staticParameterElementForOperand2;
    } else if (parent is PostfixExpressionImpl) {
      // TODO(scheglov): The same as above.
      return parent._staticParameterElementForOperand2;
    }
    return null;
  }

  @override
  bool get inConstantContext {
    return constantContext(includeSelf: false) != null;
  }

  @override
  bool get isAssignable => false;

  @override
  TypeImpl? get staticType => _staticType;

  @override
  ExpressionImpl get unParenthesized => this;

  /// Returns the [AstNode] that puts node into the constant context, and
  /// the explicit `const` keyword of that node. The keyword might be absent
  /// if the constness is implicit.
  ///
  /// Returns `null` if node is not in the constant context.
  (AstNode, Token?)? constantContext({required bool includeSelf}) {
    AstNode? current = this;
    if (!includeSelf) {
      current = current.parent;
    }

    while (true) {
      switch (current) {
        case Annotation():
          return (current, null);
        case ConstantContextForExpressionImpl():
          return (current, null);
        case ConstantPatternImpl():
          if (current.constKeyword case var constKeyword?) {
            return (current, constKeyword);
          }
          return null;
        case EnumConstantArguments():
          return (current, null);
        case InstanceCreationExpression():
          var keyword = current.keyword;
          if (keyword != null && keyword.keyword == Keyword.CONST) {
            return (current, keyword);
          }
        case RecordLiteral():
          if (current.constKeyword case var constKeyword?) {
            return (current, constKeyword);
          }
        case SwitchCase():
          return (current, null);
        case TypedLiteralImpl():
          if (current.constKeyword case var constKeyword?) {
            return (current, constKeyword);
          }
        case VariableDeclarationList():
          var keyword = current.keyword;
          if (keyword != null && keyword.keyword == Keyword.CONST) {
            return (current, keyword);
          }
          return null;
        case ArgumentList():
        case Expression():
        case ForElement():
        case IfElement():
        case InterpolationExpression():
        case MapLiteralEntry():
        case NullAwareElement():
        case SpreadElement():
        case VariableDeclaration():
          break;
        default:
          return null;
      }
      current = current?.parent;
    }
  }

  /// Record that the static type of the given node is the given type.
  ///
  /// @param expression the node whose type is to be recorded
  /// @param type the static type of the node
  void recordStaticType(DartType type, {required ResolverVisitor resolver}) {
    // TODO(paulberry): remove this cast by changing the type of the parameter
    // `type`.
    _staticType = type as TypeImpl;
    if (type.isBottom) {
      resolver.flowAnalysis.flow?.handleExit();
    }
    inferenceLogWriter?.recordStaticType(this, type);
  }

  @override
  void resolveElement(
    ResolverVisitor resolver,
    CollectionLiteralContext? context,
  ) {
    resolver.analyzeExpression(
      this,
      SharedTypeSchemaView(
        context?.elementType ?? UnknownInferredType.instance,
      ),
    );
  }

  /// Dispatches this expression to the [resolver], with the given [contextType]
  /// information.
  ///
  /// Note: most code shouldn't call this method directly, but should instead
  /// call [ResolverVisitor.dispatchExpression], which has some special logic
  /// for handling dynamic contexts.
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType);

  /// Records that the static type of `this` is [type], without triggering any
  /// [ResolverVisitor] behaviors.
  ///
  /// This is used when the expression AST node occurs in a place where it is
  /// not technically a true expression, but the analyzer chooses to assign it a
  /// static type anyway (e.g. the [SimpleIdentifier] representing the method
  /// name in a method invocation).
  void setPseudoExpressionStaticType(DartType? type) {
    // TODO(paulberry): remove this cast by changing the type of the parameter
    // `type`.
    _staticType = type as TypeImpl?;
  }
}

/// An expression used as a statement.
///
///    expressionStatement ::=
///        [Expression]? ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ExpressionStatement implements Statement {
  /// The expression that comprises the statement.
  Expression get expression;

  /// The semicolon terminating the statement, or `null` if the expression is a
  /// function expression and therefore isn't followed by a semicolon.
  Token? get semicolon;
}

final class ExpressionStatementImpl extends StatementImpl
    implements ExpressionStatement {
  ExpressionImpl _expression;

  @override
  final Token? semicolon;

  /// Initializes a newly created expression statement.
  ExpressionStatementImpl({
    required ExpressionImpl expression,
    required this.semicolon,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => _expression.beginToken;

  @override
  Token get endToken {
    if (semicolon case var semicolon?) {
      return semicolon;
    }
    return _expression.endToken;
  }

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  bool get isSynthetic =>
      _expression.isSynthetic && (semicolon == null || semicolon!.isSynthetic);

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('expression', expression)
        ..addToken('semicolon', semicolon);

  @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' [NamedType]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ExtendsClause implements AstNode {
  /// The token representing the `extends` keyword.
  Token get extendsKeyword;

  /// The name of the class that is being extended.
  NamedType get superclass;
}

final class ExtendsClauseImpl extends AstNodeImpl implements ExtendsClause {
  @override
  final Token extendsKeyword;

  NamedTypeImpl _superclass;

  /// Initializes a newly created extends clause.
  ExtendsClauseImpl({
    required this.extendsKeyword,
    required NamedTypeImpl superclass,
  }) : _superclass = superclass {
    _becomeParentOf(_superclass);
  }

  @override
  Token get beginToken => extendsKeyword;

  @override
  Token get endToken => _superclass.endToken;

  @override
  NamedTypeImpl get superclass => _superclass;

  set superclass(NamedTypeImpl name) {
    _superclass = _becomeParentOf(name);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('extendsKeyword', extendsKeyword)
        ..addNode('superclass', superclass);

  @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] [ShowClause]? [HideClause]?
///        '{' [ClassMember]* '}'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ExtensionDeclaration implements CompilationUnitMember {
  /// The `augment` keyword, or `null` if the keyword was absent.
  @experimental
  Token? get augmentKeyword;

  @experimental
  @override
  ExtensionFragment? get declaredFragment;

  /// The token representing the `extension` keyword.
  Token get extensionKeyword;

  /// The left curly bracket.
  Token get leftBracket;

  /// The members being added to the extended class.
  NodeList<ClassMember> get members;

  /// The name of the extension, or `null` if the extension doesn't have a name.
  Token? get name;

  /// The `on` clause, `null` if an augmentation.
  ExtensionOnClause? get onClause;

  /// The right curly bracket.
  Token get rightBracket;

  /// The token representing the `type` keyword.
  Token? get typeKeyword;

  /// The type parameters for the extension, or `null` if the extension doesn't
  /// have any type parameters.
  TypeParameterList? get typeParameters;
}

final class ExtensionDeclarationImpl extends CompilationUnitMemberImpl
    with AstNodeWithNameScopeMixin
    implements ExtensionDeclaration {
  @override
  final Token? augmentKeyword;

  @override
  final Token extensionKeyword;

  @override
  final Token? typeKeyword;

  @override
  final Token? name;

  TypeParameterListImpl? _typeParameters;

  @override
  ExtensionOnClauseImpl? onClause;

  @override
  final Token leftBracket;

  final NodeListImpl<ClassMemberImpl> _members = NodeListImpl._();

  @override
  final Token rightBracket;

  @override
  ExtensionElementImpl? declaredFragment;

  ExtensionDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.extensionKeyword,
    required this.typeKeyword,
    required this.name,
    required TypeParameterListImpl? typeParameters,
    required this.onClause,
    required this.leftBracket,
    required List<ClassMemberImpl> members,
    required this.rightBracket,
  }) : _typeParameters = typeParameters {
    _becomeParentOf(_typeParameters);
    _becomeParentOf(onClause);
    _members._initialize(this, members);
  }

  @override
  Token get endToken => rightBracket;

  @override
  Token get firstTokenAfterCommentAndMetadata =>
      augmentKeyword ?? extensionKeyword;

  @override
  NodeListImpl<ClassMemberImpl> get members => _members;

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('extensionKeyword', extensionKeyword)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addNode('onClause', onClause)
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('members', members)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitExtensionDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _typeParameters?.accept(visitor);
    onClause?.accept(visitor);
    _members.accept(visitor);
  }
}

/// The `on` clause in an extension declaration.
///
///    onClause ::= 'on' [TypeAnnotation]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ExtensionOnClause implements AstNode {
  /// The extended type.
  TypeAnnotation get extendedType;

  /// The 'on' keyword.
  Token get onKeyword;
}

final class ExtensionOnClauseImpl extends AstNodeImpl
    implements ExtensionOnClause {
  @override
  final Token onKeyword;

  @override
  final TypeAnnotationImpl extendedType;

  ExtensionOnClauseImpl({required this.onKeyword, required this.extendedType}) {
    _becomeParentOf(extendedType);
  }

  @override
  Token get beginToken => onKeyword;

  @override
  Token get endToken => extendedType.endToken;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('onKeyword', onKeyword)
        ..addNode('extendedType', extendedType);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitExtensionOnClause(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    extendedType.accept(visitor);
  }
}

/// An override to force resolution to choose a member from a specific
/// extension.
///
///    extensionOverride ::=
///        [Identifier] [TypeArgumentList]? [ArgumentList]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ExtensionOverride implements Expression {
  /// The list of arguments to the override.
  ///
  /// In valid code this contains a single argument that evaluates to the object
  /// being extended.
  ArgumentList get argumentList;

  /// The extension that resolution will use to resolve member references.
  @experimental
  ExtensionElement2 get element2;

  /// The actual type extended by this override, produced by applying
  /// [typeArgumentTypes] to the generic type extended by the extension, or
  /// `null` if the AST structure hasn't been resolved.
  DartType? get extendedType;

  /// The optional import prefix before [name].
  ImportPrefixReference? get importPrefix;

  /// Whether this override is null aware (as opposed to non-null).
  bool get isNullAware;

  /// The name of the extension being selected.
  Token get name;

  /// The type arguments to be applied to the extension, or `null` if there are
  /// no type arguments.
  TypeArgumentList? get typeArguments;

  /// The actual type arguments to be applied to the extension, either
  /// explicitly specified in [typeArguments], or inferred, or `null` if the AST
  /// structure hasn't been resolved.
  ///
  /// An empty list if the extension doesn't have type arguments.
  List<DartType>? get typeArgumentTypes;
}

final class ExtensionOverrideImpl extends ExpressionImpl
    implements ExtensionOverride {
  @override
  final ImportPrefixReferenceImpl? importPrefix;

  @override
  final Token name;

  @override
  final ExtensionElementImpl2 element2;

  TypeArgumentListImpl? _typeArguments;

  ArgumentListImpl _argumentList;

  @override
  List<DartType>? typeArgumentTypes;

  @override
  TypeImpl? extendedType;

  ExtensionOverrideImpl({
    required this.importPrefix,
    required this.name,
    required TypeArgumentListImpl? typeArguments,
    required ArgumentListImpl argumentList,
    required this.element2,
  }) : _typeArguments = typeArguments,
       _argumentList = argumentList {
    _becomeParentOf(importPrefix);
    _becomeParentOf(_typeArguments);
    _becomeParentOf(_argumentList);
  }

  @override
  ArgumentListImpl get argumentList => _argumentList;

  set argumentList(ArgumentListImpl argumentList) {
    _argumentList = _becomeParentOf(argumentList);
  }

  @override
  Token get beginToken => importPrefix?.name ?? name;

  @override
  Token get endToken => _argumentList.endToken;

  @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
  TypeArgumentListImpl? get typeArguments => _typeArguments;

  set typeArguments(TypeArgumentListImpl? typeArguments) {
    _typeArguments = _becomeParentOf(typeArguments);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('importPrefix', importPrefix)
        ..addToken('name', name)
        ..addNode('typeArguments', typeArguments)
        ..addNode('argumentList', argumentList);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitExtensionOverride(this);
  }

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitExtensionOverride(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    importPrefix?.accept(visitor);
    _typeArguments?.accept(visitor);
    _argumentList.accept(visitor);
  }
}

/// The declaration of an extension type.
///
///    <extensionTypeDeclaration> ::=
///        'extension' 'type' 'const'? <typeIdentifier> <typeParameters>?
///        <representationDeclaration> <interfaces>?
///        '{'
///            (<metadata> <extensionTypeMemberDeclaration>)*
///        '}'
@experimental
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ExtensionTypeDeclaration
    implements NamedCompilationUnitMember {
  /// The `augment` keyword, or `null` if the keyword was absent.
  @experimental
  Token? get augmentKeyword;

  /// The `const` keyword.
  Token? get constKeyword;

  @experimental
  @override
  ExtensionTypeFragment? get declaredFragment;

  /// The `extension` keyword.
  Token get extensionKeyword;

  /// The `implements` clause.
  ImplementsClause? get implementsClause;

  /// The left curly bracket.
  Token get leftBracket;

  /// The members.
  NodeList<ClassMember> get members;

  /// The representation declaration.
  RepresentationDeclaration get representation;

  /// The right curly bracket.
  Token get rightBracket;

  /// The `type` keyword.
  Token get typeKeyword;

  /// The type parameters.
  TypeParameterList? get typeParameters;
}

final class ExtensionTypeDeclarationImpl extends NamedCompilationUnitMemberImpl
    with AstNodeWithNameScopeMixin
    implements ExtensionTypeDeclaration {
  @override
  final Token? augmentKeyword;

  @override
  final Token extensionKeyword;

  @override
  final Token typeKeyword;

  @override
  final Token? constKeyword;

  @override
  final TypeParameterListImpl? typeParameters;

  @override
  final RepresentationDeclarationImpl representation;

  @override
  final ImplementsClauseImpl? implementsClause;

  @override
  final Token leftBracket;

  @override
  final NodeListImpl<ClassMemberImpl> members = NodeListImpl._();

  @override
  final Token rightBracket;

  @override
  ExtensionTypeElementImpl? declaredFragment;

  ExtensionTypeDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.extensionKeyword,
    required this.typeKeyword,
    required this.constKeyword,
    required super.name,
    required this.typeParameters,
    required this.representation,
    required this.implementsClause,
    required this.leftBracket,
    required List<ClassMemberImpl> members,
    required this.rightBracket,
  }) {
    _becomeParentOf(typeParameters);
    _becomeParentOf(representation);
    _becomeParentOf(implementsClause);
    this.members._initialize(this, members);
  }

  @override
  Token get endToken => rightBracket;

  @override
  Token get firstTokenAfterCommentAndMetadata =>
      augmentKeyword ?? extensionKeyword;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('extensionKeyword', extensionKeyword)
        ..addToken('typeKeyword', typeKeyword)
        ..addToken('constKeyword', constKeyword)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addNode('representation', representation)
        ..addNode('implementsClause', implementsClause)
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('members', members)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitExtensionTypeDeclaration(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    typeParameters?.accept(visitor);
    representation.accept(visitor);
    implementsClause?.accept(visitor);
    members.accept(visitor);
  }
}

/// The declaration of one or more fields of the same type.
///
///    fieldDeclaration ::=
///        'static' 'const' <type>? <staticFinalDeclarationList>
///      | 'static' 'final' <type>? <staticFinalDeclarationList>
///      | 'static' 'late' 'final' <type>? <initializedIdentifierList>
///      | 'static' 'late'? <varOrType> <initializedIdentifierList>
///      | 'covariant' 'late'? <varOrType> <initializedIdentifierList>
///      | 'late'? 'final' <type>? <initializedIdentifierList>
///      | 'late'? <varOrType> <initializedIdentifierList>
///      | 'external' ('static'? <finalVarOrType> | 'covariant' <varOrType>)
///            <identifierList>
///      | 'abstract' (<finalVarOrType> | 'covariant' <varOrType>)
///            <identifierList>
///
/// (Note: there's no `<fieldDeclaration>` production in the grammar; this is a
/// subset of the grammar production `<declaration>`, which encompasses
/// everything that can appear inside a class declaration except methods).
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FieldDeclaration implements ClassMember {
  /// The `abstract` keyword, or `null` if the keyword isn't used.
  Token? get abstractKeyword;

  /// The `augment` keyword, or `null` if the keyword was absent.
  @experimental
  Token? get augmentKeyword;

  /// The `covariant` keyword, or `null` if the keyword isn't used.
  Token? get covariantKeyword;

  /// The `external` keyword, or `null` if the keyword isn't used.
  Token? get externalKeyword;

  /// The fields being declared.
  VariableDeclarationList get fields;

  /// Whether the fields are declared to be static.
  bool get isStatic;

  /// The semicolon terminating the declaration.
  Token get semicolon;

  /// The token representing the `static` keyword, or `null` if the fields
  /// aren't static.
  Token? get staticKeyword;
}

final class FieldDeclarationImpl extends ClassMemberImpl
    implements FieldDeclaration {
  @override
  final Token? abstractKeyword;

  @override
  final Token? augmentKeyword;

  @override
  final Token? covariantKeyword;

  @override
  final Token? externalKeyword;

  @override
  final Token? staticKeyword;

  VariableDeclarationListImpl _fieldList;

  @override
  final Token semicolon;

  /// Initializes a newly created field declaration.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// declaration doesn't have the corresponding attribute.
  ///
  /// The [staticKeyword] can be `null` if the field isn't a static field.
  FieldDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.abstractKeyword,
    required this.augmentKeyword,
    required this.covariantKeyword,
    required this.externalKeyword,
    required this.staticKeyword,
    required VariableDeclarationListImpl fieldList,
    required this.semicolon,
  }) : _fieldList = fieldList {
    _becomeParentOf(_fieldList);
  }

  @override
  Fragment? get declaredFragment => null;

  @override
  Token get endToken => semicolon;

  @override
  VariableDeclarationListImpl get fields => _fieldList;

  set fields(VariableDeclarationListImpl fields) {
    _fieldList = _becomeParentOf(fields);
  }

  @override
  Token get firstTokenAfterCommentAndMetadata {
    return Token.lexicallyFirst(
          abstractKeyword,
          augmentKeyword,
          externalKeyword,
          covariantKeyword,
          staticKeyword,
        ) ??
        _fieldList.beginToken;
  }

  @override
  bool get isStatic => staticKeyword != null;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('abstractKeyword', abstractKeyword)
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('covariantKeyword', covariantKeyword)
        ..addToken('externalKeyword', externalKeyword)
        ..addToken('staticKeyword', staticKeyword)
        ..addNode('fields', fields)
        ..addToken('semicolon', semicolon);

  @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' [TypeAnnotation] | 'const' [TypeAnnotation] | 'var' |
///        [TypeAnnotation])?
///        'this' '.' name ([TypeParameterList]? [FormalParameterList])?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FieldFormalParameter implements NormalFormalParameter {
  @experimental
  @override
  FieldFormalParameterFragment? get declaredFragment;

  /// The token representing either the `final`, `const` or `var` keyword, or
  /// `null` if no keyword was used.
  Token? get keyword;

  @override
  Token get name;

  /// The parameters of the function-typed parameter, or `null` if this isn't a
  /// function-typed field formal parameter.
  FormalParameterList? get parameters;

  /// The token representing the period.
  Token get period;

  /// The question mark indicating that the function type is nullable, or `null`
  /// if there's no question mark, which will always be the case when the
  /// parameter doesn't use the older style for denoting a function typed
  /// parameter.
  ///
  /// If the parameter is function-typed, and has the question mark, then its
  /// function type is nullable. Having a nullable function type means that the
  /// parameter can be `null`.
  Token? get question;

  /// The token representing the `this` keyword.
  Token get thisKeyword;

  /// The declared type of the parameter, or `null` if the parameter doesn't
  /// have a declared type.
  ///
  /// If this is a function-typed field formal parameter this is the return type
  /// of the function.
  TypeAnnotation? get type;

  /// The type parameters associated with this method, or `null` if this method
  /// isn't a generic method.
  TypeParameterList? get typeParameters;
}

final class FieldFormalParameterImpl extends NormalFormalParameterImpl
    implements FieldFormalParameter {
  @override
  final Token? keyword;

  TypeAnnotationImpl? _type;

  @override
  final Token thisKeyword;

  @override
  final Token period;

  TypeParameterListImpl? _typeParameters;

  FormalParameterListImpl? _parameters;

  @override
  final Token? question;

  /// Initializes a newly created formal parameter.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// parameter doesn't have the corresponding attribute.
  ///
  /// The [keyword] can be `null` if there's a type.
  ///
  /// The [type] must be `null` if the keyword is `var`.
  ///
  /// The [thisKeyword] and [period] can be `null` if the keyword `this` isn't
  /// provided.
  ///
  /// The [parameters] can be `null` if this isn't a function-typed field formal
  /// parameter.
  FieldFormalParameterImpl({
    required super.comment,
    required super.metadata,
    required super.covariantKeyword,
    required super.requiredKeyword,
    required this.keyword,
    required TypeAnnotationImpl? type,
    required this.thisKeyword,
    required this.period,
    required super.name,
    required TypeParameterListImpl? typeParameters,
    required FormalParameterListImpl? parameters,
    required this.question,
  }) : _type = type,
       _typeParameters = typeParameters,
       _parameters = parameters {
    _becomeParentOf(_type);
    _becomeParentOf(_typeParameters);
    _becomeParentOf(_parameters);
  }

  @override
  FieldFormalParameterElementImpl? get declaredFragment {
    return super.declaredFragment as FieldFormalParameterElementImpl?;
  }

  @override
  Token get endToken {
    return question ?? _parameters?.endToken ?? name;
  }

  @override
  Token get firstTokenAfterCommentAndMetadata =>
      requiredKeyword ??
      covariantKeyword ??
      keyword ??
      type?.beginToken ??
      thisKeyword;

  @override
  bool get isConst => keyword?.keyword == Keyword.CONST;

  @override
  bool get isExplicitlyTyped => _parameters != null || _type != null;

  @override
  bool get isFinal => keyword?.keyword == Keyword.FINAL;

  @override
  Token get name => super.name!;

  @override
  FormalParameterListImpl? get parameters => _parameters;

  set parameters(FormalParameterListImpl? parameters) {
    _parameters = _becomeParentOf(parameters);
  }

  @override
  TypeAnnotationImpl? get type => _type;

  set type(TypeAnnotationImpl? type) {
    _type = _becomeParentOf(type as TypeAnnotationImpl);
  }

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('keyword', keyword)
        ..addNode('type', type)
        ..addToken('thisKeyword', thisKeyword)
        ..addToken('period', period)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addNode('parameters', parameters);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitFieldFormalParameter(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _type?.accept(visitor);
    _typeParameters?.accept(visitor);
    _parameters?.accept(visitor);
  }
}

/// The parts of a for-each loop that control the iteration.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class ForEachParts implements ForLoopParts {
  /// The token representing the `in` keyword.
  Token get inKeyword;

  /// The expression evaluated to produce the iterator.
  Expression get iterable;
}

sealed class ForEachPartsImpl extends ForLoopPartsImpl implements ForEachParts {
  @override
  final Token inKeyword;

  ExpressionImpl _iterable;

  /// Initializes a newly created for-each statement whose loop control variable
  /// is declared internally (in the for-loop part).
  ForEachPartsImpl({required this.inKeyword, required ExpressionImpl iterable})
    : _iterable = iterable {
    _becomeParentOf(_iterable);
  }

  @override
  Token get beginToken => inKeyword;

  @override
  Token get endToken => _iterable.endToken;

  @override
  ExpressionImpl get iterable => _iterable;

  set iterable(ExpressionImpl expression) {
    _iterable = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('inKeyword', inKeyword)
        ..addNode('iterable', iterable);

  @override
  void visitChildren(AstVisitor visitor) {
    _iterable.accept(visitor);
  }
}

/// The parts of a for-each loop that control the iteration when the loop
/// variable is declared as part of the for loop.
///
///   forLoopParts ::=
///       [DeclaredIdentifier] 'in' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ForEachPartsWithDeclaration implements ForEachParts {
  /// The declaration of the loop variable.
  DeclaredIdentifier get loopVariable;
}

final class ForEachPartsWithDeclarationImpl extends ForEachPartsImpl
    implements ForEachPartsWithDeclaration {
  DeclaredIdentifierImpl _loopVariable;

  /// Initializes a newly created for-each statement whose loop control variable
  /// is declared internally (inside the for-loop part).
  ForEachPartsWithDeclarationImpl({
    required DeclaredIdentifierImpl loopVariable,
    required super.inKeyword,
    required super.iterable,
  }) : _loopVariable = loopVariable {
    _becomeParentOf(_loopVariable);
  }

  @override
  Token get beginToken => _loopVariable.beginToken;

  @override
  DeclaredIdentifierImpl get loopVariable => _loopVariable;

  set loopVariable(DeclaredIdentifierImpl variable) {
    _loopVariable = _becomeParentOf(variable);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('loopVariable', loopVariable)
        ..addAll(super._childEntities);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitForEachPartsWithDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _loopVariable.accept(visitor);
    super.visitChildren(visitor);
  }
}

/// The parts of a for-each loop that control the iteration when the loop
/// variable is declared outside of the for loop.
///
///   forLoopParts ::=
///       [SimpleIdentifier] 'in' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ForEachPartsWithIdentifier implements ForEachParts {
  /// The loop variable.
  SimpleIdentifier get identifier;
}

final class ForEachPartsWithIdentifierImpl extends ForEachPartsImpl
    implements ForEachPartsWithIdentifier {
  SimpleIdentifierImpl _identifier;

  /// Initializes a newly created for-each statement whose loop control variable
  /// is declared externally (outside the for-loop part).
  ForEachPartsWithIdentifierImpl({
    required SimpleIdentifierImpl identifier,
    required super.inKeyword,
    required super.iterable,
  }) : _identifier = identifier {
    _becomeParentOf(_identifier);
  }

  @override
  Token get beginToken => _identifier.beginToken;

  @override
  SimpleIdentifierImpl get identifier => _identifier;

  set identifier(SimpleIdentifierImpl identifier) {
    _identifier = _becomeParentOf(identifier);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('identifier', identifier)
        ..addAll(super._childEntities);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitForEachPartsWithIdentifier(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _identifier.accept(visitor);
    _iterable.accept(visitor);
  }
}

/// A for-loop part with a pattern.
///
///    forEachPartsWithPattern ::=
///        ( 'final' | 'var' ) [DartPattern] 'in' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ForEachPartsWithPattern implements ForEachParts {
  /// The `var` or `final` keyword introducing the pattern.
  Token get keyword;

  /// The annotations associated with this node.
  NodeList<Annotation> get metadata;

  /// The pattern used to match the expression.
  DartPattern get pattern;
}

final class ForEachPartsWithPatternImpl extends ForEachPartsImpl
    implements ForEachPartsWithPattern {
  final NodeListImpl<AnnotationImpl> _metadata = NodeListImpl._();

  @override
  final Token keyword;

  @override
  final DartPatternImpl pattern;

  /// Variables declared in [pattern].
  late final List<BindPatternVariableElementImpl> variables;

  ForEachPartsWithPatternImpl({
    required List<AnnotationImpl>? metadata,
    required this.keyword,
    required this.pattern,
    required super.inKeyword,
    required super.iterable,
  }) {
    _metadata._initialize(this, metadata);
    _becomeParentOf(pattern);
  }

  @override
  Token get beginToken {
    if (_metadata.isEmpty) {
      return keyword;
    } else {
      return _metadata.beginToken!;
    }
  }

  /// If [keyword] is `final`, returns it.
  Token? get finalKeyword {
    if (keyword.keyword == Keyword.FINAL) {
      return keyword;
    }
    return null;
  }

  @override
  NodeListImpl<AnnotationImpl> get metadata => _metadata;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNodeList('metadata', metadata)
        ..addToken('keyword', keyword)
        ..addNode('pattern', pattern)
        ..addAll(super._childEntities);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitForEachPartsWithPattern(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _metadata.accept(visitor);
    pattern.accept(visitor);
    super.visitChildren(visitor);
  }
}

/// The basic structure of a for element.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ForElement
    implements CollectionElement, ForLoop<CollectionElement> {}

final class ForElementImpl extends CollectionElementImpl
    with AstNodeWithNameScopeMixin
    implements
        ForElement,
        ForLoopImpl<CollectionElement, CollectionElementImpl> {
  @override
  final Token? awaitKeyword;

  @override
  final Token forKeyword;

  @override
  final Token leftParenthesis;

  ForLoopPartsImpl _forLoopParts;

  @override
  final Token rightParenthesis;

  CollectionElementImpl _body;

  /// Initializes a newly created for element.
  ForElementImpl({
    required this.awaitKeyword,
    required this.forKeyword,
    required this.leftParenthesis,
    required ForLoopPartsImpl forLoopParts,
    required this.rightParenthesis,
    required CollectionElementImpl body,
  }) : _forLoopParts = forLoopParts,
       _body = body {
    _becomeParentOf(_forLoopParts);
    _becomeParentOf(_body);
  }

  @override
  Token get beginToken => awaitKeyword ?? forKeyword;

  @override
  CollectionElementImpl get body => _body;

  set body(CollectionElementImpl statement) {
    _body = _becomeParentOf(statement);
  }

  @override
  Token get endToken => _body.endToken;

  @override
  ForLoopPartsImpl get forLoopParts => _forLoopParts;

  set forLoopParts(ForLoopPartsImpl forLoopParts) {
    _forLoopParts = _becomeParentOf(forLoopParts);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('awaitKeyword', awaitKeyword)
        ..addToken('forKeyword', forKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('forLoopParts', forLoopParts)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addNode('body', body);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitForElement(this);

  @override
  void resolveElement(
    ResolverVisitor resolver,
    CollectionLiteralContext? context,
  ) {
    resolver.visitForElement(this, context: context);
    resolver.pushRewrite(null);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _forLoopParts.accept(visitor);
    _body.accept(visitor);
  }
}

/// A for or for-each statement or collection element.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class ForLoop<Body extends AstNode> implements AstNode {
  /// The token representing the `await` keyword, or `null` if there's no
  /// `await` keyword.
  Token? get awaitKeyword;

  /// The body of the loop.
  Body get body;

  /// The token representing the `for` keyword.
  Token get forKeyword;

  /// The parts of the for element that control the iteration.
  ForLoopParts get forLoopParts;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;
}

sealed class ForLoopImpl<Body extends AstNode, BodyImpl extends Body>
    implements AstNodeImpl, ForLoop<Body> {
  @override
  BodyImpl get body;
}

/// The parts of a for or for-each loop that control the iteration.
///
///   forLoopParts ::=
///       [VariableDeclaration] ';' [Expression]? ';' expressionList?
///     | [Expression]? ';' [Expression]? ';' expressionList?
///     | [DeclaredIdentifier] 'in' [Expression]
///     | [SimpleIdentifier] 'in' [Expression]
///
///   expressionList ::=
///       [Expression] (',' [Expression])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class ForLoopParts implements AstNode {
  @override
  ForLoop get parent;
}

sealed class ForLoopPartsImpl extends AstNodeImpl implements ForLoopParts {
  @override
  ForLoopImpl get parent => super.parent as ForLoopImpl;
}

/// A node representing a parameter to a function.
///
///    formalParameter ::=
///        [NormalFormalParameter]
///      | [DefaultFormalParameter]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class FormalParameter implements AstNode {
  /// The `covariant` keyword, or `null` if the keyword isn't used.
  Token? get covariantKeyword;

  ///The fragment declared by this parameter.
  ///
  /// Returns `null` if this parameter hasn't been resolved.
  @experimental
  FormalParameterFragment? get declaredFragment;

  /// Whether this parameter was declared with the 'const' modifier.
  bool get isConst;

  /// Whether the parameter has an explicit type.
  bool get isExplicitlyTyped;

  /// Whether this parameter was declared with the 'final' modifier.
  ///
  /// Returns `false` for parameters that are declared with the 'const' modifier
  /// even though they are implicitly final.
  bool get isFinal;

  /// Whether this parameter is a named parameter.
  ///
  /// Named parameters can either be required or optional.
  bool get isNamed;

  /// Whether this parameter is an optional parameter.
  ///
  /// Optional parameters can either be positional or named.
  bool get isOptional;

  /// Whether this parameter is both an optional and named parameter.
  bool get isOptionalNamed;

  /// Whether this parameter is both an optional and positional
  /// parameter.
  bool get isOptionalPositional;

  /// Whether this parameter is a positional parameter.
  ///
  /// Positional parameters can either be required or optional.
  bool get isPositional;

  /// Whether this parameter is a required parameter.
  ///
  /// Required parameters can either be positional or named.
  ///
  /// Note: this returns `false` for a named parameter that is annotated with
  /// the `@required` annotation.
  bool get isRequired;

  /// Whether this parameter is both a required and named parameter.
  ///
  /// Note: this returns `false` for a named parameter that is annotated with
  /// the `@required` annotation.
  bool get isRequiredNamed;

  /// Whether this parameter is both a required and positional parameter.
  bool get isRequiredPositional;

  /// The annotations associated with this parameter.
  NodeList<Annotation> get metadata;

  /// The name of the parameter being declared, or `null` if the parameter
  /// doesn't have a name, such as when it's part of a generic function type.
  Token? get name;

  /// The `required` keyword, or `null` if the keyword isn't used.
  Token? get requiredKeyword;
}

sealed class FormalParameterImpl extends AstNodeImpl
    implements FormalParameter {
  @experimental
  @override
  ParameterElementImpl? declaredFragment;

  @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;

  /// The kind of this parameter.
  ParameterKind get kind;

  @override
  NodeList<AnnotationImpl> get metadata;
}

/// The formal parameter list of a method declaration, function declaration, or
/// function type alias.
///
/// While the grammar requires all required positional parameters to be first,
/// optionally being followed by either optional positional parameters or named
/// parameters (but not both), this class doesn't 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])* '}'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FormalParameterList implements AstNode {
  /// The left square bracket ('[') or left curly brace ('{') introducing the
  /// optional or named parameters, or `null` if there are neither optional nor
  /// named parameters.
  Token? get leftDelimiter;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// A list containing the fragments representing the parameters in this list.
  ///
  /// The list contains `null`s if the parameters in this list haven't been
  /// resolved.
  @experimental
  List<FormalParameterFragment?> get parameterFragments;

  /// The parameters associated with the method.
  NodeList<FormalParameter> get parameters;

  /// The right square bracket (']') or right curly brace ('}') terminating the
  /// optional or named parameters, or `null` if there are neither optional nor
  /// named parameters.
  Token? get rightDelimiter;

  /// The right parenthesis.
  Token get rightParenthesis;
}

final class FormalParameterListImpl extends AstNodeImpl
    implements FormalParameterList {
  @override
  final Token leftParenthesis;

  final NodeListImpl<FormalParameterImpl> _parameters = NodeListImpl._();

  @override
  final Token? leftDelimiter;

  @override
  final Token? rightDelimiter;

  @override
  final Token rightParenthesis;

  /// Initializes a newly created parameter list.
  ///
  /// The [leftDelimiter] and [rightDelimiter] can be `null` if there are no
  /// optional or named parameters, but it must be the case that either both are
  /// `null` or that both are non-`null`.
  FormalParameterListImpl({
    required this.leftParenthesis,
    required List<FormalParameterImpl> parameters,
    required this.leftDelimiter,
    required this.rightDelimiter,
    required this.rightParenthesis,
  }) {
    _parameters._initialize(this, parameters);
  }

  @override
  Token get beginToken => leftParenthesis;

  @override
  Token get endToken => rightParenthesis;

  @experimental
  @override
  List<ParameterElementImpl?> get parameterFragments {
    return _parameters.map((node) => node.declaredFragment).toList();
  }

  @override
  NodeListImpl<FormalParameterImpl> get parameters => _parameters;

  @override
  ChildEntities get _childEntities {
    // TODO(paulberry): include commas.
    var result = ChildEntities()..addToken('leftParenthesis', 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.addToken('leftDelimiter', leftDelimiter);
        leftDelimiterNeeded = false;
      }
      result.addNode('parameter', parameter);
    }
    return result
      ..addToken('rightDelimiter', rightDelimiter)
      ..addToken('rightParenthesis', rightParenthesis);
  }

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitFormalParameterList(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _parameters.accept(visitor);
  }
}

/// The parts of a for loop that control the iteration.
///
///   forLoopParts ::=
///       [VariableDeclaration] ';' [Expression]? ';' expressionList?
///     | [Expression]? ';' [Expression]? ';' expressionList?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class ForParts implements ForLoopParts {
  /// The condition used to determine when to terminate the loop, or `null` if
  /// there's no condition.
  Expression? get condition;

  /// The semicolon separating the initializer and the condition.
  Token get leftSeparator;

  /// The semicolon separating the condition and the updater.
  Token get rightSeparator;

  /// The list of expressions run after each execution of the loop body.
  NodeList<Expression> get updaters;
}

sealed class ForPartsImpl extends ForLoopPartsImpl implements ForParts {
  @override
  final Token leftSeparator;

  ExpressionImpl? _condition;

  @override
  final Token rightSeparator;

  final NodeListImpl<ExpressionImpl> _updaters = NodeListImpl._();

  /// Initializes a newly created for statement.
  ///
  /// Either the [condition] and the list of [updaters] can be `null` if the
  /// loop doesn't have the corresponding attribute.
  ForPartsImpl({
    required this.leftSeparator,
    required ExpressionImpl? condition,
    required this.rightSeparator,
    required List<ExpressionImpl>? updaters,
  }) : _condition = condition {
    _becomeParentOf(_condition);
    _updaters._initialize(this, updaters);
  }

  @override
  Token get beginToken => leftSeparator;

  @override
  ExpressionImpl? get condition => _condition;

  set condition(ExpressionImpl? expression) {
    _condition = _becomeParentOf(expression);
  }

  @override
  Token get endToken => _updaters.endToken ?? rightSeparator;

  @override
  NodeListImpl<ExpressionImpl> get updaters => _updaters;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('leftSeparator', leftSeparator)
        ..addNode('condition', condition)
        ..addToken('rightSeparator', rightSeparator)
        ..addNodeList('updaters', updaters);

  @override
  void visitChildren(AstVisitor visitor) {
    _condition?.accept(visitor);
    _updaters.accept(visitor);
  }
}

/// The parts of a for loop that control the iteration when there are one or
/// more variable declarations as part of the for loop.
///
///   forLoopParts ::=
///       [VariableDeclarationList] ';' [Expression]? ';' expressionList?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ForPartsWithDeclarations implements ForParts {
  /// The declaration of the loop variables.
  VariableDeclarationList get variables;
}

final class ForPartsWithDeclarationsImpl extends ForPartsImpl
    implements ForPartsWithDeclarations {
  VariableDeclarationListImpl _variableList;

  /// Initializes a newly created for statement.
  ///
  /// Both the [condition] and the list of [updaters] can be `null` if the loop
  /// doesn't have the corresponding attribute.
  ForPartsWithDeclarationsImpl({
    required VariableDeclarationListImpl variableList,
    required super.leftSeparator,
    required super.condition,
    required super.rightSeparator,
    required super.updaters,
  }) : _variableList = variableList {
    _becomeParentOf(_variableList);
  }

  @override
  Token get beginToken => _variableList.beginToken;

  @override
  VariableDeclarationListImpl get variables => _variableList;

  set variables(VariableDeclarationListImpl? variableList) {
    _variableList = _becomeParentOf(
      variableList as VariableDeclarationListImpl,
    );
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('variables', variables)
        ..addAll(super._childEntities);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitForPartsWithDeclarations(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _variableList.accept(visitor);
    super.visitChildren(visitor);
  }
}

/// The parts of a for loop that control the iteration when there are no
/// variable declarations as part of the for loop.
///
///   forLoopParts ::=
///       [Expression]? ';' [Expression]? ';' expressionList?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ForPartsWithExpression implements ForParts {
  /// The initialization expression, or `null` if there's no initialization
  /// expression.
  ///
  /// Note that a for statement can't have both a variable list and an
  /// initialization expression, but can validly have neither.
  Expression? get initialization;
}

final class ForPartsWithExpressionImpl extends ForPartsImpl
    implements ForPartsWithExpression {
  ExpressionImpl? _initialization;

  /// Initializes a newly created for statement.
  ///
  /// Both the [condition] and the list of [updaters] can be `null` if the loop
  /// doesn't have the corresponding attribute.
  ForPartsWithExpressionImpl({
    required ExpressionImpl? initialization,
    required super.leftSeparator,
    required super.condition,
    required super.rightSeparator,
    required super.updaters,
  }) : _initialization = initialization {
    _becomeParentOf(_initialization);
  }

  @override
  Token get beginToken => initialization?.beginToken ?? super.beginToken;

  @override
  ExpressionImpl? get initialization => _initialization;

  set initialization(ExpressionImpl? initialization) {
    _initialization = _becomeParentOf(initialization);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('initialization', initialization)
        ..addAll(super._childEntities);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitForPartsWithExpression(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _initialization?.accept(visitor);
    super.visitChildren(visitor);
  }
}

/// The parts of a for loop that control the iteration when there's a pattern
/// declaration as part of the for loop.
///
///   forLoopParts ::=
///       [PatternVariableDeclaration] ';' [Expression]? ';' expressionList?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ForPartsWithPattern implements ForParts {
  /// The declaration of the loop variables.
  PatternVariableDeclaration get variables;
}

final class ForPartsWithPatternImpl extends ForPartsImpl
    implements ForPartsWithPattern {
  @override
  final PatternVariableDeclarationImpl variables;

  ForPartsWithPatternImpl({
    required this.variables,
    required super.leftSeparator,
    required super.condition,
    required super.rightSeparator,
    required super.updaters,
  }) {
    _becomeParentOf(variables);
  }

  @override
  Token get beginToken => variables.beginToken;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('variables', variables)
        ..addAll(super._childEntities);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitForPartsWithPattern(this);

  @override
  void visitChildren(AstVisitor visitor) {
    variables.accept(visitor);
    super.visitChildren(visitor);
  }
}

/// A for or for-each statement.
///
///    forStatement ::=
///        'for' '(' forLoopParts ')' [Statement]
///
///    forLoopParts ::=
///       [VariableDeclaration] ';' [Expression]? ';' expressionList?
///     | [Expression]? ';' [Expression]? ';' expressionList?
///     | [DeclaredIdentifier] 'in' [Expression]
///     | [SimpleIdentifier] 'in' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ForStatement implements Statement, ForLoop<Statement> {}

final class ForStatementImpl extends StatementImpl
    with AstNodeWithNameScopeMixin
    implements ForStatement, ForLoopImpl<Statement, StatementImpl> {
  @override
  final Token? awaitKeyword;

  @override
  final Token forKeyword;

  @override
  final Token leftParenthesis;

  ForLoopPartsImpl _forLoopParts;

  @override
  final Token rightParenthesis;

  StatementImpl _body;

  /// Initializes a newly created for statement.
  ForStatementImpl({
    required this.awaitKeyword,
    required this.forKeyword,
    required this.leftParenthesis,
    required ForLoopPartsImpl forLoopParts,
    required this.rightParenthesis,
    required StatementImpl body,
  }) : _forLoopParts = forLoopParts,
       _body = body {
    _becomeParentOf(_forLoopParts);
    _becomeParentOf(_body);
  }

  @override
  Token get beginToken => awaitKeyword ?? forKeyword;

  @override
  StatementImpl get body => _body;

  set body(StatementImpl statement) {
    _body = _becomeParentOf(statement);
  }

  @override
  Token get endToken => _body.endToken;

  @override
  ForLoopPartsImpl get forLoopParts => _forLoopParts;

  set forLoopParts(ForLoopPartsImpl forLoopParts) {
    _forLoopParts = _becomeParentOf(forLoopParts);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('awaitKeyword', awaitKeyword)
        ..addToken('forKeyword', forKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('forLoopParts', forLoopParts)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addNode('body', body);

  @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]
///      | [NativeFunctionBody]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class FunctionBody implements AstNode {
  /// Whether this function body is asynchronous.
  bool get isAsynchronous;

  /// Whether this function body is a generator.
  bool get isGenerator;

  /// Whether this function body is synchronous.
  bool get isSynchronous;

  /// The token representing the `async` or `sync` keyword, or `null` if there's
  /// no such keyword.
  Token? get keyword;

  /// The star following the `async` or `sync` keyword, or `null` if there's no
  /// star.
  Token? get star;

  /// If [variable] is a local variable or parameter declared anywhere within
  /// the top level function or method containing this [FunctionBody], return a
  /// boolean indicating whether [variable] is potentially mutated within the
  /// scope of its declaration.
  ///
  /// If [variable] isn't a local variable or parameter declared within the top
  /// level function or method containing this [FunctionBody], return `false`.
  ///
  /// Throws an exception if resolution hasn't been performed.
  @experimental
  bool isPotentiallyMutatedInScope2(VariableElement2 variable);
}

sealed 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, or
  /// `null` if resolution hasn't yet been performed.
  LocalVariableInfo? localVariableInfo;

  /// The [BodyInferenceContext] that was used during type inference of this
  /// function body, or `null` if resolution hasn't yet been performed.
  BodyInferenceContext? bodyContext;

  @override
  bool get isAsynchronous => false;

  @override
  bool get isGenerator => false;

  @override
  bool get isSynchronous => true;

  @override
  Token? get keyword => null;

  @override
  Token? get star => null;

  @override
  bool isPotentiallyMutatedInScope2(VariableElement2 variable) {
    if (localVariableInfo == null) {
      throw StateError('Resolution has not been performed');
    }
    return localVariableInfo!.potentiallyMutatedInScope.contains(variable);
  }

  /// Dispatch this function body to the resolver, imposing [imposedType] as the
  /// return type context for `return` statements.
  ///
  /// Returns value is the actual return type of the method.
  TypeImpl resolve(ResolverVisitor resolver, TypeImpl? imposedType);
}

/// A function declaration.
///
/// Wrapped in a [FunctionDeclarationStatement] to represent a local function
/// declaration, otherwise a top-level function declaration.
///
///    functionDeclaration ::=
///        'external' functionSignature
///      | functionSignature [FunctionBody]
///
///    functionSignature ::=
///        [Type]? ('get' | 'set')? name [FormalParameterList]
// TODO(brianwilkerson): This class represents both declarations that can be
//  augmented and declarations that can't be augmented. This results in getters
//  that are only sometimes applicable. Consider changing the class hierarchy so
//  that these two kinds of variables can be distinguished.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FunctionDeclaration implements NamedCompilationUnitMember {
  /// The `augment` keyword, or `null` if there is no `augment` keyword.
  @experimental
  Token? get augmentKeyword;

  /// The fragment declared by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if this node
  /// represents a local function.
  @experimental
  @override
  ExecutableFragment? get declaredFragment;

  /// The token representing the `external` keyword, or `null` if this isn't an
  /// external function.
  Token? get externalKeyword;

  /// The function expression being wrapped.
  FunctionExpression get functionExpression;

  /// Whether this function declares a getter.
  bool get isGetter;

  /// Whether this function declares a setter.
  bool get isSetter;

  /// The token representing the `get` or `set` keyword, or `null` if this is a
  /// function declaration rather than a property declaration.
  Token? get propertyKeyword;

  /// The return type of the function, or `null` if no return type was declared.
  TypeAnnotation? get returnType;
}

final class FunctionDeclarationImpl extends NamedCompilationUnitMemberImpl
    with AstNodeWithNameScopeMixin
    implements FunctionDeclaration {
  @override
  final Token? augmentKeyword;

  @override
  final Token? externalKeyword;

  TypeAnnotationImpl? _returnType;

  @override
  final Token? propertyKeyword;

  FunctionExpressionImpl _functionExpression;

  @override
  ExecutableElementImpl? declaredFragment;

  /// Initializes a newly created function declaration.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// function doesn't have the corresponding attribute.
  ///
  /// The [externalKeyword] can be `null` if the function isn't 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({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.externalKeyword,
    required TypeAnnotationImpl? returnType,
    required this.propertyKeyword,
    required super.name,
    required FunctionExpressionImpl functionExpression,
  }) : _returnType = returnType,
       _functionExpression = functionExpression {
    _becomeParentOf(_returnType);
    _becomeParentOf(_functionExpression);
  }

  @override
  Token get endToken => _functionExpression.endToken;

  @override
  Token get firstTokenAfterCommentAndMetadata {
    return augmentKeyword ??
        externalKeyword ??
        _returnType?.beginToken ??
        propertyKeyword ??
        name;
  }

  @override
  FunctionExpressionImpl get functionExpression => _functionExpression;

  set functionExpression(FunctionExpressionImpl functionExpression) {
    _functionExpression = _becomeParentOf(functionExpression);
  }

  @override
  bool get isGetter => propertyKeyword?.keyword == Keyword.GET;

  @override
  bool get isSetter => propertyKeyword?.keyword == Keyword.SET;

  @override
  TypeAnnotationImpl? get returnType => _returnType;

  set returnType(TypeAnnotationImpl? type) {
    _returnType = _becomeParentOf(type as TypeAnnotationImpl);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('externalKeyword', externalKeyword)
        ..addNode('returnType', returnType)
        ..addToken('propertyKeyword', propertyKeyword)
        ..addToken('name', name)
        ..addNode('functionExpression', functionExpression);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _returnType?.accept(visitor);
    _functionExpression.accept(visitor);
  }
}

/// A [FunctionDeclaration] used as a statement.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FunctionDeclarationStatement implements Statement {
  /// The function declaration being wrapped.
  FunctionDeclaration get functionDeclaration;
}

final class FunctionDeclarationStatementImpl extends StatementImpl
    implements FunctionDeclarationStatement {
  FunctionDeclarationImpl _functionDeclaration;

  /// Initializes a newly created function declaration statement.
  FunctionDeclarationStatementImpl({
    required FunctionDeclarationImpl functionDeclaration,
  }) : _functionDeclaration = functionDeclaration {
    _becomeParentOf(_functionDeclaration);
  }

  @override
  Token get beginToken => _functionDeclaration.beginToken;

  @override
  Token get endToken => _functionDeclaration.endToken;

  @override
  FunctionDeclarationImpl get functionDeclaration => _functionDeclaration;

  set functionDeclaration(FunctionDeclarationImpl functionDeclaration) {
    _functionDeclaration = _becomeParentOf(functionDeclaration);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addNode('functionDeclaration', functionDeclaration);

  @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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FunctionExpression implements Expression {
  /// The body of the function.
  FunctionBody get body;

  /// The fragment declared by this function expression.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  ///
  /// Returns `null` is thie expression is a closure, or the parent is a
  /// local function.
  @experimental
  ExecutableFragment? get declaredFragment;

  /// The parameters associated with the function, or `null` if the function is
  /// part of a top-level getter.
  FormalParameterList? get parameters;

  /// The type parameters associated with this method, or `null` if this method
  /// isn't a generic method.
  TypeParameterList? get typeParameters;
}

final class FunctionExpressionImpl extends ExpressionImpl
    implements FunctionExpression {
  TypeParameterListImpl? _typeParameters;

  FormalParameterListImpl? _parameters;

  FunctionBodyImpl _body;

  /// Whether a function type was supplied via context for this function
  /// expression.
  ///
  /// Returns `false` if resolution hasn't been performed yet.
  bool wasFunctionTypeSupplied = false;

  @override
  ExecutableElementImpl? declaredFragment;

  /// Initializes a newly created function declaration.
  FunctionExpressionImpl({
    required TypeParameterListImpl? typeParameters,
    required FormalParameterListImpl? parameters,
    required FunctionBodyImpl body,
  }) : _typeParameters = typeParameters,
       _parameters = parameters,
       _body = body {
    _becomeParentOf(_typeParameters);
    _becomeParentOf(_parameters);
    _becomeParentOf(_body);
  }

  @override
  Token get beginToken {
    if (typeParameters case var typeParameters?) {
      return typeParameters.beginToken;
    } else if (parameters case var parameters?) {
      return parameters.beginToken;
    }
    return _body.beginToken;
  }

  @override
  FunctionBodyImpl get body => _body;

  set body(FunctionBodyImpl functionBody) {
    _body = _becomeParentOf(functionBody);
  }

  @override
  Token get endToken {
    return _body.endToken;
  }

  @override
  FormalParameterListImpl? get parameters => _parameters;

  set parameters(FormalParameterListImpl? parameters) {
    _parameters = _becomeParentOf(parameters);
  }

  @override
  Precedence get precedence => Precedence.primary;

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('typeParameters', typeParameters)
        ..addNode('parameters', parameters)
        ..addNode('body', body);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitFunctionExpression(this, contextType: contextType);
  }

  @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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FunctionExpressionInvocation
    implements NullShortableExpression, InvocationExpression {
  /// The element associated with the function being invoked based on static
  /// type information.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or the function
  /// couldn't be resolved.
  @experimental
  ExecutableElement2? get element;

  /// The expression producing the function being invoked.
  @override
  Expression get function;
}

final class FunctionExpressionInvocationImpl extends InvocationExpressionImpl
    with NullShortableExpressionImpl
    implements FunctionExpressionInvocation, RewrittenMethodInvocationImpl {
  ExpressionImpl _function;

  @override
  ExecutableElement2? element;

  /// Initializes a newly created function expression invocation.
  FunctionExpressionInvocationImpl({
    required ExpressionImpl function,
    required super.typeArguments,
    required super.argumentList,
  }) : _function = function {
    _becomeParentOf(_function);
  }

  @override
  Token get beginToken => _function.beginToken;

  @override
  Token get endToken => _argumentList.endToken;

  @override
  ExpressionImpl get function => _function;

  set function(ExpressionImpl expression) {
    _function = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.postfix;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('function', function)
        ..addNode('typeArguments', typeArguments)
        ..addNode('argumentList', argumentList);

  @override
  AstNode? get _nullShortingExtensionCandidate => parent;

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitFunctionExpressionInvocation(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitFunctionExpressionInvocation(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _function.accept(visitor);
    _typeArguments?.accept(visitor);
    _argumentList.accept(visitor);
  }

  @override
  bool _extendsNullShorting(Expression descendant) =>
      identical(descendant, _function);
}

/// An expression representing a reference to a function, possibly with type
/// arguments applied to it.
///
/// For example, the expression `print` in `var x = print;`.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FunctionReference
    implements Expression, CommentReferableExpression {
  /// The function being referenced.
  ///
  /// In error-free code, this is either a [SimpleIdentifier] (indicating a
  /// function that is in scope), a [PrefixedIdentifier] (indicating a either
  /// function imported via prefix or a static method in a class), or a
  /// [PropertyAccess] (indicating a static method in a class imported via
  /// prefix). In code with errors, this could be other kinds of expressions.
  /// For example, `(...)<int>` parses as a [FunctionReference] whose referent
  /// is a [ParenthesizedExpression].
  Expression get function;

  /// The type arguments being applied to the function, or `null` if there are
  /// no type arguments.
  TypeArgumentList? get typeArguments;

  /// The actual type arguments being applied to the function, either
  /// explicitly specified in [typeArguments], or inferred.
  ///
  /// An empty list if the function doesn't have type parameters, or `null` if
  /// the AST structure hasn't been resolved.
  List<DartType>? get typeArgumentTypes;
}

final class FunctionReferenceImpl extends CommentReferableExpressionImpl
    implements FunctionReference {
  ExpressionImpl _function;

  TypeArgumentListImpl? _typeArguments;

  @override
  List<TypeImpl>? typeArgumentTypes;

  FunctionReferenceImpl({
    required ExpressionImpl function,
    required TypeArgumentListImpl? typeArguments,
  }) : _function = function,
       _typeArguments = typeArguments {
    _becomeParentOf(_function);
    _becomeParentOf(_typeArguments);
  }

  @override
  Token get beginToken => function.beginToken;

  @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
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('function', function)
        ..addNode('typeArguments', typeArguments);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionReference(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitFunctionReference(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    function.accept(visitor);
    typeArguments?.accept(visitor);
  }
}

/// A function type alias.
///
///    functionTypeAlias ::=
///        'typedef' functionPrefix [TypeParameterList]?
///        [FormalParameterList] ';'
///
///    functionPrefix ::=
///        [TypeAnnotation]? [SimpleIdentifier]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FunctionTypeAlias implements TypeAlias {
  @experimental
  @override
  TypeAliasFragment? get declaredFragment;

  /// The parameters associated with the function type.
  FormalParameterList get parameters;

  /// The return type of the function type being defined, or `null` if no return
  /// type was given.
  TypeAnnotation? get returnType;

  /// The type parameters for the function type, or `null` if the function type
  /// doesn't have any type parameters.
  TypeParameterList? get typeParameters;
}

final class FunctionTypeAliasImpl extends TypeAliasImpl
    implements FunctionTypeAlias {
  TypeAnnotationImpl? _returnType;

  TypeParameterListImpl? _typeParameters;

  FormalParameterListImpl _parameters;

  @override
  TypeAliasElementImpl? declaredFragment;

  /// Initializes a newly created function type alias.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// function doesn't 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({
    required super.comment,
    required super.metadata,
    required super.augmentKeyword,
    required super.typedefKeyword,
    required TypeAnnotationImpl? returnType,
    required super.name,
    required TypeParameterListImpl? typeParameters,
    required FormalParameterListImpl parameters,
    required super.semicolon,
  }) : _returnType = returnType,
       _typeParameters = typeParameters,
       _parameters = parameters {
    _becomeParentOf(_returnType);
    _becomeParentOf(_typeParameters);
    _becomeParentOf(_parameters);
  }

  @override
  FormalParameterListImpl get parameters => _parameters;

  set parameters(FormalParameterListImpl parameters) {
    _parameters = _becomeParentOf(parameters);
  }

  @override
  TypeAnnotationImpl? get returnType => _returnType;

  set returnType(TypeAnnotationImpl? type) {
    _returnType = _becomeParentOf(type);
  }

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('typedefKeyword', typedefKeyword)
        ..addNode('returnType', returnType)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addNode('parameters', parameters)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitFunctionTypeAlias(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _returnType?.accept(visitor);
    _typeParameters?.accept(visitor);
    _parameters.accept(visitor);
  }
}

/// A function-typed formal parameter.
///
///    functionSignature ::=
///        [TypeAnnotation]? name [TypeParameterList]?
///        [FormalParameterList] '?'?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class FunctionTypedFormalParameter
    implements NormalFormalParameter {
  @override
  Token get name;

  /// The parameters of the function-typed parameter.
  FormalParameterList get parameters;

  /// The question mark indicating that the function type is nullable, or `null`
  /// if there's no question mark.
  ///
  /// Having a nullable function type means that the parameter can be null.
  Token? get question;

  /// The return type of the function, or `null` if the function doesn't have a
  /// return type.
  TypeAnnotation? get returnType;

  /// The type parameters associated with this function, or `null` if this
  /// function isn't a generic function.
  TypeParameterList? get typeParameters;
}

final class FunctionTypedFormalParameterImpl extends NormalFormalParameterImpl
    implements FunctionTypedFormalParameter {
  TypeAnnotationImpl? _returnType;

  TypeParameterListImpl? _typeParameters;

  FormalParameterListImpl _parameters;

  @override
  final Token? question;

  /// Initializes a newly created formal parameter.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// parameter doesn't have the corresponding attribute.
  ///
  /// The [returnType] can be `null` if no return type was specified.
  FunctionTypedFormalParameterImpl({
    required super.comment,
    required super.metadata,
    required super.covariantKeyword,
    required super.requiredKeyword,
    required TypeAnnotationImpl? returnType,
    required super.name,
    required TypeParameterListImpl? typeParameters,
    required FormalParameterListImpl parameters,
    required this.question,
  }) : _returnType = returnType,
       _typeParameters = typeParameters,
       _parameters = parameters {
    _becomeParentOf(_returnType);
    _becomeParentOf(_typeParameters);
    _becomeParentOf(_parameters);
  }

  @override
  Token get endToken => question ?? _parameters.endToken;

  @override
  Token get firstTokenAfterCommentAndMetadata =>
      requiredKeyword ?? covariantKeyword ?? returnType?.beginToken ?? name;

  @override
  bool get isConst => false;

  @override
  bool get isExplicitlyTyped => true;

  @override
  bool get isFinal => false;

  @override
  Token get name => super.name!;

  @override
  FormalParameterListImpl get parameters => _parameters;

  set parameters(FormalParameterListImpl parameters) {
    _parameters = _becomeParentOf(parameters);
  }

  @override
  TypeAnnotationImpl? get returnType => _returnType;

  set returnType(TypeAnnotationImpl? type) {
    _returnType = _becomeParentOf(type);
  }

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('returnType', returnType)
        ..addToken('name', name)
        ..addNode('parameters', parameters);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitFunctionTypedFormalParameter(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _returnType?.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 ,? ]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class GenericFunctionType implements TypeAnnotation {
  /// The fragment declared by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  GenericFunctionTypeFragment? get declaredFragment;

  /// The `Function` keyword.
  Token get functionKeyword;

  /// The parameters associated with the function type.
  FormalParameterList get parameters;

  /// The return type of the function type being defined, or `null` if no return
  /// type was given.
  TypeAnnotation? get returnType;

  /// The type parameters for the function type, or `null` if the function type
  /// doesn't have any type parameters.
  TypeParameterList? get typeParameters;
}

final class GenericFunctionTypeImpl extends TypeAnnotationImpl
    with AstNodeWithNameScopeMixin
    implements GenericFunctionType {
  TypeAnnotationImpl? _returnType;

  @override
  final Token functionKeyword;

  TypeParameterListImpl? _typeParameters;

  FormalParameterListImpl _parameters;

  @override
  final Token? question;

  @override
  TypeImpl? type;

  /// The element associated with the function type, or `null` if the AST
  /// structure hasn't been resolved.
  @override
  GenericFunctionTypeElementImpl? declaredFragment;

  /// Initializes a newly created generic function type.
  GenericFunctionTypeImpl({
    required TypeAnnotationImpl? returnType,
    required this.functionKeyword,
    required TypeParameterListImpl? typeParameters,
    required FormalParameterListImpl parameters,
    required this.question,
  }) : _returnType = returnType,
       _typeParameters = typeParameters,
       _parameters = parameters {
    _becomeParentOf(_returnType);
    _becomeParentOf(_typeParameters);
    _becomeParentOf(_parameters);
  }

  @override
  Token get beginToken => _returnType?.beginToken ?? functionKeyword;

  @override
  Token get endToken => question ?? _parameters.endToken;

  @override
  FormalParameterListImpl get parameters => _parameters;

  set parameters(FormalParameterListImpl parameters) {
    _parameters = _becomeParentOf(parameters);
  }

  @override
  TypeAnnotationImpl? get returnType => _returnType;

  set returnType(TypeAnnotationImpl? type) {
    _returnType = _becomeParentOf(type);
  }

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('returnType', returnType)
        ..addToken('functionKeyword', functionKeyword)
        ..addNode('typeParameters', typeParameters)
        ..addNode('parameters', parameters)
        ..addToken('question', question);

  @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 ::=
///        'typedef' [SimpleIdentifier] [TypeParameterList]? =
///        [FunctionType] ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class GenericTypeAlias implements TypeAlias {
  /// The equal sign separating the name being defined from the function type.
  Token get equals;

  /// The type of function being defined by the alias, or `null` if the
  /// non-function type aliases feature is enabled and the denoted type isn't a
  /// [GenericFunctionType].
  GenericFunctionType? get functionType;

  /// The type being defined by the alias.
  TypeAnnotation get type;

  /// The type parameters for the function type, or `null` if the function type
  /// doesn't have any type parameters.
  TypeParameterList? get typeParameters;
}

final class GenericTypeAliasImpl extends TypeAliasImpl
    with AstNodeWithNameScopeMixin
    implements GenericTypeAlias {
  TypeAnnotationImpl _type;

  TypeParameterListImpl? _typeParameters;

  @override
  final Token equals;

  @override
  TypeAliasElementImpl? declaredFragment;

  /// Initializes a newly created generic type alias.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// variable list doesn't have the corresponding attribute.
  ///
  /// The [typeParameters] can be `null` if there are no type parameters.
  GenericTypeAliasImpl({
    required super.comment,
    required super.metadata,
    required super.augmentKeyword,
    required super.typedefKeyword,
    required super.name,
    required TypeParameterListImpl? typeParameters,
    required this.equals,
    required TypeAnnotationImpl type,
    required super.semicolon,
  }) : _typeParameters = typeParameters,
       _type = type {
    _becomeParentOf(_typeParameters);
    _becomeParentOf(_type);
  }

  @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 type(TypeAnnotationImpl typeAnnotation) {
    _type = _becomeParentOf(typeAnnotation);
  }

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('typedefKeyword', typedefKeyword)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addToken('equals', equals)
        ..addNode('type', type);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitGenericTypeAlias(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _typeParameters?.accept(visitor);
    _type.accept(visitor);
  }
}

/// The pattern with an optional [WhenClause].
///
///    guardedPattern ::=
///        [DartPattern] [WhenClause]?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class GuardedPattern implements AstNode {
  /// The pattern controlling whether the statements are executed.
  DartPattern get pattern;

  /// The clause controlling whether the statements are be executed.
  WhenClause? get whenClause;
}

final class GuardedPatternImpl extends AstNodeImpl implements GuardedPattern {
  @override
  final DartPatternImpl pattern;

  /// Variables declared in [pattern], available in [whenClause] guard, and
  /// to the `ifTrue` node.
  late Map<String, PatternVariableElementImpl2> variables;

  @override
  final WhenClauseImpl? whenClause;

  GuardedPatternImpl({required this.pattern, required this.whenClause}) {
    _becomeParentOf(pattern);
    _becomeParentOf(whenClause);
  }

  @override
  Token get beginToken => pattern.beginToken;

  @override
  Token get endToken => whenClause?.endToken ?? pattern.endToken;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('pattern', pattern)
        ..addNode('whenClause', whenClause);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitGuardedPattern(this);

  @override
  void visitChildren(AstVisitor visitor) {
    pattern.accept(visitor);
    whenClause?.accept(visitor);
  }
}

/// A combinator that restricts the names being imported to those that aren't
/// in a given list.
///
///    hideCombinator ::=
///        'hide' [SimpleIdentifier] (',' [SimpleIdentifier])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class HideCombinator implements Combinator {
  /// The list of names from the library that are hidden by this combinator.
  NodeList<SimpleIdentifier> get hiddenNames;
}

final class HideCombinatorImpl extends CombinatorImpl
    implements HideCombinator {
  final NodeListImpl<SimpleIdentifierImpl> _hiddenNames = NodeListImpl._();

  /// Initializes a newly created import show combinator.
  HideCombinatorImpl({
    required super.keyword,
    required List<SimpleIdentifierImpl> hiddenNames,
  }) {
    _hiddenNames._initialize(this, hiddenNames);
  }

  @override
  Token get endToken => _hiddenNames.endToken!;

  @override
  NodeListImpl<SimpleIdentifierImpl> get hiddenNames => _hiddenNames;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('keyword', keyword)
        ..addNodeList('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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class Identifier implements Expression, CommentReferableExpression {
  /// The element associated with this identifier based on static type
  /// information.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if this
  /// identifier couldn't be resolved. One example of the latter case is an
  /// identifier that isn't defined within the scope in which it appears.
  @experimental
  Element2? get element;

  /// The lexical representation of the identifier.
  String get name;

  /// Returns `true` if the given [name] is visible only within the library in
  /// which it's declared.
  static bool isPrivateName(String name) => name.isNotEmpty && name[0] == "_";
}

sealed class IdentifierImpl extends CommentReferableExpressionImpl
    implements Identifier {
  @override
  bool get isAssignable => true;
}

/// The basic structure of an if element.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class IfElement implements CollectionElement {
  /// The `case` clause used to match a pattern against the [expression].
  CaseClause? get caseClause;

  /// The statement that is executed if the condition evaluates to `false`, or
  /// `null` if there's no else statement.
  CollectionElement? get elseElement;

  /// The token representing the `else` keyword, or `null` if there's no else
  /// expression.
  Token? get elseKeyword;

  /// The expression used to either determine which of the statements is
  /// executed next or to compute the value to be matched against the pattern in
  /// the `case` clause.
  Expression get expression;

  /// The token representing the `if` keyword.
  Token get ifKeyword;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;

  /// The statement that is executed if the condition evaluates to `true`.
  CollectionElement get thenElement;
}

final class IfElementImpl extends CollectionElementImpl
    implements IfElement, IfElementOrStatementImpl<CollectionElementImpl> {
  @override
  final Token ifKeyword;

  @override
  final Token leftParenthesis;

  ExpressionImpl _expression;

  @override
  final CaseClauseImpl? caseClause;

  @override
  final Token rightParenthesis;

  @override
  final Token? elseKeyword;

  CollectionElementImpl _thenElement;

  CollectionElementImpl? _elseElement;

  /// Initializes a newly created for element.
  IfElementImpl({
    required this.ifKeyword,
    required this.leftParenthesis,
    required ExpressionImpl expression,
    required this.caseClause,
    required this.rightParenthesis,
    required CollectionElementImpl thenElement,
    required this.elseKeyword,
    required CollectionElementImpl? elseElement,
  }) : _expression = expression,
       _thenElement = thenElement,
       _elseElement = elseElement {
    _becomeParentOf(_expression);
    _becomeParentOf(caseClause);
    _becomeParentOf(_thenElement);
    _becomeParentOf(_elseElement);
  }

  @override
  Token get beginToken => ifKeyword;

  set condition(ExpressionImpl condition) {
    _expression = _becomeParentOf(condition);
  }

  @override
  CollectionElementImpl? get elseElement => _elseElement;

  set elseElement(CollectionElementImpl? element) {
    _elseElement = _becomeParentOf(element);
  }

  @override
  Token get endToken => _elseElement?.endToken ?? _thenElement.endToken;

  @override
  ExpressionImpl get expression => _expression;

  @override
  CollectionElementImpl? get ifFalse => elseElement;

  @override
  CollectionElementImpl get ifTrue => thenElement;

  @override
  CollectionElementImpl get thenElement => _thenElement;

  set thenElement(CollectionElementImpl element) {
    _thenElement = _becomeParentOf(element);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('ifKeyword', ifKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('expression', expression)
        ..addNode('caseClause', caseClause)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addNode('thenElement', thenElement)
        ..addToken('elseKeyword', elseKeyword)
        ..addNode('elseElement', elseElement);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitIfElement(this);

  @override
  void resolveElement(
    ResolverVisitor resolver,
    CollectionLiteralContext? context,
  ) {
    resolver.visitIfElement(this, context: context);
    resolver.pushRewrite(null);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    expression.accept(visitor);
    caseClause?.accept(visitor);
    _thenElement.accept(visitor);
    _elseElement?.accept(visitor);
  }
}

sealed class IfElementOrStatementImpl<E extends AstNodeImpl>
    implements AstNodeImpl {
  /// The `case` clause used to match a pattern against the [expression].
  CaseClauseImpl? get caseClause;

  /// The expression used to either determine which of the statements is
  /// executed next or to compute the value matched against the pattern in the
  /// `case` clause.
  ExpressionImpl get expression;

  /// The node that is executed if the condition evaluates to `false`.
  E? get ifFalse;

  /// The node that is executed if the condition evaluates to `true`.
  E get ifTrue;
}

/// An if statement.
///
///    ifStatement ::=
///        'if' '(' [Expression] [CaseClause]? ')'[Statement]
///        ('else' [Statement])?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class IfStatement implements Statement {
  /// The `case` clause used to match a pattern against the [expression].
  CaseClause? get caseClause;

  /// The token representing the `else` keyword, or `null` if there's no else
  /// statement.
  Token? get elseKeyword;

  /// The statement that is executed if the condition evaluates to `false`, or
  /// `null` if there's no else statement.
  Statement? get elseStatement;

  /// The expression used to either determine which of the statements is
  /// executed next or to compute the value matched against the pattern in the
  /// `case` clause.
  Expression get expression;

  /// The token representing the `if` keyword.
  // TODO(scheglov): Extract shared `IfCondition`, see the patterns spec.
  Token get ifKeyword;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;

  /// The statement that is executed if the condition evaluates to `true`.
  Statement get thenStatement;
}

final class IfStatementImpl extends StatementImpl
    implements IfStatement, IfElementOrStatementImpl<StatementImpl> {
  @override
  final Token ifKeyword;

  @override
  final Token leftParenthesis;

  ExpressionImpl _expression;

  @override
  final CaseClauseImpl? caseClause;

  @override
  final Token rightParenthesis;

  @override
  final Token? elseKeyword;

  StatementImpl _thenStatement;

  StatementImpl? _elseStatement;

  /// Initializes a newly created if statement.
  ///
  /// The [elseKeyword] and [elseStatement] can be `null` if there's no else
  /// clause.
  IfStatementImpl({
    required this.ifKeyword,
    required this.leftParenthesis,
    required ExpressionImpl expression,
    required this.caseClause,
    required this.rightParenthesis,
    required StatementImpl thenStatement,
    required this.elseKeyword,
    required StatementImpl? elseStatement,
  }) : _expression = expression,
       _thenStatement = thenStatement,
       _elseStatement = elseStatement {
    _becomeParentOf(_expression);
    _becomeParentOf(caseClause);
    _becomeParentOf(_thenStatement);
    _becomeParentOf(_elseStatement);
  }

  @override
  Token get beginToken => ifKeyword;

  set condition(ExpressionImpl condition) {
    _expression = _becomeParentOf(condition);
  }

  @override
  StatementImpl? get elseStatement => _elseStatement;

  set elseStatement(StatementImpl? statement) {
    _elseStatement = _becomeParentOf(statement);
  }

  @override
  Token get endToken {
    if (elseStatement case var elseStatement?) {
      return elseStatement.endToken;
    }
    return _thenStatement.endToken;
  }

  @override
  ExpressionImpl get expression => _expression;

  @override
  StatementImpl? get ifFalse => elseStatement;

  @override
  StatementImpl get ifTrue => thenStatement;

  @override
  StatementImpl get thenStatement => _thenStatement;

  set thenStatement(StatementImpl statement) {
    _thenStatement = _becomeParentOf(statement);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('ifKeyword', ifKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('expression', expression)
        ..addNode('caseClause', caseClause)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addNode('thenStatement', thenStatement)
        ..addToken('elseKeyword', elseKeyword)
        ..addNode('elseStatement', elseStatement);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitIfStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _expression.accept(visitor);
    caseClause?.accept(visitor);
    _thenStatement.accept(visitor);
    _elseStatement?.accept(visitor);
  }
}

/// The "implements" clause in an class declaration.
///
///    implementsClause ::=
///        'implements' [NamedType] (',' [NamedType])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ImplementsClause implements AstNode {
  /// The token representing the `implements` keyword.
  Token get implementsKeyword;

  /// The list of the interfaces that are being implemented.
  NodeList<NamedType> get interfaces;
}

final class ImplementsClauseImpl extends AstNodeImpl
    implements ImplementsClause {
  @override
  final Token implementsKeyword;

  final NodeListImpl<NamedTypeImpl> _interfaces = NodeListImpl._();

  /// Initializes a newly created implements clause.
  ImplementsClauseImpl({
    required this.implementsKeyword,
    required List<NamedTypeImpl> interfaces,
  }) {
    _interfaces._initialize(this, interfaces);
  }

  @override
  Token get beginToken => implementsKeyword;

  @override
  Token get endToken => _interfaces.endToken ?? implementsKeyword;

  @override
  NodeListImpl<NamedTypeImpl> get interfaces => _interfaces;

  @override
  // TODO(paulberry): add commas.
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('implementsKeyword', implementsKeyword)
        ..addNodeList('interfaces', interfaces);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitImplementsClause(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _interfaces.accept(visitor);
  }
}

/// An expression representing an implicit 'call' method reference.
///
/// Objects of this type aren't produced directly by the parser (because the
/// parser can't tell whether an expression refers to a callable type); they
/// are produced at resolution time.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ImplicitCallReference
    implements MethodReferenceExpression {
  /// The expression from which a `call` method is being referenced.
  Expression get expression;

  /// The type arguments being applied to the tear-off, or `null` if there are
  /// no type arguments.
  TypeArgumentList? get typeArguments;

  /// The actual type arguments being applied to the tear-off, either explicitly
  /// specified in [typeArguments], or inferred.
  ///
  /// An empty list if the 'call' method doesn't have type parameters.
  List<DartType> get typeArgumentTypes;
}

final class ImplicitCallReferenceImpl extends ExpressionImpl
    implements ImplicitCallReference {
  ExpressionImpl _expression;

  TypeArgumentListImpl? _typeArguments;

  @override
  List<DartType> typeArgumentTypes;

  @override
  MethodElement2 element;

  ImplicitCallReferenceImpl({
    required ExpressionImpl expression,
    required this.element,
    required TypeArgumentListImpl? typeArguments,
    required this.typeArgumentTypes,
  }) : _expression = expression,
       _typeArguments = typeArguments {
    _becomeParentOf(_expression);
    _becomeParentOf(_typeArguments);
  }

  @override
  Token get beginToken => expression.beginToken;

  @override
  Token get endToken => typeArguments?.endToken ?? expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl value) {
    _expression = _becomeParentOf(value);
  }

  @override
  Precedence get precedence =>
      typeArguments == null ? expression.precedence : Precedence.postfix;

  @override
  TypeArgumentListImpl? get typeArguments => _typeArguments;

  set typeArguments(TypeArgumentListImpl? value) {
    _typeArguments = _becomeParentOf(value);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('expression', expression)
        ..addNode('typeArguments', typeArguments);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitImplicitCallReference(this);
  }

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitImplicitCallReference(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    expression.accept(visitor);
    typeArguments?.accept(visitor);
  }
}

/// An import directive.
///
///    importDirective ::=
///        [Annotation] 'import' [StringLiteral] ('as' identifier)?
///        [Combinator]* ';'
///      | [Annotation] 'import' [StringLiteral] 'deferred' 'as' identifier
///        [Combinator]* ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ImportDirective implements NamespaceDirective {
  /// The token representing the `as` keyword, or `null` if the imported names
  /// aren't prefixed.
  Token? get asKeyword;

  /// The token representing the `deferred` keyword, or `null` if the imported
  /// URI isn't deferred.
  Token? get deferredKeyword;

  /// The token representing the `import` keyword.
  Token get importKeyword;

  /// Information about this import directive.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  @experimental
  LibraryImport? get libraryImport;

  /// The prefix to be used with the imported names, or `null` if the imported
  /// names aren't prefixed.
  SimpleIdentifier? get prefix;
}

final class ImportDirectiveImpl extends NamespaceDirectiveImpl
    implements ImportDirective {
  @override
  final Token importKeyword;

  @override
  final Token? deferredKeyword;

  @override
  final Token? asKeyword;

  SimpleIdentifierImpl? _prefix;

  /// Initializes a newly created import directive.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// function doesn't have the corresponding attribute.
  ///
  /// The [deferredKeyword] can be `null` if the import isn't deferred.
  ///
  /// The [asKeyword] and [prefix] can be `null` if the import doesn't specify a
  /// prefix.
  ///
  /// The list of [combinators] can be `null` if there are no combinators.
  ImportDirectiveImpl({
    required super.comment,
    required super.metadata,
    required this.importKeyword,
    required super.uri,
    required super.configurations,
    required this.deferredKeyword,
    required this.asKeyword,
    required SimpleIdentifierImpl? prefix,
    required super.combinators,
    required super.semicolon,
  }) : _prefix = prefix {
    _becomeParentOf(_prefix);
  }

  @override
  Token get firstTokenAfterCommentAndMetadata => importKeyword;

  @experimental
  @override
  LibraryImportElementImpl? get libraryImport {
    return element as LibraryImportElementImpl?;
  }

  @override
  SimpleIdentifierImpl? get prefix => _prefix;

  set prefix(SimpleIdentifierImpl? identifier) {
    _prefix = _becomeParentOf(identifier);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('importKeyword', importKeyword)
        ..addNode('uri', uri)
        ..addToken('deferredKeyword', deferredKeyword)
        ..addToken('asKeyword', asKeyword)
        ..addNode('prefix', prefix)
        ..addNodeList('combinators', combinators)
        ..addNodeList('configurations', configurations)
        ..addToken('semicolon', semicolon);

  @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);
  }

  /// Returns `true` if the non-URI components of the two directives are
  /// syntactically identical.
  ///
  /// URIs are checked outside to see if they resolve to the same absolute URI,
  /// so to the same library, regardless of the used syntax (absolute, relative,
  /// not normalized).
  static bool areSyntacticallyIdenticalExceptUri(
    NamespaceDirective node1,
    NamespaceDirective node2,
  ) {
    if (node1 is ImportDirective &&
        node2 is ImportDirective &&
        node1.prefix?.name != node2.prefix?.name) {
      return false;
    }

    bool areSameNames(
      List<SimpleIdentifier> names1,
      List<SimpleIdentifier> names2,
    ) {
      if (names1.length != names2.length) {
        return false;
      }
      for (var i = 0; i < names1.length; i++) {
        if (names1[i].name != names2[i].name) {
          return false;
        }
      }
      return true;
    }

    var combinators1 = node1.combinators;
    var combinators2 = node2.combinators;
    if (combinators1.length != combinators2.length) {
      return false;
    }
    for (var i = 0; i < combinators1.length; i++) {
      var combinator1 = combinators1[i];
      var combinator2 = combinators2[i];
      if (combinator1 is HideCombinator && combinator2 is HideCombinator) {
        if (!areSameNames(combinator1.hiddenNames, combinator2.hiddenNames)) {
          return false;
        }
      } else if (combinator1 is ShowCombinator &&
          combinator2 is ShowCombinator) {
        if (!areSameNames(combinator1.shownNames, combinator2.shownNames)) {
          return false;
        }
      } else {
        return false;
      }
    }

    return true;
  }
}

/// Reference to an import prefix name.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ImportPrefixReference implements AstNode {
  /// The element to which [name] is resolved.
  ///
  /// Usually a [PrefixElement2], but can be anything in invalid code.
  @experimental
  Element2? get element2;

  /// The name of the referenced import prefix.
  Token get name;

  /// The `.` that separates [name] from the following identifier.
  Token get period;
}

final class ImportPrefixReferenceImpl extends AstNodeImpl
    implements ImportPrefixReference {
  @override
  final Token name;

  @override
  final Token period;

  @override
  Element2? element2;

  ImportPrefixReferenceImpl({required this.name, required this.period});

  @override
  Token get beginToken => name;

  @override
  Token get endToken => period;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('name', name)
        ..addToken('period', period);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitImportPrefixReference(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {}
}

/// An index expression.
///
///    indexExpression ::=
///        [Expression] '[' [Expression] ']'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class IndexExpression
    implements NullShortableExpression, MethodReferenceExpression {
  /// The expression used to compute the index.
  Expression get index;

  /// Whether this expression is cascaded.
  ///
  /// If it is, then the target of this expression isn't stored locally but is
  /// stored in the nearest ancestor that is a [CascadeExpression].
  bool get isCascaded;

  /// Whether this index expression is null aware (as opposed to non-null).
  bool get isNullAware;

  /// The left square bracket.
  Token get leftBracket;

  /// The period (".." | "?..") before a cascaded index expression, or `null` if
  /// this index expression isn't part of a cascade expression.
  Token? get period;

  /// The question mark before the left bracket, or `null` if there's no
  /// question mark.
  Token? get question;

  /// The expression used to compute the object being indexed.
  ///
  /// If this index expression isn't part of a cascade expression, then this
  /// is the same as [target]. If this index expression is part of a cascade
  /// expression, then the target expression stored with the cascade expression
  /// is returned.
  Expression get realTarget;

  /// The right square bracket.
  Token get rightBracket;

  /// The expression used to compute the object being indexed, or `null` if this
  /// index expression is part of a cascade expression.
  ///
  /// Use [realTarget] to get the target independent of whether this is part of
  /// a cascade expression.
  Expression? get target;

  /// Returns `true` if this expression is computing a right-hand value (that
  /// is, if this expression is in a context where the operator '[]' is
  /// invoked).
  ///
  /// Note that [inGetterContext] and [inSetterContext] aren't opposites, nor
  /// are they mutually exclusive. In other words, it's possible for both
  /// methods to return `true` when invoked on the same node.
  // TODO(brianwilkerson): Convert this to a getter.
  bool inGetterContext();

  /// Returns `true` if this expression is computing a left-hand value (that is,
  /// if this expression is in a context where the operator '[]=' is
  /// invoked).
  ///
  /// Note that [inGetterContext] and [inSetterContext] aren't opposites, nor
  /// are they mutually exclusive. In other words, it's possible for both
  /// methods to return `true` when invoked on the same node.
  // TODO(brianwilkerson): Convert this to a getter.
  bool inSetterContext();
}

final class IndexExpressionImpl extends ExpressionImpl
    with NullShortableExpressionImpl
    implements IndexExpression {
  @override
  Token? period;

  ExpressionImpl? _target;

  @override
  final Token? question;

  @override
  final Token leftBracket;

  ExpressionImpl _index;

  @override
  final Token rightBracket;

  /// The element associated with the operator based on the static type of the
  /// target, or `null` if the AST structure hasn't been resolved or if the
  /// operator couldn't be resolved.
  @override
  MethodElement2? element;

  /// Initializes a newly created index expression that is a child of a cascade
  /// expression.
  IndexExpressionImpl.forCascade({
    required this.period,
    required this.question,
    required this.leftBracket,
    required ExpressionImpl index,
    required this.rightBracket,
  }) : _index = index {
    _becomeParentOf(_index);
  }

  /// Initializes a newly created index expression that isn't a child of a
  /// cascade expression.
  IndexExpressionImpl.forTarget({
    required ExpressionImpl? target,
    required this.question,
    required this.leftBracket,
    required ExpressionImpl index,
    required this.rightBracket,
  }) : _target = target,
       _index = index {
    _becomeParentOf(_target);
    _becomeParentOf(_index);
  }

  @override
  Token get beginToken {
    if (target case var target?) {
      return target.beginToken;
    }
    return period!;
  }

  @override
  Token get endToken => rightBracket;

  @override
  ExpressionImpl get index => _index;

  set index(ExpressionImpl expression) {
    _index = _becomeParentOf(expression);
  }

  @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(ExpressionImpl? expression) {
    _target = _becomeParentOf(expression);
  }

  /// 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
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('target', target)
        ..addToken('period', period)
        ..addToken('leftBracket', leftBracket)
        ..addNode('index', index)
        ..addToken('rightBracket', rightBracket);

  @override
  AstNode get _nullShortingExtensionCandidate => parent!;

  /// The parameter element representing the parameter to which the value of the
  /// index expression is bound, or `null` if the AST structure is not resolved,
  /// or the function being invoked is not known based on static type
  /// information.
  FormalParameterElementMixin? get _staticParameterElementForIndex {
    Element2? element = this.element;

    var parent = this.parent;
    if (parent is CompoundAssignmentExpression) {
      element = parent.writeElement2 ?? parent.readElement2;
    }

    if (element is ExecutableElement2OrMember) {
      var formalParameters = element.formalParameters;
      if (formalParameters.isEmpty) {
        return null;
      }
      return formalParameters[0];
    }
    return null;
  }

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitIndexExpression(this);

  @override
  bool inGetterContext() {
    // TODO(brianwilkerson): Convert this to a getter.
    var 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.
    var 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 resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitIndexExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _target?.accept(visitor);
    _index.accept(visitor);
  }

  @override
  bool _extendsNullShorting(Expression descendant) =>
      identical(descendant, _target);
}

/// An instance creation expression.
///
///    newExpression ::=
///        ('new' | 'const')? [NamedType] ('.' [SimpleIdentifier])?
///        [ArgumentList]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class InstanceCreationExpression implements Expression {
  /// The list of arguments to the constructor.
  ArgumentList get argumentList;

  /// The name of the constructor to be invoked.
  ConstructorName get constructorName;

  /// Whether this creation expression is used to invoke a constant constructor,
  /// either because the keyword `const` was explicitly provided or because no
  /// keyword was provided and this expression is in a constant context.
  bool get isConst;

  /// The `new` or `const` keyword used to indicate how an object should be
  /// created, or `null` if the keyword isn't explicitly provided.
  Token? get keyword;
}

final 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.

  @override
  Token? keyword;

  ConstructorNameImpl _constructorName;

  /// The type arguments associated with the constructor, rather than with the
  /// class in which the constructor is defined.
  ///
  /// It's 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;

  ArgumentListImpl _argumentList;

  /// Initializes a newly created instance creation expression.
  InstanceCreationExpressionImpl({
    required this.keyword,
    required ConstructorNameImpl constructorName,
    required ArgumentListImpl argumentList,
    required TypeArgumentListImpl? typeArguments,
  }) : _constructorName = constructorName,
       _argumentList = argumentList,
       _typeArguments = typeArguments {
    _becomeParentOf(_constructorName);
    _becomeParentOf(_argumentList);
    _becomeParentOf(_typeArguments);
  }

  @override
  ArgumentListImpl get argumentList => _argumentList;

  set argumentList(ArgumentListImpl argumentList) {
    _argumentList = _becomeParentOf(argumentList);
  }

  @override
  Token get beginToken => keyword ?? _constructorName.beginToken;

  @override
  ConstructorNameImpl get constructorName => _constructorName;

  set constructorName(ConstructorNameImpl name) {
    _constructorName = _becomeParentOf(name);
  }

  @override
  Token get endToken => _argumentList.endToken;

  @override
  bool get isConst {
    if (!isImplicit) {
      return keyword!.keyword == Keyword.CONST;
    } else {
      return inConstantContext;
    }
  }

  /// Whether this is an implicit constructor invocation.
  bool get isImplicit => keyword == null;

  @override
  Precedence get precedence => Precedence.primary;

  /// The type arguments associated with the constructor, rather than with the
  /// class in which the constructor is defined.
  ///
  /// It's 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;

  set typeArguments(TypeArgumentListImpl? typeArguments) {
    _typeArguments = _becomeParentOf(typeArguments);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('keyword', keyword)
        ..addNode('constructorName', constructorName)
        ..addNode('typeArguments', typeArguments)
        ..addNode('argumentList', argumentList);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitInstanceCreationExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitInstanceCreationExpression(this, contextType: contextType);
  }

  @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+
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class IntegerLiteral implements Literal {
  /// The token representing the literal.
  Token get literal;

  /// The value of the literal, or `null` when [literal] doesn't represent a
  /// valid `int` value, for example because of overflow.
  int? get value;
}

final class IntegerLiteralImpl extends LiteralImpl implements IntegerLiteral {
  @override
  final Token literal;

  @override
  int? value = 0;

  /// Initializes a newly created integer literal.
  IntegerLiteralImpl({required this.literal, required this.value});

  @override
  Token get beginToken => literal;

  @override
  Token get endToken => literal;

  /// 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
  /// is always positive.
  bool get immediatelyNegated {
    var parent = this.parent!;
    return parent is PrefixExpression &&
        parent.operator.type == TokenType.MINUS;
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('literal', literal);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitIntegerLiteral(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitIntegerLiteral(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }

  static bool isValidAsDouble(String source) {
    // Less than 16 characters must be a valid double since it's less than
    // 9007199254740992, 0x10000000000000, both 16 characters and 53 bits.
    if (source.length < 16) {
      return true;
    }

    var fullPrecision = BigInt.tryParse(source);
    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.
    var 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.
    var bottomMask = (BigInt.one << (bitLengthAsInt - 53)) - BigInt.one;

    return fullPrecision & bottomMask == BigInt.zero;
  }

  /// Whether the given [source] 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 source, bool isNegative) {
    // TODO(jmesserly): this depends on the platform int implementation, and
    // might not be accurate if run in a browser.
    //
    // (Prior to https://dart-review.googlesource.com/c/sdk/+/63023 there was
    // a partial implementation here which might 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) source = '-$source';
    return int.tryParse(source) != null;
  }

  /// Suggests 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 source) =>
      math.min(double.maxFinite, BigInt.parse(source).toDouble());
}

/// A node within a [StringInterpolation].
///
///    interpolationElement ::=
///        [InterpolationExpression]
///      | [InterpolationString]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class InterpolationElement implements AstNode {}

sealed class InterpolationElementImpl extends AstNodeImpl
    implements InterpolationElement {}

/// An expression embedded in a string interpolation.
///
///    interpolationExpression ::=
///        '$' [SimpleIdentifier]
///      | '$' '{' [Expression] '}'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class InterpolationExpression implements InterpolationElement {
  /// The expression to be evaluated for the value to be converted into a
  /// string.
  Expression get expression;

  /// The token used to introduce the interpolation expression.
  ///
  /// This will either be `$` if the expression is a simple identifier or `${`
  /// if the expression is a full expression.
  Token get leftBracket;

  /// The right curly bracket, or `null` if the expression is an identifier
  /// without brackets.
  Token? get rightBracket;
}

final class InterpolationExpressionImpl extends InterpolationElementImpl
    implements InterpolationExpression {
  @override
  final Token leftBracket;

  ExpressionImpl _expression;

  @override
  final Token? rightBracket;

  /// Initializes a newly created interpolation expression.
  InterpolationExpressionImpl({
    required this.leftBracket,
    required ExpressionImpl expression,
    required this.rightBracket,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => leftBracket;

  @override
  Token get endToken => rightBracket ?? _expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('leftBracket', leftBracket)
        ..addNode('expression', expression)
        ..addToken('rightBracket', rightBracket);

  @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
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class InterpolationString implements InterpolationElement {
  /// The characters that are added to the string.
  Token get contents;

  /// The offset of the after-last contents character.
  int get contentsEnd;

  /// The offset of the first contents character.
  int get contentsOffset;

  /// The value of the literal.
  String get value;
}

final class InterpolationStringImpl extends InterpolationElementImpl
    implements InterpolationString {
  @override
  final Token contents;

  @override
  String value;

  /// Initializes a newly created string of characters that are part of a string
  /// interpolation.
  InterpolationStringImpl({required this.contents, required this.value});

  @override
  Token get beginToken => 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;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('contents', contents);

  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) {}
}

/// The invocation of a function or method.
///
/// This will either be a [FunctionExpressionInvocation], a [MethodInvocation],
/// a [DotShorthandConstructorInvocation], or a [DotShorthandInvocation].
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class InvocationExpression implements Expression {
  /// The list of arguments to the method.
  ArgumentList get argumentList;

  /// The expression that identifies the function or method being invoked.
  ///
  /// For example:
  ///
  /// ```dart
  /// (o.m)<TArgs>(args); // target is `o.m`
  /// o.m<TArgs>(args);   // target is `m`
  /// ```
  ///
  /// In either case, the `function.staticType` is the [staticInvokeType] before
  /// applying type arguments `TArgs`.
  Expression get function;

  /// The function type of the invocation based on the static type information,
  /// or `null` if the AST structure hasn't been resolved, or if the invoke
  /// couldn't be resolved.
  ///
  /// This is usually a [FunctionType], but it can also be `dynamic` or
  /// `Function`. In the case of interface types that have a `call` method, we
  /// store the type of that `call` method here as parameterized.
  DartType? get staticInvokeType;

  /// The type arguments to be applied to the method being invoked, or `null` if
  /// no type arguments were provided.
  TypeArgumentList? get typeArguments;

  /// The actual type arguments of the invocation, either explicitly specified
  /// in [typeArguments], or inferred, or `null` if the AST structure hasn't
  /// been resolved.
  ///
  /// An empty list if the [function] doesn't have type parameters.
  List<DartType>? get typeArgumentTypes;
}

sealed class InvocationExpressionImpl extends ExpressionImpl
    implements InvocationExpression {
  ArgumentListImpl _argumentList;

  TypeArgumentListImpl? _typeArguments;

  @override
  List<TypeImpl>? typeArgumentTypes;

  @override
  TypeImpl? staticInvokeType;

  /// Initializes a newly created invocation.
  InvocationExpressionImpl({
    required TypeArgumentListImpl? typeArguments,
    required ArgumentListImpl argumentList,
  }) : _typeArguments = typeArguments,
       _argumentList = argumentList {
    _becomeParentOf(_typeArguments);
    _becomeParentOf(_argumentList);
  }

  @override
  ArgumentListImpl get argumentList => _argumentList;

  set argumentList(ArgumentListImpl argumentList) {
    _argumentList = _becomeParentOf(argumentList);
  }

  @override
  TypeArgumentListImpl? get typeArguments => _typeArguments;

  set typeArguments(TypeArgumentListImpl? typeArguments) {
    _typeArguments = _becomeParentOf(typeArguments);
  }
}

/// An is expression.
///
///    isExpression ::=
///        [Expression] 'is' '!'? [TypeAnnotation]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class IsExpression implements Expression {
  /// The expression used to compute the value whose type is being tested.
  Expression get expression;

  /// The is operator.
  Token get isOperator;

  /// The not operator, or `null` if the sense of the test isn't negated.
  Token? get notOperator;

  /// The type being tested for.
  TypeAnnotation get type;
}

final class IsExpressionImpl extends ExpressionImpl implements IsExpression {
  ExpressionImpl _expression;

  @override
  final Token isOperator;

  @override
  final Token? notOperator;

  TypeAnnotationImpl _type;

  /// Initializes a newly created is expression.
  ///
  /// The [notOperator] can be `null` if the sense of the test isn't negated.
  IsExpressionImpl({
    required ExpressionImpl expression,
    required this.isOperator,
    required this.notOperator,
    required TypeAnnotationImpl type,
  }) : _expression = expression,
       _type = type {
    _becomeParentOf(_expression);
    _becomeParentOf(_type);
  }

  @override
  Token get beginToken => _expression.beginToken;

  @override
  Token get endToken => _type.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.relational;

  @override
  TypeAnnotationImpl get type => _type;

  set type(TypeAnnotationImpl type) {
    _type = _becomeParentOf(type);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('expression', expression)
        ..addToken('isOperator', isOperator)
        ..addToken('notOperator', notOperator)
        ..addNode('type', type);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitIsExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitIsExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _expression.accept(visitor);
    _type.accept(visitor);
  }
}

/// A label on either a [LabeledStatement] or a [NamedExpression].
///
///    label ::=
///        [SimpleIdentifier] ':'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Label implements AstNode {
  /// The colon that separates the label from the statement.
  Token get colon;

  /// The fragment declared by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  LabelFragment? get declaredFragment;

  /// The label being associated with the statement.
  SimpleIdentifier get label;
}

/// A statement that has a label associated with them.
///
///    labeledStatement ::=
///       [Label]+ [Statement]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class LabeledStatement implements Statement {
  /// The labels being associated with the statement.
  NodeList<Label> get labels;

  /// The statement with which the labels are being associated.
  Statement get statement;
}

final class LabeledStatementImpl extends StatementImpl
    implements LabeledStatement {
  final NodeListImpl<LabelImpl> _labels = NodeListImpl._();

  StatementImpl _statement;

  /// Initializes a newly created labeled statement.
  LabeledStatementImpl({
    required List<LabelImpl> labels,
    required StatementImpl statement,
  }) : _statement = statement {
    _labels._initialize(this, labels);
    _becomeParentOf(_statement);
  }

  @override
  Token get beginToken {
    if (_labels.isNotEmpty) {
      return _labels.beginToken!;
    }
    return _statement.beginToken;
  }

  @override
  Token get endToken => _statement.endToken;

  @override
  NodeListImpl<LabelImpl> get labels => _labels;

  @override
  StatementImpl get statement => _statement;

  set statement(StatementImpl statement) {
    _statement = _becomeParentOf(statement);
  }

  @override
  StatementImpl get unlabeled => _statement.unlabeled;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNodeList('labels', labels)
        ..addNode('statement', statement);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitLabeledStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _labels.accept(visitor);
    _statement.accept(visitor);
  }
}

final class LabelImpl extends AstNodeImpl implements Label {
  SimpleIdentifierImpl _label;

  @override
  final Token colon;

  /// Initializes a newly created label.
  LabelImpl({required SimpleIdentifierImpl label, required this.colon})
    : _label = label {
    _becomeParentOf(_label);
  }

  @override
  Token get beginToken => _label.beginToken;

  @override
  LabelElementImpl? get declaredFragment =>
      (label.element as LabelElementImpl2?)?.firstFragment;

  @override
  Token get endToken => colon;

  @override
  SimpleIdentifierImpl get label => _label;

  set label(SimpleIdentifierImpl label) {
    _label = _becomeParentOf(label);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('label', label)
        ..addToken('colon', colon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitLabel(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _label.accept(visitor);
  }
}

/// A library directive.
///
///    libraryDirective ::=
///        [Annotation] 'library' [LibraryIdentifier]? ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class LibraryDirective implements Directive {
  /// The element associated with this directive.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if this
  /// directive couldn't be resolved.
  @experimental
  LibraryElement2? get element2;

  /// The token representing the `library` keyword.
  Token get libraryKeyword;

  /// The name of the library being defined.
  LibraryIdentifier? get name2;

  /// The semicolon terminating the directive.
  Token get semicolon;
}

final class LibraryDirectiveImpl extends DirectiveImpl
    implements LibraryDirective {
  @override
  final Token libraryKeyword;

  LibraryIdentifierImpl? _name;

  @override
  final Token semicolon;

  /// Initializes a newly created library directive.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// directive doesn't have the corresponding attribute.
  LibraryDirectiveImpl({
    required super.comment,
    required super.metadata,
    required this.libraryKeyword,
    required LibraryIdentifierImpl? name,
    required this.semicolon,
  }) : _name = name {
    _becomeParentOf(_name);
  }

  @experimental
  @override
  LibraryElementImpl? get element2 => element as LibraryElementImpl?;

  @override
  Token get endToken => semicolon;

  @override
  Token get firstTokenAfterCommentAndMetadata => libraryKeyword;

  set name(LibraryIdentifierImpl? name) {
    _name = _becomeParentOf(name);
  }

  @override
  LibraryIdentifierImpl? get name2 => _name;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('libraryKeyword', libraryKeyword)
        ..addNode('name', name2)
        ..addToken('semicolon', semicolon);

  @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])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class LibraryIdentifier implements Identifier {
  /// The components of the identifier.
  NodeList<SimpleIdentifier> get components;
}

final class LibraryIdentifierImpl extends IdentifierImpl
    implements LibraryIdentifier {
  final NodeListImpl<SimpleIdentifierImpl> _components = NodeListImpl._();

  /// Initializes a newly created prefixed identifier.
  LibraryIdentifierImpl({required List<SimpleIdentifierImpl> components}) {
    _components._initialize(this, components);
  }

  @override
  Token get beginToken => _components.beginToken!;

  @override
  NodeListImpl<SimpleIdentifierImpl> get components => _components;

  @override
  Element2? get element => null;

  @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 considerCanonicalizeString(buffer.toString());
  }

  @override
  Precedence get precedence => Precedence.postfix;

  @override
  // TODO(paulberry): add "." tokens.
  ChildEntities get _childEntities =>
      ChildEntities()..addNodeList('components', components);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitLibraryIdentifier(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitLibraryIdentifier(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _components.accept(visitor);
  }
}

/// A list literal.
///
///    listLiteral ::=
///        'const'? [TypeAnnotationList]? '[' elements? ']'
///
///    elements ::=
///        [CollectionElement] (',' [CollectionElement])* ','?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ListLiteral implements TypedLiteral {
  /// The syntactic elements used to compute the elements of the list.
  NodeList<CollectionElement> get elements;

  /// The left square bracket.
  Token get leftBracket;

  /// The right square bracket.
  Token get rightBracket;
}

final class ListLiteralImpl extends TypedLiteralImpl implements ListLiteral {
  @override
  final Token leftBracket;

  final NodeListImpl<CollectionElementImpl> _elements = NodeListImpl._();

  @override
  final Token rightBracket;

  /// Initializes a newly created list literal.
  ///
  /// The [constKeyword] can be `null` if the literal isn't 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({
    required super.constKeyword,
    required super.typeArguments,
    required this.leftBracket,
    required List<CollectionElementImpl> elements,
    required this.rightBracket,
  }) {
    _elements._initialize(this, elements);
  }

  @override
  Token get beginToken {
    if (constKeyword case var constKeyword?) {
      return constKeyword;
    }
    var typeArguments = this.typeArguments;
    if (typeArguments != null) {
      return typeArguments.beginToken;
    }
    return leftBracket;
  }

  @override
  NodeListImpl<CollectionElementImpl> get elements => _elements;

  @override
  Token get endToken => rightBracket;

  @override
  // TODO(paulberry): add commas.
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('elements', elements)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitListLiteral(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitListLiteral(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _elements.accept(visitor);
  }
}

/// A list pattern.
///
///    listPattern ::=
///        [TypeArgumentList]? '[' [DartPattern] (',' [DartPattern])* ','? ']'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ListPattern implements DartPattern {
  /// The elements in this pattern.
  NodeList<ListPatternElement> get elements;

  /// The left square bracket.
  Token get leftBracket;

  /// The required type, specified by [typeArguments] or inferred from the
  /// matched value type, or `null` if the node isn't resolved yet.
  DartType? get requiredType;

  /// The right square bracket.
  Token get rightBracket;

  /// The type arguments associated with this pattern, or `null` if no type
  /// arguments were declared.
  TypeArgumentList? get typeArguments;
}

/// An element of a list pattern.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class ListPatternElement implements AstNode {}

abstract final class ListPatternElementImpl
    implements AstNodeImpl, ListPatternElement {}

final class ListPatternImpl extends DartPatternImpl implements ListPattern {
  @override
  final TypeArgumentListImpl? typeArguments;

  @override
  final Token leftBracket;

  final NodeListImpl<ListPatternElementImpl> _elements = NodeListImpl._();

  @override
  final Token rightBracket;

  @override
  TypeImpl? requiredType;

  ListPatternImpl({
    required this.typeArguments,
    required this.leftBracket,
    required List<ListPatternElementImpl> elements,
    required this.rightBracket,
  }) {
    _becomeParentOf(typeArguments);
    _elements._initialize(this, elements);
  }

  @override
  Token get beginToken => typeArguments?.beginToken ?? leftBracket;

  @override
  NodeList<ListPatternElementImpl> get elements => _elements;

  @override
  Token get endToken => rightBracket;

  @override
  PatternPrecedence get precedence => PatternPrecedence.primary;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('typeArguments', typeArguments)
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('elements', elements)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitListPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    var elementType = typeArguments?.arguments.elementAtOrNull(0)?.typeOrThrow;
    return resolverVisitor
        .analyzeListPatternSchema(
          elementType: elementType?.wrapSharedTypeView(),
          elements: elements,
        )
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var analysisResult = resolverVisitor.listPatternResolver.resolve(
      node: this,
      context: context,
    );
    inferenceLogWriter?.exitPattern(this);
    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    typeArguments?.accept(visitor);
    elements.accept(visitor);
  }
}

/// A node that represents a literal expression.
///
///    literal ::=
///        [BooleanLiteral]
///      | [DoubleLiteral]
///      | [IntegerLiteral]
///      | [ListLiteral]
///      | [NullLiteral]
///      | [RecordLiteral]
///      | [SetOrMapLiteral]
///      | [StringLiteral]
///      | [SymbolLiteral]
///      | [TypedLiteral]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class Literal implements Expression {}

sealed 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 the scope of their declarations.
  final Set<VariableElement2> potentiallyMutatedInScope = {};
}

/// A logical-and pattern.
///
///    logicalAndPattern ::=
///        [DartPattern] '&&' [DartPattern]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class LogicalAndPattern implements DartPattern {
  /// The left sub-pattern.
  DartPattern get leftOperand;

  /// The `&&` operator.
  Token get operator;

  /// The right sub-pattern.
  DartPattern get rightOperand;
}

final class LogicalAndPatternImpl extends DartPatternImpl
    implements LogicalAndPattern {
  @override
  final DartPatternImpl leftOperand;

  @override
  final Token operator;

  @override
  final DartPatternImpl rightOperand;

  LogicalAndPatternImpl({
    required this.leftOperand,
    required this.operator,
    required this.rightOperand,
  }) {
    _becomeParentOf(leftOperand);
    _becomeParentOf(rightOperand);
  }

  @override
  Token get beginToken => leftOperand.beginToken;

  @override
  Token get endToken => rightOperand.endToken;

  @override
  PatternPrecedence get precedence => PatternPrecedence.logicalAnd;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('leftOperand', leftOperand)
        ..addToken('operator', operator)
        ..addNode('rightOperand', rightOperand);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitLogicalAndPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeLogicalAndPatternSchema(leftOperand, rightOperand)
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var analysisResult = resolverVisitor.analyzeLogicalAndPattern(
      context,
      this,
      leftOperand,
      rightOperand,
    );
    inferenceLogWriter?.exitPattern(this);
    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    leftOperand.accept(visitor);
    rightOperand.accept(visitor);
  }
}

/// A logical-or pattern.
///
///    logicalOrPattern ::=
///        [DartPattern] '||' [DartPattern]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class LogicalOrPattern implements DartPattern {
  /// The left sub-pattern.
  DartPattern get leftOperand;

  /// The `||` operator.
  Token get operator;

  /// The right sub-pattern.
  DartPattern get rightOperand;
}

final class LogicalOrPatternImpl extends DartPatternImpl
    implements LogicalOrPattern {
  @override
  final DartPatternImpl leftOperand;

  @override
  final Token operator;

  @override
  final DartPatternImpl rightOperand;

  LogicalOrPatternImpl({
    required this.leftOperand,
    required this.operator,
    required this.rightOperand,
  }) {
    _becomeParentOf(leftOperand);
    _becomeParentOf(rightOperand);
  }

  @override
  Token get beginToken => leftOperand.beginToken;

  @override
  Token get endToken => rightOperand.endToken;

  @override
  PatternPrecedence get precedence => PatternPrecedence.logicalOr;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('leftOperand', leftOperand)
        ..addToken('operator', operator)
        ..addNode('rightOperand', rightOperand);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitLogicalOrPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeLogicalOrPatternSchema(leftOperand, rightOperand)
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var analysisResult = resolverVisitor.analyzeLogicalOrPattern(
      context,
      this,
      leftOperand,
      rightOperand,
    );
    resolverVisitor.nullSafetyDeadCodeVerifier.flowEnd(rightOperand);
    inferenceLogWriter?.exitPattern(this);
    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    leftOperand.accept(visitor);
    rightOperand.accept(visitor);
  }
}

/// A single key/value pair in a map literal.
///
///    mapLiteralEntry ::=
///        '?'? [Expression] ':' '?'? [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class MapLiteralEntry implements CollectionElement {
  /// The expression computing the key with which the value is associated.
  Expression get key;

  /// The question prefix for the key that may present in null-aware map
  /// entries.
  Token? get keyQuestion;

  /// The colon that separates the key from the value.
  Token get separator;

  /// The expression computing the value that is associated with the key.
  Expression get value;

  /// The question prefix for the value that may present in null-aware map
  /// entries.
  Token? get valueQuestion;
}

final class MapLiteralEntryImpl extends CollectionElementImpl
    implements MapLiteralEntry {
  @override
  final Token? keyQuestion;

  ExpressionImpl _key;

  @override
  final Token separator;

  @override
  final Token? valueQuestion;

  ExpressionImpl _value;

  /// Initializes a newly created map literal entry.
  MapLiteralEntryImpl({
    required this.keyQuestion,
    required ExpressionImpl key,
    required this.separator,
    required this.valueQuestion,
    required ExpressionImpl value,
  }) : _key = key,
       _value = value {
    _becomeParentOf(_key);
    _becomeParentOf(_value);
  }

  @override
  Token get beginToken => keyQuestion ?? _key.beginToken;

  @override
  Token get endToken => _value.endToken;

  @override
  ExpressionImpl get key => _key;

  set key(ExpressionImpl string) {
    _key = _becomeParentOf(string);
  }

  @override
  ExpressionImpl get value => _value;

  set value(ExpressionImpl expression) {
    _value = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('keyQuestion', keyQuestion)
        ..addNode('key', key)
        ..addToken('separator', separator)
        ..addToken('valueQuestion', valueQuestion)
        ..addNode('value', value);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitMapLiteralEntry(this);

  @override
  void resolveElement(
    ResolverVisitor resolver,
    CollectionLiteralContext? context,
  ) {
    resolver.visitMapLiteralEntry(this, context: context);
    resolver.pushRewrite(null);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _key.accept(visitor);
    _value.accept(visitor);
  }
}

/// A map pattern.
///
///    mapPattern ::=
///        [TypeArgumentList]? '{' [MapPatternEntry] (',' [MapPatternEntry])*
///        ','? '}'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class MapPattern implements DartPattern {
  /// The elements in this pattern.
  NodeList<MapPatternElement> get elements;

  /// The left curly bracket.
  Token get leftBracket;

  /// The matched value type, or `null` if the node isn't resolved yet.
  DartType? get requiredType;

  /// The right curly bracket.
  Token get rightBracket;

  /// The type arguments associated with this pattern, or `null` if no type
  /// arguments were declared.
  TypeArgumentList? get typeArguments;
}

/// An element of a map pattern.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class MapPatternElement implements AstNode {}

sealed class MapPatternElementImpl implements AstNodeImpl, MapPatternElement {}

/// An entry in a map pattern.
///
///    mapPatternEntry ::=
///        [Expression] ':' [DartPattern]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class MapPatternEntry implements AstNode, MapPatternElement {
  /// The expression computing the key of the entry to be matched.
  Expression get key;

  /// The colon that separates the key from the value.
  Token get separator;

  /// The pattern used to match the value.
  DartPattern get value;
}

final class MapPatternEntryImpl extends AstNodeImpl
    implements MapPatternEntry, MapPatternElementImpl {
  ExpressionImpl _key;

  @override
  final Token separator;

  @override
  final DartPatternImpl value;

  MapPatternEntryImpl({
    required ExpressionImpl key,
    required this.separator,
    required this.value,
  }) : _key = key {
    _becomeParentOf(_key);
    _becomeParentOf(value);
  }

  @override
  Token get beginToken => key.beginToken;

  @override
  Token get endToken => value.endToken;

  @override
  ExpressionImpl get key => _key;

  set key(ExpressionImpl key) {
    _key = _becomeParentOf(key);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('key', key)
        ..addToken('separator', separator)
        ..addNode('value', value);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitMapPatternEntry(this);

  @override
  void visitChildren(AstVisitor visitor) {
    key.accept(visitor);
    value.accept(visitor);
  }
}

final class MapPatternImpl extends DartPatternImpl implements MapPattern {
  @override
  final TypeArgumentListImpl? typeArguments;

  @override
  final Token leftBracket;

  final NodeListImpl<MapPatternElementImpl> _elements = NodeListImpl._();

  @override
  final Token rightBracket;

  @override
  TypeImpl? requiredType;

  MapPatternImpl({
    required this.typeArguments,
    required this.leftBracket,
    required List<MapPatternElementImpl> elements,
    required this.rightBracket,
  }) {
    _becomeParentOf(typeArguments);
    _elements._initialize(this, elements);
  }

  @override
  Token get beginToken => typeArguments?.beginToken ?? leftBracket;

  @override
  NodeList<MapPatternElementImpl> get elements => _elements;

  @override
  Token get endToken => rightBracket;

  @override
  PatternPrecedence get precedence => PatternPrecedence.primary;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('typeArguments', typeArguments)
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('elements', elements)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitMapPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    var typeArgumentNodes = this.typeArguments?.arguments;
    ({SharedTypeView keyType, SharedTypeView valueType})? typeArguments;
    if (typeArgumentNodes != null && typeArgumentNodes.length == 2) {
      typeArguments = (
        keyType: SharedTypeView(typeArgumentNodes[0].typeOrThrow),
        valueType: SharedTypeView(typeArgumentNodes[1].typeOrThrow),
      );
    }
    return resolverVisitor
        .analyzeMapPatternSchema(
          typeArguments: typeArguments,
          elements: elements,
        )
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    return resolverVisitor.resolveMapPattern(node: this, context: context);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    typeArguments?.accept(visitor);
    elements.accept(visitor);
  }
}

/// A method declaration.
///
///    methodDeclaration ::=
///        methodSignature [FunctionBody]
///
///    methodSignature ::=
///        'external'? ('abstract' | 'static')? [Type]? ('get' | 'set')?
///        methodName [TypeParameterList] [FormalParameterList]
///
///    methodName ::=
///        [SimpleIdentifier]
///      | 'operator' [SimpleIdentifier]
///
/// Prior to the 'extension-methods' experiment, these nodes were always
/// children of a class declaration. When the experiment is enabled, these nodes
/// can also be children of an extension declaration.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class MethodDeclaration implements ClassMember {
  /// The token for the `augment` keyword.
  Token? get augmentKeyword;

  /// The body of the method.
  FunctionBody get body;

  @experimental
  @override
  ExecutableFragment? get declaredFragment;

  /// The token for the `external` keyword, or `null` if the constructor isn't
  /// external.
  Token? get externalKeyword;

  /// Whether this method is declared to be an abstract method.
  bool get isAbstract;

  /// Whether this method declares a getter.
  bool get isGetter;

  /// Whether this method declares an operator.
  bool get isOperator;

  /// Whether this method declares a setter.
  bool get isSetter;

  /// Whether this method is declared to be a static method.
  bool get isStatic;

  /// The token representing the `abstract` or `static` keyword, or `null` if
  /// neither modifier was specified.
  Token? get modifierKeyword;

  /// The name of the method.
  Token get name;

  /// The token representing the `operator` keyword, or `null` if this method
  /// doesn't declare an operator.
  Token? get operatorKeyword;

  /// The parameters associated with the method, or `null` if this method
  /// declares a getter.
  FormalParameterList? get parameters;

  /// The token representing the `get` or `set` keyword, or `null` if this is a
  /// method declaration rather than a property
  /// declaration.
  Token? get propertyKeyword;

  /// The return type of the method, or `null` if no return type was declared.
  TypeAnnotation? get returnType;

  /// The type parameters associated with this method, or `null` if this method
  /// isn't a generic method.
  TypeParameterList? get typeParameters;
}

final class MethodDeclarationImpl extends ClassMemberImpl
    with AstNodeWithNameScopeMixin
    implements MethodDeclaration {
  @override
  final Token? augmentKeyword;

  @override
  final Token? externalKeyword;

  @override
  final Token? modifierKeyword;

  @override
  final TypeAnnotationImpl? returnType;

  @override
  final Token? propertyKeyword;

  @override
  final Token? operatorKeyword;

  @override
  final Token name;

  @override
  final TypeParameterListImpl? typeParameters;

  @override
  final FormalParameterListImpl? parameters;

  @override
  final FunctionBodyImpl body;

  @override
  ExecutableElementImpl? declaredFragment;

  MethodDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.externalKeyword,
    required this.modifierKeyword,
    required this.returnType,
    required this.propertyKeyword,
    required this.operatorKeyword,
    required this.name,
    required this.typeParameters,
    required this.parameters,
    required this.body,
  }) {
    _becomeParentOf(returnType);
    _becomeParentOf(typeParameters);
    _becomeParentOf(parameters);
    _becomeParentOf(body);
  }

  @override
  Token get endToken => body.endToken;

  @override
  Token get firstTokenAfterCommentAndMetadata {
    return augmentKeyword ??
        Token.lexicallyFirst(externalKeyword, modifierKeyword) ??
        returnType?.beginToken ??
        Token.lexicallyFirst(propertyKeyword, operatorKeyword) ??
        name;
  }

  @override
  bool get isAbstract {
    var body = this.body;
    return externalKeyword == null &&
        (body is EmptyFunctionBodyImpl && !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
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('externalKeyword', externalKeyword)
        ..addToken('modifierKeyword', modifierKeyword)
        ..addNode('returnType', returnType)
        ..addToken('propertyKeyword', propertyKeyword)
        ..addToken('operatorKeyword', operatorKeyword)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addNode('parameters', parameters)
        ..addNode('body', body);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitMethodDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    returnType?.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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class MethodInvocation
    implements NullShortableExpression, InvocationExpression {
  /// Whether this expression is cascaded.
  ///
  /// If it is, then the target of this expression isn't stored locally but is
  /// stored in the nearest ancestor that is a [CascadeExpression].
  bool get isCascaded;

  /// Whether this method invocation is null aware (as opposed to non-null).
  bool get isNullAware;

  /// The name of the method being invoked.
  SimpleIdentifier get methodName;

  /// The operator that separates the target from the method name, or `null` if
  /// there's no target.
  ///
  /// In an ordinary method invocation this is either a period (`.`) or a
  /// null-aware opertator (`?.`). In a cascade section this is the cascade
  /// operator ('..').
  Token? get operator;

  /// The expression used to compute the receiver of the invocation.
  ///
  /// If this invocation isn't part of a cascade expression, then this is the
  /// same as [target]. If this invocation is part of a cascade expression,
  /// then the target stored with the cascade expression is returned.
  Expression? get realTarget;

  /// The expression producing the object on which the method is defined, or
  /// `null` if there's no target (that is, the target is implicitly `this`) or
  /// if this method invocation is part of a cascade expression.
  ///
  /// Use [realTarget] to get the target independent of whether this is part of
  /// a cascade expression.
  Expression? get target;
}

final class MethodInvocationImpl extends InvocationExpressionImpl
    with NullShortableExpressionImpl, DotShorthandMixin
    implements MethodInvocation {
  ExpressionImpl? _target;

  @override
  Token? operator;

  SimpleIdentifierImpl _methodName;

  /// The invoke type of the [methodName] if the target element is a getter,
  /// or `null` otherwise.
  DartType? _methodNameType;

  /// Initializes a newly created method invocation.
  ///
  /// The [target] and [operator] can be `null` if there's no target.
  MethodInvocationImpl({
    required ExpressionImpl? target,
    required this.operator,
    required SimpleIdentifierImpl methodName,
    required super.typeArguments,
    required super.argumentList,
  }) : _target = target,
       _methodName = methodName {
    _becomeParentOf(_target);
    _becomeParentOf(_methodName);
  }

  @override
  Token get beginToken {
    if (target case var target?) {
      return target.beginToken;
    } else if (operator case var operator?) {
      return operator;
    }
    return _methodName.beginToken;
  }

  @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(SimpleIdentifierImpl identifier) {
    _methodName = _becomeParentOf(identifier);
  }

  /// The invoke type of the [methodName].
  ///
  /// If the target element is a [MethodElement2], this is the same as the
  /// [staticInvokeType].
  ///
  /// If the target element is a getter, presumably returning an
  /// [ExecutableElement2] 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 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(ExpressionImpl? expression) {
    _target = _becomeParentOf(expression);
  }

  /// 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
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('target', target)
        ..addToken('operator', operator)
        ..addNode('methodName', methodName)
        ..addNode('typeArguments', typeArguments)
        ..addNode('argumentList', argumentList);

  @override
  AstNode? get _nullShortingExtensionCandidate => parent;

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitMethodInvocation(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitMethodInvocation(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _target?.accept(visitor);
    _methodName.accept(visitor);
    _typeArguments?.accept(visitor);
    _argumentList.accept(visitor);
  }

  @override
  bool _extendsNullShorting(Expression descendant) =>
      identical(descendant, _target);
}

/// An expression that implicitly makes reference to a method.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class MethodReferenceExpression implements Expression {
  /// The element associated with the expression based on the static types.
  ///
  /// Returns`null` if the AST structure hasn't been resolved, or there's no
  /// meaningful element to return. The latter case can occur, for example, when
  /// this is a non-compound assignment expression, or when the method referred
  /// to couldn't be resolved.
  @experimental
  MethodElement2? get element;
}

/// The declaration of a mixin.
///
///    mixinDeclaration ::=
///        'base'? 'mixin' name [TypeParameterList]?
///        [OnClause]? [ImplementsClause]? '{' [ClassMember]* '}'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class MixinDeclaration implements NamedCompilationUnitMember {
  /// The `augment` keyword, or `null` if the keyword was absent.
  Token? get augmentKeyword;

  /// The `base` keyword, or `null` if the keyword was absent.
  Token? get baseKeyword;

  @experimental
  @override
  MixinFragment? get declaredFragment;

  /// The `implements` clause for the mixin, or `null` if the mixin doesn't
  /// implement any interfaces.
  ImplementsClause? get implementsClause;

  /// The left curly bracket.
  Token get leftBracket;

  /// The members defined by the mixin.
  NodeList<ClassMember> get members;

  /// The token representing the `mixin` keyword.
  Token get mixinKeyword;

  /// The on clause for the mixin, or `null` if the mixin doesn't have any
  /// superclass constraints.
  MixinOnClause? get onClause;

  /// The right curly bracket.
  Token get rightBracket;

  /// The type parameters for the mixin, or `null` if the mixin doesn't have any
  /// type parameters.
  TypeParameterList? get typeParameters;
}

final class MixinDeclarationImpl extends NamedCompilationUnitMemberImpl
    with AstNodeWithNameScopeMixin
    implements MixinDeclaration {
  @override
  final Token? augmentKeyword;

  @override
  final Token? baseKeyword;

  @override
  final Token mixinKeyword;

  @override
  final TypeParameterListImpl? typeParameters;

  @override
  final MixinOnClauseImpl? onClause;

  @override
  final ImplementsClauseImpl? implementsClause;

  @override
  final Token leftBracket;

  @override
  final NodeListImpl<ClassMemberImpl> members = NodeListImpl._();

  @override
  final Token rightBracket;

  @override
  MixinElementImpl? declaredFragment;

  MixinDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.baseKeyword,
    required this.mixinKeyword,
    required super.name,
    required this.typeParameters,
    required this.onClause,
    required this.implementsClause,
    required this.leftBracket,
    required List<ClassMemberImpl> members,
    required this.rightBracket,
  }) {
    _becomeParentOf(typeParameters);
    _becomeParentOf(onClause);
    _becomeParentOf(implementsClause);
    this.members._initialize(this, members);
  }

  @override
  Token get endToken => rightBracket;

  @override
  Token get firstTokenAfterCommentAndMetadata {
    return augmentKeyword ?? baseKeyword ?? mixinKeyword;
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('baseKeyword', baseKeyword)
        ..addToken('mixinKeyword', mixinKeyword)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addNode('onClause', onClause)
        ..addNode('implementsClause', implementsClause)
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('members', members)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitMixinDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    typeParameters?.accept(visitor);
    onClause?.accept(visitor);
    implementsClause?.accept(visitor);
    members.accept(visitor);
  }
}

/// The "on" clause in a mixin declaration.
///
///    onClause ::=
///        'on' [NamedType] (',' [NamedType])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class MixinOnClause implements AstNode {
  /// The token representing the `on` keyword.
  Token get onKeyword;

  /// The list of the classes are superclass constraints for the mixin.
  NodeList<NamedType> get superclassConstraints;
}

final class MixinOnClauseImpl extends AstNodeImpl implements MixinOnClause {
  @override
  final Token onKeyword;

  final NodeListImpl<NamedTypeImpl> _superclassConstraints = NodeListImpl._();

  MixinOnClauseImpl({
    required this.onKeyword,
    required List<NamedTypeImpl> superclassConstraints,
  }) {
    _superclassConstraints._initialize(this, superclassConstraints);
  }

  @override
  Token get beginToken => onKeyword;

  @override
  Token get endToken => _superclassConstraints.endToken ?? onKeyword;

  @override
  NodeListImpl<NamedTypeImpl> get superclassConstraints =>
      _superclassConstraints;

  @override
  // TODO(paulberry): add commas.
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('onKeyword', onKeyword)
        ..addNodeList('superclassConstraints', superclassConstraints);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitMixinOnClause(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _superclassConstraints.accept(visitor);
  }
}

/// A node that declares a single name within the scope of a compilation unit.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NamedCompilationUnitMember
    implements CompilationUnitMember {
  /// The name of the member being declared.
  Token get name;
}

sealed class NamedCompilationUnitMemberImpl extends CompilationUnitMemberImpl
    implements NamedCompilationUnitMember {
  @override
  final Token name;

  /// Initializes a newly created compilation unit member with the given [name].
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the member
  /// doesn't have the corresponding attribute.
  NamedCompilationUnitMemberImpl({
    required super.comment,
    required super.metadata,
    required this.name,
  });
}

/// An expression that has a name associated with it.
///
/// They are only used in method invocations when there are named parameters.
///
///    namedExpression ::=
///        [Label] [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NamedExpression implements Expression {
  /// The element representing the parameter being named by this expression.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if there's no
  /// parameter with the same name as this expression.
  @experimental
  FormalParameterElement? get element2;

  /// The expression with which the name is associated.
  Expression get expression;

  /// The name associated with the expression.
  Label get name;
}

final class NamedExpressionImpl extends ExpressionImpl
    implements NamedExpression {
  LabelImpl _name;

  ExpressionImpl _expression;

  /// Initializes a newly created named expression.
  NamedExpressionImpl({
    required LabelImpl name,
    required ExpressionImpl expression,
  }) : _name = name,
       _expression = expression {
    _becomeParentOf(_name);
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => _name.beginToken;

  @experimental
  @override
  FormalParameterElementMixin? get element2 {
    return _name.label.element?.ifTypeOrNull();
  }

  @override
  Token get endToken => _expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  LabelImpl get name => _name;

  set name(LabelImpl identifier) {
    _name = _becomeParentOf(identifier);
  }

  @override
  Precedence get precedence => Precedence.none;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('name', name)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitNamedExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitNamedExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _name.accept(visitor);
    _expression.accept(visitor);
  }
}

/// A named type, which can optionally include type arguments.
///
///    namedType ::=
///        [ImportPrefixReference]? name typeArguments?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NamedType implements TypeAnnotation {
  /// The element of [name2] considering [importPrefix].
  ///
  /// This could be a [ClassElement2], [TypeAliasElement2], or other type defining
  /// element.
  ///
  /// Returns `null` if [name2] can't be resolved, or there's no element for the
  /// type name, such as for `void`.
  @experimental
  Element2? get element2;

  /// The optional import prefix before [name2].
  ImportPrefixReference? get importPrefix;

  /// Whether this type is a deferred type.
  ///
  /// A deferred type is a type that is referenced through an import prefix
  /// (such as `p.T`), where the prefix is used by a deferred import.
  ///
  /// Returns `false` if the AST structure hasn't been resolved.
  bool get isDeferred;

  /// The name of the type.
  Token get name2;

  /// The type being named, or `null` if the AST structure hasn't been resolved,
  /// or if this is part of a [ConstructorReference].
  @override
  DartType? get type;

  /// The type arguments associated with the type, or `null` if there are no
  /// type arguments.
  TypeArgumentList? get typeArguments;
}

final class NamedTypeImpl extends TypeAnnotationImpl implements NamedType {
  ImportPrefixReferenceImpl? _importPrefix;

  @override
  final Token name2;

  @experimental
  @override
  Element2? element2;

  @override
  TypeArgumentListImpl? typeArguments;

  @override
  final Token? question;

  @override
  TypeImpl? type;

  /// Initializes a newly created type name.
  ///
  /// The [typeArguments] can be `null` if there are no type arguments.
  NamedTypeImpl({
    required ImportPrefixReferenceImpl? importPrefix,
    required this.name2,
    required this.typeArguments,
    required this.question,
  }) {
    this.importPrefix = importPrefix;
    _becomeParentOf(typeArguments);
  }

  @override
  Token get beginToken => importPrefix?.beginToken ?? name2;

  @override
  Token get endToken => question ?? typeArguments?.endToken ?? name2;

  @override
  ImportPrefixReferenceImpl? get importPrefix {
    return _importPrefix;
  }

  set importPrefix(ImportPrefixReferenceImpl? value) {
    _importPrefix = value;
    _becomeParentOf(value);
  }

  @override
  bool get isDeferred {
    var importPrefixElement = importPrefix?.element2;
    if (importPrefixElement is PrefixElement2) {
      return importPrefixElement.fragments.any(
        (fragment) => fragment.isDeferred,
      );
    }
    return false;
  }

  @override
  bool get isSynthetic => name2.isSynthetic && typeArguments == null;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('importPrefix', importPrefix)
        ..addToken('name', name2)
        ..addNode('typeArguments', typeArguments)
        ..addToken('question', question);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitNamedType(this);

  @override
  void visitChildren(AstVisitor visitor) {
    importPrefix?.accept(visitor);
    typeArguments?.accept(visitor);
  }
}

/// A node that represents a directive that impacts the namespace of a library.
///
///    directive ::=
///        [ExportDirective]
///      | [ImportDirective]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class NamespaceDirective implements UriBasedDirective {
  /// The combinators used to control how names are imported or exported.
  NodeList<Combinator> get combinators;

  /// The configurations used to control which library is actually loaded at
  /// run-time.
  NodeList<Configuration> get configurations;

  /// The semicolon terminating the directive.
  Token get semicolon;
}

sealed class NamespaceDirectiveImpl extends UriBasedDirectiveImpl
    implements NamespaceDirective {
  final NodeListImpl<ConfigurationImpl> _configurations = NodeListImpl._();

  final NodeListImpl<CombinatorImpl> _combinators = NodeListImpl._();

  @override
  final Token semicolon;

  /// Initializes a newly created namespace directive.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// directive doesn't have the corresponding attribute.
  ///
  /// The list of [combinators] can be `null` if there are no combinators.
  NamespaceDirectiveImpl({
    required super.comment,
    required super.metadata,
    required super.uri,
    required List<ConfigurationImpl>? configurations,
    required List<CombinatorImpl>? combinators,
    required this.semicolon,
  }) {
    _configurations._initialize(this, configurations);
    _combinators._initialize(this, combinators);
  }

  @override
  NodeListImpl<CombinatorImpl> get combinators => _combinators;

  @override
  NodeListImpl<ConfigurationImpl> get configurations => _configurations;

  @override
  Token get endToken => semicolon;
}

/// The "native" clause in an class declaration.
///
///    nativeClause ::=
///        'native' [StringLiteral]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NativeClause implements AstNode {
  /// The name of the native object that implements the class.
  StringLiteral? get name;

  /// The token representing the `native` keyword.
  Token get nativeKeyword;
}

final class NativeClauseImpl extends AstNodeImpl implements NativeClause {
  @override
  final Token nativeKeyword;

  @override
  final StringLiteralImpl? name;

  /// Initializes a newly created native clause.
  NativeClauseImpl({required this.nativeKeyword, required this.name}) {
    _becomeParentOf(name);
  }

  @override
  Token get beginToken => nativeKeyword;

  @override
  Token get endToken {
    return name?.endToken ?? nativeKeyword;
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('nativeKeyword', nativeKeyword)
        ..addNode('name', name);

  @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] ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NativeFunctionBody implements FunctionBody {
  /// The token representing 'native' that marks the start of the function body.
  Token get nativeKeyword;

  /// The token representing the semicolon that marks the end of the function
  /// body.
  Token get semicolon;

  /// The string literal representing the string after the 'native' token.
  StringLiteral? get stringLiteral;
}

final class NativeFunctionBodyImpl extends FunctionBodyImpl
    implements NativeFunctionBody {
  @override
  final Token nativeKeyword;

  StringLiteralImpl? _stringLiteral;

  @override
  final Token semicolon;

  /// Initializes a newly created function body consisting of the 'native'
  /// token, a string literal, and a semicolon.
  NativeFunctionBodyImpl({
    required this.nativeKeyword,
    required StringLiteralImpl? stringLiteral,
    required this.semicolon,
  }) : _stringLiteral = stringLiteral {
    _becomeParentOf(_stringLiteral);
  }

  @override
  Token get beginToken => nativeKeyword;

  @override
  Token get endToken => semicolon;

  @override
  StringLiteralImpl? get stringLiteral => _stringLiteral;

  set stringLiteral(StringLiteralImpl? stringLiteral) {
    _stringLiteral = _becomeParentOf(stringLiteral);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('nativeKeyword', nativeKeyword)
        ..addNode('stringLiteral', stringLiteral)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitNativeFunctionBody(this);

  @override
  TypeImpl resolve(ResolverVisitor resolver, TypeImpl? imposedType) =>
      resolver.visitNativeFunctionBody(this, imposedType: imposedType);

  @override
  void visitChildren(AstVisitor visitor) {
    _stringLiteral?.accept(visitor);
  }
}

/// A list of AST nodes that have a common parent.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NodeList<E extends AstNode> implements List<E> {
  /// The first token included in this node list's source range, or `null` if
  /// the list is empty.
  Token? get beginToken;

  /// The last token included in this node list's source range, or `null` if the
  /// list is empty.
  Token? get endToken;

  @Deprecated('NodeList cannot be resized')
  @override
  set length(int newLength);

  /// The node that is the parent of each of the elements in the list.
  AstNode get owner;

  /// Returns the node at the given [index] in the list or throw a [RangeError]
  /// if [index] is out of bounds.
  @override
  E operator [](int index);

  /// Use the given [visitor] to visit each of the nodes in this list.
  void accept(AstVisitor visitor);

  @Deprecated('NodeList cannot be resized')
  @override
  void add(E element);

  @Deprecated('NodeList cannot be resized')
  @override
  void addAll(Iterable<E> iterable);

  @Deprecated('NodeList cannot be resized')
  @override
  void clear();

  @Deprecated('NodeList cannot be resized')
  @override
  void insert(int index, E element);

  @Deprecated('NodeList cannot be resized')
  @override
  E removeAt(int index);
}

final class NodeListImpl<E extends AstNode>
    with ListMixin<E>
    implements NodeList<E> {
  late final AstNodeImpl _owner;

  late final List<E> _elements;

  /// Initializes a newly created list of nodes such that all of the nodes that
  /// are added to the list 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;

  @Deprecated('NodeList cannot be resized')
  @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);
    }
  }

  @Deprecated('NodeList cannot be resized')
  @override
  void add(E element) {
    throw UnsupportedError("Cannot resize NodeList.");
  }

  @Deprecated('NodeList cannot be resized')
  @override
  void addAll(Iterable<E> iterable) {
    throw UnsupportedError("Cannot resize NodeList.");
  }

  @Deprecated('NodeList cannot be resized')
  @override
  void clear() {
    throw UnsupportedError("Cannot resize NodeList.");
  }

  @Deprecated('NodeList cannot be resized')
  @override
  void insert(int index, E element) {
    throw UnsupportedError("Cannot resize NodeList.");
  }

  @Deprecated('NodeList cannot be resized')
  @override
  E removeAt(int index) {
    throw UnsupportedError("Cannot resize NodeList.");
  }

  /// Set the [owner] of this container, and populate it with [elements].
  void _initialize(AstNodeImpl owner, List<E>? elements) {
    _owner = owner;
    if (elements == null || elements.isEmpty) {
      _elements = const <Never>[];
    } else {
      _elements = elements.toList(growable: false);
      var length = elements.length;
      for (var i = 0; i < length; i++) {
        var node = elements[i];
        owner._becomeParentOf(node as AstNodeImpl);
      }
    }
  }
}

/// A formal parameter that is required (isn't optional).
///
///    normalFormalParameter ::=
///        [FunctionTypedFormalParameter]
///      | [FieldFormalParameter]
///      | [SimpleFormalParameter]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class NormalFormalParameter implements FormalParameter, AnnotatedNode {}

sealed class NormalFormalParameterImpl extends FormalParameterImpl
    with _AnnotatedNodeMixin
    implements NormalFormalParameter {
  @override
  final Token? covariantKeyword;

  @override
  final Token? requiredKeyword;

  @override
  final Token? name;

  /// Initializes a newly created formal parameter.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// parameter doesn't have the corresponding attribute.
  NormalFormalParameterImpl({
    required CommentImpl? comment,
    required List<AnnotationImpl>? metadata,
    required this.covariantKeyword,
    required this.requiredKeyword,
    required this.name,
  }) {
    _initializeCommentAndAnnotations(comment, metadata);
  }

  @override
  Token get beginToken =>
      metadata.beginToken ?? firstTokenAfterCommentAndMetadata;

  @override
  ParameterKind get kind {
    var parent = this.parent;
    if (parent is DefaultFormalParameterImpl) {
      return parent.kind;
    }
    return ParameterKind.REQUIRED;
  }

  @override
  ChildEntities get _childEntities {
    return super._childEntities
      ..addToken('requiredKeyword', requiredKeyword)
      ..addToken('covariantKeyword', covariantKeyword);
  }

  @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.
    //
    _visitCommentAndAnnotations(visitor);
  }
}

/// A null-assert pattern.
///
///    nullAssertPattern ::=
///        [DartPattern] '!'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NullAssertPattern implements DartPattern {
  /// The `!` token.
  Token get operator;

  /// The sub-pattern.
  DartPattern get pattern;
}

final class NullAssertPatternImpl extends DartPatternImpl
    implements NullAssertPattern {
  @override
  final DartPatternImpl pattern;

  @override
  final Token operator;

  NullAssertPatternImpl({required this.pattern, required this.operator}) {
    _becomeParentOf(pattern);
  }

  @override
  Token get beginToken => pattern.beginToken;

  @override
  Token get endToken => operator;

  @override
  PatternPrecedence get precedence => PatternPrecedence.postfix;

  @override
  VariablePatternImpl? get variablePattern => pattern.variablePattern;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('pattern', pattern)
        ..addToken('operator', operator);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitNullAssertPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeNullCheckOrAssertPatternSchema(pattern, isAssert: true)
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var analysisResult = resolverVisitor.analyzeNullCheckOrAssertPattern(
      context,
      this,
      pattern,
      isAssert: true,
    );
    inferenceLogWriter?.exitPattern(this);
    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    pattern.accept(visitor);
  }
}

/// A null-aware element in a list or set literal.
///
///    <nullAwareExpressionElement> ::= '?' <expression>
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NullAwareElement implements CollectionElement {
  /// The question mark before the expression.
  Token get question;

  /// The expression computing the value that is associated with the element.
  Expression get value;
}

final class NullAwareElementImpl extends CollectionElementImpl
    implements NullAwareElement {
  @override
  final Token question;

  ExpressionImpl _value;

  /// Initializes a newly created null-aware element.
  NullAwareElementImpl({required this.question, required ExpressionImpl value})
    : _value = value {
    _becomeParentOf(_value);
  }

  @override
  Token get beginToken => question;

  @override
  Token get endToken => _value.endToken;

  @override
  ExpressionImpl get value => _value;

  set value(ExpressionImpl expression) {
    _value = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('question', question)
        ..addNode('value', value);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitNullAwareElement(this);

  @override
  void resolveElement(
    ResolverVisitor resolver,
    CollectionLiteralContext? context,
  ) {
    resolver.visitNullAwareElement(this, context: context);
    resolver.pushRewrite(null);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _value.accept(visitor);
  }
}

/// A null-check pattern.
///
///    nullCheckPattern ::=
///        [DartPattern] '?'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NullCheckPattern implements DartPattern {
  /// The `?` token.
  Token get operator;

  /// The sub-pattern.
  DartPattern get pattern;
}

final class NullCheckPatternImpl extends DartPatternImpl
    implements NullCheckPattern {
  @override
  final DartPatternImpl pattern;

  @override
  final Token operator;

  NullCheckPatternImpl({required this.pattern, required this.operator}) {
    _becomeParentOf(pattern);
  }

  @override
  Token get beginToken => pattern.beginToken;

  @override
  Token get endToken => operator;

  @override
  PatternPrecedence get precedence => PatternPrecedence.postfix;

  @override
  VariablePatternImpl? get variablePattern => pattern.variablePattern;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('pattern', pattern)
        ..addToken('operator', operator);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitNullCheckPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeNullCheckOrAssertPatternSchema(pattern, isAssert: false)
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var analysisResult = resolverVisitor.analyzeNullCheckOrAssertPattern(
      context,
      this,
      pattern,
      isAssert: false,
    );
    inferenceLogWriter?.exitPattern(this);
    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    pattern.accept(visitor);
  }
}

/// A null literal expression.
///
///    nullLiteral ::=
///        'null'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NullLiteral implements Literal {
  /// The token representing the literal.
  Token get literal;
}

final class NullLiteralImpl extends LiteralImpl implements NullLiteral {
  @override
  final Token literal;

  /// Initializes a newly created null literal.
  NullLiteralImpl({required this.literal});

  @override
  Token get beginToken => literal;

  @override
  Token get endToken => literal;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('literal', literal);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitNullLiteral(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitNullLiteral(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// Abstract interface for expressions that may participate in null-shorting.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class NullShortableExpression implements Expression {
  /// The expression that terminates any null shorting that might occur in this
  /// expression.
  ///
  /// This might be called regardless of whether this expression is itself
  /// null-aware.
  ///
  /// For example, the statement `a?.b[c] = d;` contains the following
  /// null-shortable subexpressions:
  /// - `a?.b`
  /// - `a?.b[c]`
  /// - `a?.b[c] = d`
  ///
  /// Calling [nullShortingTermination] on any of these subexpressions yields
  /// the expression `a?.b[c] = d`, indicating that the null-shorting induced by
  /// the `?.` causes the rest of the subexpression `a?.b[c] = d` to be skipped.
  Expression get nullShortingTermination;
}

base 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;
      }
    }
  }

  /// 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's the cascade expression itself, which might be a
  /// more distant ancestor.
  AstNode? get _nullShortingExtensionCandidate;

  /// 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);
}

/// An object pattern.
///
///    objectPattern ::=
///        [Identifier] [TypeArgumentList]? '(' [PatternField] ')'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ObjectPattern implements DartPattern {
  /// The patterns matching the properties of the object.
  NodeList<PatternField> get fields;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;

  /// The name of the type of object from which values are extracted.
  NamedType get type;
}

final class ObjectPatternImpl extends DartPatternImpl implements ObjectPattern {
  final NodeListImpl<PatternFieldImpl> _fields = NodeListImpl._();

  @override
  final Token leftParenthesis;

  @override
  final Token rightParenthesis;

  @override
  final NamedTypeImpl type;

  ObjectPatternImpl({
    required this.type,
    required this.leftParenthesis,
    required List<PatternFieldImpl> fields,
    required this.rightParenthesis,
  }) {
    _becomeParentOf(type);
    _fields._initialize(this, fields);
  }

  @override
  Token get beginToken => type.beginToken;

  @override
  Token get endToken => rightParenthesis;

  @override
  NodeList<PatternFieldImpl> get fields => _fields;

  @override
  PatternPrecedence get precedence => PatternPrecedence.primary;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('type', type)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNodeList('fields', fields)
        ..addToken('rightParenthesis', rightParenthesis);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitObjectPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeObjectPatternSchema(SharedTypeView(type.typeOrThrow))
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var result = resolverVisitor.analyzeObjectPattern(
      context,
      this,
      fields: resolverVisitor.buildSharedPatternFields(
        fields,
        mustBeNamed: true,
      ),
    );

    resolverVisitor.checkPatternNeverMatchesValueType(
      context: context,
      pattern: this,
      requiredType: result.requiredType.unwrapTypeView(),
      matchedValueType: result.matchedValueType.unwrapTypeView(),
    );
    inferenceLogWriter?.exitPattern(this);

    return result;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    type.accept(visitor);
    fields.accept(visitor);
  }
}

/// A parenthesized expression.
///
///    parenthesizedExpression ::=
///        '(' [Expression] ')'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ParenthesizedExpression implements Expression {
  /// The expression within the parentheses.
  Expression get expression;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;
}

final class ParenthesizedExpressionImpl extends ExpressionImpl
    implements ParenthesizedExpression {
  @override
  final Token leftParenthesis;

  ExpressionImpl _expression;

  @override
  final Token rightParenthesis;

  /// Initializes a newly created parenthesized expression.
  ParenthesizedExpressionImpl({
    required this.leftParenthesis,
    required ExpressionImpl expression,
    required this.rightParenthesis,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => leftParenthesis;

  @override
  Token get endToken => rightParenthesis;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @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
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('expression', expression)
        ..addToken('rightParenthesis', rightParenthesis);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitParenthesizedExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitParenthesizedExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _expression.accept(visitor);
  }
}

/// A parenthesized pattern.
///
///    parenthesizedPattern ::=
///        '(' [DartPattern] ')'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ParenthesizedPattern implements DartPattern {
  /// The left parenthesis.
  Token get leftParenthesis;

  /// The pattern within the parentheses.
  DartPattern get pattern;

  /// The right parenthesis.
  Token get rightParenthesis;
}

final class ParenthesizedPatternImpl extends DartPatternImpl
    implements ParenthesizedPattern {
  @override
  final Token leftParenthesis;

  @override
  final DartPatternImpl pattern;

  @override
  final Token rightParenthesis;

  ParenthesizedPatternImpl({
    required this.leftParenthesis,
    required this.pattern,
    required this.rightParenthesis,
  }) {
    _becomeParentOf(pattern);
  }

  @override
  Token get beginToken => leftParenthesis;

  @override
  Token get endToken => rightParenthesis;

  @override
  PatternPrecedence get precedence => PatternPrecedence.primary;

  @override
  DartPattern get unParenthesized {
    var result = pattern;
    while (result is ParenthesizedPatternImpl) {
      result = result.pattern;
    }
    return result;
  }

  @override
  VariablePatternImpl? get variablePattern => pattern.variablePattern;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('pattern', pattern)
        ..addToken('rightParenthesis', rightParenthesis);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitParenthesizedPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .dispatchPatternSchema(pattern)
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var analysisResult = resolverVisitor.dispatchPattern(context, pattern);
    inferenceLogWriter?.exitPattern(this);
    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    pattern.accept(visitor);
  }
}

/// A part directive.
///
///    partDirective ::=
///        [Annotation] 'part' [StringLiteral] ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PartDirective implements UriBasedDirective {
  /// The configurations that control which file is actually included.
  NodeList<Configuration> get configurations;

  /// Information about this part directive.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  @experimental
  PartInclude? get partInclude;

  /// The token representing the `part` keyword.
  Token get partKeyword;

  /// The semicolon terminating the directive.
  Token get semicolon;
}

final class PartDirectiveImpl extends UriBasedDirectiveImpl
    implements PartDirective {
  @override
  final Token partKeyword;

  @override
  final NodeListImpl<ConfigurationImpl> configurations = NodeListImpl._();

  @override
  final Token semicolon;

  /// Initializes a newly created part directive.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// directive doesn't have the corresponding attribute.
  PartDirectiveImpl({
    required super.comment,
    required super.metadata,
    required this.partKeyword,
    required super.uri,
    required List<ConfigurationImpl>? configurations,
    required this.semicolon,
  }) {
    this.configurations._initialize(this, configurations);
  }

  @override
  Token get endToken => semicolon;

  @override
  Token get firstTokenAfterCommentAndMetadata => partKeyword;

  @experimental
  @override
  PartElementImpl? get partInclude => element as PartElementImpl?;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('partKeyword', partKeyword)
        ..addNode('uri', uri)
        ..addNodeList('configurations', configurations)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitPartDirective(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    configurations.accept(visitor);
  }
}

/// A part-of directive.
///
///    partOfDirective ::=
///        [Annotation] 'part' 'of' [Identifier] ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PartOfDirective implements Directive {
  /// 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).
  LibraryIdentifier? get libraryName;

  /// The token representing the `of` keyword.
  Token get ofKeyword;

  /// The token representing the `part` keyword.
  Token get partKeyword;

  /// The semicolon terminating the directive.
  Token get semicolon;

  /// The URI of the library that the containing compilation unit is part of, or
  /// `null` if no URI was given (typically because a library name was provided).
  StringLiteral? get uri;
}

final class PartOfDirectiveImpl extends DirectiveImpl
    implements PartOfDirective {
  @override
  final Token partKeyword;

  @override
  final Token ofKeyword;

  StringLiteralImpl? _uri;

  LibraryIdentifierImpl? _libraryName;

  @override
  final Token semicolon;

  /// Initializes a newly created part-of directive.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// directive doesn't have the corresponding attribute.
  PartOfDirectiveImpl({
    required super.comment,
    required super.metadata,
    required this.partKeyword,
    required this.ofKeyword,
    required StringLiteralImpl? uri,
    required LibraryIdentifierImpl? libraryName,
    required this.semicolon,
  }) : _uri = uri,
       _libraryName = libraryName {
    _becomeParentOf(_uri);
    _becomeParentOf(_libraryName);
  }

  @override
  Token get endToken => semicolon;

  @override
  Token get firstTokenAfterCommentAndMetadata => partKeyword;

  @override
  LibraryIdentifierImpl? get libraryName => _libraryName;

  set libraryName(LibraryIdentifierImpl? libraryName) {
    _libraryName = _becomeParentOf(libraryName);
  }

  @override
  StringLiteralImpl? get uri => _uri;

  set uri(StringLiteralImpl? uri) {
    _uri = _becomeParentOf(uri);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('partKeyword', partKeyword)
        ..addToken('ofKeyword', ofKeyword)
        ..addNode('uri', uri)
        ..addNode('libraryName', libraryName)
        ..addToken('semicolon', semicolon);

  @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 pattern assignment.
///
///    patternAssignment ::=
///        [DartPattern] '=' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PatternAssignment implements Expression {
  /// The equal sign separating the pattern from the expression.
  Token get equals;

  /// The expression that is matched by the pattern.
  Expression get expression;

  /// The pattern that matches the expression.
  DartPattern get pattern;
}

final class PatternAssignmentImpl extends ExpressionImpl
    implements PatternAssignment {
  @override
  final Token equals;

  ExpressionImpl _expression;

  @override
  final DartPatternImpl pattern;

  /// The pattern type schema, used for downward inference of [expression];
  /// or `null` if the node isn't resolved yet.
  TypeImpl? patternTypeSchema;

  PatternAssignmentImpl({
    required this.pattern,
    required this.equals,
    required ExpressionImpl expression,
  }) : _expression = expression {
    _becomeParentOf(pattern);
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => pattern.beginToken;

  @override
  Token get endToken => expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  // TODO(brianwilkerson): Create a new precedence constant for pattern
  //  assignments. The proposal doesn't make the actual value clear.
  Precedence get precedence => Precedence.assignment;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('pattern', pattern)
        ..addToken('equals', equals)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitPatternAssignment(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitPatternAssignment(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    pattern.accept(visitor);
    expression.accept(visitor);
  }
}

/// A field in an object or record pattern.
///
///    patternField ::=
///        [PatternFieldName]? [DartPattern]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PatternField implements AstNode {
  /// The effective name of the field, or `null` if [name] is `null` and
  /// [pattern] isn't a variable pattern.
  ///
  /// The effective name can either be specified explicitly by [name], or
  /// implied by the variable pattern inside [pattern].
  String? get effectiveName;

  /// The element referenced by [effectiveName].
  ///
  /// Returns `null` if the AST structure is not resolved yet.
  ///
  /// Returns non-`null` inside valid [ObjectPattern]s; always returns `null`
  /// inside [RecordPattern]s.
  @experimental
  Element2? get element2;

  /// The name of the field, or `null` if the field is a positional field.
  PatternFieldName? get name;

  /// The pattern used to match the corresponding record field.
  DartPattern get pattern;
}

final class PatternFieldImpl extends AstNodeImpl implements PatternField {
  @override
  Element2? element2;

  @override
  final PatternFieldNameImpl? name;

  @override
  final DartPatternImpl pattern;

  PatternFieldImpl({required this.name, required this.pattern}) {
    _becomeParentOf(name);
    _becomeParentOf(pattern);
  }

  @override
  Token get beginToken => name?.beginToken ?? pattern.beginToken;

  @override
  String? get effectiveName {
    var nameNode = name;
    if (nameNode != null) {
      var nameToken = nameNode.name ?? pattern.variablePattern?.name;
      return nameToken?.lexeme;
    }
    return null;
  }

  @override
  Token get endToken => pattern.endToken;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('name', name)
        ..addNode('pattern', pattern);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitPatternField(this);

  @override
  void visitChildren(AstVisitor visitor) {
    name?.accept(visitor);
    pattern.accept(visitor);
  }
}

/// A field name in an object or record pattern field.
///
///    patternFieldName ::=
///        [Token]? ':'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PatternFieldName implements AstNode {
  /// The colon following the name.
  Token get colon;

  /// The name of the field.
  Token? get name;
}

final class PatternFieldNameImpl extends AstNodeImpl
    implements PatternFieldName {
  @override
  final Token colon;

  @override
  final Token? name;

  PatternFieldNameImpl({required this.name, required this.colon});

  @override
  Token get beginToken => name ?? colon;

  @override
  Token get endToken => colon;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('name', name)
        ..addToken('colon', colon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitPatternFieldName(this);

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// A pattern variable declaration.
///
///    patternDeclaration ::=
///        ( 'final' | 'var' ) [DartPattern] '=' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PatternVariableDeclaration implements AnnotatedNode {
  /// The equal sign separating the pattern from the expression.
  Token get equals;

  /// The expression that is matched by the pattern.
  Expression get expression;

  /// The `var` or `final` keyword introducing the declaration.
  Token get keyword;

  /// The pattern that matches the expression.
  DartPattern get pattern;
}

final class PatternVariableDeclarationImpl extends AnnotatedNodeImpl
    implements PatternVariableDeclaration {
  @override
  final Token equals;

  ExpressionImpl _expression;

  @override
  final Token keyword;

  @override
  final DartPatternImpl pattern;

  /// The pattern type schema, used for downward inference of [expression];
  /// or `null` if the node isn't resolved yet.
  TypeImpl? patternTypeSchema;

  /// Variables declared in [pattern].
  late final List<BindPatternVariableElementImpl2> elements;

  PatternVariableDeclarationImpl({
    required this.keyword,
    required this.pattern,
    required this.equals,
    required ExpressionImpl expression,
    required super.comment,
    required super.metadata,
  }) : _expression = expression {
    _becomeParentOf(pattern);
    _becomeParentOf(_expression);
  }

  @override
  Token get endToken => expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  /// If [keyword] is `final`, returns it.
  Token? get finalKeyword {
    if (keyword.keyword == Keyword.FINAL) {
      return keyword;
    }
    return null;
  }

  @override
  Token get firstTokenAfterCommentAndMetadata => keyword;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('keyword', keyword)
        ..addNode('pattern', pattern)
        ..addToken('equals', equals)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitPatternVariableDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    pattern.accept(visitor);
    expression.accept(visitor);
  }
}

/// A pattern variable declaration statement.
///
///    patternDeclaration ::=
///        [PatternVariableDeclaration] ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PatternVariableDeclarationStatement implements Statement {
  /// The pattern declaration.
  PatternVariableDeclaration get declaration;

  /// The semicolon terminating the statement.
  Token get semicolon;
}

final class PatternVariableDeclarationStatementImpl extends StatementImpl
    implements PatternVariableDeclarationStatement {
  @override
  final PatternVariableDeclarationImpl declaration;

  @override
  final Token semicolon;

  PatternVariableDeclarationStatementImpl({
    required this.declaration,
    required this.semicolon,
  }) {
    _becomeParentOf(declaration);
  }

  @override
  Token get beginToken => declaration.beginToken;

  @override
  Token get endToken => semicolon;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('declaration', declaration)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitPatternVariableDeclarationStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    declaration.accept(visitor);
  }
}

/// A postfix unary expression.
///
///    postfixExpression ::=
///        [Expression] [Token]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PostfixExpression
    implements
        Expression,
        NullShortableExpression,
        MethodReferenceExpression,
        CompoundAssignmentExpression {
  /// The element associated with the operator based on the static type of the
  /// operand, or `null` if the AST structure hasn't been resolved, if the
  /// operator isn't user definable, or if the operator couldn't be resolved.
  @override
  MethodElement2? get element;

  /// The expression computing the operand for the operator.
  Expression get operand;

  /// The postfix operator being applied to the operand.
  Token get operator;
}

final class PostfixExpressionImpl extends ExpressionImpl
    with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl
    implements PostfixExpression {
  ExpressionImpl _operand;

  @override
  final Token operator;

  @override
  MethodElement2? element;

  /// Initializes a newly created postfix expression.
  PostfixExpressionImpl({
    required ExpressionImpl operand,
    required this.operator,
  }) : _operand = operand {
    _becomeParentOf(_operand);
  }

  @override
  Token get beginToken => _operand.beginToken;

  @override
  Token get endToken => operator;

  @override
  ExpressionImpl get operand => _operand;

  set operand(ExpressionImpl expression) {
    _operand = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.postfix;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('operand', operand)
        ..addToken('operator', operator);

  @override
  AstNode? get _nullShortingExtensionCandidate => parent;

  /// The parameter element representing the parameter to which the value of the
  /// operand is bound, or `null` ff the AST structure is not resolved or the
  /// function being invoked isn't known based on static type information.
  FormalParameterElementMixin? get _staticParameterElementForOperand2 {
    if (element == null) {
      return null;
    }
    var parameters = element!.formalParameters;
    if (parameters.isEmpty) {
      return null;
    }
    // TODO(paulberry): eliminate this cast by changing the type of
    // `staticElement` to `MethodElement2OrMember?`.
    return parameters[0] as FormalParameterElementMixin;
  }

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitPostfixExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitPostfixExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _operand.accept(visitor);
  }

  @override
  bool _extendsNullShorting(Expression descendant) =>
      identical(descendant, 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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PrefixedIdentifier implements Identifier {
  /// The identifier being prefixed.
  SimpleIdentifier get identifier;

  /// Whether this type is a deferred type.
  ///
  /// A deferred type is a type that is referenced through an import prefix
  /// (such as `p.T`), where the prefix is used by a deferred import.
  ///
  /// Returns `false` if the AST structure hasn't been resolved.
  bool get isDeferred;

  /// The period used to separate the prefix from the identifier.
  Token get period;

  /// The prefix associated with the library in which the identifier is defined.
  SimpleIdentifier get prefix;
}

final class PrefixedIdentifierImpl extends IdentifierImpl
    implements PrefixedIdentifier {
  SimpleIdentifierImpl _prefix;

  @override
  final Token period;

  SimpleIdentifierImpl _identifier;

  /// Initializes a newly created prefixed identifier.
  PrefixedIdentifierImpl({
    required SimpleIdentifierImpl prefix,
    required this.period,
    required SimpleIdentifierImpl identifier,
  }) : _prefix = prefix,
       _identifier = identifier {
    _becomeParentOf(_prefix);
    _becomeParentOf(_identifier);
  }

  @override
  Token get beginToken => _prefix.beginToken;

  @override
  Element2? get element {
    return _identifier.element;
  }

  @override
  Token get endToken => _identifier.endToken;

  @override
  SimpleIdentifierImpl get identifier => _identifier;

  set identifier(SimpleIdentifierImpl identifier) {
    _identifier = _becomeParentOf(identifier);
  }

  @override
  bool get isDeferred {
    var element = _prefix.element;
    if (element is PrefixElement2) {
      return element.fragments.any((fragment) => fragment.isDeferred);
    }
    return false;
  }

  @override
  String get name => "${_prefix.name}.${_identifier.name}";

  @override
  Precedence get precedence => Precedence.postfix;

  @override
  SimpleIdentifierImpl get prefix => _prefix;

  set prefix(SimpleIdentifierImpl identifier) {
    _prefix = _becomeParentOf(identifier);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('prefix', prefix)
        ..addToken('period', period)
        ..addNode('identifier', identifier);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitPrefixedIdentifier(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitPrefixedIdentifier(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _prefix.accept(visitor);
    _identifier.accept(visitor);
  }
}

/// A prefix unary expression.
///
///    prefixExpression ::=
///        [Token] [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PrefixExpression
    implements
        Expression,
        NullShortableExpression,
        MethodReferenceExpression,
        CompoundAssignmentExpression {
  /// The element associated with the operator based on the static type of the
  /// operand, or `null` if the AST structure hasn't been resolved, if the
  /// operator isn't user definable, or if the operator couldn't be resolved.
  @override
  MethodElement2? get element;

  /// The expression computing the operand for the operator.
  Expression get operand;

  /// The prefix operator being applied to the operand.
  Token get operator;
}

final class PrefixExpressionImpl extends ExpressionImpl
    with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl
    implements PrefixExpression {
  @override
  final Token operator;

  ExpressionImpl _operand;

  @override
  MethodElement2? element;

  /// Initializes a newly created prefix expression.
  PrefixExpressionImpl({
    required this.operator,
    required ExpressionImpl operand,
  }) : _operand = operand {
    _becomeParentOf(_operand);
  }

  @override
  Token get beginToken => operator;

  @override
  Token get endToken => _operand.endToken;

  @override
  ExpressionImpl get operand => _operand;

  set operand(ExpressionImpl expression) {
    _operand = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.prefix;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('operator', operator)
        ..addNode('operand', operand);

  @override
  AstNode? get _nullShortingExtensionCandidate => parent;

  /// The parameter element representing the parameter to which the value of the
  /// operand is bound, or `null` if the AST structure is not resolved or the
  /// function being invoked isn't known based on static type information.
  FormalParameterElementMixin? get _staticParameterElementForOperand2 {
    if (element == null) {
      return null;
    }
    var parameters = element!.formalParameters;
    if (parameters.isEmpty) {
      return null;
    }
    // TODO(paulberry): eliminate this cast by changing the type of
    // `staticElement` to `MethodElementOrMember?`.
    return parameters[0] as FormalParameterElementMixin;
  }

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitPrefixExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitPrefixExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _operand.accept(visitor);
  }

  @override
  bool _extendsNullShorting(Expression descendant) =>
      identical(descendant, 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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class PropertyAccess
    implements NullShortableExpression, CommentReferableExpression {
  /// Whether this expression is cascaded.
  ///
  /// If it is, then the target of this expression isn't stored locally but is
  /// stored in the nearest ancestor that is a [CascadeExpression].
  bool get isCascaded;

  /// Whether this property access is null aware (as opposed to non-null).
  bool get isNullAware;

  /// The property access operator.
  Token get operator;

  /// The name of the property being accessed.
  SimpleIdentifier get propertyName;

  /// The expression used to compute the receiver of the invocation.
  ///
  /// If this invocation isn't part of a cascade expression, then this is the
  /// same as [target]. If this invocation is part of a cascade expression,
  /// then the target stored with the cascade expression is returned.
  Expression get realTarget;

  /// The expression computing the object defining the property being accessed,
  /// or `null` if this property access is part of a cascade expression.
  ///
  /// Use [realTarget] to get the target independent of whether this is part of
  /// a cascade expression.
  Expression? get target;
}

final class PropertyAccessImpl extends CommentReferableExpressionImpl
    with NullShortableExpressionImpl, DotShorthandMixin
    implements PropertyAccess {
  ExpressionImpl? _target;

  @override
  final Token operator;

  SimpleIdentifierImpl _propertyName;

  /// Initializes a newly created property access expression.
  PropertyAccessImpl({
    required ExpressionImpl? target,
    required this.operator,
    required SimpleIdentifierImpl propertyName,
  }) : _target = target,
       _propertyName = propertyName {
    _becomeParentOf(_target);
    _becomeParentOf(_propertyName);
  }

  @override
  Token get beginToken {
    if (target case var target?) {
      return target.beginToken;
    }
    return operator;
  }

  @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(SimpleIdentifierImpl identifier) {
    _propertyName = _becomeParentOf(identifier);
  }

  @override
  ExpressionImpl get realTarget {
    if (isCascaded) {
      return _ancestorCascade.target;
    }
    return _target!;
  }

  @override
  ExpressionImpl? get target => _target;

  set target(ExpressionImpl? expression) {
    _target = _becomeParentOf(expression);
  }

  /// The cascade that contains this [IndexExpression].
  ///
  /// This method assumes that [isCascaded] is `true`.
  CascadeExpressionImpl get _ancestorCascade {
    assert(isCascaded);
    for (var ancestor = parent!; ; ancestor = ancestor.parent!) {
      if (ancestor is CascadeExpressionImpl) {
        return ancestor;
      }
    }
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('target', target)
        ..addToken('operator', operator)
        ..addNode('propertyName', propertyName);

  @override
  AstNode? get _nullShortingExtensionCandidate => parent;

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitPropertyAccess(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitPropertyAccess(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _target?.accept(visitor);
    _propertyName.accept(visitor);
  }

  @override
  bool _extendsNullShorting(Expression descendant) =>
      identical(descendant, _target);
}

/// A record literal.
///
///    recordLiteral ::= '(' recordField (',' recordField)* ','? ')'
///
///    recordField  ::= (identifier ':')? [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RecordLiteral implements Literal {
  /// The token representing the `const` keyword, or `null` if the literal isn't
  /// a constant.
  Token? get constKeyword;

  /// The syntactic elements used to compute the fields of the record.
  NodeList<Expression> get fields;

  /// Whether this literal is a constant expression.
  ///
  /// It is a constant expression if either the keyword `const` was explicitly
  /// provided or because no keyword was provided and this expression occurs in
  /// a constant context.
  bool get isConst;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;
}

final class RecordLiteralImpl extends LiteralImpl implements RecordLiteral {
  @override
  final Token? constKeyword;

  @override
  final Token leftParenthesis;

  final NodeListImpl<ExpressionImpl> _fields = NodeListImpl._();

  @override
  final Token rightParenthesis;

  /// Initializes a newly created record literal.
  RecordLiteralImpl({
    required this.constKeyword,
    required this.leftParenthesis,
    required List<ExpressionImpl> fields,
    required this.rightParenthesis,
  }) {
    _fields._initialize(this, fields);
  }

  @override
  Token get beginToken => constKeyword ?? leftParenthesis;

  @override
  Token get endToken => rightParenthesis;

  @override
  NodeList<ExpressionImpl> get fields => _fields;

  @override
  bool get isConst => constKeyword != null || inConstantContext;

  @override
  // TODO(paulberry): add commas.
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('constKeyword', constKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNodeList('fields', fields)
        ..addToken('rightParenthesis', rightParenthesis);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitRecordLiteral(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitRecordLiteral(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _fields.accept(visitor);
  }
}

/// A record pattern.
///
///    recordPattern ::=
///        '(' [PatternField] (',' [PatternField])* ')'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RecordPattern implements DartPattern {
  /// The fields of the record pattern.
  NodeList<PatternField> get fields;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;
}

final class RecordPatternImpl extends DartPatternImpl implements RecordPattern {
  final NodeListImpl<PatternFieldImpl> _fields = NodeListImpl._();

  @override
  final Token leftParenthesis;

  @override
  final Token rightParenthesis;

  bool hasDuplicateNamedField = false;

  RecordPatternImpl({
    required this.leftParenthesis,
    required List<PatternFieldImpl> fields,
    required this.rightParenthesis,
  }) {
    _fields._initialize(this, fields);
  }

  @override
  Token get beginToken => leftParenthesis;

  @override
  Token get endToken => rightParenthesis;

  @override
  NodeList<PatternFieldImpl> get fields => _fields;

  @override
  PatternPrecedence get precedence => PatternPrecedence.primary;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNodeList('fields', fields)
        ..addToken('rightParenthesis', rightParenthesis);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitRecordPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeRecordPatternSchema(
          fields: resolverVisitor.buildSharedPatternFields(
            fields,
            mustBeNamed: false,
          ),
        )
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var result = resolverVisitor.analyzeRecordPattern(
      context,
      this,
      fields: resolverVisitor.buildSharedPatternFields(
        fields,
        mustBeNamed: false,
      ),
    );

    if (!hasDuplicateNamedField) {
      resolverVisitor.checkPatternNeverMatchesValueType(
        context: context,
        pattern: this,
        requiredType: result.requiredType.unwrapTypeView(),
        matchedValueType: result.matchedValueType.unwrapTypeView(),
      );
    }
    inferenceLogWriter?.exitPattern(this);

    return result;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    fields.accept(visitor);
  }
}

/// A record type.
///
/// recordType ::=
///     '(' recordTypeFields ',' recordTypeNamedFields ')'
///   | '(' recordTypeFields ','? ')'
///   | '(' recordTypeNamedFields ')'
///
/// recordTypeFields ::= recordTypeField ( ',' recordTypeField )*
///
/// recordTypeField ::= metadata type identifier?
///
/// recordTypeNamedFields ::=
///     '{' recordTypeNamedField
///     ( ',' recordTypeNamedField )* ','? '}'
///
/// recordTypeNamedField ::= metadata type identifier
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RecordTypeAnnotation implements TypeAnnotation {
  /// The left parenthesis.
  Token get leftParenthesis;

  /// The optional named fields.
  RecordTypeAnnotationNamedFields? get namedFields;

  /// The positional fields (might be empty).
  NodeList<RecordTypeAnnotationPositionalField> get positionalFields;

  /// The right parenthesis.
  Token get rightParenthesis;
}

/// A field in a [RecordTypeAnnotation].
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class RecordTypeAnnotationField implements AstNode {
  /// The annotations associated with the field.
  NodeList<Annotation> get metadata;

  /// The name of the field.
  Token? get name;

  /// The type of the field.
  TypeAnnotation get type;
}

sealed class RecordTypeAnnotationFieldImpl extends AstNodeImpl
    implements RecordTypeAnnotationField {
  @override
  final NodeListImpl<AnnotationImpl> metadata = NodeListImpl._();

  @override
  final TypeAnnotationImpl type;

  RecordTypeAnnotationFieldImpl({
    required List<AnnotationImpl>? metadata,
    required this.type,
  }) {
    this.metadata._initialize(this, metadata);
    _becomeParentOf(type);
  }

  @override
  Token get beginToken => metadata.beginToken ?? type.beginToken;

  @override
  Token get endToken => name ?? type.endToken;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNodeList('metadata', metadata)
        ..addNode('type', type)
        ..addToken('name', name);

  @override
  void visitChildren(AstVisitor visitor) {
    metadata.accept(visitor);
    type.accept(visitor);
  }
}

final class RecordTypeAnnotationImpl extends TypeAnnotationImpl
    implements RecordTypeAnnotation {
  @override
  final Token leftParenthesis;

  @override
  final NodeListImpl<RecordTypeAnnotationPositionalFieldImpl> positionalFields =
      NodeListImpl._();

  @override
  final RecordTypeAnnotationNamedFieldsImpl? namedFields;

  @override
  final Token rightParenthesis;

  @override
  final Token? question;

  @override
  TypeImpl? type;

  RecordTypeAnnotationImpl({
    required this.leftParenthesis,
    required List<RecordTypeAnnotationPositionalFieldImpl> positionalFields,
    required this.namedFields,
    required this.rightParenthesis,
    required this.question,
  }) {
    _becomeParentOf(namedFields);
    this.positionalFields._initialize(this, positionalFields);
  }

  @override
  Token get beginToken => leftParenthesis;

  @override
  Token get endToken => question ?? rightParenthesis;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNodeList('positionalFields', positionalFields)
        ..addNode('namedFields', namedFields)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addToken('question', question);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitRecordTypeAnnotation(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    positionalFields.accept(visitor);
    namedFields?.accept(visitor);
  }
}

/// A named field in a [RecordTypeAnnotation].
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RecordTypeAnnotationNamedField
    implements RecordTypeAnnotationField {
  @override
  Token get name;
}

final class RecordTypeAnnotationNamedFieldImpl
    extends RecordTypeAnnotationFieldImpl
    implements RecordTypeAnnotationNamedField {
  @override
  final Token name;

  RecordTypeAnnotationNamedFieldImpl({
    required super.metadata,
    required super.type,
    required this.name,
  });

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitRecordTypeAnnotationNamedField(this);
  }
}

/// The portion of a [RecordTypeAnnotation] with named fields.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RecordTypeAnnotationNamedFields implements AstNode {
  /// The fields contained in the block.
  NodeList<RecordTypeAnnotationNamedField> get fields;

  /// The left curly bracket.
  Token get leftBracket;

  /// The right curly bracket.
  Token get rightBracket;
}

final class RecordTypeAnnotationNamedFieldsImpl extends AstNodeImpl
    implements RecordTypeAnnotationNamedFields {
  @override
  final Token leftBracket;

  @override
  final NodeListImpl<RecordTypeAnnotationNamedFieldImpl> fields =
      NodeListImpl._();

  @override
  final Token rightBracket;

  RecordTypeAnnotationNamedFieldsImpl({
    required this.leftBracket,
    required List<RecordTypeAnnotationNamedFieldImpl> fields,
    required this.rightBracket,
  }) {
    this.fields._initialize(this, fields);
  }

  @override
  Token get beginToken => leftBracket;

  @override
  Token get endToken => rightBracket;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('fields', fields)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitRecordTypeAnnotationNamedFields(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    fields.accept(visitor);
  }
}

/// A positional field in a [RecordTypeAnnotation].
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RecordTypeAnnotationPositionalField
    implements RecordTypeAnnotationField {}

final class RecordTypeAnnotationPositionalFieldImpl
    extends RecordTypeAnnotationFieldImpl
    implements RecordTypeAnnotationPositionalField {
  @override
  final Token? name;

  RecordTypeAnnotationPositionalFieldImpl({
    required super.metadata,
    required super.type,
    required this.name,
  });

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitRecordTypeAnnotationPositionalField(this);
  }
}

/// The invocation of a constructor in the same class from within a
/// constructor's initialization list.
///
///    redirectingConstructorInvocation ::=
///        'this' ('.' identifier)? arguments
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RedirectingConstructorInvocation
    implements ConstructorInitializer, ConstructorReferenceNode {
  /// The list of arguments to the constructor.
  ArgumentList get argumentList;

  /// The name of the constructor that is being invoked, or `null` if the
  /// unnamed constructor is being invoked.
  SimpleIdentifier? get constructorName;

  /// The token for the period before the name of the constructor that is being
  /// invoked, or `null` if the unnamed constructor is being invoked.
  Token? get period;

  /// The token for the `this` keyword.
  Token get thisKeyword;
}

final class RedirectingConstructorInvocationImpl
    extends ConstructorInitializerImpl
    implements RedirectingConstructorInvocation {
  @override
  final Token thisKeyword;

  @override
  final Token? period;

  SimpleIdentifierImpl? _constructorName;

  ArgumentListImpl _argumentList;

  @override
  ConstructorElementImpl2? element;

  /// Initializes 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({
    required this.thisKeyword,
    required this.period,
    required SimpleIdentifierImpl? constructorName,
    required ArgumentListImpl argumentList,
  }) : _constructorName = constructorName,
       _argumentList = argumentList {
    _becomeParentOf(_constructorName);
    _becomeParentOf(_argumentList);
  }

  @override
  ArgumentListImpl get argumentList => _argumentList;

  set argumentList(ArgumentListImpl argumentList) {
    _argumentList = _becomeParentOf(argumentList);
  }

  @override
  Token get beginToken => thisKeyword;

  @override
  SimpleIdentifierImpl? get constructorName => _constructorName;

  set constructorName(SimpleIdentifierImpl? identifier) {
    _constructorName = _becomeParentOf(identifier);
  }

  @override
  Token get endToken => _argumentList.endToken;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('thisKeyword', thisKeyword)
        ..addToken('period', period)
        ..addNode('constructorName', constructorName)
        ..addNode('argumentList', argumentList);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitRedirectingConstructorInvocation(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _constructorName?.accept(visitor);
    _argumentList.accept(visitor);
  }
}

/// A relational pattern.
///
///    relationalPattern ::=
///        (equalityOperator | relationalOperator) [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RelationalPattern implements DartPattern {
  /// The element of the [operator] for the matched type.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if the
  /// operator couldn't be resolved.
  @experimental
  MethodElement2? get element2;

  /// The expression used to compute the operand.
  Expression get operand;

  /// The relational operator being applied.
  Token get operator;
}

final class RelationalPatternImpl extends DartPatternImpl
    implements RelationalPattern {
  ExpressionImpl _operand;

  @override
  final Token operator;

  @override
  MethodElement2? element2;

  RelationalPatternImpl({
    required this.operator,
    required ExpressionImpl operand,
  }) : _operand = operand {
    _becomeParentOf(operand);
  }

  @override
  Token get beginToken => operator;

  @override
  Token get endToken => operand.endToken;

  @override
  ExpressionImpl get operand => _operand;

  set operand(ExpressionImpl operand) {
    _operand = _becomeParentOf(operand);
  }

  @override
  PatternPrecedence get precedence => PatternPrecedence.relational;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('operator', operator)
        ..addNode('operand', operand);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitRelationalPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeRelationalPatternSchema()
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    inferenceLogWriter?.enterPattern(this);
    var analysisResult = resolverVisitor.analyzeRelationalPattern(
      context,
      this,
      operand,
    );
    resolverVisitor.popRewrite();
    inferenceLogWriter?.exitPattern(this);
    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    operand.accept(visitor);
  }
}

/// The name of the primary constructor of an extension type.
@experimental
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RepresentationConstructorName implements AstNode {
  /// The name of the primary constructor.
  Token get name;

  /// The period separating [name] from the previous token.
  Token get period;
}

final class RepresentationConstructorNameImpl extends AstNodeImpl
    implements RepresentationConstructorName {
  @override
  final Token period;

  @override
  final Token name;

  RepresentationConstructorNameImpl({required this.period, required this.name});

  @override
  Token get beginToken => period;

  @override
  Token get endToken => name;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('period', period)
        ..addToken('name', name);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitRepresentationConstructorName(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {}
}

/// The declaration of an extension type representation.
///
/// It declares both the representation field and the primary constructor.
///
///    <representationDeclaration> ::=
///        ('.' <identifierOrNew>)? '(' <metadata> <type> <identifier> ')'
@experimental
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RepresentationDeclaration implements AstNode {
  /// The fragment of the primary constructor contained in this declaration.
  @experimental
  ConstructorFragment? get constructorFragment;

  /// The optional name of the primary constructor.
  RepresentationConstructorName? get constructorName;

  /// The fragment for [fieldName] with [fieldType] contained in this
  /// declaration.
  @experimental
  FieldFragment? get fieldFragment;

  /// The annotations associated with the field.
  NodeList<Annotation> get fieldMetadata;

  /// The representation name.
  Token get fieldName;

  /// The representation type.
  TypeAnnotation get fieldType;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;
}

final class RepresentationDeclarationImpl extends AstNodeImpl
    implements RepresentationDeclaration {
  @override
  final RepresentationConstructorNameImpl? constructorName;

  @override
  ConstructorElementImpl? constructorFragment;

  @override
  final Token leftParenthesis;

  @override
  final NodeListImpl<AnnotationImpl> fieldMetadata = NodeListImpl._();

  @override
  final TypeAnnotationImpl fieldType;

  @override
  final Token fieldName;

  @override
  FieldElementImpl? fieldFragment;

  @override
  final Token rightParenthesis;

  RepresentationDeclarationImpl({
    required this.constructorName,
    required this.leftParenthesis,
    required List<AnnotationImpl> fieldMetadata,
    required this.fieldType,
    required this.fieldName,
    required this.rightParenthesis,
  }) {
    this.fieldMetadata._initialize(this, fieldMetadata);
    _becomeParentOf(constructorName);
    _becomeParentOf(fieldType);
  }

  @override
  Token get beginToken => constructorName?.beginToken ?? leftParenthesis;

  @override
  Token get endToken => rightParenthesis;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('constructorName', constructorName)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNodeList('fieldMetadata', fieldMetadata)
        ..addNode('fieldType', fieldType)
        ..addToken('fieldName', fieldName)
        ..addToken('rightParenthesis', rightParenthesis);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitRepresentationDeclaration(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    constructorName?.accept(visitor);
    fieldMetadata.accept(visitor);
    fieldType.accept(visitor);
  }
}

/// A rest pattern element.
///
///    restPatternElement ::= '...' [DartPattern]?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RestPatternElement
    implements ListPatternElement, MapPatternElement {
  /// The operator token '...'.
  Token get operator;

  /// The optional pattern.
  DartPattern? get pattern;
}

final class RestPatternElementImpl extends AstNodeImpl
    implements
        RestPatternElement,
        ListPatternElementImpl,
        MapPatternElementImpl {
  @override
  final Token operator;

  @override
  final DartPatternImpl? pattern;

  RestPatternElementImpl({required this.operator, required this.pattern}) {
    _becomeParentOf(pattern);
  }

  @override
  Token get beginToken => operator;

  @override
  Token get endToken => pattern?.endToken ?? operator;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('operator', operator)
        ..addNode('pattern', pattern);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitRestPatternElement(this);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    pattern?.accept(visitor);
  }
}

/// A rethrow expression.
///
///    rethrowExpression ::=
///        'rethrow'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class RethrowExpression implements Expression {
  /// The token representing the `rethrow` keyword.
  Token get rethrowKeyword;
}

final class RethrowExpressionImpl extends ExpressionImpl
    implements RethrowExpression {
  @override
  final Token rethrowKeyword;

  /// Initializes a newly created rethrow expression.
  RethrowExpressionImpl({required this.rethrowKeyword});

  @override
  Token get beginToken => rethrowKeyword;

  @override
  Token get endToken => rethrowKeyword;

  @override
  Precedence get precedence => Precedence.assignment;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('rethrowKeyword', rethrowKeyword);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitRethrowExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitRethrowExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// A return statement.
///
///    returnStatement ::=
///        'return' [Expression]? ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ReturnStatement implements Statement {
  /// The expression computing the value to be returned, or `null` if no
  /// explicit value was provided.
  Expression? get expression;

  /// The token representing the `return` keyword.
  Token get returnKeyword;

  /// The semicolon terminating the statement.
  Token get semicolon;
}

final class ReturnStatementImpl extends StatementImpl
    implements ReturnStatement {
  @override
  final Token returnKeyword;

  ExpressionImpl? _expression;

  @override
  final Token semicolon;

  /// Initializes a newly created return statement.
  ///
  /// The [expression] can be `null` if no explicit value was provided.
  ReturnStatementImpl({
    required this.returnKeyword,
    required ExpressionImpl? expression,
    required this.semicolon,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => returnKeyword;

  @override
  Token get endToken => semicolon;

  @override
  ExpressionImpl? get expression => _expression;

  set expression(ExpressionImpl? expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('returnKeyword', returnKeyword)
        ..addNode('expression', expression)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitReturnStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _expression?.accept(visitor);
  }
}

/// A resolved dot shorthand invocation.
///
/// Either a [FunctionExpressionInvocationImpl], a static method invocation, or
/// a [DotShorthandConstructorInvocationImpl], a constructor invocation.
sealed class RewrittenMethodInvocationImpl implements ExpressionImpl {}

/// A script tag that can optionally occur at the beginning of a compilation
/// unit.
///
///    scriptTag ::=
///        '#!' (~NEWLINE)* NEWLINE
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ScriptTag implements AstNode {
  /// The token representing this script tag.
  Token get scriptTag;
}

final class ScriptTagImpl extends AstNodeImpl implements ScriptTag {
  @override
  final Token scriptTag;

  /// Initializes a newly created script tag.
  ScriptTagImpl({required this.scriptTag});

  @override
  Token get beginToken => scriptTag;

  @override
  Token get endToken => scriptTag;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('scriptTag', scriptTag);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitScriptTag(this);

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// A set or map literal.
///
///    setOrMapLiteral ::=
///        'const'? [TypeArgumentList]? '{' elements? '}'
///
///    elements ::=
///        [CollectionElement] ( ',' [CollectionElement] )* ','?
///
/// This is the class that is used to represent either a map or set literal when
/// either the 'control-flow-collections' or 'spread-collections' experiments
/// are enabled. If neither of those experiments are enabled, then `MapLiteral`
/// is used to represent a map literal and `SetLiteral` is used for set
/// literals.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SetOrMapLiteral implements TypedLiteral {
  /// The syntactic elements used to compute the elements of the set or map.
  NodeList<CollectionElement> get elements;

  /// Whether this literal represents a map literal.
  ///
  /// This getter always returns `false` if [isSet] returns `true`.
  ///
  /// However, this getter is _not_ the inverse of [isSet]. It's possible for
  /// both getters to return `false` if
  ///
  /// - the AST hasn't been resolved (because determining the kind of the
  ///   literal is done during resolution),
  /// - the literal is ambiguous (contains one or more spread elements and none
  ///   of those elements can be used to determine the kind of the literal), or
  /// - the literal is invalid because it contains both expressions (for sets)
  ///   and map entries (for maps).
  ///
  /// In both of the latter two cases there are compilation errors associated
  /// with the literal.
  bool get isMap;

  /// Whether this literal represents a set literal.
  ///
  /// This getter always returns `false` if [isMap] returns `true`.
  ///
  /// However, this getter is _not_ the inverse of [isMap]. It's possible for
  /// both getters to return `false` if
  ///
  /// - the AST hasn't been resolved (because determining the kind of the
  ///   literal is done during resolution),
  /// - the literal is ambiguous (contains one or more spread elements and none
  ///   of those elements can be used to determine the kind of the literal), or
  /// - the literal is invalid because it contains both expressions (for sets)
  ///   and map entries (for maps).
  ///
  /// In both of the latter two cases there are compilation errors associated
  /// with the literal.
  bool get isSet;

  /// The left curly bracket.
  Token get leftBracket;

  /// The right curly bracket.
  Token get rightBracket;
}

final class SetOrMapLiteralImpl extends TypedLiteralImpl
    implements SetOrMapLiteral {
  @override
  final Token leftBracket;

  final NodeListImpl<CollectionElementImpl> _elements = NodeListImpl._();

  @override
  final Token rightBracket;

  /// A representation of whether this literal represents a map or a set, or
  /// whether the kind hasn't or can't be determined.
  _SetOrMapKind _resolvedKind = _SetOrMapKind.unresolved;

  /// The context type computed by [TypedLiteralResolver].
  InterfaceType? contextType;

  /// Initializes a newly created set or map literal.
  ///
  /// The [constKeyword] can be `null` if the literal isn't a constant.
  ///
  /// The [typeArguments] can be `null` if no type arguments were declared.
  ///
  /// The [elements] can be `null` if the set is empty.
  SetOrMapLiteralImpl({
    required super.constKeyword,
    required super.typeArguments,
    required this.leftBracket,
    required List<CollectionElementImpl> elements,
    required this.rightBracket,
  }) {
    _elements._initialize(this, elements);
  }

  @override
  Token get beginToken {
    if (constKeyword case var constKeyword?) {
      return constKeyword;
    }
    var typeArguments = this.typeArguments;
    if (typeArguments != null) {
      return typeArguments.beginToken;
    }
    return leftBracket;
  }

  @override
  NodeListImpl<CollectionElementImpl> get elements => _elements;

  @override
  Token get endToken => rightBracket;

  @override
  bool get isMap => _resolvedKind == _SetOrMapKind.map;

  @override
  bool get isSet => _resolvedKind == _SetOrMapKind.set;

  @override
  // TODO(paulberry): add commas.
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('elements', elements)
        ..addToken('rightBracket', rightBracket);

  @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 resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitSetOrMapLiteral(this, contextType: contextType);
  }

  @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])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ShowCombinator implements Combinator {
  /// The list of names from the library that are made visible by this
  /// combinator.
  NodeList<SimpleIdentifier> get shownNames;
}

final class ShowCombinatorImpl extends CombinatorImpl
    implements ShowCombinator {
  final NodeListImpl<SimpleIdentifierImpl> _shownNames = NodeListImpl._();

  /// Initializes a newly created import show combinator.
  ShowCombinatorImpl({
    required super.keyword,
    required List<SimpleIdentifierImpl> shownNames,
  }) {
    _shownNames._initialize(this, shownNames);
  }

  @override
  Token get endToken => _shownNames.endToken!;

  @override
  NodeListImpl<SimpleIdentifierImpl> get shownNames => _shownNames;

  @override
  // TODO(paulberry): add commas.
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('keyword', keyword)
        ..addNodeList('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' [TypeAnnotation] | 'var' | [TypeAnnotation])?
///        [SimpleIdentifier]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SimpleFormalParameter implements NormalFormalParameter {
  /// The token representing either the `final`, `const` or `var` keyword, or
  /// `null` if no keyword was used.
  Token? get keyword;

  /// The declared type of the parameter, or `null` if the parameter doesn't
  /// have a declared type.
  TypeAnnotation? get type;
}

final class SimpleFormalParameterImpl extends NormalFormalParameterImpl
    implements SimpleFormalParameter {
  @override
  final Token? keyword;

  TypeAnnotationImpl? _type;

  /// Initializes a newly created formal parameter.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// parameter doesn't 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({
    required super.comment,
    required super.metadata,
    required super.covariantKeyword,
    required super.requiredKeyword,
    required this.keyword,
    required TypeAnnotationImpl? type,
    required super.name,
  }) : _type = type {
    _becomeParentOf(_type);
  }

  @override
  Token get endToken => name ?? type!.endToken;

  @override
  Token get firstTokenAfterCommentAndMetadata =>
      requiredKeyword ??
      covariantKeyword ??
      keyword ??
      type?.beginToken ??
      name!;

  @override
  bool get isConst => keyword?.keyword == Keyword.CONST;

  @override
  bool get isExplicitlyTyped => _type != null;

  @override
  bool get isFinal => keyword?.keyword == Keyword.FINAL;

  @override
  TypeAnnotationImpl? get type => _type;

  set type(TypeAnnotationImpl? type) {
    _type = _becomeParentOf(type);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('keyword', keyword)
        ..addNode('type', type)
        ..addToken('name', name);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitSimpleFormalParameter(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _type?.accept(visitor);
  }
}

/// A simple identifier.
///
///    simpleIdentifier ::=
///        initialCharacter internalCharacter*
///
///    initialCharacter ::= '_' | '$' | letter
///
///    internalCharacter ::= '_' | '$' | letter | digit
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SimpleIdentifier implements Identifier {
  /// Whether this identifier is the "name" part of a prefixed identifier or a
  /// method invocation.
  bool get isQualified;

  /// If the identifier is a tear-off, return the inferred type arguments
  /// applied to the function type of the element to produce its `[staticType]`.
  ///
  /// An empty list if the function type doesn't have type parameters or if the
  /// context type has type parameters, or `null` if this node isn't a tear-off
  /// or if the AST structure hasn't been resolved.
  List<DartType>? get tearOffTypeArgumentTypes;

  /// The token representing the identifier.
  Token get token;

  /// Whether this identifier is the name being declared in a declaration.
  // TODO(brianwilkerson): Convert this to a getter.
  bool inDeclarationContext();

  /// Whether this expression is computing a right-hand value.
  ///
  /// Note that [inGetterContext] and [inSetterContext] aren't opposites, nor
  /// are they mutually exclusive. In other words, it's possible for both
  /// methods to return `true` when invoked on the same node.
  // TODO(brianwilkerson): Convert this to a getter.
  bool inGetterContext();

  /// Whether this expression is computing a left-hand value.
  ///
  /// Note that [inGetterContext] and [inSetterContext] aren't opposites, nor
  /// are they mutually exclusive. In other words, it's possible for both
  /// methods to return `true` when invoked on the same node.
  // TODO(brianwilkerson): Convert this to a getter.
  bool inSetterContext();
}

final class SimpleIdentifierImpl extends IdentifierImpl
    implements SimpleIdentifier {
  @override
  Token token;

  /// The element associated with this identifier based on static type
  /// information, or `null` if the AST structure hasn't been resolved or if
  /// this identifier couldn't be resolved.
  @override
  Element2? element;

  @override
  List<TypeImpl>? tearOffTypeArgumentTypes;

  /// If this identifier is meant to be looked up in the enclosing scope, the
  /// raw result the scope lookup, prior to figuring out whether a write or a
  /// read context is intended, and prior to falling back on implicit `this` (if
  /// appropriate).
  ///
  /// Or `null` if this identifier isn't meant to be looked up in the enclosing
  /// scope.
  ScopeLookupResult? scopeLookupResult;

  /// Initializes a newly created identifier.
  SimpleIdentifierImpl(this.token);

  /// The cascade that contains this [SimpleIdentifier].
  CascadeExpressionImpl? get ancestorCascade {
    var operatorType = token.previous?.type;
    if (operatorType == TokenType.PERIOD_PERIOD ||
        operatorType == TokenType.QUESTION_PERIOD_PERIOD) {
      return thisOrAncestorOfType<CascadeExpressionImpl>();
    }
    return null;
  }

  @override
  Token get beginToken => token;

  @override
  Token get endToken => token;

  @override
  bool get isQualified {
    var 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;

  @override
  ChildEntities get _childEntities => ChildEntities()..addToken('token', token);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitSimpleIdentifier(this);

  @override
  bool inDeclarationContext() {
    var parent = this.parent;
    switch (parent) {
      case ImportDirective():
        return parent.prefix == this;
      case Label():
        var parent2 = parent.parent;
        return parent2 is Statement || parent2 is SwitchMember;
    }
    return false;
  }

  @override
  bool inGetterContext() {
    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;
      }
    }
    return true;
  }

  @override
  bool inSetterContext() {
    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 resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitSimpleIdentifier(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// A string literal expression that doesn't contain any interpolations.
///
///    simpleStringLiteral ::=
///        rawStringLiteral
///      | basicStringLiteral
///
///    rawStringLiteral ::=
///        'r' basicStringLiteral
///
///    basicStringLiteral ::=
///        multiLineStringLiteral
///      | singleLineStringLiteral
///
///    multiLineStringLiteral ::=
///        "'''" characters "'''"
///      | '"""' characters '"""'
///
///    singleLineStringLiteral ::=
///        "'" characters "'"
///      | '"' characters '"'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SimpleStringLiteral implements SingleStringLiteral {
  /// The token representing the literal.
  Token get literal;

  /// The value of the literal.
  String get value;
}

final class SimpleStringLiteralImpl extends SingleStringLiteralImpl
    implements SimpleStringLiteral {
  @override
  final Token literal;

  @override
  String value;

  /// Initializes a newly created simple string literal.
  SimpleStringLiteralImpl({required this.literal, required this.value});

  @override
  Token get beginToken => 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
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('literal', literal);

  StringLexemeHelper get _helper {
    return StringLexemeHelper(literal.lexeme, true, true);
  }

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitSimpleStringLiteral(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitSimpleStringLiteral(this, contextType: contextType);
  }

  @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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class SingleStringLiteral implements StringLiteral {
  /// The offset of the after-last contents character.
  int get contentsEnd;

  /// The offset of the first contents character.
  ///
  /// If the string is multiline, then leading whitespaces are skipped.
  int get contentsOffset;

  /// Whether this string literal is a multi-line string.
  bool get isMultiline;

  /// Whether this string literal is a raw string.
  bool get isRaw;

  /// Whether this string literal uses single quotes (' or ''').
  ///
  /// If `false` is returned then the string literal uses double quotes
  /// (" or """).
  bool get isSingleQuoted;
}

sealed class SingleStringLiteralImpl extends StringLiteralImpl
    implements SingleStringLiteral {}

/// A spread element.
///
///    spreadElement:
///        ( '...' | '...?' ) [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SpreadElement implements CollectionElement {
  /// The expression used to compute the collection being spread.
  Expression get expression;

  /// Whether this is a null-aware spread, as opposed to a non-null spread.
  bool get isNullAware;

  /// The spread operator, either '...' or '...?'.
  Token get spreadOperator;
}

final class SpreadElementImpl extends AstNodeImpl
    implements CollectionElementImpl, SpreadElement {
  @override
  final Token spreadOperator;

  ExpressionImpl _expression;

  SpreadElementImpl({
    required this.spreadOperator,
    required ExpressionImpl expression,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => spreadOperator;

  @override
  Token get endToken => _expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  bool get isNullAware =>
      spreadOperator.type == TokenType.PERIOD_PERIOD_PERIOD_QUESTION;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('spreadOperator', spreadOperator)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) {
    return visitor.visitSpreadElement(this);
  }

  @override
  void resolveElement(
    ResolverVisitor resolver,
    CollectionLiteralContext? context,
  ) {
    resolver.visitSpreadElement(this, context: context);
    resolver.pushRewrite(null);
  }

  @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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class Statement implements AstNode {
  /// If this is a labeled statement, returns the statement being labeled,
  /// otherwise returns the statement itself.
  Statement get unlabeled;
}

sealed class StatementImpl extends AstNodeImpl implements Statement {
  @override
  StatementImpl get unlabeled => this;
}

/// A string interpolation literal.
///
///    stringInterpolation ::=
///        ''' [InterpolationElement]* '''
///      | '"' [InterpolationElement]* '"'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class StringInterpolation implements SingleStringLiteral {
  /// The elements that are composed to produce the resulting string.
  ///
  /// The list includes [firstString] and [lastString].
  NodeList<InterpolationElement> get elements;

  /// The first element in this interpolation, which is always a string.
  ///
  /// The string might be empty if there's no text before the first
  /// interpolation expression (such as in `'$foo bar'`).
  InterpolationString get firstString;

  /// The last element in this interpolation, which is always a string.
  ///
  /// The string might be empty if there's no text after the last
  /// interpolation expression (such as in `'foo $bar'`).
  InterpolationString get lastString;
}

final class StringInterpolationImpl extends SingleStringLiteralImpl
    implements StringInterpolation {
  /// The elements that are composed to produce the resulting string.
  final NodeListImpl<InterpolationElementImpl> _elements = NodeListImpl._();

  /// Initializes a newly created string interpolation expression.
  StringInterpolationImpl({required List<InterpolationElementImpl> 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
  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;
  }

  @override
  NodeListImpl<InterpolationElementImpl> 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;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addNodeList('elements', elements);

  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 resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitStringInterpolation(this, contextType: contextType);
  }

  @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 (lexeme.startsWith("'''", start)) {
        isSingleQuoted = true;
        isMultiline = true;
        start += 3;
        start = _trimInitialWhitespace(start);
      } else if (lexeme.startsWith('"""', start)) {
        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 &&
          (lexeme.endsWith("'''") || lexeme.endsWith('"""'))) {
        end -= 3;
      } else if (start + 1 <= end &&
          (lexeme.endsWith("'") || lexeme.endsWith('"'))) {
        end -= 1;
      }
    }
  }

  /// Given the [lexeme] for a multi-line string whose content begins at the
  /// given [start] index, returns 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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class StringLiteral implements Literal {
  /// The value of the string literal, or `null` if the string isn't a constant
  /// string without any string interpolation.
  String? get stringValue;
}

sealed 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 isn't 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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SuperConstructorInvocation
    implements ConstructorInitializer, ConstructorReferenceNode {
  /// The list of arguments to the constructor.
  ArgumentList get argumentList;

  /// The name of the constructor that is being invoked, or `null` if the
  /// unnamed constructor is being invoked.
  SimpleIdentifier? get constructorName;

  /// The token for the period before the name of the constructor that is being
  /// invoked, or `null` if the unnamed constructor is being invoked.
  Token? get period;

  /// The token for the `super` keyword.
  Token get superKeyword;
}

final class SuperConstructorInvocationImpl extends ConstructorInitializerImpl
    implements SuperConstructorInvocation {
  @override
  final Token superKeyword;

  @override
  final Token? period;

  SimpleIdentifierImpl? _constructorName;

  ArgumentListImpl _argumentList;

  @override
  ConstructorElementMixin2? element;

  /// Initializes 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({
    required this.superKeyword,
    required this.period,
    required SimpleIdentifierImpl? constructorName,
    required ArgumentListImpl argumentList,
  }) : _constructorName = constructorName,
       _argumentList = argumentList {
    _becomeParentOf(_constructorName);
    _becomeParentOf(_argumentList);
  }

  @override
  ArgumentListImpl get argumentList => _argumentList;

  set argumentList(ArgumentListImpl argumentList) {
    _argumentList = _becomeParentOf(argumentList);
  }

  @override
  Token get beginToken => superKeyword;

  @override
  SimpleIdentifierImpl? get constructorName => _constructorName;

  set constructorName(SimpleIdentifierImpl? identifier) {
    _constructorName = _becomeParentOf(identifier);
  }

  @override
  Token get endToken => _argumentList.endToken;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('superKeyword', superKeyword)
        ..addToken('period', period)
        ..addNode('constructorName', constructorName)
        ..addNode('argumentList', argumentList);

  @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'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SuperExpression implements Expression {
  /// The token representing the `super` keyword.
  Token get superKeyword;
}

final class SuperExpressionImpl extends ExpressionImpl
    implements SuperExpression {
  @override
  final Token superKeyword;

  /// Initializes a newly created super expression.
  SuperExpressionImpl({required this.superKeyword});

  @override
  Token get beginToken => superKeyword;

  @override
  Token get endToken => superKeyword;

  @override
  Precedence get precedence => Precedence.primary;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('superKeyword', superKeyword);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitSuperExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitSuperExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// A super-initializer formal parameter.
///
///    superFormalParameter ::=
///        ('final' [TypeAnnotation] | 'const' [TypeAnnotation] | 'var' |
///        [TypeAnnotation])?
///        'super' '.' name ([TypeParameterList]? [FormalParameterList])?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SuperFormalParameter implements NormalFormalParameter {
  /// The token representing either the `final`, `const` or `var` keyword, or
  /// `null` if no keyword was used.
  Token? get keyword;

  /// The name of the parameter being declared.
  @override
  Token get name;

  /// The parameters of the function-typed parameter, or `null` if this isn't a
  /// function-typed field formal parameter.
  FormalParameterList? get parameters;

  /// The token representing the period.
  Token get period;

  /// The question mark indicating that the function type is nullable, or `null`
  /// if there's no question mark, which will always be the case when the
  /// parameter doesn't use the older style for denoting a function typed
  /// parameter.
  ///
  /// If the parameter is function-typed, and has the question mark, then its
  /// function type is nullable. Having a nullable function type means that the
  /// parameter can be `null`.
  Token? get question;

  /// The token representing the `super` keyword.
  Token get superKeyword;

  /// The declared type of the parameter, or `null` if the parameter doesn't
  /// have a declared type.
  ///
  /// If this is a function-typed field formal parameter this is the return type
  /// of the function.
  TypeAnnotation? get type;

  /// The type parameters associated with this method, or `null` if this method
  /// isn't a generic method.
  TypeParameterList? get typeParameters;
}

final class SuperFormalParameterImpl extends NormalFormalParameterImpl
    implements SuperFormalParameter {
  @override
  final Token? keyword;

  TypeAnnotationImpl? _type;

  @override
  final Token superKeyword;

  @override
  final Token period;

  TypeParameterListImpl? _typeParameters;

  FormalParameterListImpl? _parameters;

  @override
  final Token? question;

  /// Initializes a newly created formal parameter.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// parameter doesn't have the corresponding attribute.
  ///
  /// The [keyword] can be `null` if there's a type.
  ///
  /// The [type] must be `null` if the keyword is `var`.
  ///
  /// The[parameters] can be `null` if this isn't a function-typed field formal
  /// parameter.
  SuperFormalParameterImpl({
    required super.comment,
    required super.metadata,
    required super.covariantKeyword,
    required super.requiredKeyword,
    required this.keyword,
    required TypeAnnotationImpl? type,
    required this.superKeyword,
    required this.period,
    required super.name,
    required TypeParameterListImpl? typeParameters,
    required FormalParameterListImpl? parameters,
    required this.question,
  }) : _type = type,
       _typeParameters = typeParameters,
       _parameters = parameters {
    _becomeParentOf(_type);
    _becomeParentOf(_typeParameters);
    _becomeParentOf(_parameters);
  }

  @override
  Token get endToken {
    return question ?? _parameters?.endToken ?? name;
  }

  @override
  Token get firstTokenAfterCommentAndMetadata =>
      requiredKeyword ??
      covariantKeyword ??
      keyword ??
      type?.beginToken ??
      superKeyword;

  @override
  bool get isConst => keyword?.keyword == Keyword.CONST;

  @override
  bool get isExplicitlyTyped => _parameters != null || _type != null;

  @override
  bool get isFinal => keyword?.keyword == Keyword.FINAL;

  @override
  Token get name => super.name!;

  @override
  FormalParameterListImpl? get parameters => _parameters;

  set parameters(FormalParameterListImpl? parameters) {
    _parameters = _becomeParentOf(parameters);
  }

  @override
  TypeAnnotationImpl? get type => _type;

  set type(TypeAnnotationImpl? type) {
    _type = _becomeParentOf(type as TypeAnnotationImpl);
  }

  @override
  TypeParameterListImpl? get typeParameters => _typeParameters;

  set typeParameters(TypeParameterListImpl? typeParameters) {
    _typeParameters = _becomeParentOf(typeParameters);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('keyword', keyword)
        ..addNode('type', type)
        ..addToken('superKeyword', superKeyword)
        ..addToken('period', period)
        ..addToken('name', name)
        ..addNode('typeParameters', typeParameters)
        ..addNode('parameters', parameters);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitSuperFormalParameter(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _type?.accept(visitor);
    _typeParameters?.accept(visitor);
    _parameters?.accept(visitor);
  }
}

/// A case in a switch statement.
///
///    switchCase ::=
///        [SimpleIdentifier]* 'case' [Expression] ':' [Statement]*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SwitchCase implements SwitchMember {
  /// The expression controlling whether the statements are executed.
  Expression get expression;
}

final class SwitchCaseImpl extends SwitchMemberImpl implements SwitchCase {
  ExpressionImpl _expression;

  /// Initializes a newly created switch case.
  ///
  /// The list of [labels] can be `null` if there are no labels.
  SwitchCaseImpl({
    required super.labels,
    required super.keyword,
    required ExpressionImpl expression,
    required super.colon,
    required super.statements,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNodeList('labels', labels)
        ..addToken('keyword', keyword)
        ..addNode('expression', expression)
        ..addToken('colon', colon)
        ..addNodeList('statements', statements);

  @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]*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SwitchDefault implements SwitchMember {}

final class SwitchDefaultImpl extends SwitchMemberImpl
    implements SwitchDefault {
  /// Initializes a newly created switch default.
  ///
  /// The list of [labels] can be `null` if there are no labels.
  SwitchDefaultImpl({
    required super.labels,
    required super.keyword,
    required super.colon,
    required super.statements,
  });

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNodeList('labels', labels)
        ..addToken('keyword', keyword)
        ..addToken('colon', colon)
        ..addNodeList('statements', statements);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchDefault(this);

  @override
  void visitChildren(AstVisitor visitor) {
    labels.accept(visitor);
    statements.accept(visitor);
  }
}

/// A switch expression.
///
///    switchExpression ::=
///        'switch' '(' [Expression] ')' '{' [SwitchExpressionCase]
///        (',' [SwitchExpressionCase])* ','? '}'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SwitchExpression implements Expression {
  /// The cases that can be selected by the expression.
  NodeList<SwitchExpressionCase> get cases;

  /// The expression used to determine which of the switch cases is selected.
  Expression get expression;

  /// The left curly bracket.
  Token get leftBracket;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right curly bracket.
  Token get rightBracket;

  /// The right parenthesis.
  Token get rightParenthesis;

  /// The token representing the `switch` keyword.
  Token get switchKeyword;
}

/// A case in a switch expression.
///
///    switchExpressionCase ::=
///        [GuardedPattern] '=>' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SwitchExpressionCase implements AstNode {
  /// The arrow separating the pattern from the expression.
  Token get arrow;

  /// The expression whose value is returned from the switch expression if the
  /// pattern matches.
  Expression get expression;

  /// The refutable pattern that must match for the [expression] to be executed.
  GuardedPattern get guardedPattern;
}

final class SwitchExpressionCaseImpl extends AstNodeImpl
    with AstNodeWithNameScopeMixin
    implements SwitchExpressionCase, CaseNodeImpl {
  @override
  final GuardedPatternImpl guardedPattern;

  @override
  final Token arrow;

  ExpressionImpl _expression;

  SwitchExpressionCaseImpl({
    required this.guardedPattern,
    required this.arrow,
    required ExpressionImpl expression,
  }) : _expression = expression {
    _becomeParentOf(guardedPattern);
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => guardedPattern.beginToken;

  @override
  Token get endToken => expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNode('guardedPattern', guardedPattern)
        ..addToken('arrow', arrow)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitSwitchExpressionCase(this);

  @override
  void visitChildren(AstVisitor visitor) {
    guardedPattern.accept(visitor);
    expression.accept(visitor);
  }
}

final class SwitchExpressionImpl extends ExpressionImpl
    implements SwitchExpression {
  @override
  final Token switchKeyword;

  @override
  final Token leftParenthesis;

  ExpressionImpl _expression;

  @override
  final Token rightParenthesis;

  @override
  final Token leftBracket;

  @override
  final NodeListImpl<SwitchExpressionCaseImpl> cases = NodeListImpl._();

  @override
  final Token rightBracket;

  SwitchExpressionImpl({
    required this.switchKeyword,
    required this.leftParenthesis,
    required ExpressionImpl expression,
    required this.rightParenthesis,
    required this.leftBracket,
    required List<SwitchExpressionCaseImpl> cases,
    required this.rightBracket,
  }) : _expression = expression {
    _becomeParentOf(_expression);
    this.cases._initialize(this, cases);
  }

  @override
  Token get beginToken => switchKeyword;

  @override
  Token get endToken => rightBracket;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.primary;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('switchKeyword', switchKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('expression', expression)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('cases', cases)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitSwitchExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    expression.accept(visitor);
    cases.accept(visitor);
  }
}

/// An element within a switch statement.
///
///    switchMember ::=
///        [SwitchCase]
///      | [SwitchDefault]
///      | [SwitchPatternCase]
///
/// The class [SwitchPatternCase] exists only to support the 'patterns' feature.
///
/// Note that when the patterns feature is enabled by default, the class
/// [SwitchPatternCase] might replace [SwitchCase] entirely. If we do that, then
/// legacy code (code opted into a version prior to the release of patterns)
/// will likely wrap the expression in a [ConstantPattern] with synthetic
/// tokens.
// TODO(brianwilkerson): Consider renaming `SwitchMember`, `SwitchCase`, and
//  `SwitchDefault` to start with `SwitchStatement` for consistency.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class SwitchMember implements AstNode {
  /// The colon separating the keyword or the expression from the statements.
  Token get colon;

  /// The token representing the `case` or `default` keyword.
  Token get keyword;

  /// The labels associated with the switch member.
  NodeList<Label> get labels;

  /// The statements that are executed if this switch member is selected.
  NodeList<Statement> get statements;
}

sealed class SwitchMemberImpl extends AstNodeImpl
    with AstNodeWithNameScopeMixin
    implements SwitchMember {
  final NodeListImpl<LabelImpl> _labels = NodeListImpl._();

  @override
  final Token keyword;

  @override
  final Token colon;

  final NodeListImpl<StatementImpl> _statements = NodeListImpl._();

  /// Initializes a newly created switch member.
  ///
  /// The list of [labels] can be `null` if there are no labels.
  SwitchMemberImpl({
    required List<LabelImpl> labels,
    required this.keyword,
    required this.colon,
    required List<StatementImpl> 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<LabelImpl> get labels => _labels;

  @override
  NodeListImpl<StatementImpl> get statements => _statements;
}

/// A pattern-based case in a switch statement.
///
///    switchPatternCase ::=
///        [Label]* 'case' [DartPattern] [WhenClause]? ':' [Statement]*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SwitchPatternCase implements SwitchMember {
  /// The pattern controlling whether the statements is executed.
  GuardedPattern get guardedPattern;
}

final class SwitchPatternCaseImpl extends SwitchMemberImpl
    implements SwitchPatternCase, CaseNodeImpl {
  @override
  final GuardedPatternImpl guardedPattern;

  SwitchPatternCaseImpl({
    required super.labels,
    required super.keyword,
    required this.guardedPattern,
    required super.colon,
    required super.statements,
  }) {
    _becomeParentOf(guardedPattern);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addNodeList('labels', labels)
        ..addToken('keyword', keyword)
        ..addNode('guardedPattern', guardedPattern)
        ..addToken('colon', colon)
        ..addNodeList('statements', statements);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchPatternCase(this);

  @override
  void visitChildren(AstVisitor visitor) {
    labels.accept(visitor);
    guardedPattern.accept(visitor);
    statements.accept(visitor);
  }
}

/// A switch statement.
///
///    switchStatement ::=
///        'switch' '(' [Expression] ')' '{' [SwitchCase]* [SwitchDefault]? '}'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SwitchStatement implements Statement {
  /// The expression used to determine which of the switch members is selected.
  Expression get expression;

  /// The left curly bracket.
  Token get leftBracket;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The switch members that can be selected by the expression.
  NodeList<SwitchMember> get members;

  /// The right curly bracket.
  Token get rightBracket;

  /// The right parenthesis.
  Token get rightParenthesis;

  /// The token representing the `switch` keyword.
  Token get switchKeyword;
}

class SwitchStatementCaseGroup {
  final List<SwitchMemberImpl> members;
  final bool hasLabels;

  /// Joined variables declared in [members], available in [statements].
  late Map<String, PromotableElementImpl2> variables;

  SwitchStatementCaseGroup(this.members, this.hasLabels);

  NodeListImpl<StatementImpl> get statements {
    return members.last.statements;
  }
}

final class SwitchStatementImpl extends StatementImpl
    implements SwitchStatement {
  @override
  final Token switchKeyword;

  @override
  final Token leftParenthesis;

  ExpressionImpl _expression;

  @override
  final Token rightParenthesis;

  @override
  final Token leftBracket;

  final NodeListImpl<SwitchMemberImpl> _members = NodeListImpl._();

  late final List<SwitchStatementCaseGroup> memberGroups =
      _computeMemberGroups();

  @override
  final Token rightBracket;

  /// Initializes a newly created switch statement.
  ///
  /// The list of [members] can be `null` if there are no switch members.
  SwitchStatementImpl({
    required this.switchKeyword,
    required this.leftParenthesis,
    required ExpressionImpl expression,
    required this.rightParenthesis,
    required this.leftBracket,
    required List<SwitchMemberImpl> members,
    required this.rightBracket,
  }) : _expression = expression {
    _becomeParentOf(_expression);
    _members._initialize(this, members);
  }

  @override
  Token get beginToken => switchKeyword;

  @override
  Token get endToken => rightBracket;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  NodeListImpl<SwitchMemberImpl> get members => _members;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('switchKeyword', switchKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('expression', expression)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('members', members)
        ..addToken('rightBracket', rightBracket);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitSwitchStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _expression.accept(visitor);
    _members.accept(visitor);
  }

  List<SwitchStatementCaseGroup> _computeMemberGroups() {
    var groups = <SwitchStatementCaseGroup>[];
    var groupMembers = <SwitchMemberImpl>[];
    var groupHasLabels = false;
    for (var member in members) {
      groupMembers.add(member);
      groupHasLabels |= member.labels.isNotEmpty;
      if (member.statements.isNotEmpty) {
        groups.add(SwitchStatementCaseGroup(groupMembers, groupHasLabels));
        groupMembers = [];
        groupHasLabels = false;
      }
    }
    if (groupMembers.isNotEmpty) {
      groups.add(SwitchStatementCaseGroup(groupMembers, groupHasLabels));
    }
    return groups;
  }
}

/// A symbol literal expression.
///
///    symbolLiteral ::=
///        '#' (operator | (identifier ('.' identifier)*))
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class SymbolLiteral implements Literal {
  /// The components of the literal.
  List<Token> get components;

  /// The token introducing the literal.
  Token get poundSign;
}

final class SymbolLiteralImpl extends LiteralImpl implements SymbolLiteral {
  @override
  final Token poundSign;

  @override
  final List<Token> components;

  /// Initializes a newly created symbol literal.
  SymbolLiteralImpl({required this.poundSign, required this.components});

  @override
  Token get beginToken => poundSign;

  @override
  Token get endToken => components[components.length - 1];

  @override
  // TODO(paulberry): add "." tokens.
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('poundSign', poundSign)
        ..addTokenList('components', components);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitSymbolLiteral(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitSymbolLiteral(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// An identifier that can be used to look up names in the lexical scope when
/// there's no identifier in the AST structure.
///
/// For example, there's no identifier in the AST when the parser can't
/// distinguish between a method invocation and an invocation of a top-level
/// function imported with a prefix.
final class SyntheticIdentifier implements SimpleIdentifier {
  @override
  final String name;

  SyntheticIdentifier(this.name);

  @override
  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

/// A this expression.
///
///    thisExpression ::=
///        'this'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ThisExpression implements Expression {
  /// The token representing the `this` keyword.
  Token get thisKeyword;
}

final class ThisExpressionImpl extends ExpressionImpl
    implements ThisExpression {
  @override
  final Token thisKeyword;

  /// Initializes a newly created this expression.
  ThisExpressionImpl({required this.thisKeyword});

  @override
  Token get beginToken => thisKeyword;

  @override
  Token get endToken => thisKeyword;

  @override
  Precedence get precedence => Precedence.primary;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()..addToken('thisKeyword', thisKeyword);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitThisExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitThisExpression(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    // There are no children to visit.
  }
}

/// A throw expression.
///
///    throwExpression ::=
///        'throw' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class ThrowExpression implements Expression {
  /// The expression computing the exception to be thrown.
  Expression get expression;

  /// The token representing the `throw` keyword.
  Token get throwKeyword;
}

final class ThrowExpressionImpl extends ExpressionImpl
    implements ThrowExpression {
  @override
  final Token throwKeyword;

  ExpressionImpl _expression;

  /// Initializes a newly created throw expression.
  ThrowExpressionImpl({
    required this.throwKeyword,
    required ExpressionImpl expression,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken => throwKeyword;

  @override
  Token get endToken {
    return _expression.endToken;
  }

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  Precedence get precedence => Precedence.assignment;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('throwKeyword', throwKeyword)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitThrowExpression(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitThrowExpression(this, contextType: contextType);
  }

  @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> ';'
///      | 'late' 'final' <type>? <initializedIdentifierList> ';'
///      | 'late'? <varOrType> <initializedIdentifierList> ';'
///      | 'external' <finalVarOrType> <identifierList> ';'
///
/// (Note: there's no `<topLevelVariableDeclaration>` production in the grammar;
/// this is a subset of the grammar production `<topLevelDeclaration>`, which
/// encompasses everything that can appear inside a Dart file after part
/// directives).
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class TopLevelVariableDeclaration
    implements CompilationUnitMember {
  /// The `augment` keyword, or `null` if the keyword was absent.
  @experimental
  Token? get augmentKeyword;

  /// The `external` keyword, or `null` if the keyword isn't used.
  Token? get externalKeyword;

  /// The semicolon terminating the declaration.
  Token get semicolon;

  /// The top-level variables being declared.
  VariableDeclarationList get variables;
}

final class TopLevelVariableDeclarationImpl extends CompilationUnitMemberImpl
    implements TopLevelVariableDeclaration {
  VariableDeclarationListImpl _variableList;

  @override
  final Token? augmentKeyword;

  @override
  final Token? externalKeyword;

  @override
  final Token semicolon;

  /// Initializes a newly created top-level variable declaration.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// variable doesn't have the corresponding attribute.
  TopLevelVariableDeclarationImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.externalKeyword,
    required VariableDeclarationListImpl variableList,
    required this.semicolon,
  }) : _variableList = variableList {
    _becomeParentOf(_variableList);
  }

  @override
  Fragment? get declaredFragment => null;

  @override
  Token get endToken => semicolon;

  @override
  Token get firstTokenAfterCommentAndMetadata =>
      augmentKeyword ?? externalKeyword ?? _variableList.beginToken;

  @override
  VariableDeclarationListImpl get variables => _variableList;

  set variables(VariableDeclarationListImpl variables) {
    _variableList = _becomeParentOf(variables);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('augmentKeyword', augmentKeyword)
        ..addToken('externalKeyword', externalKeyword)
        ..addNode('variables', variables)
        ..addToken('semicolon', semicolon);

  @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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class TryStatement implements Statement {
  /// The body of the statement.
  Block get body;

  /// The catch clauses contained in the try statement.
  NodeList<CatchClause> get catchClauses;

  /// The finally block contained in the try statement, or `null` if the
  /// statement doesn't contain a finally clause.
  Block? get finallyBlock;

  /// The token representing the `finally` keyword, or `null` if the statement
  /// doesn't contain a finally clause.
  Token? get finallyKeyword;

  /// The token representing the `try` keyword.
  Token get tryKeyword;
}

final class TryStatementImpl extends StatementImpl implements TryStatement {
  @override
  final Token tryKeyword;

  BlockImpl _body;

  final NodeListImpl<CatchClauseImpl> _catchClauses = NodeListImpl._();

  @override
  final Token? finallyKeyword;

  BlockImpl? _finallyBlock;

  /// Initializes a newly created try statement.
  ///
  /// The [finallyKeyword] and [finallyBlock] can be `null` if there's no
  /// finally clause.
  TryStatementImpl({
    required this.tryKeyword,
    required BlockImpl body,
    required List<CatchClauseImpl> catchClauses,
    required this.finallyKeyword,
    required BlockImpl? finallyBlock,
  }) : _body = body,
       _finallyBlock = finallyBlock {
    _becomeParentOf(_body);
    _catchClauses._initialize(this, catchClauses);
    _becomeParentOf(_finallyBlock);
  }

  @override
  Token get beginToken => tryKeyword;

  @override
  BlockImpl get body => _body;

  set body(BlockImpl block) {
    _body = _becomeParentOf(block);
  }

  @override
  NodeListImpl<CatchClauseImpl> get catchClauses => _catchClauses;

  @override
  Token get endToken {
    if (finallyBlock case var finallyBlock?) {
      return finallyBlock.endToken;
    } else if (finallyKeyword case var finallyKeyword?) {
      return finallyKeyword;
    } else if (_catchClauses case [..., var last]) {
      return last.endToken;
    }
    return _body.endToken;
  }

  @override
  BlockImpl? get finallyBlock => _finallyBlock;

  set finallyBlock(BlockImpl? block) {
    _finallyBlock = _becomeParentOf(block);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('tryKeyword', tryKeyword)
        ..addNode('body', body)
        ..addNodeList('catchClauses', catchClauses)
        ..addToken('finallyKeyword', finallyKeyword)
        ..addNode('finallyBlock', finallyBlock);

  @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 ::=
///        [ClassTypeAlias]
///      | [FunctionTypeAlias]
///      | [GenericTypeAlias]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class TypeAlias implements NamedCompilationUnitMember {
  /// The `augment` keyword, or `null` if the keyword was absent.
  @experimental
  Token? get augmentKeyword;

  /// The semicolon terminating the declaration.
  Token get semicolon;

  /// The token representing the `typedef` or `class` keyword.
  Token get typedefKeyword;
}

sealed class TypeAliasImpl extends NamedCompilationUnitMemberImpl
    implements TypeAlias {
  @override
  final Token? augmentKeyword;

  @override
  final Token typedefKeyword;

  @override
  final Token semicolon;

  /// Initializes a newly created type alias.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// declaration doesn't have the corresponding attribute.
  TypeAliasImpl({
    required super.comment,
    required super.metadata,
    required this.augmentKeyword,
    required this.typedefKeyword,
    required super.name,
    required this.semicolon,
  });

  @override
  Token get endToken => semicolon;

  @override
  Token get firstTokenAfterCommentAndMetadata {
    return augmentKeyword ?? typedefKeyword;
  }
}

/// A type annotation.
///
///    type ::=
///        [NamedType]
///      | [GenericFunctionType]
///      | [RecordTypeAnnotation]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class TypeAnnotation implements AstNode {
  /// The question mark indicating that the type is nullable, or `null` if
  /// there's no question mark.
  Token? get question;

  /// The type being named, or `null` if the AST structure hasn't been resolved.
  DartType? get type;
}

sealed class TypeAnnotationImpl extends AstNodeImpl implements TypeAnnotation {
  @override
  TypeImpl? get type;
}

/// A list of type arguments.
///
///    typeArguments ::=
///        '<' typeName (',' typeName)* '>'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class TypeArgumentList implements AstNode {
  /// The type arguments associated with the type.
  NodeList<TypeAnnotation> get arguments;

  /// The left bracket.
  Token get leftBracket;

  /// The right bracket.
  Token get rightBracket;
}

final class TypeArgumentListImpl extends AstNodeImpl
    implements TypeArgumentList {
  @override
  final Token leftBracket;

  final NodeListImpl<TypeAnnotationImpl> _arguments = NodeListImpl._();

  @override
  final Token rightBracket;

  /// Initializes a newly created list of type arguments.
  TypeArgumentListImpl({
    required this.leftBracket,
    required List<TypeAnnotationImpl> arguments,
    required this.rightBracket,
  }) {
    _arguments._initialize(this, arguments);
  }

  @override
  NodeListImpl<TypeAnnotationImpl> get arguments => _arguments;

  @override
  Token get beginToken => leftBracket;

  @override
  Token get endToken => rightBracket;

  @override
  // TODO(paulberry): Add commas.
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('arguments', arguments)
        ..addToken('rightBracket', 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]
///      | [SetOrMapLiteral]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class TypedLiteral implements Literal {
  /// The token representing the `const` keyword, or `null` if the literal isn't
  /// a constant.
  Token? get constKeyword;

  /// Whether this literal is a constant expression.
  ///
  /// It is a constant expression if either the keyword `const` was explicitly
  /// provided or because no keyword was provided and this expression occurs in
  /// a constant context.
  bool get isConst;

  /// The type argument associated with this literal, or `null` if no type
  /// arguments were declared.
  TypeArgumentList? get typeArguments;
}

sealed class TypedLiteralImpl extends LiteralImpl implements TypedLiteral {
  @override
  Token? constKeyword;

  TypeArgumentListImpl? _typeArguments;

  /// Initializes a newly created typed literal.
  ///
  /// The [constKeyword] can be `null` if the literal isn't a constant.
  ///
  /// The [typeArguments] can be `null` if no type arguments were declared.
  TypedLiteralImpl({
    required this.constKeyword,
    required TypeArgumentListImpl? typeArguments,
  }) : _typeArguments = typeArguments {
    _becomeParentOf(_typeArguments);
  }

  @override
  bool get isConst {
    return constKeyword != null || inConstantContext;
  }

  @override
  TypeArgumentListImpl? get typeArguments => _typeArguments;

  set typeArguments(TypeArgumentListImpl? typeArguments) {
    _typeArguments = _becomeParentOf(typeArguments);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('constKeyword', constKeyword)
        ..addNode('typeArguments', typeArguments);

  @override
  void visitChildren(AstVisitor visitor) {
    _typeArguments?.accept(visitor);
  }
}

/// An expression representing a type, such as the expression `int` in
/// `var x = int;`.
///
/// Objects of this type aren't produced directly by the parser (because the
/// parser can't tell whether an identifier refers to a type); they are
/// produced at resolution time.
///
/// The `.staticType` getter returns the type of the expression (which is
/// always the type `Type`). To get the type represented by the type literal
/// use `.typeName.type`.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class TypeLiteral
    implements Expression, CommentReferableExpression {
  /// The type represented by this literal.
  NamedType get type;
}

final class TypeLiteralImpl extends CommentReferableExpressionImpl
    implements TypeLiteral {
  NamedTypeImpl _typeName;

  TypeLiteralImpl({required NamedTypeImpl typeName}) : _typeName = typeName {
    _becomeParentOf(_typeName);
  }

  @override
  Token get beginToken => _typeName.beginToken;

  @override
  Token get endToken => _typeName.endToken;

  @override
  Precedence get precedence {
    if (_typeName.typeArguments != null) {
      return Precedence.postfix;
    } else if (_typeName.importPrefix != null) {
      return Precedence.postfix;
    } else {
      return Precedence.primary;
    }
  }

  @override
  NamedTypeImpl get type => _typeName;

  set typeName(NamedTypeImpl value) {
    _typeName = _becomeParentOf(value);
  }

  @override
  ChildEntities get _childEntities => ChildEntities()..addNode('type', type);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeLiteral(this);

  @override
  void resolveExpression(ResolverVisitor resolver, TypeImpl contextType) {
    resolver.visitTypeLiteral(this, contextType: contextType);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    _typeName.accept(visitor);
  }
}

/// A type parameter.
///
///    typeParameter ::=
///        name ('extends' [TypeAnnotation])?
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class TypeParameter implements Declaration {
  /// The upper bound for legal arguments, or `null` if there's no explicit
  /// upper bound.
  TypeAnnotation? get bound;

  @experimental
  @override
  TypeParameterFragment? get declaredFragment;

  /// The token representing the `extends` keyword, or `null` if there's no
  /// explicit upper bound.
  Token? get extendsKeyword;

  /// The name of the type parameter.
  Token get name;
}

final class TypeParameterImpl extends DeclarationImpl implements TypeParameter {
  @override
  final Token name;

  /// The token representing the variance modifier keyword, or `null` if there's
  /// no explicit variance modifier, meaning legacy covariance.
  Token? varianceKeyword;

  @override
  Token? extendsKeyword;

  TypeAnnotationImpl? _bound;

  @override
  TypeParameterElementImpl? declaredFragment;

  /// Initializes a newly created type parameter.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// parameter doesn't have the corresponding attribute.
  ///
  /// The [extendsKeyword] and [bound] can be `null` if the parameter doesn't
  /// have a bound.
  TypeParameterImpl({
    required super.comment,
    required super.metadata,
    required this.name,
    required this.extendsKeyword,
    required TypeAnnotationImpl? bound,
    this.varianceKeyword,
  }) : _bound = bound {
    _becomeParentOf(_bound);
  }

  @override
  TypeAnnotationImpl? get bound => _bound;

  set bound(TypeAnnotationImpl? type) {
    _bound = _becomeParentOf(type);
  }

  @override
  Token get endToken {
    return _bound?.endToken ?? name;
  }

  @override
  Token get firstTokenAfterCommentAndMetadata => varianceKeyword ?? name;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('name', name)
        ..addToken('extendsKeyword', extendsKeyword)
        ..addNode('bound', bound);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitTypeParameter(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _bound?.accept(visitor);
  }
}

/// Type parameters within a declaration.
///
///    typeParameterList ::=
///        '<' [TypeParameter] (',' [TypeParameter])* '>'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class TypeParameterList implements AstNode {
  /// The left angle bracket.
  Token get leftBracket;

  /// The right angle bracket.
  Token get rightBracket;

  /// The type parameters for the type.
  NodeList<TypeParameter> get typeParameters;
}

final class TypeParameterListImpl extends AstNodeImpl
    implements TypeParameterList {
  @override
  final Token leftBracket;

  final NodeListImpl<TypeParameterImpl> _typeParameters = NodeListImpl._();

  @override
  final Token rightBracket;

  /// Initializes a newly created list of type parameters.
  TypeParameterListImpl({
    required this.leftBracket,
    required List<TypeParameterImpl> typeParameters,
    required this.rightBracket,
  }) {
    _typeParameters._initialize(this, typeParameters);
  }

  @override
  Token get beginToken => leftBracket;

  @override
  Token get endToken => rightBracket;

  @override
  NodeListImpl<TypeParameterImpl> get typeParameters => _typeParameters;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('leftBracket', leftBracket)
        ..addNodeList('typeParameters', typeParameters)
        ..addToken('rightBracket', rightBracket);

  @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 ::=
///        [LibraryAugmentationDirective]
///        [ExportDirective]
///      | [ImportDirective]
///      | [PartDirective]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class UriBasedDirective implements Directive {
  /// The URI referenced by this directive.
  StringLiteral get uri;
}

sealed class UriBasedDirectiveImpl extends DirectiveImpl
    implements UriBasedDirective {
  StringLiteralImpl _uri;

  /// Initializes a newly create URI-based directive.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// directive doesn't have the corresponding attribute.
  UriBasedDirectiveImpl({
    required super.comment,
    required super.metadata,
    required StringLiteralImpl uri,
  }) : _uri = uri {
    _becomeParentOf(_uri);
  }

  @override
  StringLiteralImpl get uri => _uri;

  set uri(StringLiteralImpl uri) {
    _uri = _becomeParentOf(uri);
  }

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(visitor);
    _uri.accept(visitor);
  }

  /// Validate this directive, but don't check for existence.
  ///
  /// Returns a code indicating the problem if a problem was found, or `null` if
  /// there's 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;
    }
    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 [UriBasedDirectiveImpl.validateUri].
class UriValidationCode {
  static const UriValidationCode INVALID_URI = UriValidationCode('INVALID_URI');

  static const UriValidationCode URI_WITH_INTERPOLATION = UriValidationCode(
    'URI_WITH_INTERPOLATION',
  );

  /// The name of the validation code.
  final String name;

  /// Initializes 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 ::=
///        name ('=' [Expression])?
// TODO(paulberry): The grammar doesn't 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] doesn't
//  extend [Declaration].
//
// TODO(brianwilkerson): This class represents both declarations that can be
//  augmented and declarations that can't be augmented. This results in getters
//  that are only sometimes applicable. Consider changing the class hierarchy so
//  that these two kinds of variables can be distinguished.
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class VariableDeclaration implements Declaration {
  /// The element declared by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if this node
  /// represents the declaration of a top-level variable or a field.
  @experimental
  LocalVariableElement2? get declaredElement2;

  /// The fragment declared by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if this node
  /// represents the declaration of a local variable.
  @experimental
  @override
  VariableFragment? get declaredFragment;

  /// The equal sign separating the variable name from the initial value, or
  /// `null` if the initial value isn't specified.
  Token? get equals;

  /// The expression used to compute the initial value for the variable, or
  /// `null` if the initial value isn't specified.
  Expression? get initializer;

  /// Whether this variable was declared with the 'const' modifier.
  bool get isConst;

  /// Whether this variable was declared with the 'final' modifier.
  ///
  /// Variables that are declared with the 'const' modifier return `false` even
  /// though they are implicitly final.
  bool get isFinal;

  /// Whether this variable was declared with the 'late' modifier.
  bool get isLate;

  /// The name of the variable being declared.
  Token get name;
}

final class VariableDeclarationImpl extends DeclarationImpl
    implements VariableDeclaration {
  @override
  final Token name;

  @override
  VariableElementImpl? declaredFragment;

  @override
  final Token? equals;

  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;

  /// Initializes a newly created variable declaration.
  ///
  /// The [equals] and [initializer] can be `null` if there's no initializer.
  VariableDeclarationImpl({
    required this.name,
    required this.equals,
    required ExpressionImpl? initializer,
  }) : _initializer = initializer,
       super(comment: null, metadata: null) {
    _becomeParentOf(_initializer);
  }

  @experimental
  @override
  LocalVariableElementImpl2? get declaredElement2 {
    return declaredFragment?.element.ifTypeOrNull<LocalVariableElementImpl2>();
  }

  /// 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 case var initializer?) {
      return initializer.endToken;
    }
    return name;
  }

  @override
  Token get firstTokenAfterCommentAndMetadata => name;

  @override
  ExpressionImpl? get initializer => _initializer;

  set initializer(ExpressionImpl? expression) {
    _initializer = _becomeParentOf(expression);
  }

  @override
  bool get isConst {
    var parent = this.parent;
    return parent is VariableDeclarationList && parent.isConst;
  }

  @override
  bool get isFinal {
    var parent = this.parent;
    return parent is VariableDeclarationList && parent.isFinal;
  }

  @override
  bool get isLate {
    var parent = this.parent;
    return parent is VariableDeclarationList && parent.isLate;
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('name', name)
        ..addToken('equals', equals)
        ..addNode('initializer', initializer);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitVariableDeclaration(this);

  @override
  void visitChildren(AstVisitor visitor) {
    super.visitChildren(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]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class VariableDeclarationList implements AnnotatedNode {
  /// Whether the variables in this list were declared with the 'const'
  /// modifier.
  bool get isConst;

  /// Whether the variables in this list were declared with the 'final'
  /// modifier.
  ///
  /// Variables that are declared with the 'const' modifier return `false` even
  /// though they are implicitly final. (In other words, this is a syntactic
  /// check rather than a semantic check.)
  bool get isFinal;

  /// Whether the variables in this list were declared with the 'late' modifier.
  bool get isLate;

  /// The token representing the `final`, `const` or `var` keyword, or `null` if
  /// no keyword was included.
  Token? get keyword;

  /// The token representing the `late` keyword, or `null` if the late modifier
  /// isn't included.
  Token? get lateKeyword;

  /// The type of the variables being declared, or `null` if no type was
  /// provided.
  TypeAnnotation? get type;

  /// A list containing the individual variables being declared.
  NodeList<VariableDeclaration> get variables;
}

final class VariableDeclarationListImpl extends AnnotatedNodeImpl
    implements VariableDeclarationList {
  @override
  final Token? keyword;

  @override
  final Token? lateKeyword;

  TypeAnnotationImpl? _type;

  final NodeListImpl<VariableDeclarationImpl> _variables = NodeListImpl._();

  /// Initializes a newly created variable declaration list.
  ///
  /// Either or both of the [comment] and [metadata] can be `null` if the
  /// variable list doesn't 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({
    required super.comment,
    required super.metadata,
    required this.lateKeyword,
    required this.keyword,
    required TypeAnnotationImpl? type,
    required List<VariableDeclarationImpl> variables,
  }) : _type = type {
    _becomeParentOf(_type);
    _variables._initialize(this, 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(TypeAnnotationImpl? type) {
    _type = _becomeParentOf(type);
  }

  @override
  NodeListImpl<VariableDeclarationImpl> get variables => _variables;

  @override
  // TODO(paulberry): include commas.
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('lateKeyword', lateKeyword)
        ..addToken('keyword', keyword)
        ..addNode('type', type)
        ..addNodeList('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] ';'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class VariableDeclarationStatement implements Statement {
  /// The semicolon terminating the statement.
  Token get semicolon;

  /// The variables being declared.
  VariableDeclarationList get variables;
}

final class VariableDeclarationStatementImpl extends StatementImpl
    implements VariableDeclarationStatement {
  VariableDeclarationListImpl _variableList;

  @override
  final Token semicolon;

  /// Initializes a newly created variable declaration statement.
  VariableDeclarationStatementImpl({
    required VariableDeclarationListImpl variableList,
    required this.semicolon,
  }) : _variableList = variableList {
    _becomeParentOf(_variableList);
  }

  @override
  Token get beginToken => _variableList.beginToken;

  @override
  Token get endToken => semicolon;

  @override
  VariableDeclarationListImpl get variables => _variableList;

  set variables(VariableDeclarationListImpl variables) {
    _variableList = _becomeParentOf(variables);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addNode('variables', variables)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) =>
      visitor.visitVariableDeclarationStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _variableList.accept(visitor);
  }
}

/// The shared interface of [AssignedVariablePattern] and
/// [DeclaredVariablePattern].
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
sealed class VariablePattern implements DartPattern {
  /// The name of the variable declared or referenced by the pattern.
  Token get name;
}

sealed class VariablePatternImpl extends DartPatternImpl
    implements VariablePattern {
  @override
  final Token name;

  /// If this variable was used to resolve an implicitly named field, the
  /// implicit name node is recorded here for a future use.
  PatternFieldNameImpl? fieldNameWithImplicitName;

  VariablePatternImpl({required this.name});

  @override
  VariablePatternImpl? get variablePattern => this;
}

/// A guard in a pattern-based `case` in a `switch` statement, `switch`
/// expression, `if` statement, or `if` element.
///
///    switchCase ::=
///        'when' [Expression]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class WhenClause implements AstNode {
  /// The condition that is evaluated when the pattern matches, that must
  /// evaluate to `true` in order for the [expression] to be executed.
  Expression get expression;

  /// The `when` keyword.
  Token get whenKeyword;
}

final class WhenClauseImpl extends AstNodeImpl implements WhenClause {
  ExpressionImpl _expression;

  @override
  final Token whenKeyword;

  WhenClauseImpl({
    required this.whenKeyword,
    required ExpressionImpl expression,
  }) : _expression = expression {
    _becomeParentOf(expression);
  }

  @override
  Token get beginToken => whenKeyword;

  @override
  Token get endToken => expression.endToken;

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('whenKeyword', whenKeyword)
        ..addNode('expression', expression);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitWhenClause(this);

  @override
  void visitChildren(AstVisitor visitor) {
    expression.accept(visitor);
  }
}

/// A while statement.
///
///    whileStatement ::=
///        'while' '(' [Expression] ')' [Statement]
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class WhileStatement implements Statement {
  /// The body of the loop.
  Statement get body;

  /// The expression used to determine whether to execute the body of the loop.
  Expression get condition;

  /// The left parenthesis.
  Token get leftParenthesis;

  /// The right parenthesis.
  Token get rightParenthesis;

  /// The token representing the `while` keyword.
  Token get whileKeyword;
}

final class WhileStatementImpl extends StatementImpl implements WhileStatement {
  @override
  final Token whileKeyword;

  @override
  final Token leftParenthesis;

  ExpressionImpl _condition;

  @override
  final Token rightParenthesis;

  StatementImpl _body;

  /// Initializes a newly created while statement.
  WhileStatementImpl({
    required this.whileKeyword,
    required this.leftParenthesis,
    required ExpressionImpl condition,
    required this.rightParenthesis,
    required StatementImpl body,
  }) : _condition = condition,
       _body = body {
    _becomeParentOf(_condition);
    _becomeParentOf(_body);
  }

  @override
  Token get beginToken => whileKeyword;

  @override
  StatementImpl get body => _body;

  set body(StatementImpl statement) {
    _body = _becomeParentOf(statement);
  }

  @override
  ExpressionImpl get condition => _condition;

  set condition(ExpressionImpl expression) {
    _condition = _becomeParentOf(expression);
  }

  @override
  Token get endToken => _body.endToken;

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('whileKeyword', whileKeyword)
        ..addToken('leftParenthesis', leftParenthesis)
        ..addNode('condition', condition)
        ..addToken('rightParenthesis', rightParenthesis)
        ..addNode('body', body);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitWhileStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _condition.accept(visitor);
    _body.accept(visitor);
  }
}

/// A wildcard pattern.
///
///    wildcardPattern ::=
///        ( 'var' | 'final' | 'final'? [TypeAnnotation])? '_'
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class WildcardPattern implements DartPattern {
  /// The `var` or `final` keyword.
  Token? get keyword;

  /// The `_` token.
  Token get name;

  /// The type that the pattern is required to match, or `null` if any type is
  /// matched.
  TypeAnnotation? get type;
}

final class WildcardPatternImpl extends DartPatternImpl
    implements WildcardPattern {
  @override
  final Token? keyword;

  @override
  final Token name;

  @override
  final TypeAnnotationImpl? type;

  WildcardPatternImpl({
    required this.name,
    required this.keyword,
    required this.type,
  }) {
    _becomeParentOf(type);
  }

  @override
  Token get beginToken => type?.beginToken ?? name;

  @override
  Token get endToken => name;

  /// If [keyword] is `final`, returns it.
  Token? get finalKeyword {
    var keyword = this.keyword;
    if (keyword != null && keyword.keyword == Keyword.FINAL) {
      return keyword;
    }
    return null;
  }

  @override
  PatternPrecedence get precedence => PatternPrecedence.primary;

  @override
  ChildEntities get _childEntities =>
      super._childEntities
        ..addToken('keyword', keyword)
        ..addNode('type', type)
        ..addToken('name', name);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitWildcardPattern(this);

  @override
  TypeImpl computePatternSchema(ResolverVisitor resolverVisitor) {
    return resolverVisitor
        .analyzeDeclaredVariablePatternSchema(
          type?.typeOrThrow.wrapSharedTypeView(),
        )
        .unwrapTypeSchemaView();
  }

  @override
  PatternResult resolvePattern(
    ResolverVisitor resolverVisitor,
    SharedMatchContext context,
  ) {
    var declaredType = type?.typeOrThrow;
    var analysisResult = resolverVisitor.analyzeWildcardPattern(
      context: context,
      node: this,
      declaredType: declaredType?.wrapSharedTypeView(),
    );

    if (declaredType != null) {
      resolverVisitor.checkPatternNeverMatchesValueType(
        context: context,
        pattern: this,
        requiredType: declaredType,
        matchedValueType: analysisResult.matchedValueType.unwrapTypeView(),
      );
    }

    return analysisResult;
  }

  @override
  void visitChildren(AstVisitor visitor) {
    type?.accept(visitor);
  }
}

/// The with clause in a class declaration.
///
///    withClause ::=
///        'with' [NamedType] (',' [NamedType])*
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class WithClause implements AstNode {
  /// The names of the mixins that were specified.
  NodeList<NamedType> get mixinTypes;

  /// The token representing the `with` keyword.
  Token get withKeyword;
}

final class WithClauseImpl extends AstNodeImpl implements WithClause {
  @override
  final Token withKeyword;

  final NodeListImpl<NamedTypeImpl> _mixinTypes = NodeListImpl._();

  /// Initializes a newly created with clause.
  WithClauseImpl({
    required this.withKeyword,
    required List<NamedTypeImpl> mixinTypes,
  }) {
    _mixinTypes._initialize(this, mixinTypes);
  }

  @override
  Token get beginToken => withKeyword;

  @override
  Token get endToken => _mixinTypes.endToken ?? withKeyword;

  @override
  NodeListImpl<NamedTypeImpl> get mixinTypes => _mixinTypes;

  @override
  // TODO(paulberry): add commas.
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('withKeyword', withKeyword)
        ..addNodeList('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] ‘;’
@AnalyzerPublicApi(message: 'exported by lib/dart/ast/ast.dart')
abstract final class YieldStatement implements Statement {
  /// The expression whose value is yielded.
  Expression get expression;

  /// The semicolon following the expression.
  Token get semicolon;

  /// The star optionally following the `yield` keyword.
  Token? get star;

  /// The `yield` keyword.
  Token get yieldKeyword;
}

final class YieldStatementImpl extends StatementImpl implements YieldStatement {
  @override
  final Token yieldKeyword;

  @override
  final Token? star;

  ExpressionImpl _expression;

  @override
  final Token semicolon;

  /// Initializes a newly created yield expression.
  ///
  /// The [star] can be `null` if no star was provided.
  YieldStatementImpl({
    required this.yieldKeyword,
    required this.star,
    required ExpressionImpl expression,
    required this.semicolon,
  }) : _expression = expression {
    _becomeParentOf(_expression);
  }

  @override
  Token get beginToken {
    return yieldKeyword;
  }

  @override
  Token get endToken {
    return semicolon;
  }

  @override
  ExpressionImpl get expression => _expression;

  set expression(ExpressionImpl expression) {
    _expression = _becomeParentOf(expression);
  }

  @override
  ChildEntities get _childEntities =>
      ChildEntities()
        ..addToken('yieldKeyword', yieldKeyword)
        ..addToken('star', star)
        ..addNode('expression', expression)
        ..addToken('semicolon', semicolon);

  @override
  E? accept<E>(AstVisitor<E> visitor) => visitor.visitYieldStatement(this);

  @override
  void visitChildren(AstVisitor visitor) {
    _expression.accept(visitor);
  }
}

/// Mixin implementing shared functionality for AST nodes that can have optional
/// annotations and an optional documentation comment.
base mixin _AnnotatedNodeMixin on AstNodeImpl implements AnnotatedNode {
  CommentImpl? _comment;

  final NodeListImpl<AnnotationImpl> _metadata = NodeListImpl._();

  @override
  CommentImpl? get documentationComment => _comment;

  set documentationComment(CommentImpl? comment) {
    _comment = _becomeParentOf(comment);
  }

  /// The first token following the comment and metadata.
  @override
  Token get firstTokenAfterCommentAndMetadata;

  @override
  NodeListImpl<AnnotationImpl> get metadata => _metadata;

  @override
  List<AstNode> get sortedCommentAndAnnotations {
    var comment = _comment;
    return <AstNode>[if (comment != null) comment, ..._metadata]
      ..sort(AstNode.LEXICAL_ORDER);
  }

  @override
  @mustCallSuper
  ChildEntities get _childEntities {
    return ChildEntities()
      ..addNode('documentationComment', documentationComment)
      ..addNodeList('metadata', metadata);
  }

  /// Returns `true` if there are no annotations before the comment.
  ///
  /// Note that a result of `true` doesn't imply that there's 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;
  }

  /// Initializes the comment and metadata pointed to by this node.
  ///
  /// Intended to be called from the constructor.
  void _initializeCommentAndAnnotations(
    CommentImpl? comment,
    List<AnnotationImpl>? metadata,
  ) {
    _comment = _becomeParentOf(comment);
    _metadata._initialize(this, metadata);
  }

  /// Visits the AST nodes associated with [documentationComment] and
  /// [metadata] (if any).
  ///
  /// Intended to be called from the [AstNode.visitChildren] method.
  void _visitCommentAndAnnotations(AstVisitor<dynamic> 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);
      }
    }
  }
}

/// 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 hasn't yet been
  ///   performed, or
  /// - the literal is invalid because resolution isn't able to resolve the
  ///   ambiguity.
  unresolved,
}
