// 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.

// ignore_for_file: analyzer_use_new_elements

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/member.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/element.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
  ChildEntities get _childEntities {
    return ChildEntities()
      ..addNode('documentationComment', documentationComment)
      ..addNodeList('metadata', metadata);
  }

  @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, or `null` if the AST
  /// structure hasn't been resolved or if this annotation couldn't be resolved.
  Element? get element;

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

  Element? _element;

  @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
  Element? get element {
    if (_element case var element?) {
      return element;
    } else if (_constructorName == null) {
      return _name.staticElement;
    }
    return null;
  }

  set element(Element? element) {
    _element = element;
  }

  @experimental
  @override
  Element2? get element2 {
    return element?.asElement2;
  }

  set element2(Element2? value) {
    element = value?.asElement;
  }

  @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<ParameterElementMixin?>? _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<ParameterElementMixin?>? get correspondingStaticParameters =>
      _correspondingStaticParameters;

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

  List<FormalParameterElement?>? get correspondingStaticParameters2 =>
      _correspondingStaticParameters
          ?.map((parameter) => parameter?.asElement2)
          .toList();

  @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
  ParameterElementMixin? _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, or `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 [LocalVariableElement] or a
  /// [ParameterElement].
  Element? get element;

  /// 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
  Element? element;

  AssignedVariablePatternImpl({
    required super.name,
  });

  @override
  Token get beginToken => name;

  @experimental
  @override
  Element2? get element2 {
    return element.asElement2;
  }

  @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
  MethodElement? staticElement;

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

  @experimental
  @override
  MethodElement2? get element => staticElement?.asElement2;

  set element(MethodElement2? element) {
    staticElement = element?.asElement;
  }

  @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.
  ParameterElementMixin? get _staticParameterElementForRightHandSide {
    Element? executableElement;
    if (operator.type != TokenType.EQ) {
      executableElement = staticElement;
    } else {
      executableElement = writeElement;
    }

    if (executableElement is ExecutableElement) {
      List<ParameterElement> parameters = executableElement.parameters;
      if (parameters.isEmpty) {
        return null;
      }
      if (operator.type == TokenType.EQ && leftHandSide is IndexExpression) {
        return parameters.length == 2
            ? (parameters[1] as ParameterElementMixin)
            : null;
      }
      return parameters[0] as ParameterElementMixin;
    }

    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? 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 [element] 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 [element] 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 [element] 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 [element] is the augmented [MethodElement].
/// The [staticType] is the type of `this`.
///
/// Augmenting index operators: `augmented` must be the index target,
/// e.g. `augmented[0]`.
/// The [element] is the augmented [MethodElement].
/// The [staticType] is the type of `this`.
///
/// Augmenting prefix operators: `augmented` must be the target, e.g.
/// `~augmented`.
/// The [element] is the augmented [MethodElement].
/// 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 element: getter, setter, variable.
  Element? get element;

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

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

  @override
  Element? element;

  AugmentedExpressionImpl({
    required this.augmentedKeyword,
  });

  @override
  Token get beginToken => augmentedKeyword;

  @override
  Token get endToken => augmentedKeyword;

  @experimental
  @override
  Fragment? get fragment => element as Fragment?;

  set fragment(Fragment? value) {
    element = value as Element?;
  }

  @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.
  ExecutableElement? get element;

  /// 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.
  // TODO(brianwilkerson): Consider resolving this to a fragment rather than an
  //  element. In this case I think that's closer to the right semantics.
  @experimental
  ExecutableElement2? get element2;

  /// 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
  ExecutableElement? element;

  @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;

  @experimental
  @override
  ExecutableElement2? get element2 => (element as ExecutableFragment?)?.element;

  @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
  MethodElement? staticElement;

  @override
  FunctionType? 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;

  @experimental
  @override
  MethodElement2? get element => staticElement?.asElement2;

  set element(MethodElement2? value) {
    staticElement = value?.asElement;
  }

  @override
  Token get endToken => _rightOperand.endToken;

  set fragment(MethodFragment? value) {
    staticElement = value as MethodElement;
  }

  @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
  DartType 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 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, or `null` if the AST hasn't been resolved.
  LocalVariableElement? get declaredElement;

  /// The declared element.
  ///
  /// Returns `null` if the AST hasn't been resolved.
  @experimental
  LocalVariableElement2? get declaredElement2;

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

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

  @override
  LocalVariableElementImpl? declaredElement;

  CatchClauseParameterImpl({
    required this.name,
  });

  @override
  Token get beginToken => name;

  @experimental
  @override
  LocalVariableElementImpl2? get declaredElement2 {
    return declaredElement.asElement2 as LocalVariableElementImpl2?;
  }

  @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;

  @override
  ClassElement? get declaredElement;

  @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? declaredElement;

  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);
  }

  @experimental
  @override
  ClassElementImpl? get declaredFragment => declaredElement;

  @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;

  @override
  ClassElement? get declaredElement;

  @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? declaredElement;

  /// 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);
  }

  @experimental
  @override
  ClassElementImpl? get declaredFragment => declaredElement;

  @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 element associated with this compilation unit, or `null` if the AST
  /// structure hasn't been resolved.
  CompilationUnitElement? get declaredElement;

  /// 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
  Token beginToken;

  ScriptTagImpl? _scriptTag;

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

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

  @override
  final Token endToken;

  @override
  CompilationUnitElementImpl? declaredElement;

  @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;

  @experimental
  @override
  CompilationUnitElementImpl? get declaredFragment {
    return declaredElement;
  }

  @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, or `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 [LocalVariableElement], a
  /// [ParameterElement], or a [PropertyAccessorElement] getter.
  ///
  /// In invalid code this element is `null`. For example, in `int += 2`, for
  /// recovery purposes, [writeElement] is filled, and can be used for
  /// navigation.
  Element? get readElement;

  /// 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, [writeElement] is filled, and can be
  /// used for navigation.
  @experimental
  Element2? get readElement2;

  /// The type of the value read with the [readElement], 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, or `null` if the AST
  /// structure hasn't been resolved, or if the target couldn't be resolved.
  ///
  /// In valid code this is a [LocalVariableElement], [ParameterElement], or a
  /// [PropertyAccessorElement] setter.
  ///
  /// In invalid code, for recovery, we might use other elements, for example a
  /// [PropertyAccessorElement] getter `myGetter = 0` even though the getter
  /// can't be used to write 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, e. g. `x += 2`, both [readElement]
  /// and [writeElement] could be non-`null`.
  Element? get writeElement;

  /// 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
  /// [readElement] and [writeElement] 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
  Element? readElement;

  @override
  Element? writeElement;

  @override
  TypeImpl? readType;

  @override
  TypeImpl? writeType;

  @experimental
  @override
  Element2? get readElement2 {
    if (readElement is Fragment) {
      return (readElement as Fragment).element;
    } else if (readElement is Element2) {
      return readElement as Element2;
    }
    return null;
  }

  @experimental
  @override
  Element2? get writeElement2 => writeElement.asElement2;
}

