// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:_fe_analyzer_shared/src/parser/async_modifier.dart';
import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
import 'package:_fe_analyzer_shared/src/scanner/error_token.dart'
    show ErrorToken;
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
    show ScannerConfiguration, ScannerResult, scanString;
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart' show CompilationUnitImpl;
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/fasta/ast_builder.dart';
import 'package:analyzer/src/generated/parser.dart' as analyzer;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/string_source.dart';
import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
import 'package:pub_semver/src/version.dart';
import 'package:test/test.dart';

import 'parser_fasta_listener.dart';
import 'test_support.dart';

/// Abstract base class for parser tests, which does not make assumptions about
/// which parser is used.
abstract class AbstractParserTestCase implements ParserTestHelpers {
  bool get allowNativeClause;

  set allowNativeClause(bool value);

  /// Set a flag indicating whether the parser should parse instance creation
  /// expressions that lack either the `new` or `const` keyword.
  set enableOptionalNewAndConst(bool value);

  /// Set a flag indicating whether the parser is to parse part-of directives
  /// that specify a URI rather than a library name.
  set enableUriInPartOf(bool value);

  /// The error listener to which scanner and parser errors will be reported.
  ///
  /// This field is typically initialized by invoking [createParser].
  GatheringErrorListener get listener;

  /// Get the parser used by the test.
  ///
  /// Caller must first invoke [createParser].
  analyzer.Parser get parser;

  /// Assert that the number and codes of errors occurred during parsing is the
  /// same as the [expectedErrorCodes].
  void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes);

  /// Asserts that no errors occurred during parsing.
  void assertNoErrors();

  /// Prepares to parse using tokens scanned from the given [content] string.
  ///
  /// [expectedEndOffset] is the expected offset of the next token to be parsed
  /// after the parser has finished parsing,
  /// or `null` (the default) if EOF is expected.
  /// In general, the analyzer tests do not assert that the last token is EOF,
  /// but the fasta parser adapter tests do assert this.
  /// For any analyzer test where the last token is not EOF, set this value.
  /// It is ignored when not using the fasta parser.
  void createParser(
    String content, {
    int expectedEndOffset,
    FeatureSet featureSet,
  });

  ExpectedError expectedError(ErrorCode code, int offset, int length);

  void expectNotNullIfNoErrors(Object result);

  Expression parseAdditiveExpression(String code);

  Expression parseAssignableExpression(String code, bool primaryAllowed);

  Expression parseAssignableSelector(String code, bool optional,
      {bool allowConditional = true});

  AwaitExpression parseAwaitExpression(String code);

  Expression parseBitwiseAndExpression(String code);

  Expression parseBitwiseOrExpression(String code);

  Expression parseBitwiseXorExpression(String code);

  Expression parseCascadeSection(String code);

  CommentReference? parseCommentReference(
      String referenceSource, int sourceOffset);

  CompilationUnit parseCompilationUnit(String source,
      {List<ErrorCode> codes, List<ExpectedError> errors});

  ConditionalExpression parseConditionalExpression(String code);

  Expression parseConstExpression(String code);

  ConstructorInitializer parseConstructorInitializer(String code);

  /// Parse the given source as a compilation unit.
  ///
  /// @param source the source to be parsed
  /// @param errorCodes the error codes of the errors that are expected to be
  ///          found
  /// @return the compilation unit that was parsed
  /// @throws Exception if the source could not be parsed, if the compilation
  ///           errors in the source do not match those that are expected, or if
  ///           the result would have been `null`
  CompilationUnit parseDirectives(String source,
      [List<ErrorCode> errorCodes = const <ErrorCode>[]]);

  BinaryExpression parseEqualityExpression(String code);

  Expression parseExpression(String source,
      {List<ErrorCode> codes,
      List<ExpectedError> errors,
      int expectedEndOffset});

  List<Expression> parseExpressionList(String code);

  Expression parseExpressionWithoutCascade(String code);

  FormalParameter parseFormalParameter(String code, ParameterKind kind,
      {List<ErrorCode> errorCodes = const <ErrorCode>[]});

  FormalParameterList parseFormalParameterList(String code,
      {bool inFunctionType = false,
      List<ErrorCode> errorCodes = const <ErrorCode>[],
      List<ExpectedError> errors});

  /// Parses a single top level member of a compilation unit (other than a
  /// directive), including any comment and/or metadata that precedes it.
  CompilationUnitMember parseFullCompilationUnitMember();

  /// Parses a single top level directive, including any comment and/or metadata
  /// that precedes it.
  Directive parseFullDirective();

  FunctionExpression parseFunctionExpression(String code);

  InstanceCreationExpression parseInstanceCreationExpression(
      String code, Token newToken);

  ListLiteral parseListLiteral(
      Token token, String typeArgumentsCode, String code);

  TypedLiteral parseListOrMapLiteral(Token modifier, String code);

  Expression parseLogicalAndExpression(String code);

  Expression parseLogicalOrExpression(String code);

  SetOrMapLiteral parseMapLiteral(
      Token token, String typeArgumentsCode, String code);

  MapLiteralEntry parseMapLiteralEntry(String code);

  Expression parseMultiplicativeExpression(String code);

  InstanceCreationExpression parseNewExpression(String code);

  NormalFormalParameter parseNormalFormalParameter(String code,
      {bool inFunctionType = false,
      List<ErrorCode> errorCodes = const <ErrorCode>[]});

  Expression parsePostfixExpression(String code);

  Identifier parsePrefixedIdentifier(String code);

  Expression parsePrimaryExpression(String code,
      {int expectedEndOffset, List<ExpectedError> errors});

  Expression parseRelationalExpression(String code);

  RethrowExpression parseRethrowExpression(String code);

  BinaryExpression parseShiftExpression(String code);

  SimpleIdentifier parseSimpleIdentifier(String code);

  Statement parseStatement(String source, {int expectedEndOffset});

  Expression parseStringLiteral(String code);

  SymbolLiteral parseSymbolLiteral(String code);

  Expression parseThrowExpression(String code);

  Expression parseThrowExpressionWithoutCascade(String code);

  PrefixExpression parseUnaryExpression(String code);

  VariableDeclarationList parseVariableDeclarationList(String source);
}

