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

import 'dart:typed_data' show Uint8List;

import 'dart:io' show File;

import 'package:_fe_analyzer_shared/src/messages/codes.dart';
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
    show ScannerConfiguration;

import 'package:_fe_analyzer_shared/src/parser/parser.dart'
    show ClassMemberParser, Parser;

import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'
    show Utf8BytesScanner;

import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;

import 'package:_fe_analyzer_shared/src/parser/listener.dart'
    show UnescapeErrorListener;

import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';

import 'package:_fe_analyzer_shared/src/parser/quote.dart' show unescapeString;

import '../source/diet_parser.dart';

import 'parser_ast_helper.dart';

CompilationUnitEnd getAST(List<int> rawBytes,
    {bool includeBody: true,
    bool includeComments: false,
    bool enableExtensionMethods: false,
    bool enableNonNullable: false,
    bool enableTripleShift: false,
    List<Token>? languageVersionsSeen}) {
  Uint8List bytes = new Uint8List(rawBytes.length + 1);
  bytes.setRange(0, rawBytes.length, rawBytes);

  ScannerConfiguration scannerConfiguration = new ScannerConfiguration(
      enableExtensionMethods: enableExtensionMethods,
      enableNonNullable: enableNonNullable,
      enableTripleShift: enableTripleShift);

  Utf8BytesScanner scanner = new Utf8BytesScanner(
    bytes,
    includeComments: includeComments,
    configuration: scannerConfiguration,
    languageVersionChanged: (scanner, languageVersion) {
      // For now don't do anything, but having it (making it non-null) means the
      // configuration won't be reset.
      languageVersionsSeen?.add(languageVersion);
    },
  );
  Token firstToken = scanner.tokenize();
  // ignore: unnecessary_null_comparison
  if (firstToken == null) {
    throw "firstToken is null";
  }

  ParserASTListener listener = new ParserASTListener();
  Parser parser;
  if (includeBody) {
    parser = new Parser(listener,
        useImplicitCreationExpression: useImplicitCreationExpressionInCfe);
  } else {
    parser = new ClassMemberParser(listener,
        useImplicitCreationExpression: useImplicitCreationExpressionInCfe);
  }
  parser.parseUnit(firstToken);
  return listener.data.single as CompilationUnitEnd;
}

/// Best-effort visitor for ParserAstNode that visits top-level entries
/// and class members only (i.e. no bodies, no field initializer content, no
/// names etc).
class ParserAstVisitor {
  void accept(ParserAstNode node) {
    if (node is CompilationUnitEnd ||
        node is TopLevelDeclarationEnd ||
        node is ClassOrMixinOrExtensionBodyEnd ||
        node is MemberEnd) {
      visitChildren(node);
      return;
    }

    if (node.type == ParserAstType.BEGIN) {
      // Ignored. These are basically just dummy nodes anyway.
      assert(node.children == null);
      return;
    }
    if (node.type == ParserAstType.HANDLE) {
      // Ignored at least for know.
      assert(node.children == null);
      return;
    }
    if (node is TypeVariablesEnd ||
        node is TypeArgumentsEnd ||
        node is TypeListEnd ||
        node is FunctionTypeEnd ||
        node is BlockEnd) {
      // Ignored at least for know.
      return;
    }
    if (node is MetadataStarEnd) {
      MetadataStarEnd metadata = node;
      visitMetadataStar(metadata);
      return;
    }
    if (node is TypedefEnd) {
      TypedefEnd typedefDecl = node;
      visitTypedef(
          typedefDecl, typedefDecl.typedefKeyword, typedefDecl.endToken);
      return;
    }
    if (node is ClassDeclarationEnd) {
      ClassDeclarationEnd cls = node;
      visitClass(cls, cls.beginToken, cls.endToken);
      return;
    }
    if (node is TopLevelMethodEnd) {
      TopLevelMethodEnd method = node;
      visitTopLevelMethod(method, method.beginToken, method.endToken);
      return;
    }
    if (node is ClassMethodEnd) {
      ClassMethodEnd method = node;
      visitClassMethod(method, method.beginToken, method.endToken);
      return;
    }
    if (node is ExtensionMethodEnd) {
      ExtensionMethodEnd method = node;
      visitExtensionMethod(method, method.beginToken, method.endToken);
      return;
    }
    if (node is MixinMethodEnd) {
      MixinMethodEnd method = node;
      visitMixinMethod(method, method.beginToken, method.endToken);
      return;
    }
    if (node is ImportEnd) {
      ImportEnd import = node;
      visitImport(import, import.importKeyword, import.semicolon);
      return;
    }
    if (node is ExportEnd) {
      ExportEnd export = node;
      visitExport(export, export.exportKeyword, export.semicolon);
      return;
    }
    if (node is TopLevelFieldsEnd) {
      // TODO(jensj): Possibly this could go into more details too
      // (e.g. to split up a field declaration).
      TopLevelFieldsEnd fields = node;
      visitTopLevelFields(fields, fields.beginToken, fields.endToken);
      return;
    }
    if (node is ClassFieldsEnd) {
      // TODO(jensj): Possibly this could go into more details too
      // (e.g. to split up a field declaration).
      ClassFieldsEnd fields = node;
      visitClassFields(fields, fields.beginToken, fields.endToken);
      return;
    }
    if (node is ExtensionFieldsEnd) {
      // TODO(jensj): Possibly this could go into more details too
      // (e.g. to split up a field declaration).
      ExtensionFieldsEnd fields = node;
      visitExtensionFields(fields, fields.beginToken, fields.endToken);
      return;
    }
    if (node is MixinFieldsEnd) {
      // TODO(jensj): Possibly this could go into more details too
      // (e.g. to split up a field declaration).
      MixinFieldsEnd fields = node;
      visitMixinFields(fields, fields.beginToken, fields.endToken);
      return;
    }
    if (node is NamedMixinApplicationEnd) {
      NamedMixinApplicationEnd namedMixin = node;
      visitNamedMixin(namedMixin, namedMixin.begin, namedMixin.endToken);
      return;
    }
    if (node is MixinDeclarationEnd) {
      MixinDeclarationEnd declaration = node;
      visitMixin(declaration, declaration.mixinKeyword, declaration.endToken);
      return;
    }
    if (node is EnumEnd) {
      EnumEnd declaration = node;
      visitEnum(declaration, declaration.enumKeyword,
          declaration.leftBrace.endGroup!);
      return;
    }
    if (node is LibraryNameEnd) {
      LibraryNameEnd name = node;
      visitLibraryName(name, name.libraryKeyword, name.semicolon);
      return;
    }
    if (node is PartEnd) {
      PartEnd part = node;
      visitPart(part, part.partKeyword, part.semicolon);
      return;
    }
    if (node is PartOfEnd) {
      PartOfEnd partOf = node;
      visitPartOf(partOf, partOf.partKeyword, partOf.semicolon);
      return;
    }
    if (node is ExtensionDeclarationEnd) {
      ExtensionDeclarationEnd ext = node;
      visitExtension(ext, ext.extensionKeyword, ext.endToken);
      return;
    }
    if (node is ClassConstructorEnd) {
      ClassConstructorEnd decl = node;
      visitClassConstructor(decl, decl.beginToken, decl.endToken);
      return;
    }
    if (node is ExtensionConstructorEnd) {
      ExtensionConstructorEnd decl = node;
      visitExtensionConstructor(decl, decl.beginToken, decl.endToken);
      return;
    }
    if (node is ClassFactoryMethodEnd) {
      ClassFactoryMethodEnd decl = node;
      visitClassFactoryMethod(decl, decl.beginToken, decl.endToken);
      return;
    }
    if (node is ExtensionFactoryMethodEnd) {
      ExtensionFactoryMethodEnd decl = node;
      visitExtensionFactoryMethod(decl, decl.beginToken, decl.endToken);
      return;
    }
    if (node is MetadataEnd) {
      MetadataEnd decl = node;
      // TODO(jensj): endToken is not part of the metadata! It's the first token
      // of the next thing.
      visitMetadata(decl, decl.beginToken, decl.endToken.previous!);
      return;
    }

    throw "Unknown: $node (${node.runtimeType} @ ${node.what})";
  }