/// 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 Element 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;

  @override
  ConstructorElement? get declaredElement;

  @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.
  ///
  /// This can be different than the type in which the constructor is being
  /// declared if the constructor is the implementation of a factory
  /// constructor.
  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? declaredElement;

  /// 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);
  }

  @experimental
  @override
  ConstructorElementImpl? get declaredFragment =>
      declaredElement as ConstructorElementImpl;

  @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
  ConstructorElement? staticElement;

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

  @experimental
  @override
  ConstructorElement2? get element => staticElement?.asElement2;

  set element(ConstructorElement2? element) {
    staticElement = element?.asElement;
  }

  @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 element associated with the referenced constructor based on static
  /// type information, or `null` if the AST structure hasn't been resolved or
  /// if the constructor couldn't be resolved.
  ConstructorElement? get staticElement;
}

/// 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 element associated with this declaration, or `null` if either this
  /// node corresponds to a list of declarations or if the AST structure hasn't
  /// been resolved.
  Element? get declaredElement;

  /// 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 {
  @override
  LocalVariableElement? get declaredElement;

  /// 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? declaredElement;

  /// 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 declaredElement.asElement2 as LocalVariableElementImpl2?;
  }

  @override
  LocalVariableFragment? get declaredFragment => declaredElement;

  @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 associated with this declaration, or `null` if the AST
  /// structure hasn't been resolved.
  BindPatternVariableElement? get declaredElement;

  /// The element declared by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved.
  @experimental
  BindPatternVariableElement2? get declaredElement2;

  /// 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? declaredElement;

  @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 declaredElement?.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!,
        declaredElement!.name,
        type?.typeOrThrow.wrapSharedTypeView());
    declaredElement!.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;

  @override
  ParameterElementImpl? get declaredElement => _parameter.declaredElement;

  @experimental
  @override
  FormalParameterFragment? 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 {
  /// The element associated with this directive, or `null` if the AST structure
  /// hasn't been resolved or if this directive couldn't be resolved.
  Element? get element;
}

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,
  });

  @override
  ElementImpl? get element => _element;

  set element(ElementImpl? element) {
    _element = element;
  }
}