/// This class just narrows the type of [parser] to [ParserProxy].
abstract class AbstractParserViaProxyTestCase
    implements AbstractParserTestCase {
  @override
  ParserProxy get parser;
}

/// Implementation of [AbstractParserTestCase] specialized for testing the
/// Fasta parser.
class FastaParserTestCase
    with ParserTestHelpers
    implements AbstractParserTestCase {
  static final List<ErrorCode> NO_ERROR_COMPARISON = <ErrorCode>[];

  final constructorTearoffs = FeatureSet.fromEnableFlags2(
    sdkLanguageVersion: ExperimentStatus.currentVersion,
    flags: [EnableString.constructor_tearoffs],
  );

  final controlFlow = FeatureSet.latestLanguageVersion();

  final spread = FeatureSet.latestLanguageVersion();

  final nonNullable = FeatureSet.latestLanguageVersion();

  final preConstructorTearoffs = FeatureSet.fromEnableFlags2(
      sdkLanguageVersion: Version.parse('2.13.0'), flags: []);

  final preNonNullable = FeatureSet.fromEnableFlags2(
    sdkLanguageVersion: Version.parse('2.9.0'),
    flags: [],
  );

  late ParserProxy parserProxy;

  late Token _fastaTokens;

  @override
  bool allowNativeClause = false;

  @override
  set enableOptionalNewAndConst(bool enable) {
    // ignored
  }

  @override
  set enableUriInPartOf(bool value) {
    if (value == false) {
      throw UnimplementedError(
          'URIs in "part of" declarations cannot be disabled in Fasta.');
    }
  }

  @override
  GatheringErrorListener get listener => parserProxy.errorListener;

  @override
  ParserProxy get parser => parserProxy;

  void assertErrors({List<ErrorCode>? codes, List<ExpectedError>? errors}) {
    if (codes != null) {
      if (!identical(codes, NO_ERROR_COMPARISON)) {
        assertErrorsWithCodes(codes);
      }
    } else if (errors != null) {
      listener.assertErrors(errors);
    } else {
      assertNoErrors();
    }
  }

  @override
  void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
    parserProxy.errorListener.assertErrorsWithCodes(
        _toFastaGeneratedAnalyzerErrorCodes(expectedErrorCodes));
  }

  @override
  void assertNoErrors() {
    parserProxy.errorListener.assertNoErrors();
  }

  @override
  void createParser(String content,
      {int? expectedEndOffset, FeatureSet? featureSet}) {
    featureSet ??= FeatureSet.latestLanguageVersion();
    var result = scanString(content,
        configuration: featureSet.isEnabled(Feature.non_nullable)
            ? ScannerConfiguration.nonNullable
            : ScannerConfiguration.classic,
        includeComments: true);
    _fastaTokens = result.tokens;
    parserProxy = ParserProxy(_fastaTokens, featureSet,
        allowNativeClause: allowNativeClause,
        expectedEndOffset: expectedEndOffset);
  }

  @override
  ExpectedError expectedError(ErrorCode code, int offset, int length) =>
      ExpectedError(_toFastaGeneratedAnalyzerErrorCode(code), offset, length);

  @override
  void expectNotNullIfNoErrors(Object? result) {
    if (!listener.hasErrors) {
      expect(result, isNotNull);
    }
  }

  @override
  Expression parseAdditiveExpression(String code) {
    return _parseExpression(code);
  }

  Expression parseArgument(String source) {
    createParser(source);
    return parserProxy.parseArgument();
  }

  @override
  Expression parseAssignableExpression(String code, bool primaryAllowed) {
    return _parseExpression(code);
  }

  @override
  Expression parseAssignableSelector(String code, bool optional,
      {bool allowConditional = true}) {
    if (optional) {
      if (code.isEmpty) {
        return _parseExpression('foo');
      }
      return _parseExpression('(foo)$code');
    }
    return _parseExpression('foo$code');
  }

  @override
  AwaitExpression parseAwaitExpression(String code) {
    var function = _parseExpression('() async => $code') as FunctionExpression;
    return (function.body as ExpressionFunctionBody).expression
        as AwaitExpression;
  }

  @override
  Expression parseBitwiseAndExpression(String code) {
    return _parseExpression(code);
  }

  @override
  Expression parseBitwiseOrExpression(String code) {
    return _parseExpression(code);
  }

  @override
  Expression parseBitwiseXorExpression(String code) {
    return _parseExpression(code);
  }

  @override
  Expression parseCascadeSection(String code) {
    var cascadeExpression = _parseExpression('null$code') as CascadeExpression;
    return cascadeExpression.cascadeSections.first;
  }

  @override
  CommentReference? parseCommentReference(
      String referenceSource, int sourceOffset) {
    String padding = ' '.padLeft(sourceOffset - 4, 'a');
    String source = '/**$padding[$referenceSource] */ class C { }';
    CompilationUnit unit = parseCompilationUnit(source);
    var clazz = unit.declarations[0] as ClassDeclaration;
    var comment = clazz.documentationComment!;
    List<CommentReference> references = comment.references;
    if (references.isEmpty) {
      return null;
    } else {
      expect(references, hasLength(1));
      return references[0];
    }
  }

  @override
  CompilationUnitImpl parseCompilationUnit(String content,
      {List<ErrorCode>? codes,
      List<ExpectedError>? errors,
      FeatureSet? featureSet}) {
    GatheringErrorListener listener = GatheringErrorListener(checkRanges: true);

    var unit = parseCompilationUnit2(content, listener, featureSet: featureSet);

    // Assert and return result
    if (codes != null) {
      listener
          .assertErrorsWithCodes(_toFastaGeneratedAnalyzerErrorCodes(codes));
    } else if (errors != null) {
      listener.assertErrors(errors);
    } else {
      listener.assertNoErrors();
    }
    return unit;
  }

  CompilationUnitImpl parseCompilationUnit2(
      String content, GatheringErrorListener listener,
      {FeatureSet? featureSet}) {
    featureSet ??= FeatureSet.latestLanguageVersion();
    var source = StringSource(content, 'parser_test_StringSource.dart');

    // Adjust the feature set based on language version comment.
    void languageVersionChanged(
        fasta.Scanner scanner, LanguageVersionToken languageVersion) {
      featureSet = featureSet!.restrictToVersion(
          Version(languageVersion.major, languageVersion.minor, 0));
      scanner.configuration = Scanner.buildConfig(featureSet);
    }

    // Scan tokens
    ScannerResult result = scanString(content,
        includeComments: true,
        configuration: Scanner.buildConfig(featureSet),
        languageVersionChanged: languageVersionChanged);
    _fastaTokens = result.tokens;

    // Run parser
    ErrorReporter errorReporter = ErrorReporter(
      listener,
      source,
      isNonNullableByDefault: false,
    );
    AstBuilder astBuilder =
        AstBuilder(errorReporter, source.uri, true, featureSet!);
    fasta.Parser parser = fasta.Parser(astBuilder);
    astBuilder.parser = parser;
    astBuilder.allowNativeClause = allowNativeClause;
    parser.parseUnit(_fastaTokens);
    var unit = astBuilder.pop() as CompilationUnitImpl;

    expect(unit, isNotNull);
    return unit;
  }

  @override
  ConditionalExpression parseConditionalExpression(String code) {
    return _parseExpression(code) as ConditionalExpression;
  }

  @override
  Expression parseConstExpression(String code) {
    return _parseExpression(code);
  }

  @override
  ConstructorInitializer parseConstructorInitializer(String code) {
    createParser('class __Test { __Test() : $code; }');
    CompilationUnit unit = parserProxy.parseCompilationUnit2();
    assertNoErrors();
    var clazz = unit.declarations[0] as ClassDeclaration;
    var constructor = clazz.members[0] as ConstructorDeclaration;
    return constructor.initializers.single;
  }

  @override
  CompilationUnit parseDirectives(String source,
      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
    createParser(source);
    CompilationUnit unit =
        parserProxy.parseDirectives(parserProxy.currentToken);
    expect(unit, isNotNull);
    expect(unit.declarations, hasLength(0));
    listener.assertErrorsWithCodes(errorCodes);
    return unit;
  }

  @override
  BinaryExpression parseEqualityExpression(String code) {
    return _parseExpression(code) as BinaryExpression;
  }

  @override
  Expression parseExpression(String source,
      {List<ErrorCode>? codes,
      List<ExpectedError>? errors,
      int? expectedEndOffset,
      bool inAsync = false,
      FeatureSet? featureSet}) {
    createParser(source,
        expectedEndOffset: expectedEndOffset, featureSet: featureSet);
    if (inAsync) {
      parserProxy.fastaParser.asyncState = AsyncModifier.Async;
    }
    Expression result = parserProxy.parseExpression2();
    assertErrors(codes: codes, errors: errors);
    return result;
  }

  @override
  List<Expression> parseExpressionList(String code) {
    return (_parseExpression('[$code]') as ListLiteral)
        .elements
        .toList()
        .cast<Expression>();
  }

  @override
  Expression parseExpressionWithoutCascade(String code) {
    return _parseExpression(code);
  }

  @override
  FormalParameter parseFormalParameter(String code, ParameterKind kind,
      {List<ErrorCode> errorCodes = const <ErrorCode>[],
      FeatureSet? featureSet}) {
    String parametersCode;
    if (kind == ParameterKind.REQUIRED) {
      parametersCode = '($code)';
    } else if (kind == ParameterKind.POSITIONAL) {
      parametersCode = '([$code])';
    } else if (kind == ParameterKind.NAMED) {
      parametersCode = '({$code})';
    } else {
      fail('$kind');
    }
    FormalParameterList list = parseFormalParameterList(parametersCode,
        inFunctionType: false, errorCodes: errorCodes, featureSet: featureSet);
    return list.parameters.single;
  }

  @override
  FormalParameterList parseFormalParameterList(String code,
      {bool inFunctionType = false,
      List<ErrorCode> errorCodes = const <ErrorCode>[],
      List<ExpectedError>? errors,
      FeatureSet? featureSet}) {
    createParser(code, featureSet: featureSet);
    FormalParameterList result =
        parserProxy.parseFormalParameterList(inFunctionType: inFunctionType);
    assertErrors(codes: errors != null ? null : errorCodes, errors: errors);
    return result;
  }

  @override
  CompilationUnitMember parseFullCompilationUnitMember() {
    return parserProxy.parseTopLevelDeclaration(false) as CompilationUnitMember;
  }

  @override
  Directive parseFullDirective() {
    return parserProxy.parseTopLevelDeclaration(true) as Directive;
  }

  @override
  FunctionExpression parseFunctionExpression(String code) {
    return _parseExpression(code) as FunctionExpression;
  }

  @override
  InstanceCreationExpression parseInstanceCreationExpression(
      String code, Token newToken) {
    return _parseExpression('$newToken $code') as InstanceCreationExpression;
  }

  @override
  ListLiteral parseListLiteral(
      Token? token, String? typeArgumentsCode, String code) {
    String sc = '';
    if (token != null) {
      sc += token.lexeme + ' ';
    }
    if (typeArgumentsCode != null) {
      sc += typeArgumentsCode;
    }
    sc += code;
    return _parseExpression(sc) as ListLiteral;
  }

  @override
  TypedLiteral parseListOrMapLiteral(Token? modifier, String code) {
    String literalCode = modifier != null ? '$modifier $code' : code;
    return parsePrimaryExpression(literalCode) as TypedLiteral;
  }

  @override
  Expression parseLogicalAndExpression(String code) {
    return _parseExpression(code);
  }

  @override
  Expression parseLogicalOrExpression(String code) {
    return _parseExpression(code);
  }

  @override
  SetOrMapLiteral parseMapLiteral(
      Token? token, String? typeArgumentsCode, String code) {
    String sc = '';
    if (token != null) {
      sc += token.lexeme + ' ';
    }
    if (typeArgumentsCode != null) {
      sc += typeArgumentsCode;
    }
    sc += code;
    return parsePrimaryExpression(sc) as SetOrMapLiteral;
  }

  @override
  MapLiteralEntry parseMapLiteralEntry(String code) {
    var mapLiteral = parseMapLiteral(null, null, '{ $code }');
    return mapLiteral.elements.single as MapLiteralEntry;
  }

  @override
  Expression parseMultiplicativeExpression(String code) {
    return _parseExpression(code);
  }

  @override
  InstanceCreationExpression parseNewExpression(String code) {
    return _parseExpression(code) as InstanceCreationExpression;
  }

  @override
  NormalFormalParameter parseNormalFormalParameter(String code,
      {bool inFunctionType = false,
      List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
    FormalParameterList list = parseFormalParameterList('($code)',
        inFunctionType: inFunctionType, errorCodes: errorCodes);
    return list.parameters.single as NormalFormalParameter;
  }

  @override
  Expression parsePostfixExpression(String code) {
    return _parseExpression(code);
  }

  @override
  Identifier parsePrefixedIdentifier(String code) {
    return _parseExpression(code) as Identifier;
  }

  @override
  Expression parsePrimaryExpression(String code,
      {int? expectedEndOffset, List<ExpectedError>? errors}) {
    createParser(code, expectedEndOffset: expectedEndOffset);
    Expression result = parserProxy.parsePrimaryExpression();
    assertErrors(codes: null, errors: errors);
    return result;
  }

  @override
  Expression parseRelationalExpression(String code) {
    return _parseExpression(code);
  }

  @override
  RethrowExpression parseRethrowExpression(String code) {
    return _parseExpression(code) as RethrowExpression;
  }

  @override
  BinaryExpression parseShiftExpression(String code) {
    return _parseExpression(code) as BinaryExpression;
  }

  @override
  SimpleIdentifier parseSimpleIdentifier(String code) {
    return _parseExpression(code) as SimpleIdentifier;
  }

  @override
  Statement parseStatement(String source,
      {int? expectedEndOffset, FeatureSet? featureSet, bool inAsync = false}) {
    createParser(source,
        expectedEndOffset: expectedEndOffset, featureSet: featureSet);
    if (inAsync) {
      parserProxy.fastaParser.asyncState = AsyncModifier.Async;
    }
    Statement statement = parserProxy.parseStatement2();
    assertErrors(codes: NO_ERROR_COMPARISON);
    return statement;
  }

  @override
  Expression parseStringLiteral(String code) {
    return _parseExpression(code);
  }

  @override
  SymbolLiteral parseSymbolLiteral(String code) {
    return _parseExpression(code) as SymbolLiteral;
  }

  @override
  Expression parseThrowExpression(String code) {
    return _parseExpression(code);
  }

  @override
  Expression parseThrowExpressionWithoutCascade(String code) {
    return _parseExpression(code);
  }

  @override
  PrefixExpression parseUnaryExpression(String code) {
    return _parseExpression(code) as PrefixExpression;
  }

  @override
  VariableDeclarationList parseVariableDeclarationList(String code) {
    var statement = parseStatement('$code;') as VariableDeclarationStatement;
    return statement.variables;
  }

  Expression _parseExpression(String code) {
    var statement = parseStatement('$code;') as ExpressionStatement;
    return statement.expression;
  }

  ErrorCode _toFastaGeneratedAnalyzerErrorCode(ErrorCode code) {
    if (code == ParserErrorCode.ABSTRACT_ENUM ||
        code == ParserErrorCode.ABSTRACT_TOP_LEVEL_FUNCTION ||
        code == ParserErrorCode.ABSTRACT_TOP_LEVEL_VARIABLE ||
        code == ParserErrorCode.ABSTRACT_TYPEDEF ||
        code == ParserErrorCode.CONST_ENUM ||
        code == ParserErrorCode.CONST_TYPEDEF ||
        code == ParserErrorCode.COVARIANT_TOP_LEVEL_DECLARATION ||
        code == ParserErrorCode.FINAL_CLASS ||
        code == ParserErrorCode.FINAL_ENUM ||
        code == ParserErrorCode.FINAL_TYPEDEF ||
        code == ParserErrorCode.STATIC_TOP_LEVEL_DECLARATION) {
      return ParserErrorCode.EXTRANEOUS_MODIFIER;
    }
    return code;
  }

  List<ErrorCode> _toFastaGeneratedAnalyzerErrorCodes(
          List<ErrorCode> expectedErrorCodes) =>
      expectedErrorCodes.map(_toFastaGeneratedAnalyzerErrorCode).toList();
}