  void visitChildren(ParserAstNode node) {
    if (node.children == null) return;
    final int numChildren = node.children!.length;
    for (int i = 0; i < numChildren; i++) {
      ParserAstNode child = node.children![i];
      accept(child);
    }
  }

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitImport(ImportEnd node, Token startInclusive, Token? endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitExport(ExportEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitTypedef(
      TypedefEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers can call visitChildren on this node.
  void visitMetadataStar(MetadataStarEnd node) {
    visitChildren(node);
  }

  /// Note: Implementers can call visitChildren on this node.
  void visitClass(
      ClassDeclarationEnd node, Token startInclusive, Token endInclusive) {
    visitChildren(node);
  }

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitTopLevelMethod(
      TopLevelMethodEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitClassMethod(
      ClassMethodEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitExtensionMethod(
      ExtensionMethodEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitMixinMethod(
      MixinMethodEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitTopLevelFields(
      TopLevelFieldsEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitClassFields(
      ClassFieldsEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitExtensionFields(
      ExtensionFieldsEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitMixinFields(
      MixinFieldsEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers can call visitChildren on this node.
  void visitNamedMixin(
      NamedMixinApplicationEnd node, Token startInclusive, Token endInclusive) {
    visitChildren(node);
  }

  /// Note: Implementers can call visitChildren on this node.
  void visitMixin(
      MixinDeclarationEnd node, Token startInclusive, Token endInclusive) {
    visitChildren(node);
  }

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitEnum(EnumEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitLibraryName(
      LibraryNameEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitPart(PartEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitPartOf(PartOfEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers can call visitChildren on this node.
  void visitExtension(
      ExtensionDeclarationEnd node, Token startInclusive, Token endInclusive) {
    visitChildren(node);
  }

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitClassConstructor(
      ClassConstructorEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitExtensionConstructor(
      ExtensionConstructorEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitClassFactoryMethod(
      ClassFactoryMethodEnd node, Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitExtensionFactoryMethod(ExtensionFactoryMethodEnd node,
      Token startInclusive, Token endInclusive) {}

  /// Note: Implementers are NOT expected to call visitChildren on this node.
  void visitMetadata(
      MetadataEnd node, Token startInclusive, Token endInclusive) {}
}

extension GeneralASTContentExtension on ParserAstNode {
  bool isClass() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first
        // ignore: lines_longer_than_80_chars
        is! ClassOrMixinOrNamedMixinApplicationPreludeBegin) {
      return false;
    }
    if (children!.last is! ClassDeclarationEnd) {
      return false;
    }

    return true;
  }

  ClassDeclarationEnd asClass() {
    if (!isClass()) throw "Not class";
    return children!.last as ClassDeclarationEnd;
  }

  bool isImport() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! UncategorizedTopLevelDeclarationBegin) {
      return false;
    }
    if (children!.last is! ImportEnd) {
      return false;
    }

    return true;
  }

  ImportEnd asImport() {
    if (!isImport()) throw "Not import";
    return children!.last as ImportEnd;
  }

  bool isExport() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! UncategorizedTopLevelDeclarationBegin) {
      return false;
    }
    if (children!.last is! ExportEnd) {
      return false;
    }

    return true;
  }

  ExportEnd asExport() {
    if (!isExport()) throw "Not export";
    return children!.last as ExportEnd;
  }

  bool isEnum() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! UncategorizedTopLevelDeclarationBegin) {
      return false;
    }
    if (children!.last is! EnumEnd) {
      return false;
    }

    return true;
  }

  EnumEnd asEnum() {
    if (!isEnum()) throw "Not enum";
    return children!.last as EnumEnd;
  }

  bool isTypedef() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! UncategorizedTopLevelDeclarationBegin) {
      return false;
    }
    if (children!.last is! TypedefEnd) {
      return false;
    }

    return true;
  }

  TypedefEnd asTypedef() {
    if (!isTypedef()) throw "Not typedef";
    return children!.last as TypedefEnd;
  }

  bool isScript() {
    if (this is! ScriptHandle) {
      return false;
    }
    return true;
  }

  ScriptHandle asScript() {
    if (!isScript()) throw "Not script";
    return this as ScriptHandle;
  }

  bool isExtension() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! ExtensionDeclarationPreludeBegin) {
      return false;
    }
    if (children!.last is! ExtensionDeclarationEnd) {
      return false;
    }

    return true;
  }

  ExtensionDeclarationEnd asExtension() {
    if (!isExtension()) throw "Not extension";
    return children!.last as ExtensionDeclarationEnd;
  }

  bool isInvalidTopLevelDeclaration() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! TopLevelMemberBegin) {
      return false;
    }
    if (children!.last is! InvalidTopLevelDeclarationHandle) {
      return false;
    }

    return true;
  }

  bool isRecoverableError() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! UncategorizedTopLevelDeclarationBegin) {
      return false;
    }
    if (children!.last is! RecoverableErrorHandle) {
      return false;
    }

    return true;
  }

  bool isRecoverImport() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! UncategorizedTopLevelDeclarationBegin) {
      return false;
    }
    if (children!.last is! RecoverImportHandle) {
      return false;
    }

    return true;
  }