/// 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 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
  DartType 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 is invoked by this enum constant, or `null` if the
  /// AST structure hasn't been resolved, or if the constructor couldn't be
  /// resolved.
  ConstructorElement? get constructorElement;

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

  @override
  FieldElement? get declaredElement;

  @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? declaredElement;

  @override
  final EnumConstantArgumentsImpl? arguments;

  @override
  ConstructorElement? constructorElement;

  /// 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);
  }

  @experimental
  @override
  ConstructorElement2? get constructorElement2 =>
      constructorElement?.asElement2;

  @experimental
  @override
  FieldFragment? get declaredFragment => declaredElement as FieldFragment?;

  @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;

  @override
  EnumElement? get declaredElement;

  @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? declaredElement;

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

  @experimental
  @override
  EnumElementImpl? get declaredFragment => declaredElement;

  @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 element associated with this directive, or `null` if the AST structure
  /// hasn't been resolved.
  @override
  LibraryExportElement? get element;

  /// 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
  LibraryExportElementImpl? get element {
    return super.element as LibraryExportElementImpl?;
  }

  @override
  Token get firstTokenAfterCommentAndMetadata => exportKeyword;

  @experimental
  @override
  LibraryExport? get libraryExport => element as LibraryExport?;

  @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 parameter element representing the parameter to which the value of
  /// this expression is bound, or `null` if any of these conditions are not
  /// `true`
  /// - this expression is an argument to an invocation
  /// - the AST structure is 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
  ParameterElement? get staticParameterElement;

  /// 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
  DartType 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
  FormalParameterElement? get correspondingParameter {
    return switch (staticParameterElement) {
      FormalParameterFragment(:var element) => element,
      ParameterMember member => member,
      _ => null,
    };
  }

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

  @override
  bool get isAssignable => false;

  @override
  ParameterElementMixin? get staticParameterElement {
    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?.parameters;
        if (parameters != null && parameters.isNotEmpty) {
          // TODO(paulberry): eliminate this cast by changing the type of
          // `BinaryExpressionImpl.staticInvokeType` to `FunctionTypeImpl`.
          return parameters[0] as ParameterElementMixin;
        }
        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._staticParameterElementForOperand;
    } else if (parent is PostfixExpressionImpl) {
      // TODO(scheglov): The same as above.
      return parent._staticParameterElementForOperand;
    }
    return null;
  }

  @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 IfElement():
        case ForElement():
        case MapLiteralEntry():
        case SpreadElement():
        case NullAwareElement():
        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;

  @override
  ExtensionElement? get declaredElement;

  @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? declaredElement;

  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);
  }

  @experimental
  @override
  ExtensionElementImpl? get declaredFragment => declaredElement;

  @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 => 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 forced extension element.
  ExtensionElement get element;

  /// 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
  DartType? 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
  ExtensionElementImpl get element =>
      element2.firstFragment;

  @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;

  @override
  ExtensionTypeElement? get declaredElement;

  @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? declaredElement;

  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);
  }

  @experimental
  @override
  ExtensionTypeElementImpl? get declaredFragment => declaredElement;

  @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
  Element? get declaredElement => null;

  @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 {
  /// The token representing the `await` keyword, or `null` if there was no
  /// `await` keyword.
  Token? get awaitKeyword;

  /// The body of the loop.
  CollectionElement 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;
}