/// Proxy implementation of the analyzer parser, implemented in terms of the
/// Fasta parser.
///
/// This allows many of the analyzer parser tests to be run on Fasta, even if
/// they call into the analyzer parser class directly.
class ParserProxy extends analyzer.Parser {
  /// The error listener to which scanner and parser errors will be reported.
  final GatheringErrorListener errorListener;

  late final ForwardingTestListener _eventListener;

  final int? expectedEndOffset;

  /// Creates a [ParserProxy] which is prepared to begin parsing at the given
  /// Fasta token.
  factory ParserProxy(Token firstToken, FeatureSet featureSet,
      {bool allowNativeClause = false, int? expectedEndOffset}) {
    TestSource source = TestSource();
    var errorListener = GatheringErrorListener(checkRanges: true);
    return ParserProxy._(firstToken, source, errorListener, featureSet,
        allowNativeClause: allowNativeClause,
        expectedEndOffset: expectedEndOffset);
  }

  ParserProxy._(Token firstToken, Source source, this.errorListener,
      FeatureSet featureSet,
      {bool allowNativeClause = false, this.expectedEndOffset})
      : super(source, errorListener,
            featureSet: featureSet, allowNativeClause: allowNativeClause) {
    _eventListener = ForwardingTestListener(astBuilder);
    fastaParser.listener = _eventListener;
    currentToken = firstToken;
  }

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