  bool isMixinDeclaration() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first
        // ignore: lines_longer_than_80_chars
        is! ClassOrMixinOrNamedMixinApplicationPreludeBegin) {
      return false;
    }
    if (children!.last is! MixinDeclarationEnd) {
      return false;
    }

    return true;
  }

  MixinDeclarationEnd asMixinDeclaration() {
    if (!isMixinDeclaration()) throw "Not mixin declaration";
    return children!.last as MixinDeclarationEnd;
  }

  bool isNamedMixinDeclaration() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first
        // ignore: lines_longer_than_80_chars
        is! ClassOrMixinOrNamedMixinApplicationPreludeBegin) {
      return false;
    }
    if (children!.last is! NamedMixinApplicationEnd) {
      return false;
    }

    return true;
  }

  NamedMixinApplicationEnd asNamedMixinDeclaration() {
    if (!isNamedMixinDeclaration()) throw "Not named mixin declaration";
    return children!.last as NamedMixinApplicationEnd;
  }

  bool isTopLevelMethod() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! TopLevelMemberBegin) {
      return false;
    }
    if (children!.last is! TopLevelMethodEnd) {
      return false;
    }

    return true;
  }

  TopLevelMethodEnd asTopLevelMethod() {
    if (!isTopLevelMethod()) throw "Not top level method";
    return children!.last as TopLevelMethodEnd;
  }

  bool isTopLevelFields() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! TopLevelMemberBegin) {
      return false;
    }
    if (children!.last is! TopLevelFieldsEnd) {
      return false;
    }

    return true;
  }

  TopLevelFieldsEnd asTopLevelFields() {
    if (!isTopLevelFields()) throw "Not top level fields";
    return children!.last as TopLevelFieldsEnd;
  }

  bool isLibraryName() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! UncategorizedTopLevelDeclarationBegin) {
      return false;
    }
    if (children!.last is! LibraryNameEnd) {
      return false;
    }

    return true;
  }

  LibraryNameEnd asLibraryName() {
    if (!isLibraryName()) throw "Not library name";
    return children!.last as LibraryNameEnd;
  }

  bool isPart() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! UncategorizedTopLevelDeclarationBegin) {
      return false;
    }
    if (children!.last is! PartEnd) {
      return false;
    }

    return true;
  }

  PartEnd asPart() {
    if (!isPart()) throw "Not part";
    return children!.last as PartEnd;
  }

  bool isPartOf() {
    if (this is! TopLevelDeclarationEnd) {
      return false;
    }
    if (children!.first is! UncategorizedTopLevelDeclarationBegin) {
      return false;
    }
    if (children!.last is! PartOfEnd) {
      return false;
    }

    return true;
  }

  PartOfEnd asPartOf() {
    if (!isPartOf()) throw "Not part of";
    return children!.last as PartOfEnd;
  }

  bool isMetadata() {
    if (this is! MetadataStarEnd) {
      return false;
    }
    if (children!.first is! MetadataStarBegin) {
      return false;
    }
    return true;
  }

  MetadataStarEnd asMetadata() {
    if (!isMetadata()) throw "Not metadata";
    return this as MetadataStarEnd;
  }

  bool isFunctionBody() {
    if (this is BlockFunctionBodyEnd) return true;
    return false;
  }

  BlockFunctionBodyEnd asFunctionBody() {
    if (!isFunctionBody()) throw "Not function body";
    return this as BlockFunctionBodyEnd;
  }

  List<E> recursivelyFind<E extends ParserAstNode>() {
    Set<E> result = {};
    _recursivelyFindInternal(this, result);
    return result.toList();
  }

  static void _recursivelyFindInternal<E extends ParserAstNode>(
      ParserAstNode node, Set<E> result) {
    if (node is E) {
      result.add(node);
      return;
    }
    if (node.children == null) return;
    for (ParserAstNode child in node.children!) {
      _recursivelyFindInternal(child, result);
    }
  }

  void debugDumpNodeRecursively({String indent = ""}) {
    print("$indent${runtimeType} (${what}) "
        "(${deprecatedArguments})");
    if (children == null) return;
    for (ParserAstNode child in children!) {
      child.debugDumpNodeRecursively(indent: "  $indent");
    }
  }
}