final class ForElementImpl extends CollectionElementImpl
    with AstNodeWithNameScopeMixin
    implements ForElement {
  @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);
  }
}

/// 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 {}

sealed class ForLoopPartsImpl extends AstNodeImpl implements ForLoopParts {}

/// 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 element representing this parameter, or `null` if this parameter
  /// hasn't been resolved.
  ParameterElement? get declaredElement;

  ///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 {
  @override
  ParameterElementImpl? declaredElement;

  @experimental
  @override
  FormalParameterFragment? get declaredFragment =>
      declaredElement as FormalParameterFragment?;

  @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 elements representing the parameters in this list.
  ///
  /// The list contains `null`s if the parameters in this list haven't been
  /// resolved.
  List<ParameterElement?> get parameterElements;

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

  @override
  List<ParameterElement?> get parameterElements {
    int count = _parameters.length;
    var types = <ParameterElement?>[];
    for (int i = 0; i < count; i++) {
      types.add(_parameters[i].declaredElement);
    }
    return types;
  }

  @experimental
  @override
  List<FormalParameterFragment?> get parameterFragments =>
      parameterElements.cast<FormalParameterFragment?>();

  @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 {
  /// The token representing the `await` keyword, or `null` if there's no
  /// `await` keyword.
  Token? get awaitKeyword;

  /// The body of the loop.
  Statement 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;
}

final class ForStatementImpl extends StatementImpl
    with AstNodeWithNameScopeMixin
    implements ForStatement {
  @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.
  bool isPotentiallyMutatedInScope(VariableElement variable);

  /// 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 isPotentiallyMutatedInScope(VariableElement variable) {
    if (localVariableInfo == null) {
      throw StateError('Resolution has not been performed');
    }
    return localVariableInfo!.potentiallyMutatedInScope.contains(variable);
  }

  @experimental
  @override
  bool isPotentiallyMutatedInScope2(VariableElement2 variable) {
    return switch (variable) {
      LocalVariableElementImpl2() =>
        isPotentiallyMutatedInScope(variable.wrappedElement),
      VariableElement() =>
        isPotentiallyMutatedInScope(variable as VariableElement),
      FormalParameterElement(:VariableElement firstFragment) =>
        isPotentiallyMutatedInScope(firstFragment),
      _ => false,
    };
  }

  /// 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.
  DartType 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 element defined by this declaration.
  ///
  /// Returns `null` if the AST structure hasn't been resolved or if this node
  /// represents a top-level function.
  @override
  ExecutableElement? get declaredElement;

  /// 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? declaredElement;

  /// 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);
  }

  @experimental
  @override
  ExecutableElementImpl? get declaredFragment {
    return declaredElement;
  }

  @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 element associated with the function, or `null` if the AST structure
  /// hasn't been resolved.
  ExecutableElement? get declaredElement;

  /// 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? declaredElement;

  @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;

  /// The element associated with the function being invoked based on static
  /// type information, or `null` if the AST structure hasn't been resolved or
  /// the function couldn't be resolved.
  ExecutableElement? get staticElement;
}