  Annotation parseAnnotation() {
    return _run('MetadataStar', () {
      currentToken = fastaParser
          .parseMetadata(fastaParser.syntheticPreviousToken(currentToken))
          .next!;
      return astBuilder.pop() as Annotation;
    });
  }

  ArgumentList parseArgumentList() {
    return _run('unspecified', () {
      currentToken = fastaParser
          .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
          .next!;
      var result = astBuilder.pop();
      return result is MethodInvocation
          ? result.argumentList
          : result as ArgumentList;
    });
  }

  ClassMember parseClassMember(String className) {
    return parseClassMemberOrNull(className)!;
  }

  ClassMember? parseClassMemberOrNull(String className) {
    return _run('ClassOrMixinBody', () {
      astBuilder.classDeclaration = astFactory.classDeclaration(
        null,
        null,
        null,
        null,
        Token(Keyword.CLASS, 0),
        astFactory.simpleIdentifier(
            fasta.StringToken.fromString(TokenType.IDENTIFIER, className, 6)),
        null,
        null,
        null,
        null,
        Tokens.openCurlyBracket() /* leftBracket */,
        <ClassMember>[],
        Tokens.closeCurlyBracket() /* rightBracket */,
      );
      // TODO(danrubel): disambiguate between class and mixin
      currentToken = fastaParser.parseClassMember(currentToken, className);
      //currentToken = fastaParser.parseMixinMember(currentToken);
      ClassDeclaration declaration = astBuilder.classDeclaration!;
      astBuilder.classDeclaration = null;
      return declaration.members.isNotEmpty ? declaration.members[0] : null;
    });
  }