extension MetadataStarExtension on MetadataStarEnd {
  List<MetadataEnd> getMetadataEntries() {
    List<MetadataEnd> result = [];
    for (ParserAstNode topLevel in children!) {
      if (topLevel is! MetadataEnd) continue;
      result.add(topLevel);
    }
    return result;
  }
}

extension CompilationUnitExtension on CompilationUnitEnd {
  List<TopLevelDeclarationEnd> getClasses() {
    List<TopLevelDeclarationEnd> result = [];
    for (ParserAstNode topLevel in children!) {
      if (!topLevel.isClass()) continue;
      result.add(topLevel as TopLevelDeclarationEnd);
    }
    return result;
  }

  List<TopLevelDeclarationEnd> getMixinDeclarations() {
    List<TopLevelDeclarationEnd> result = [];
    for (ParserAstNode topLevel in children!) {
      if (!topLevel.isMixinDeclaration()) continue;
      result.add(topLevel as TopLevelDeclarationEnd);
    }
    return result;
  }

  List<ImportEnd> getImports() {
    List<ImportEnd> result = [];
    for (ParserAstNode topLevel in children!) {
      if (!topLevel.isImport()) continue;
      result.add(topLevel.children!.last as ImportEnd);
    }
    return result;
  }

  List<ExportEnd> getExports() {
    List<ExportEnd> result = [];
    for (ParserAstNode topLevel in children!) {
      if (!topLevel.isExport()) continue;
      result.add(topLevel.children!.last as ExportEnd);
    }
    return result;
  }

  // List<MetadataStarEnd> getMetadata() {
  //   List<MetadataStarEnd> result = [];
  //   for (ParserAstNode topLevel in children) {
  //     if (!topLevel.isMetadata()) continue;
  //     result.add(topLevel);
  //   }
  //   return result;
  // }

  // List<EnumEnd> getEnums() {
  //   List<EnumEnd> result = [];
  //   for (ParserAstNode topLevel in children) {
  //     if (!topLevel.isEnum()) continue;
  //     result.add(topLevel.children.last);
  //   }
  //   return result;
  // }

  // List<FunctionTypeAliasEnd> getTypedefs() {
  //   List<FunctionTypeAliasEnd> result = [];
  //   for (ParserAstNode topLevel in children) {
  //     if (!topLevel.isTypedef()) continue;
  //     result.add(topLevel.children.last);
  //   }
  //   return result;
  // }

  // List<MixinDeclarationEnd> getMixinDeclarations() {
  //   List<MixinDeclarationEnd> result = [];
  //   for (ParserAstNode topLevel in children) {
  //     if (!topLevel.isMixinDeclaration()) continue;
  //     result.add(topLevel.children.last);
  //   }
  //   return result;
  // }

  // List<TopLevelMethodEnd> getTopLevelMethods() {
  //   List<TopLevelMethodEnd> result = [];
  //   for (ParserAstNode topLevel in children) {
  //     if (!topLevel.isTopLevelMethod()) continue;
  //     result.add(topLevel.children.last);
  //   }
  //   return result;
  // }

  CompilationUnitBegin getBegin() {
    return children!.first as CompilationUnitBegin;
  }
}

extension TopLevelDeclarationExtension on TopLevelDeclarationEnd {
  IdentifierHandle getIdentifier() {
    for (ParserAstNode child in children!) {
      if (child is IdentifierHandle) return child;
    }
    throw "Not found.";
  }

  ClassDeclarationEnd getClassDeclaration() {
    if (!isClass()) {
      throw "Not a class";
    }
    for (ParserAstNode child in children!) {
      if (child is ClassDeclarationEnd) {
        return child;
      }
    }
    throw "Not found.";
  }
}

extension MixinDeclarationExtension on MixinDeclarationEnd {
  ClassOrMixinOrExtensionBodyEnd getClassOrMixinOrExtensionBody() {
    for (ParserAstNode child in children!) {
      if (child is ClassOrMixinOrExtensionBodyEnd) {
        return child;
      }
    }
    throw "Not found.";
  }
}