final class FunctionExpressionInvocationImpl extends InvocationExpressionImpl
    with NullShortableExpressionImpl
    implements FunctionExpressionInvocation {
  ExpressionImpl _function;

  @override
  ExecutableElement? staticElement;

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

  @experimental
  @override
  ExecutableElement2? get element {
    return staticElement?.asElement2;
  }

  @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<DartType>? 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 {
  @override
  TypeAliasElement? get declaredElement;

  @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? declaredElement;

  /// 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);
  }

  @experimental
  @override
  TypeAliasElementImpl? get declaredFragment => declaredElement;

  @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 `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.
  GenericFunctionTypeElementImpl? declaredElement;

  /// 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? declaredElement;

  /// 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);
  }

  @experimental
  @override
  TypeAliasElementImpl? get declaredFragment => declaredElement;

  @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 => ChildEntities()
    ..addNodeList('metadata', metadata)
    ..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;

  /// 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. One example of the latter case is an
  /// identifier that isn't defined within the scope in which it appears.
  Element? get staticElement;

  /// 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 {
  @experimental
  @override
  Element2? get element {
    return staticElement.asElement2;
  }

  @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 element associated with the implicit `call` reference based on the
  /// static types.
  @override
  MethodElement get staticElement;

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

  @experimental
  @override
  MethodElement get staticElement => element.asElement;

  @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 element associated with this directive, or `null` if the AST structure
  /// hasn't been resolved.
  @override
  LibraryImportElement? get element;

  /// 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
  LibraryImportElementImpl? get element =>
      super.element as LibraryImportElementImpl?;

  @override
  Token get firstTokenAfterCommentAndMetadata => importKeyword;

  @experimental
  @override
  LibraryImport? get libraryImport => element as LibraryImport?;

  @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 [PrefixElement], but can be anything in invalid code.
  Element? get element;

  /// 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
  Element? element;

  ImportPrefixReferenceImpl({
    required this.name,
    required this.period,
  });

  @override
  Token get beginToken => name;

  @experimental
  @override
  Element2? get element2 {
    return element?.asElement2;
  }

  set element2(Element2? value) {
    element = value?.asElement;
  }

  @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
  MethodElement? staticElement;

  /// 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!;
  }

  @experimental
  @override
  MethodElement2? get element => staticElement?.asElement2;

  @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.
  ParameterElementMixin? get _staticParameterElementForIndex {
    Element? element = staticElement;

    var parent = this.parent;
    if (parent is CompoundAssignmentExpression) {
      element = parent.writeElement ?? parent.readElement;
    }

    if (element is ExecutableElementOrMember) {
      List<ParameterElement> parameters = element.parameters;
      if (parameters.isEmpty) {
        return null;
      }
      // TODO(paulberry): eliminate this cast by changing the type of
      // `ExecutableElementOrMember.parameters` to
      // `List<ParameterElementMixin>`.
      return parameters[0] as ParameterElementMixin;
    }
    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] or a
/// [MethodInvocation].
@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<DartType>? typeArgumentTypes;

  @override
  DartType? 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 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
  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 {
  @override
  LibraryElement? get element;

  /// 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);
  }

  @override
  LibraryElementImpl? get element {
    return super.element as LibraryElementImpl?;
  }

  @experimental
  @override
  LibraryElement2? get element2 => element as LibraryElement2?;

  @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
  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
  Element? get staticElement => null;

  @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]
///      | [SetOrMapLiteral]
///      | [StringLiteral]
@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<VariableElement> potentiallyMutatedInScope = <VariableElement>{};
}

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

  @override
  ExecutableElement? get declaredElement;

  @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? declaredElement;

  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);
  }

  @experimental
  @override
  ExecutableElementImpl? get declaredFragment => declaredElement;

  @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
    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 [MethodElement], this is the same as the
  /// [staticInvokeType].
  ///
  /// If the target element is a getter, presumably returning an
  /// [ExecutableElement] so that it can be invoked in this [MethodInvocation],
  /// then this type is the type of the getter, and the [staticInvokeType] is
  /// the invoked type of the returned element.
  DartType? get methodNameType => _methodNameType ?? staticInvokeType;

  set 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 element associated with the expression based on the static types, or
  /// `null` if the AST structure hasn't been resolved, or there's no meaningful
  /// static 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.
  MethodElement? get staticElement;
}

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

  @override
  MixinElement? get declaredElement;

  @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? declaredElement;

  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);
  }

  @experimental
  @override
  MixinElementImpl? get declaredFragment => declaredElement;

  @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, or
  /// `null` if the AST structure hasn't been resolved or if there's no
  /// parameter with the same name as this expression.
  ParameterElement? get element;

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

  @override
  ParameterElement? get element {
    var element = _name.label.staticElement;
    if (element is ParameterElement) {
      return element;
    }
    return null;
  }

  @experimental
  @override
  FormalParameterElement? get element2 {
    return element?.asElement2;
  }

  @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] for example a
  /// [ClassElement], or [TypeAliasElement], or `null` if [name2] can't be
  /// resolved, or there's no element for the type name, such as for `void`.
  Element? get element;

  /// The element of [name2] considering [importPrefix].
  ///
  /// This could be a [ClassElement], [TypeAliasElement], 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
  Element? get element {
    return element2.asElement;
  }

  @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?.element;
    if (importPrefixElement is PrefixElement) {
      var imports = importPrefixElement.imports;
      if (imports.length != 1) {
        return false;
      }
      return imports[0].prefix is DeferredImportElementPrefix;
    }
    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
  DartType 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 ChildEntities()
      ..addNode('documentationComment', documentationComment)
      ..addNodeList('metadata', metadata)
      ..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;

  @override
  PartElement? get element;

  /// 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
  PartElementImpl? get element {
    return super.element as PartElementImpl?;
  }

  @override
  Token get endToken => semicolon;

  @override
  Token get firstTokenAfterCommentAndMetadata => partKeyword;

  @experimental
  @override
  PartInclude? get partInclude => element as PartInclude?;

  @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], or `null` if not resolved yet,
  /// non-`null` inside valid [ObjectPattern]s, always `null` inside
  /// [RecordPattern]s.
  Element? get element;

  /// 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
  Element? element;

  @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;
  }

  @experimental
  @override
  Element2? get element2 {
    var element = this.element;
    if (element case Fragment fragment) {
      return fragment.element;
    } else if (element case Element2 element) {
      return element;
    }
    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 expression computing the operand for the operator.
  Expression get operand;

  /// The postfix operator being applied to the operand.
  Token get operator;

  /// 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
  MethodElement? get staticElement;
}

final class PostfixExpressionImpl extends ExpressionImpl
    with NullShortableExpressionImpl, CompoundAssignmentExpressionImpl
    implements PostfixExpression {
  ExpressionImpl _operand;

  @override
  final Token operator;

  @override
  MethodElement? staticElement;

  /// Initializes a newly created postfix expression.
  PostfixExpressionImpl({
    required ExpressionImpl operand,
    required this.operator,
  }) : _operand = operand {
    _becomeParentOf(_operand);
  }

  @override
  Token get beginToken => _operand.beginToken;

  @experimental
  @override
  MethodElement2? get element => staticElement?.asElement2;

  set element(MethodElement2? value) {
    staticElement = value?.asElement;
  }

  @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.
  ParameterElementMixin? get _staticParameterElementForOperand {
    if (staticElement == null) {
      return null;
    }
    List<ParameterElement> parameters = staticElement!.parameters;
    if (parameters.isEmpty) {
      return null;
    }
    // TODO(paulberry): eliminate this cast by changing the type of
    // `staticElement` to `MethodElementOrMember?`.
    return parameters[0] as ParameterElementMixin;
  }

  @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
  Token get endToken => _identifier.endToken;

  @override
  SimpleIdentifierImpl get identifier => _identifier;

  set identifier(SimpleIdentifierImpl identifier) {
    _identifier = _becomeParentOf(identifier);
  }

  @override
  bool get isDeferred {
    Element? element = _prefix.staticElement;
    if (element is PrefixElement) {
      var imports = element.imports;
      if (imports.length != 1) {
        return false;
      }
      return imports[0].prefix is DeferredImportElementPrefix;
    }
    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
  Element? get staticElement {
    return _identifier.staticElement;
  }

  @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
  MethodElement? staticElement;

  /// 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
  MethodElement? staticElement;

  /// Initializes a newly created prefix expression.
  PrefixExpressionImpl({
    required this.operator,
    required ExpressionImpl operand,
  }) : _operand = operand {
    _becomeParentOf(_operand);
  }

  @override
  Token get beginToken => operator;

  @experimental
  @override
  MethodElement2? get element => staticElement?.asElement2;

  set element(MethodElement2? element) {
    staticElement = element?.asElement;
  }

  @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.
  ParameterElementMixin? get _staticParameterElementForOperand {
    if (staticElement == null) {
      return null;
    }
    List<ParameterElement> parameters = staticElement!.parameters;
    if (parameters.isEmpty) {
      return null;
    }
    // TODO(paulberry): eliminate this cast by changing the type of
    // `staticElement` to `MethodElementOrMember?`.
    return parameters[0] as ParameterElementMixin;
  }

  @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
    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 element associated with the constructor based on static type
  /// information, or `null` if the AST structure hasn't been resolved or if the
  /// constructor couldn't be resolved.
  @override
  ConstructorElement? get staticElement;

  /// 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
  ConstructorElement? staticElement;

  /// 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);
  }

  @experimental
  @override
  ConstructorElement2? get element => staticElement?.asElement2;

  set element(ConstructorElement2? value) {
    staticElement = value?.asElement;
  }

  @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.
  MethodElement? get element;

  /// 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
  MethodElement? element;

  RelationalPatternImpl({
    required this.operator,
    required ExpressionImpl operand,
  }) : _operand = operand {
    _becomeParentOf(operand);
  }

  @override
  Token get beginToken => operator;

  @experimental
  @override
  MethodElement2? get element2 {
    if (element case MethodFragment fragment) {
      return fragment.element;
    }
    return null;
  }

  @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 element of the primary constructor.
  ConstructorElement? get constructorElement;

  /// 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 element for [fieldName] with [fieldType].
  FieldElement? get fieldElement;

  /// 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? constructorElement;

  @override
  final Token leftParenthesis;

  @override
  final NodeListImpl<AnnotationImpl> fieldMetadata = NodeListImpl._();

  @override
  final TypeAnnotationImpl fieldType;

  @override
  final Token fieldName;

  @override
  FieldElementImpl? fieldElement;

  @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;

  @experimental
  @override
  ConstructorFragment? get constructorFragment =>
      constructorElement as ConstructorFragment?;

  @override
  Token get endToken => rightParenthesis;

  @experimental
  @override
  FieldFragment? get fieldFragment => fieldElement as FieldFragment?;

  @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 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.
  Element? _staticElement;

  @override
  List<DartType>? 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;

  set element(Element2? element) {
    staticElement = element?.asElement;
  }

  @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;

  /// The element being referenced by this identifier, or `null` if this
  /// identifier is used to either read or write a value, the AST structure
  /// hasn't been resolved, or if this identifier couldn't be resolved.
  ///
  /// This element is set when this identifier is used not as an expression,
  /// but just to reference some element.
  ///
  /// Examples are the name of the type in a [NamedType], the name of the method
  /// in a [MethodInvocation], the name of the constructor in a
  /// [ConstructorName], the name of the property in a [PropertyAccess], the
  /// prefix and the identifier in a [PrefixedIdentifier] (which then can be
  /// used to read or write a value).
  ///
  /// In invalid code, for recovery, any element could be used. For example, in
  /// `set mySetter(_) {} mySetter topVar;` a setter is used as a type name. We
  /// do this to help the user to navigate to this element, and maybe change its
  /// name, add a new declaration, etc.
  ///
  /// If either [readElement] or [writeElement] aren't `null`, the
  /// [referenceElement] is `null`, because the identifier is being used to
  /// read or write a value.
  ///
  /// All three of [readElement], [writeElement], and [referenceElement] can be
  /// `null` when the AST structure hasn't been resolved, or this identifier
  /// couldn't be resolved.
  Element? get referenceElement => null;

  @override
  Element? get staticElement => _staticElement;

  set staticElement(Element? element) {
    _staticElement = element;
  }

  @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
  ConstructorElement? staticElement;

  /// 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);
  }

  @experimental
  @override
  ConstructorElement2? get element => staticElement?.asElement2;

  set element(ConstructorElement2? value) {
    staticElement = value?.asElement;
  }

  @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
  Element? get declaredElement => null;

  @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;

  @override
  TypeParameterElement? get declaredElement;

  @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? declaredElement;

  /// 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);
  }

  @experimental
  @override
  TypeParameterElementImpl? get declaredFragment => declaredElement;

  @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.
  @override
  VariableElement? get declaredElement;

  /// 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? declaredElement;

  @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
  LocalVariableElement2? get declaredElement2 {
    return declaredElement.asElement2.ifTypeOrNull<LocalVariableElement2>();
  }

  @experimental
  @override
  VariableElementImpl? get declaredFragment {
    return declaredElement;
  }

  /// 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;
  }

  DartType get type {
    if (declaredElement2 case var declaredElement?) {
      return declaredElement.type;
    }
    // SAFETY: The variable declaration is either a local variable,
    // of a fragment of: top-level, field, formal parameter.
    return declaredFragment!.element.type;
  }

  @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);
  }

  /// 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
}