  List<Combinator> parseCombinators() {
    return _run('Import', () {
      currentToken = fastaParser
          .parseCombinatorStar(fastaParser.syntheticPreviousToken(currentToken))
          .next!;
      return astBuilder.pop() as List<Combinator>;
    });
  }

  List<CommentReference> parseCommentReferences(
      List<DocumentationCommentToken> tokens) {
    for (int index = 0; index < tokens.length - 1; ++index) {
      var next = tokens[index].next;
      if (next == null) {
        tokens[index].setNext(tokens[index + 1]);
      } else {
        expect(next, tokens[index + 1]);
      }
    }
    expect(tokens[tokens.length - 1].next, isNull);
    List<CommentReference> references =
        astBuilder.parseCommentReferences(tokens.first);
    if (astBuilder.stack.isNotEmpty) {
      throw 'Expected empty stack, but found:'
          '\n  ${astBuilder.stack.values.join('\n  ')}';
    }
    return references;
  }

  @override
  CompilationUnitImpl parseCompilationUnit2() {
    var result = super.parseCompilationUnit2();
    expect(currentToken.isEof, isTrue, reason: currentToken.lexeme);
    expect(astBuilder.stack, hasLength(0));
    _eventListener.expectEmpty();
    return result;
  }

  @override
  Configuration parseConfiguration() {
    return _run('ConditionalUris', () => super.parseConfiguration());
  }

  @override
  DottedName parseDottedName() {
    return _run('unspecified', () => super.parseDottedName());
  }

  @override
  Expression parseExpression2() {
    return _run('unspecified', () => super.parseExpression2());
  }

  @override
  FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
    return _run('unspecified',
        () => super.parseFormalParameterList(inFunctionType: inFunctionType));
  }

  @override
  FunctionBody parseFunctionBody(
      bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
    Token? lastToken;
    FunctionBody body = _run('unspecified', () {
      FunctionBody body =
          super.parseFunctionBody(mayBeEmpty, emptyErrorCode, inExpression);
      lastToken = currentToken;
      currentToken = currentToken.next!;
      return body;
    });
    if (!inExpression) {
      if (![';', '}'].contains(lastToken!.lexeme)) {
        fail('Expected ";" or "}", but found: ${lastToken!.lexeme}');
      }
    }
    return body;
  }

  @override
  Expression parsePrimaryExpression() {
    return _run('unspecified', () => super.parsePrimaryExpression());
  }

  @override
  Statement parseStatement(Token token) {
    return _run('unspecified', () => super.parseStatement(token));
  }

  @override
  Statement parseStatement2() {
    return _run('unspecified', () => super.parseStatement2());
  }

  @override
  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
    return _run(
        'CompilationUnit', () => super.parseTopLevelDeclaration(isDirective));
  }

  @override
  TypeAnnotation parseTypeAnnotation(bool inExpression) {
    return _run('unspecified', () => super.parseTypeAnnotation(inExpression));
  }

  @override
  TypeArgumentList parseTypeArgumentList() {
    return _run('unspecified', () => super.parseTypeArgumentList());
  }

  @override
  NamedType parseTypeName(bool inExpression) {
    return _run('unspecified', () => super.parseTypeName(inExpression));
  }

  @override
  TypeParameter parseTypeParameter() {
    return _run('unspecified', () => super.parseTypeParameter());
  }

  @override
  TypeParameterList? parseTypeParameterList() {
    return _run('unspecified', () => super.parseTypeParameterList());
  }

  /// Runs the specified function and returns the result. It checks the
  /// enclosing listener events, that the parse consumed all of the tokens, and
  /// that the result stack is empty.
  _run(String enclosingEvent, Function() f) {
    _eventListener.begin(enclosingEvent);

    // Simulate error handling of parseUnit by skipping error tokens
    // before parsing and reporting them after parsing is complete.
    Token errorToken = currentToken;
    currentToken = fastaParser.skipErrorTokens(currentToken);
    var result = f();
    fastaParser.reportAllErrorTokens(errorToken);

    _eventListener.end(enclosingEvent);

    String lexeme = currentToken is ErrorToken
        ? currentToken.runtimeType.toString()
        : currentToken.lexeme;
    if (expectedEndOffset == null) {
      expect(currentToken.isEof, isTrue, reason: lexeme);
    } else {
      expect(currentToken.offset, expectedEndOffset, reason: lexeme);
    }
    expect(astBuilder.stack, hasLength(0));
    expect(astBuilder.directives, hasLength(0));
    expect(astBuilder.declarations, hasLength(0));
    return result;
  }
}