extension ClassDeclarationExtension on ClassDeclarationEnd {
  ClassOrMixinOrExtensionBodyEnd getClassOrMixinOrExtensionBody() {
    for (ParserAstNode child in children!) {
      if (child is ClassOrMixinOrExtensionBodyEnd) {
        return child;
      }
    }
    throw "Not found.";
  }

  ClassExtendsHandle getClassExtends() {
    for (ParserAstNode child in children!) {
      if (child is ClassExtendsHandle) return child;
    }
    throw "Not found.";
  }

  ImplementsHandle getClassImplements() {
    for (ParserAstNode child in children!) {
      if (child is ImplementsHandle) {
        return child;
      }
    }
    throw "Not found.";
  }

  ClassWithClauseHandle? getClassWithClause() {
    for (ParserAstNode child in children!) {
      if (child is ClassWithClauseHandle) {
        return child;
      }
    }
    return null;
  }
}

extension ClassOrMixinBodyExtension on ClassOrMixinOrExtensionBodyEnd {
  List<MemberEnd> getMembers() {
    List<MemberEnd> members = [];
    for (ParserAstNode child in children!) {
      if (child is MemberEnd) {
        members.add(child);
      }
    }
    return members;
  }
}

extension MemberExtension on MemberEnd {
  bool isClassConstructor() {
    ParserAstNode child = children![1];
    if (child is ClassConstructorEnd) return true;
    return false;
  }

  ClassConstructorEnd getClassConstructor() {
    ParserAstNode child = children![1];
    if (child is ClassConstructorEnd) return child;
    throw "Not found";
  }

  bool isClassFactoryMethod() {
    ParserAstNode child = children![1];
    if (child is ClassFactoryMethodEnd) return true;
    return false;
  }

  ClassFactoryMethodEnd getClassFactoryMethod() {
    ParserAstNode child = children![1];
    if (child is ClassFactoryMethodEnd) return child;
    throw "Not found";
  }

  bool isClassFields() {
    ParserAstNode child = children![1];
    if (child is ClassFieldsEnd) return true;
    return false;
  }

  ClassFieldsEnd getClassFields() {
    ParserAstNode child = children![1];
    if (child is ClassFieldsEnd) return child;
    throw "Not found";
  }

  bool isMixinFields() {
    ParserAstNode child = children![1];
    if (child is MixinFieldsEnd) return true;
    return false;
  }

  MixinFieldsEnd getMixinFields() {
    ParserAstNode child = children![1];
    if (child is MixinFieldsEnd) return child;
    throw "Not found";
  }

  bool isMixinMethod() {
    ParserAstNode child = children![1];
    if (child is MixinMethodEnd) return true;
    return false;
  }

  MixinMethodEnd getMixinMethod() {
    ParserAstNode child = children![1];
    if (child is MixinMethodEnd) return child;
    throw "Not found";
  }

  bool isMixinFactoryMethod() {
    ParserAstNode child = children![1];
    if (child is MixinFactoryMethodEnd) return true;
    return false;
  }

  MixinFactoryMethodEnd getMixinFactoryMethod() {
    ParserAstNode child = children![1];
    if (child is MixinFactoryMethodEnd) return child;
    throw "Not found";
  }

  bool isMixinConstructor() {
    ParserAstNode child = children![1];
    if (child is MixinConstructorEnd) return true;
    return false;
  }

  MixinConstructorEnd getMixinConstructor() {
    ParserAstNode child = children![1];
    if (child is MixinConstructorEnd) return child;
    throw "Not found";
  }

  bool isClassMethod() {
    ParserAstNode child = children![1];
    if (child is ClassMethodEnd) return true;
    return false;
  }

  ClassMethodEnd getClassMethod() {
    ParserAstNode child = children![1];
    if (child is ClassMethodEnd) return child;
    throw "Not found";
  }

  bool isClassRecoverableError() {
    ParserAstNode child = children![1];
    if (child is RecoverableErrorHandle) return true;
    return false;
  }
}

extension MixinFieldsExtension on MixinFieldsEnd {
  List<IdentifierHandle> getFieldIdentifiers() {
    int countLeft = count;
    List<IdentifierHandle>? identifiers;
    for (int i = children!.length - 1; i >= 0; i--) {
      ParserAstNode child = children![i];
      if (child is IdentifierHandle &&
          child.context == IdentifierContext.fieldDeclaration) {
        countLeft--;
        if (identifiers == null) {
          identifiers = new List<IdentifierHandle>.filled(count, child);
        } else {
          identifiers[countLeft] = child;
        }
        if (countLeft == 0) break;
      }
    }
    if (countLeft != 0) throw "Didn't find the expected number of identifiers";
    return identifiers ?? [];
  }
}

extension ExtensionFieldsExtension on ExtensionFieldsEnd {
  List<IdentifierHandle> getFieldIdentifiers() {
    int countLeft = count;
    List<IdentifierHandle>? identifiers;
    for (int i = children!.length - 1; i >= 0; i--) {
      ParserAstNode child = children![i];
      if (child is IdentifierHandle &&
          child.context == IdentifierContext.fieldDeclaration) {
        countLeft--;
        if (identifiers == null) {
          identifiers = new List<IdentifierHandle>.filled(count, child);
        } else {
          identifiers[countLeft] = child;
        }
        if (countLeft == 0) break;
      }
    }
    if (countLeft != 0) throw "Didn't find the expected number of identifiers";
    return identifiers ?? [];
  }
}

