// 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/ast/ast.dart'
    show ClassDeclarationImpl, 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 '../util/feature_sets.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>[];

  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);
    var lineInfo = LineInfo(result.lineStarts);
    _fastaTokens = result.tokens;
    parserProxy = ParserProxy(_fastaTokens, featureSet,
        allowNativeClause: allowNativeClause,
        expectedEndOffset: expectedEndOffset,
        lineInfo: lineInfo);
  }

  @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!, LineInfo.fromContent(content));
    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,
      required LineInfo lineInfo}) {
    TestSource source = TestSource();
    var errorListener = GatheringErrorListener(checkRanges: true);
    return ParserProxy._(firstToken, source, errorListener, featureSet,
        allowNativeClause: allowNativeClause,
        expectedEndOffset: expectedEndOffset,
        lineInfo: lineInfo);
  }

  ParserProxy._(Token firstToken, Source source, this.errorListener,
      FeatureSet featureSet,
      {bool allowNativeClause = false,
      this.expectedEndOffset,
      required LineInfo lineInfo})
      : super(source, errorListener,
            featureSet: featureSet,
            allowNativeClause: allowNativeClause,
            lineInfo: lineInfo) {
    _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 = ClassDeclarationImpl(
        comment: null,
        metadata: null,
        abstractKeyword: null,
        macroKeyword: null,
        augmentKeyword: null,
        classKeyword: Token(Keyword.CLASS, 0),
        name: astFactory.simpleIdentifier(fasta.StringTokenImpl.fromString(
            TokenType.IDENTIFIER, className, 6)),
        typeParameters: null,
        extendsClause: null,
        withClause: null,
        implementsClause: null,
        leftBracket: Tokens.openCurlyBracket(),
        members: <ClassMember>[],
        rightBracket: Tokens.closeCurlyBracket(),
      );
      // 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);
    LineInfo lineInfo = LineInfo(result.lineStarts);
    listener.setLineInfo(source, lineInfo);

    parser = analyzer.Parser(
      source,
      listener,
      featureSet: featureSet,
      lineInfo: lineInfo,
    );
    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);
    LineInfo lineInfo = LineInfo(result.lineStarts);
    listener.setLineInfo(source, lineInfo);

    analyzer.Parser parser = analyzer.Parser(
      source,
      listener,
      featureSet: FeatureSets.latestWithExperiments,
      lineInfo: lineInfo,
    );
    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);
    LineInfo lineInfo = LineInfo(result.lineStarts);

    analyzer.Parser parser = analyzer.Parser(
      source,
      listener,
      featureSet: FeatureSet.latestLanguageVersion(),
      lineInfo: lineInfo,
    );
    parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
    var unit = parser.parseCompilationUnit(result.tokens);
    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);
    LineInfo lineInfo = LineInfo(result.lineStarts);
    listener.setLineInfo(source, lineInfo);

    analyzer.Parser parser = analyzer.Parser(
      source,
      listener,
      featureSet: FeatureSet.latestLanguageVersion(),
      lineInfo: lineInfo,
    );
    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]);
    }
  }
}