/// Implementation of [AbstractParserTestCase] specialized for testing the
/// analyzer parser.
class ParserTestCase with ParserTestHelpers implements AbstractParserTestCase {
  /// A flag indicating whether parser is to parse function bodies.
  static bool parseFunctionBodies = true;

  @override
  bool allowNativeClause = true;

  /// A flag indicating whether parser is to parse async.
  bool parseAsync = true;

  /// A flag indicating whether the parser should parse instance creation
  /// expressions that lack either the `new` or `const` keyword.
  bool enableOptionalNewAndConst = false;

  /// A flag indicating whether the parser should parse mixin declarations.
  /// https://github.com/dart-lang/language/issues/12
  bool isMixinSupportEnabled = false;

  /// A flag indicating whether the parser is to parse part-of directives that
  /// specify a URI rather than a library name.
  bool enableUriInPartOf = false;

  @override
  late final GatheringErrorListener listener;

  /// The parser used by the test.
  ///
  /// This field is typically initialized by invoking [createParser].
  @override
  late final analyzer.Parser parser;

  @override
  void assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
    listener.assertErrorsWithCodes(expectedErrorCodes);
  }

  @override
  void assertNoErrors() {
    listener.assertNoErrors();
  }

  /// Create the [parser] and [listener] used by a test. The [parser] will be
  /// prepared to parse the tokens scanned from the given [content].
  @override
  void createParser(
    String content, {
    int? expectedEndOffset,
    LanguageVersionToken? languageVersion,
    FeatureSet? featureSet,
  }) {
    featureSet ??= FeatureSet.latestLanguageVersion();
    Source source = TestSource();
    listener = GatheringErrorListener();

    fasta.ScannerResult result =
        fasta.scanString(content, includeComments: true);
    listener.setLineInfo(source, result.lineStarts);

    parser = analyzer.Parser(
      source,
      listener,
      featureSet: featureSet,
    );
    parser.allowNativeClause = allowNativeClause;
    parser.parseFunctionBodies = parseFunctionBodies;
    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
    parser.currentToken = result.tokens;
  }

  @override
  ExpectedError expectedError(ErrorCode code, int offset, int length) =>
      ExpectedError(code, offset, length);

  @override
  void expectNotNullIfNoErrors(Object result) {
    if (!listener.hasErrors) {
      expect(result, isNotNull);
    }
  }

  @override
  Expression parseAdditiveExpression(String code) {
    createParser(code);
    return parser.parseAdditiveExpression();
  }

  @override
  Expression parseAssignableExpression(String code, bool primaryAllowed) {
    createParser(code);
    return parser.parseAssignableExpression(primaryAllowed);
  }

  @override
  Expression parseAssignableSelector(String code, bool optional,
      {bool allowConditional = true}) {
    if (optional) {
      if (code.isEmpty) {
        createParser('foo');
      } else {
        createParser('(foo)$code');
      }
    } else {
      createParser('foo$code');
    }
    return parser.parseExpression2();
  }

  @override
  AwaitExpression parseAwaitExpression(String code) {
    createParser('() async => $code');
    var function = parser.parseExpression2() as FunctionExpression;
    return (function.body as ExpressionFunctionBody).expression
        as AwaitExpression;
  }

  @override
  Expression parseBitwiseAndExpression(String code) {
    createParser(code);
    return parser.parseBitwiseAndExpression();
  }

  @override
  Expression parseBitwiseOrExpression(String code) {
    createParser(code);
    return parser.parseBitwiseOrExpression();
  }

  @override
  Expression parseBitwiseXorExpression(String code) {
    createParser(code);
    return parser.parseBitwiseXorExpression();
  }

  @override
  Expression parseCascadeSection(String code) {
    var statement = parseStatement('null$code;') as ExpressionStatement;
    var cascadeExpression = statement.expression as CascadeExpression;
    return cascadeExpression.cascadeSections.first;
  }

  @override
  CommentReference? parseCommentReference(
      String referenceSource, int sourceOffset) {
    String padding = ' '.padLeft(sourceOffset - 4, 'a');
    String source = '/**$padding[$referenceSource] */ class C { }';
    CompilationUnit unit = parseCompilationUnit(source);
    var clazz = unit.declarations[0] as ClassDeclaration;
    var comment = clazz.documentationComment!;
    List<CommentReference> references = comment.references;
    if (references.isEmpty) {
      return null;
    } else {
      expect(references, hasLength(1));
      return references[0];
    }
  }

  /// Parse the given source as a compilation unit.
  ///
  /// @param source the source to be parsed
  /// @param errorCodes the error codes of the errors that are expected to be
  ///          found
  /// @return the compilation unit that was parsed
  /// @throws Exception if the source could not be parsed, if the compilation
  ///           errors in the source do not match those that are expected, or if
  ///           the result would have been `null`
  @override
  CompilationUnit parseCompilationUnit(String content,
      {List<ErrorCode>? codes, List<ExpectedError>? errors}) {
    Source source = TestSource();
    GatheringErrorListener listener = GatheringErrorListener();

    fasta.ScannerResult result =
        fasta.scanString(content, includeComments: true);
    listener.setLineInfo(source, result.lineStarts);

    analyzer.Parser parser = analyzer.Parser(
      source,
      listener,
      featureSet: FeatureSet.latestLanguageVersion(),
    );
    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
    CompilationUnit unit = parser.parseCompilationUnit(result.tokens);
    expect(unit, isNotNull);
    if (codes != null) {
      listener.assertErrorsWithCodes(codes);
    } else if (errors != null) {
      listener.assertErrors(errors);
    } else {
      listener.assertNoErrors();
    }
    return unit;
  }

  /// Parse the given [content] as a compilation unit.
  CompilationUnit parseCompilationUnit2(String content,
      {AnalysisErrorListener? listener}) {
    Source source = NonExistingSource.unknown;
    listener ??= AnalysisErrorListener.NULL_LISTENER;

    fasta.ScannerResult result =
        fasta.scanString(content, includeComments: true);

    analyzer.Parser parser = analyzer.Parser(
      source,
      listener,
      featureSet: FeatureSet.latestLanguageVersion(),
    );
    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
    var unit = parser.parseCompilationUnit(result.tokens);
    unit.lineInfo = LineInfo(result.lineStarts);
    return unit;
  }

  @override
  ConditionalExpression parseConditionalExpression(String code) {
    createParser(code);
    return parser.parseConditionalExpression() as ConditionalExpression;
  }

  @override
  Expression parseConstExpression(String code) {
    createParser(code);
    return parser.parseConstExpression();
  }

  @override
  ConstructorInitializer parseConstructorInitializer(String code) {
    createParser('class __Test { __Test() : $code; }');
    CompilationUnit unit = parser.parseCompilationUnit2();
    var clazz = unit.declarations[0] as ClassDeclaration;
    var constructor = clazz.members[0] as ConstructorDeclaration;
    return constructor.initializers.single;
  }

  @override
  CompilationUnit parseDirectives(String source,
      [List<ErrorCode> errorCodes = const <ErrorCode>[]]) {
    createParser(source);
    CompilationUnit unit = parser.parseDirectives2();
    expect(unit, isNotNull);
    expect(unit.declarations, hasLength(0));
    listener.assertErrorsWithCodes(errorCodes);
    return unit;
  }

  @override
  BinaryExpression parseEqualityExpression(String code) {
    createParser(code);
    return parser.parseEqualityExpression() as BinaryExpression;
  }

  /// Parse the given [source] as an expression. If a list of error [codes] is
  /// provided, then assert that the produced errors matches the list.
  /// Otherwise, if a list of [errors] is provided, the assert that the produced
  /// errors matches the list. Otherwise, assert that there are no errors.
  @override
  Expression parseExpression(String source,
      {List<ErrorCode>? codes,
      List<ExpectedError>? errors,
      int? expectedEndOffset}) {
    createParser(source, expectedEndOffset: expectedEndOffset);
    Expression expression = parser.parseExpression2();
    expectNotNullIfNoErrors(expression);
    if (codes != null) {
      listener.assertErrorsWithCodes(codes);
    } else if (errors != null) {
      listener.assertErrors(errors);
    } else {
      assertNoErrors();
    }
    return expression;
  }

  @override
  List<Expression> parseExpressionList(String code) {
    createParser('[$code]');
    return (parser.parseExpression2() as ListLiteral)
        .elements
        .toList()
        .cast<Expression>();
  }

  @override
  Expression parseExpressionWithoutCascade(String code) {
    createParser(code);
    return parser.parseExpressionWithoutCascade();
  }

  @override
  FormalParameter parseFormalParameter(String code, ParameterKind kind,
      {List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
    String parametersCode;
    if (kind == ParameterKind.REQUIRED) {
      parametersCode = '($code)';
    } else if (kind == ParameterKind.POSITIONAL) {
      parametersCode = '([$code])';
    } else if (kind == ParameterKind.NAMED) {
      parametersCode = '({$code})';
    } else {
      fail('$kind');
    }
    FormalParameterList list = parseFormalParameterList(parametersCode,
        inFunctionType: false, errorCodes: errorCodes);
    return list.parameters.single;
  }

  @override
  FormalParameterList parseFormalParameterList(String code,
      {bool inFunctionType = false,
      List<ErrorCode> errorCodes = const <ErrorCode>[],
      List<ExpectedError>? errors}) {
    createParser(code);
    FormalParameterList list =
        parser.parseFormalParameterList(inFunctionType: inFunctionType);
    if (errors != null) {
      errorCodes = errors.map((e) => e.code).toList();
    }
    assertErrorsWithCodes(errorCodes);
    return list;
  }

  /// Parses a single top level member of a compilation unit (other than a
  /// directive), including any comment and/or metadata that precedes it.
  @override
  CompilationUnitMember parseFullCompilationUnitMember() =>
      parser.parseCompilationUnit2().declarations.first;

  @override
  Directive parseFullDirective() {
    return parser.parseTopLevelDeclaration(true) as Directive;
  }

  @override
  FunctionExpression parseFunctionExpression(String code) {
    createParser(code);
    return parser.parseFunctionExpression();
  }

  @override
  InstanceCreationExpression parseInstanceCreationExpression(
      String code, Token newToken) {
    createParser('$newToken $code');
    return parser.parseExpression2() as InstanceCreationExpression;
  }

  @override
  ListLiteral parseListLiteral(
      Token? token, String? typeArgumentsCode, String code) {
    String sc = '';
    if (token != null) {
      sc += token.lexeme + ' ';
    }
    if (typeArgumentsCode != null) {
      sc += typeArgumentsCode;
    }
    sc += code;
    createParser(sc);
    return parser.parseExpression2() as ListLiteral;
  }

  @override
  TypedLiteral parseListOrMapLiteral(Token? modifier, String code) {
    String literalCode = modifier != null ? '$modifier $code' : code;
    createParser(literalCode);
    return parser.parseExpression2() as TypedLiteral;
  }

  @override
  Expression parseLogicalAndExpression(String code) {
    createParser(code);
    return parser.parseLogicalAndExpression();
  }

  @override
  Expression parseLogicalOrExpression(String code) {
    createParser(code);
    return parser.parseLogicalOrExpression();
  }

  @override
  SetOrMapLiteral parseMapLiteral(
      Token? token, String? typeArgumentsCode, String code) {
    String sc = '';
    if (token != null) {
      sc += token.lexeme + ' ';
    }
    if (typeArgumentsCode != null) {
      sc += typeArgumentsCode;
    }
    sc += code;
    createParser(sc);
    return parser.parseExpression2() as SetOrMapLiteral;
  }

  @override
  MapLiteralEntry parseMapLiteralEntry(String code) {
    var mapLiteral = parseMapLiteral(null, null, '{ $code }');
    return mapLiteral.elements.single as MapLiteralEntry;
  }

  @override
  Expression parseMultiplicativeExpression(String code) {
    createParser(code);
    return parser.parseMultiplicativeExpression();
  }

  @override
  InstanceCreationExpression parseNewExpression(String code) {
    createParser(code);
    return parser.parseNewExpression();
  }

  @override
  NormalFormalParameter parseNormalFormalParameter(String code,
      {bool inFunctionType = false,
      List<ErrorCode> errorCodes = const <ErrorCode>[]}) {
    FormalParameterList list = parseFormalParameterList('($code)',
        inFunctionType: inFunctionType, errorCodes: errorCodes);
    return list.parameters.single as NormalFormalParameter;
  }

  @override
  Expression parsePostfixExpression(String code) {
    createParser(code);
    return parser.parsePostfixExpression();
  }

  @override
  Identifier parsePrefixedIdentifier(String code) {
    createParser(code);
    return parser.parsePrefixedIdentifier();
  }

  @override
  Expression parsePrimaryExpression(String code,
      {int? expectedEndOffset, List<ExpectedError>? errors}) {
    createParser(code);
    var expression = parser.parsePrimaryExpression();
    if (errors != null) {
      listener.assertErrors(errors);
    }
    return expression;
  }

  @override
  Expression parseRelationalExpression(String code) {
    createParser(code);
    return parser.parseRelationalExpression();
  }

  @override
  RethrowExpression parseRethrowExpression(String code) {
    createParser(code);
    return parser.parseRethrowExpression() as RethrowExpression;
  }

  @override
  BinaryExpression parseShiftExpression(String code) {
    createParser(code);
    return parser.parseShiftExpression() as BinaryExpression;
  }

  @override
  SimpleIdentifier parseSimpleIdentifier(String code) {
    createParser(code);
    return parser.parseSimpleIdentifier();
  }

  /// Parse the given [content] as a statement. If
  /// [enableLazyAssignmentOperators] is `true`, then lazy assignment operators
  /// should be enabled.
  @override
  Statement parseStatement(String content, {int? expectedEndOffset}) {
    Source source = TestSource();
    listener = GatheringErrorListener();

    fasta.ScannerResult result =
        fasta.scanString(content, includeComments: true);
    listener.setLineInfo(source, result.lineStarts);

    analyzer.Parser parser = analyzer.Parser(
      source,
      listener,
      featureSet: FeatureSet.latestLanguageVersion(),
    );
    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
    Statement statement = parser.parseStatement(result.tokens);
    expect(statement, isNotNull);
    return statement;
  }

  @override
  Expression parseStringLiteral(String code) {
    createParser(code);
    return parser.parseStringLiteral();
  }

  @override
  SymbolLiteral parseSymbolLiteral(String code) {
    createParser(code);
    return parser.parseSymbolLiteral();
  }

  @override
  Expression parseThrowExpression(String code) {
    createParser(code);
    return parser.parseThrowExpression();
  }

  @override
  Expression parseThrowExpressionWithoutCascade(String code) {
    createParser(code);
    return parser.parseThrowExpressionWithoutCascade();
  }

  @override
  PrefixExpression parseUnaryExpression(String code) {
    createParser(code);
    return parser.parseUnaryExpression() as PrefixExpression;
  }

  @override
  VariableDeclarationList parseVariableDeclarationList(String code) {
    var statement = parseStatement('$code;') as VariableDeclarationStatement;
    return statement.variables;
  }

  void setUp() {
    parseFunctionBodies = true;
  }
}

/// Helper methods that aid in parser tests.
///
/// Intended to be mixed in to parser test case classes.
mixin ParserTestHelpers {
  void expectCommentText(Comment? comment, String expectedText) {
    comment!;
    expect(comment.beginToken, same(comment.endToken));
    expect(comment.beginToken.lexeme, expectedText);
  }

  void expectDottedName(DottedName name, List<String> expectedComponents) {
    int count = expectedComponents.length;
    NodeList<SimpleIdentifier> components = name.components;
    expect(components, hasLength(count));
    for (int i = 0; i < count; i++) {
      SimpleIdentifier component = components[i];
      expect(component, isNotNull);
      expect(component.name, expectedComponents[i]);
    }
  }
}