extension ClassFieldsExtension on ClassFieldsEnd {
  List<IdentifierHandle> getFieldIdentifiers() {
    int countLeft = count;
    List<IdentifierHandle>? identifiers;
    for (int i = children!.length - 1; i >= 0; i--) {
      ParserAstNode child = children![i];
      if (child is IdentifierHandle &&
          child.context == IdentifierContext.fieldDeclaration) {
        countLeft--;
        if (identifiers == null) {
          identifiers = new List<IdentifierHandle>.filled(count, child);
        } else {
          identifiers[countLeft] = child;
        }
        if (countLeft == 0) break;
      }
    }
    if (countLeft != 0) throw "Didn't find the expected number of identifiers";
    return identifiers ?? [];
  }

  TypeHandle? getFirstType() {
    for (ParserAstNode child in children!) {
      if (child is TypeHandle) return child;
    }
    return null;
  }

  FieldInitializerEnd? getFieldInitializer() {
    for (ParserAstNode child in children!) {
      if (child is FieldInitializerEnd) return child;
    }
    return null;
  }
}

extension EnumExtension on EnumEnd {
  List<IdentifierHandle> getIdentifiers() {
    List<IdentifierHandle> ids = [];
    for (ParserAstNode child in children!) {
      if (child is IdentifierHandle) ids.add(child);
    }
    return ids;
  }
}

extension ExtensionDeclarationExtension on ExtensionDeclarationEnd {
  List<IdentifierHandle> getIdentifiers() {
    List<IdentifierHandle> ids = [];
    for (ParserAstNode child in children!) {
      if (child is IdentifierHandle) ids.add(child);
    }
    return ids;
  }
}

extension TopLevelMethodExtension on TopLevelMethodEnd {
  IdentifierHandle getNameIdentifier() {
    for (ParserAstNode child in children!) {
      if (child is IdentifierHandle) {
        if (child.context == IdentifierContext.topLevelFunctionDeclaration) {
          return child;
        }
      }
    }
    throw "Didn't find the name identifier!";
  }
}

extension TypedefExtension on TypedefEnd {
  IdentifierHandle getNameIdentifier() {
    for (ParserAstNode child in children!) {
      if (child is IdentifierHandle) {
        if (child.context == IdentifierContext.typedefDeclaration) {
          return child;
        }
      }
    }
    throw "Didn't find the name identifier!";
  }
}

extension ImportExtension on ImportEnd {
  IdentifierHandle? getImportPrefix() {
    for (ParserAstNode child in children!) {
      if (child is IdentifierHandle) {
        if (child.context == IdentifierContext.importPrefixDeclaration) {
          return child;
        }
      }
    }
    return null;
  }

  String getImportUriString() {
    StringBuffer sb = new StringBuffer();
    bool foundOne = false;
    for (ParserAstNode child in children!) {
      if (child is LiteralStringEnd) {
        LiteralStringBegin uri = child.children!.single as LiteralStringBegin;
        sb.write(unescapeString(
            uri.token.lexeme, uri.token, const UnescapeErrorListenerDummy()));
        foundOne = true;
      }
    }
    if (!foundOne) throw "Didn't find any";
    return sb.toString();
  }

  List<String>? getConditionalImportUriStrings() {
    List<String>? result;
    for (ParserAstNode child in children!) {
      if (child is ConditionalUrisEnd) {
        for (ParserAstNode child2 in child.children!) {
          if (child2 is ConditionalUriEnd) {
            LiteralStringEnd end = child2.children!.last as LiteralStringEnd;
            LiteralStringBegin uri = end.children!.single as LiteralStringBegin;
            (result ??= []).add(unescapeString(uri.token.lexeme, uri.token,
                const UnescapeErrorListenerDummy()));
          }
        }
        return result;
      }
    }
    return result;
  }
}

extension ExportExtension on ExportEnd {
  String getExportUriString() {
    StringBuffer sb = new StringBuffer();
    bool foundOne = false;
    for (ParserAstNode child in children!) {
      if (child is LiteralStringEnd) {
        LiteralStringBegin uri = child.children!.single as LiteralStringBegin;
        sb.write(unescapeString(
            uri.token.lexeme, uri.token, const UnescapeErrorListenerDummy()));
        foundOne = true;
      }
    }
    if (!foundOne) throw "Didn't find any";
    return sb.toString();
  }

  List<String>? getConditionalExportUriStrings() {
    List<String>? result;
    for (ParserAstNode child in children!) {
      if (child is ConditionalUrisEnd) {
        for (ParserAstNode child2 in child.children!) {
          if (child2 is ConditionalUriEnd) {
            LiteralStringEnd end = child2.children!.last as LiteralStringEnd;
            LiteralStringBegin uri = end.children!.single as LiteralStringBegin;
            (result ??= []).add(unescapeString(uri.token.lexeme, uri.token,
                const UnescapeErrorListenerDummy()));
          }
        }
        return result;
      }
    }
    return result;
  }
}

extension PartExtension on PartEnd {
  String getPartUriString() {
    StringBuffer sb = new StringBuffer();
    bool foundOne = false;
    for (ParserAstNode child in children!) {
      if (child is LiteralStringEnd) {
        LiteralStringBegin uri = child.children!.single as LiteralStringBegin;
        sb.write(unescapeString(
            uri.token.lexeme, uri.token, const UnescapeErrorListenerDummy()));
        foundOne = true;
      }
    }
    if (!foundOne) throw "Didn't find any";
    return sb.toString();
  }
}

class UnescapeErrorListenerDummy implements UnescapeErrorListener {
  const UnescapeErrorListenerDummy();

  @override
  void handleUnescapeError(
      Message message, covariant location, int offset, int length) {
    // Purposely doesn't do anything.
  }
}

extension TopLevelFieldsExtension on TopLevelFieldsEnd {
  List<IdentifierHandle> getFieldIdentifiers() {
    int countLeft = count;
    List<IdentifierHandle>? identifiers;
    for (int i = children!.length - 1; i >= 0; i--) {
      ParserAstNode child = children![i];
      if (child is IdentifierHandle &&
          child.context == IdentifierContext.topLevelVariableDeclaration) {
        countLeft--;
        if (identifiers == null) {
          identifiers = new List<IdentifierHandle>.filled(count, child);
        } else {
          identifiers[countLeft] = child;
        }
        if (countLeft == 0) break;
      }
    }
    if (countLeft != 0) throw "Didn't find the expected number of identifiers";
    return identifiers ?? [];
  }
}

extension ClassMethodExtension on ClassMethodEnd {
  BlockFunctionBodyEnd? getBlockFunctionBody() {
    for (ParserAstNode child in children!) {
      if (child is BlockFunctionBodyEnd) {
        return child;
      }
    }
    return null;
  }

  String getNameIdentifier() {
    bool foundType = false;
    for (ParserAstNode child in children!) {
      if (child is TypeHandle ||
          child is NoTypeHandle ||
          child is VoidKeywordHandle ||
          child is FunctionTypeEnd) {
        foundType = true;
      }
      if (foundType && child is IdentifierHandle) {
        return child.token.lexeme;
      } else if (foundType && child is OperatorNameHandle) {
        return child.token.lexeme;
      }
    }
    throw "No identifier found: $children";
  }
}

extension MixinMethodExtension on MixinMethodEnd {
  String getNameIdentifier() {
    bool foundType = false;
    for (ParserAstNode child in children!) {
      if (child is TypeHandle ||
          child is NoTypeHandle ||
          child is VoidKeywordHandle) {
        foundType = true;
      }
      if (foundType && child is IdentifierHandle) {
        return child.token.lexeme;
      } else if (foundType && child is OperatorNameHandle) {
        return child.token.lexeme;
      }
    }
    throw "No identifier found: $children";
  }
}

extension ExtensionMethodExtension on ExtensionMethodEnd {
  String getNameIdentifier() {
    bool foundType = false;
    for (ParserAstNode child in children!) {
      if (child is TypeHandle ||
          child is NoTypeHandle ||
          child is VoidKeywordHandle) {
        foundType = true;
      }
      if (foundType && child is IdentifierHandle) {
        return child.token.lexeme;
      } else if (foundType && child is OperatorNameHandle) {
        return child.token.lexeme;
      }
    }
    throw "No identifier found: $children";
  }
}

extension ClassFactoryMethodExtension on ClassFactoryMethodEnd {
  List<IdentifierHandle> getIdentifiers() {
    List<IdentifierHandle> result = [];
    for (ParserAstNode child in children!) {
      if (child is IdentifierHandle) {
        result.add(child);
      } else if (child is FormalParametersEnd) {
        break;
      }
    }
    return result;
  }
}

extension ClassConstructorExtension on ClassConstructorEnd {
  FormalParametersEnd getFormalParameters() {
    for (ParserAstNode child in children!) {
      if (child is FormalParametersEnd) {
        return child;
      }
    }
    throw "Not found";
  }

  InitializersEnd? getInitializers() {
    for (ParserAstNode child in children!) {
      if (child is InitializersEnd) {
        return child;
      }
    }
    return null;
  }

  BlockFunctionBodyEnd? getBlockFunctionBody() {
    for (ParserAstNode child in children!) {
      if (child is BlockFunctionBodyEnd) {
        return child;
      }
    }
    return null;
  }

  List<IdentifierHandle> getIdentifiers() {
    List<IdentifierHandle> result = [];
    for (ParserAstNode child in children!) {
      if (child is IdentifierHandle) {
        result.add(child);
      }
    }
    return result;
  }
}

extension FormalParametersExtension on FormalParametersEnd {
  List<FormalParameterEnd> getFormalParameters() {
    List<FormalParameterEnd> result = [];
    for (ParserAstNode child in children!) {
      if (child is FormalParameterEnd) {
        result.add(child);
      }
    }
    return result;
  }

  OptionalFormalParametersEnd? getOptionalFormalParameters() {
    for (ParserAstNode child in children!) {
      if (child is OptionalFormalParametersEnd) {
        return child;
      }
    }
    return null;
  }
}

extension FormalParameterExtension on FormalParameterEnd {
  FormalParameterBegin getBegin() {
    return children!.first as FormalParameterBegin;
  }
}

extension OptionalFormalParametersExtension on OptionalFormalParametersEnd {
  List<FormalParameterEnd> getFormalParameters() {
    List<FormalParameterEnd> result = [];
    for (ParserAstNode child in children!) {
      if (child is FormalParameterEnd) {
        result.add(child);
      }
    }
    return result;
  }
}

extension InitializersExtension on InitializersEnd {
  List<InitializerEnd> getInitializers() {
    List<InitializerEnd> result = [];
    for (ParserAstNode child in children!) {
      if (child is InitializerEnd) {
        result.add(child);
      }
    }
    return result;
  }

  InitializersBegin getBegin() {
    return children!.first as InitializersBegin;
  }
}

extension InitializerExtension on InitializerEnd {
  InitializerBegin getBegin() {
    return children!.first as InitializerBegin;
  }
}

void main(List<String> args) {
  File f = new File(args[0]);
  Uint8List data = f.readAsBytesSync();
  ParserAstNode ast = getAST(data);
  if (args.length > 1 && args[1] == "--benchmark") {
    Stopwatch stopwatch = new Stopwatch()..start();
    int numRuns = 100;
    for (int i = 0; i < numRuns; i++) {
      ParserAstNode ast2 = getAST(data);
      if (ast.what != ast2.what) {
        throw "Not the same result every time";
      }
    }
    stopwatch.stop();
    print("First $numRuns took ${stopwatch.elapsedMilliseconds} ms "
        "(i.e. ${stopwatch.elapsedMilliseconds / numRuns}ms/iteration)");
    stopwatch = new Stopwatch()..start();
    numRuns = 2500;
    for (int i = 0; i < numRuns; i++) {
      ParserAstNode ast2 = getAST(data);
      if (ast.what != ast2.what) {
        throw "Not the same result every time";
      }
    }
    stopwatch.stop();
    print("Next $numRuns took ${stopwatch.elapsedMilliseconds} ms "
        "(i.e. ${stopwatch.elapsedMilliseconds / numRuns}ms/iteration)");
  } else {
    print(ast);
  }
}

class ParserASTListener extends AbstractParserAstListener {
  @override
  void seen(ParserAstNode entry) {
    switch (entry.type) {
      case ParserAstType.BEGIN:
      case ParserAstType.HANDLE:
        // This just adds stuff.
        data.add(entry);
        break;
      case ParserAstType.END:
        // End should gobble up everything until the corresponding begin (which
        // should be the latest begin).
        int? beginIndex;
        for (int i = data.length - 1; i >= 0; i--) {
          if (data[i].type == ParserAstType.BEGIN) {
            beginIndex = i;
            break;
          }
        }
        if (beginIndex == null) {
          throw "Couldn't find a begin for ${entry.what}. Has:\n"
              "${data.map((e) => "${e.what}: ${e.type}").join("\n")}";
        }
        String begin = data[beginIndex].what;
        String end = entry.what;
        if (begin == end) {
          // Exact match.
        } else if (end == "TopLevelDeclaration" &&
            (begin == "ExtensionDeclarationPrelude" ||
                begin == "ClassOrMixinOrNamedMixinApplicationPrelude" ||
                begin == "TopLevelMember" ||
                begin == "UncategorizedTopLevelDeclaration")) {
          // endTopLevelDeclaration is started by one of
          // beginExtensionDeclarationPrelude,
          // beginClassOrNamedMixinApplicationPrelude
          // beginTopLevelMember or beginUncategorizedTopLevelDeclaration.
        } else if (begin == "Method" &&
            (end == "ClassConstructor" ||
                end == "ClassMethod" ||
                end == "ExtensionConstructor" ||
                end == "ExtensionMethod" ||
                end == "MixinConstructor" ||
                end == "MixinMethod" ||
                end == "EnumConstructor" ||
                end == "EnumMethod")) {
          // beginMethod is ended by one of endClassConstructor,
          // endClassMethod, endExtensionMethod, endMixinConstructor,
          // endMixinMethod, endEnumMethod or endEnumConstructor.
        } else if (begin == "Fields" &&
            (end == "TopLevelFields" ||
                end == "ClassFields" ||
                end == "MixinFields" ||
                end == "ExtensionFields" ||
                end == "EnumFields")) {
          // beginFields is ended by one of endTopLevelFields, endMixinFields,
          // endEnumFields or endExtensionFields.
        } else if (begin == "ForStatement" && end == "ForIn") {
          // beginForStatement is ended by either endForStatement or endForIn.
        } else if (begin == "FactoryMethod" &&
            (end == "ClassFactoryMethod" ||
                end == "MixinFactoryMethod" ||
                end == "ExtensionFactoryMethod" ||
                end == "EnumFactoryMethod")) {
          // beginFactoryMethod is ended by either endClassFactoryMethod,
          // endMixinFactoryMethod, endExtensionFactoryMethod, or
          // endEnumFactoryMethod.
        } else if (begin == "ForControlFlow" && (end == "ForInControlFlow")) {
          // beginForControlFlow is ended by either endForControlFlow or
          // endForInControlFlow.
        } else if (begin == "IfControlFlow" && (end == "IfElseControlFlow")) {
          // beginIfControlFlow is ended by either endIfControlFlow or
          // endIfElseControlFlow.
        } else if (begin == "AwaitExpression" &&
            (end == "InvalidAwaitExpression")) {
          // beginAwaitExpression is ended by either endAwaitExpression or
          // endInvalidAwaitExpression.
        } else if (begin == "YieldStatement" &&
            (end == "InvalidYieldStatement")) {
          // beginYieldStatement is ended by either endYieldStatement or
          // endInvalidYieldStatement.
        } else {
          throw "Unknown combination: begin$begin and end$end";
        }
        List<ParserAstNode> children = data.sublist(beginIndex);
        for (ParserAstNode child in children) {
          child.parent = entry;
        }
        data.length = beginIndex;
        data.add(entry..children = children);
        break;
    }
  }

  @override
  void reportVarianceModifierNotEnabled(Token? variance) {
    throw new UnimplementedError();
  }

  @override
  Uri get uri => throw new UnimplementedError();

  @override
  void logEvent(String name) {
    throw new UnimplementedError();
  }
}
