// 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/parser/class_member_parser.dart'
    show ClassMemberParser;

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

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

import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
    show ErrorToken, LanguageVersionToken, Scanner;

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

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

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

import '../messages.dart' show Message;

abstract class _Chunk implements Comparable<_Chunk> {
  late int originalPosition;

  List<_MetadataChunk>? metadata;

  void _printNormalHeaderWithMetadata(
      StringBuffer sb, bool extraLine, String indent) {
    if (sb.isNotEmpty) {
      sb.write("\n");
      if (extraLine) sb.write("\n");
    }
    printMetadata(sb, indent);
    sb.write(indent);
  }

  void printOn(StringBuffer sb, {String indent: "", bool extraLine: true});

  void printMetadata(StringBuffer sb, String indent) {
    if (metadata != null) {
      for (_MetadataChunk m in metadata!) {
        m.printMetadataOn(sb, indent);
      }
    }
  }

  /// Merge and sort this chunk internally (e.g. a class might merge and sort
  /// its members).
  /// The provided [sb] should be clean and be thought of as dirty after this
  /// call.
  void internalMergeAndSort(StringBuffer sb);

  @override
  int compareTo(_Chunk other) {
    // Generally we compare according to the original position.
    if (originalPosition < other.originalPosition) return -1;
    return 1;
  }

  /// Prints tokens from [fromToken] to [toToken] into [sb].
  ///
  /// Adds space as "normal" given the tokens start and end.
  ///
  /// If [skipContentOnEndGroupUntilToToken] is true, upon meeting a token that
  /// has an endGroup where the endGroup is [toToken] the Tokens between that
  /// and [toToken] is skipped, i.e. it jumps directly to [toToken].
  void printTokenRange(Token fromToken, Token toToken, StringBuffer sb,
      {bool skipContentOnEndGroupUntilToToken: false,
      bool includeToToken: true}) {
    int endOfLast = fromToken.end;
    Token token = fromToken;
    Token afterEnd = toToken;
    if (includeToToken) afterEnd = toToken.next!;
    bool nextTokenIsEndGroup = false;
    while (token != afterEnd) {
      if (token.offset > endOfLast && !nextTokenIsEndGroup) {
        sb.write(" ");
      }

      sb.write(token.lexeme);
      endOfLast = token.end;
      if (skipContentOnEndGroupUntilToToken &&
          token.endGroup != null &&
          token.endGroup == toToken) {
        token = token.endGroup!;
        nextTokenIsEndGroup = true;
      } else {
        token = token.next!;
        nextTokenIsEndGroup = false;
      }
    }
  }
}

class _LanguageVersionChunk extends _Chunk {
  final int major;
  final int minor;

  _LanguageVersionChunk(this.major, this.minor);

  @override
  void printOn(StringBuffer sb, {String indent: "", bool extraLine: true}) {
    _printNormalHeaderWithMetadata(sb, extraLine, indent);
    sb.write("// @dart = ${major}.${minor}");
  }

  @override
  void internalMergeAndSort(StringBuffer sb) {
    // Cannot be sorted.
    assert(sb.isEmpty);
  }
}

abstract class _TokenChunk extends _Chunk {
  final Token startToken;
  final Token endToken;

  _TokenChunk(this.startToken, this.endToken);

  void _printOnWithoutHeaderAndMetadata(StringBuffer sb) {
    printTokenRange(startToken, endToken, sb);
  }

  @override
  void printOn(StringBuffer sb, {String indent: "", bool extraLine: true}) {
    _printNormalHeaderWithMetadata(sb, extraLine, indent);
    _printOnWithoutHeaderAndMetadata(sb);
  }

  @override
  void internalMergeAndSort(StringBuffer sb) {
    // Generally cannot be sorted.
    assert(sb.isEmpty);
  }
}

abstract class _SortableChunk extends _TokenChunk {
  _SortableChunk(Token startToken, Token endToken)
      : super(startToken, endToken);

  @override
  int compareTo(_Chunk o) {
    if (o is! _SortableChunk) return super.compareTo(o);

    _SortableChunk other = o;

    // Compare lexemes from startToken and at most the next 10 tokens.
    // For valid code this should be more than enough. Note that this won't
    // sort as a text-sort would as for instance "C<Foo>" and "C2<Foo>" will
    // say "C" < "C2" where a text-sort would say "C<" > "C2". This doesn't
    // really matter as long as the sorting is consistent (i.e. the textual
    // outline always sorts like this).
    Token thisToken = startToken;
    Token otherToken = other.startToken;
    int steps = 0;
    while (thisToken.lexeme == otherToken.lexeme) {
      if (steps++ > 10) break;
      thisToken = thisToken.next!;
      otherToken = otherToken.next!;
    }
    if (thisToken.lexeme == otherToken.lexeme) return super.compareTo(o);
    return thisToken.lexeme.compareTo(otherToken.lexeme);
  }
}

class _ImportExportChunk extends _Chunk {
  final List<_SingleImportExportChunk> content;

  _ImportExportChunk(this.content, int originalPosition) {
    this.originalPosition = originalPosition;
  }

  @override
  void printOn(StringBuffer sb, {String indent: "", bool extraLine: true}) {
    if (sb.isNotEmpty) {
      sb.write("\n");
    }

    for (int i = 0; i < content.length; i++) {
      _SingleImportExportChunk chunk = content[i];
      chunk.printOn(sb,
          indent: indent,
          // add extra space if there's metadata
          extraLine: chunk.metadata != null);
    }
  }

  @override
  void internalMergeAndSort(StringBuffer sb) {
    assert(sb.isEmpty);
    content.sort();
  }
}

abstract class _SingleImportExportChunk extends _SortableChunk {
  final Token? firstShowOrHide;
  final List<_NamespaceCombinator>? combinators;
  String? sortedShowAndHide;

  _SingleImportExportChunk(
      Token startToken, Token endToken, this.firstShowOrHide, this.combinators)
      : super(startToken, endToken);

  @override
  void internalMergeAndSort(StringBuffer sb) {
    assert(sb.isEmpty);
    if (firstShowOrHide == null) return;
    for (int i = 0; i < combinators!.length; i++) {
      sb.write(" ");
      _NamespaceCombinator combinator = combinators![i];
      sb.write(combinator.isShow ? "show " : "hide ");
      List<String> sorted = combinator.names.toList()..sort();
      for (int j = 0; j < sorted.length; j++) {
        if (j > 0) sb.write(", ");
        sb.write(sorted[j]);
      }
    }
    sb.write(";");
    sortedShowAndHide = sb.toString();
  }

  @override
  void _printOnWithoutHeaderAndMetadata(StringBuffer sb) {
    if (sortedShowAndHide == null) {
      return super._printOnWithoutHeaderAndMetadata(sb);
    }
    printTokenRange(startToken, firstShowOrHide!, sb, includeToToken: false);
    sb.write(sortedShowAndHide);
  }
}

class _ImportChunk extends _SingleImportExportChunk {
  _ImportChunk(Token startToken, Token endToken, Token? firstShowOrHide,
      List<_NamespaceCombinator>? combinators)
      : super(startToken, endToken, firstShowOrHide, combinators);
}

class _ExportChunk extends _SingleImportExportChunk {
  _ExportChunk(Token startToken, Token endToken, Token? firstShowOrHide,
      List<_NamespaceCombinator>? combinators)
      : super(startToken, endToken, firstShowOrHide, combinators);
}

class _NamespaceCombinator {
  final bool isShow;
  final Set<String> names;

  _NamespaceCombinator.hide(List<String> names)
      : isShow = false,
        names = names.toSet();

  _NamespaceCombinator.show(List<String> names)
      : isShow = true,
        names = names.toSet();
}

class _LibraryNameChunk extends _TokenChunk {
  _LibraryNameChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _PartChunk extends _TokenChunk {
  _PartChunk(Token startToken, Token endToken) : super(startToken, endToken);
}

class _PartOfChunk extends _TokenChunk {
  _PartOfChunk(Token startToken, Token endToken) : super(startToken, endToken);
}

abstract class _ClassChunk extends _SortableChunk {
  List<_Chunk> content = <_Chunk>[];
  Token? headerEnd;
  Token? footerStart;

  _ClassChunk(Token startToken, Token endToken) : super(startToken, endToken);

  @override
  void printOn(StringBuffer sb, {String indent: "", bool extraLine: true}) {
    _printNormalHeaderWithMetadata(sb, extraLine, indent);

    // Header.
    printTokenRange(startToken, headerEnd!, sb);

    // Content.
    for (int i = 0; i < content.length; i++) {
      _Chunk chunk = content[i];
      chunk.printOn(sb, indent: "  $indent", extraLine: false);
    }

    // Footer.
    if (footerStart != null) {
      if (content.isNotEmpty) {
        sb.write("\n");
      }
      sb.write(indent);

      printTokenRange(footerStart!, endToken, sb);
    }
  }

  @override
  void internalMergeAndSort(StringBuffer sb) {
    assert(sb.isEmpty);
    content = _mergeAndSort(content);
  }
}

class _ClassDeclarationChunk extends _ClassChunk {
  _ClassDeclarationChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _MixinDeclarationChunk extends _ClassChunk {
  _MixinDeclarationChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _ExtensionDeclarationChunk extends _ClassChunk {
  _ExtensionDeclarationChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _NamedMixinApplicationChunk extends _ClassChunk {
  _NamedMixinApplicationChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

abstract class _ProcedureEtcChunk extends _SortableChunk {
  _ProcedureEtcChunk(Token startToken, Token endToken)
      : super(startToken, endToken);

  @override
  void _printOnWithoutHeaderAndMetadata(StringBuffer sb) {
    printTokenRange(startToken, endToken, sb,
        skipContentOnEndGroupUntilToToken: true);
  }
}

class _ClassMethodChunk extends _ProcedureEtcChunk {
  _ClassMethodChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _TopLevelMethodChunk extends _ProcedureEtcChunk {
  _TopLevelMethodChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _ClassFactoryMethodChunk extends _ProcedureEtcChunk {
  _ClassFactoryMethodChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _ClassFieldsChunk extends _ProcedureEtcChunk {
  _ClassFieldsChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _TopLevelFieldsChunk extends _ProcedureEtcChunk {
  _TopLevelFieldsChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _FunctionTypeAliasChunk extends _ProcedureEtcChunk {
  _FunctionTypeAliasChunk(Token startToken, Token endToken)
      : super(startToken, endToken);
}

class _EnumChunk extends _SortableChunk {
  _EnumChunk(Token startToken, Token endToken) : super(startToken, endToken);
}

class _MetadataChunk extends _TokenChunk {
  _MetadataChunk(Token startToken, Token endToken)
      : super(startToken, endToken);

  void printMetadataOn(StringBuffer sb, String indent) {
    sb.write(indent);
    printTokenRange(startToken, endToken, sb);
    sb.write("\n");
  }
}

class _UnknownChunk extends _TokenChunk {
  final bool addMarkerForUnknownForTest;
  _UnknownChunk(
      this.addMarkerForUnknownForTest, Token startToken, Token endToken)
      : super(startToken, endToken);

  @override
  void _printOnWithoutHeaderAndMetadata(StringBuffer sb) {
    if (addMarkerForUnknownForTest) {
      sb.write("---- unknown chunk starts ----\n");
      super._printOnWithoutHeaderAndMetadata(sb);
      sb.write("\n---- unknown chunk ends ----");
      return;
    }
    super._printOnWithoutHeaderAndMetadata(sb);
  }
}

class _UnknownTokenBuilder {
  Token? start;
  Token? interimEnd;
}

class BoxedInt {
  int value;
  BoxedInt(this.value);
}

// TODO(jensj): Better support for not carring about preexisting spaces, e.g.
//              "foo(int a, int b)" will be different from "foo(int a,int b)".
// TODO(jensj): Specify scanner settings to match that of the compiler.
// TODO(jensj): Canonicalize show/hides on imports/exports. E.g.
//              "show A hide B" could just be "show A".
//              "show A show B" could just be "show A, B".
//              "show A, B, C hide A show A" would be empty.

String? textualOutline(
  List<int> rawBytes,
  ScannerConfiguration configuration, {
  bool throwOnUnexpected: false,
  bool performModelling: false,
  bool addMarkerForUnknownForTest: false,
  bool returnNullOnError: true,
}) {
  Uint8List bytes = new Uint8List(rawBytes.length + 1);
  bytes.setRange(0, rawBytes.length, rawBytes);

  List<_Chunk> parsedChunks = <_Chunk>[];

  BoxedInt originalPosition = new BoxedInt(0);

  Utf8BytesScanner scanner = new Utf8BytesScanner(bytes,
      includeComments: false,
      configuration: configuration, languageVersionChanged:
          (Scanner scanner, LanguageVersionToken languageVersion) {
    parsedChunks.add(
        new _LanguageVersionChunk(languageVersion.major, languageVersion.minor)
          ..originalPosition = originalPosition.value++);
  });
  Token firstToken = scanner.tokenize();
  // ignore: unnecessary_null_comparison
  if (firstToken == null) {
    if (throwOnUnexpected) throw "firstToken is null";
    return null;
  }

  TextualOutlineListener listener = new TextualOutlineListener();
  ClassMemberParser classMemberParser = new ClassMemberParser(listener);
  classMemberParser.parseUnit(firstToken);
  if (listener.gotError && returnNullOnError) {
    return null;
  }

  Token? nextToken = firstToken;
  _UnknownTokenBuilder currentUnknown = new _UnknownTokenBuilder();
  while (nextToken != null) {
    if (nextToken is ErrorToken) {
      return null;
    }
    if (nextToken.isEof) break;

    nextToken = _textualizeTokens(listener, nextToken, currentUnknown,
        parsedChunks, originalPosition, addMarkerForUnknownForTest);
  }
  outputUnknownChunk(currentUnknown, parsedChunks, originalPosition,
      addMarkerForUnknownForTest);

  if (nextToken == null) return null;

  if (performModelling) {
    parsedChunks = _mergeAndSort(parsedChunks);
  }

  StringBuffer sb = new StringBuffer();
  for (_Chunk chunk in parsedChunks) {
    chunk.printOn(sb);
  }

  return sb.toString();
}

List<_Chunk> _mergeAndSort(List<_Chunk> chunks) {
  List<_Chunk> result = [];
  List<_MetadataChunk>? metadataChunks;
  List<_SingleImportExportChunk>? importExportChunks;
  StringBuffer sb = new StringBuffer();
  for (_Chunk chunk in chunks) {
    if (chunk is _MetadataChunk) {
      metadataChunks ??= <_MetadataChunk>[];
      metadataChunks.add(chunk);
    } else {
      chunk.metadata = metadataChunks;
      metadataChunks = null;
      chunk.internalMergeAndSort(sb);
      sb.clear();

      if (chunk is _SingleImportExportChunk) {
        importExportChunks ??= <_SingleImportExportChunk>[];
        importExportChunks.add(chunk);
      } else {
        if (importExportChunks != null) {
          _ImportExportChunk importExportChunk = new _ImportExportChunk(
              importExportChunks, importExportChunks.first.originalPosition);
          importExportChunk.internalMergeAndSort(sb);
          sb.clear();
          result.add(importExportChunk);
          importExportChunks = null;
        }
        result.add(chunk);
      }
    }
  }
  if (metadataChunks != null) {
    for (_MetadataChunk metadata in metadataChunks) {
      result.add(metadata);
    }
  }
  if (importExportChunks != null) {
    _ImportExportChunk importExportChunk = new _ImportExportChunk(
        importExportChunks, importExportChunks.first.originalPosition);
    importExportChunk.internalMergeAndSort(sb);
    sb.clear();
    result.add(importExportChunk);
    importExportChunks = null;
  }

  result.sort();
  return result;
}

/// Parses a chunk of tokens and returns the next - unparsed - token or null
/// on error.
Token? _textualizeTokens(
    TextualOutlineListener listener,
    Token token,
    _UnknownTokenBuilder currentUnknown,
    List<_Chunk> parsedChunks,
    BoxedInt originalPosition,
    bool addMarkerForUnknownForTest) {
  _ClassChunk? classChunk = listener.classStartToChunk[token];
  if (classChunk != null) {
    outputUnknownChunk(currentUnknown, parsedChunks, originalPosition,
        addMarkerForUnknownForTest);
    parsedChunks.add(classChunk..originalPosition = originalPosition.value++);
    return _textualizeClass(
        listener, classChunk, originalPosition, addMarkerForUnknownForTest);
  }

  _SingleImportExportChunk? singleImportExport =
      listener.importExportsStartToChunk[token];
  if (singleImportExport != null) {
    outputUnknownChunk(currentUnknown, parsedChunks, originalPosition,
        addMarkerForUnknownForTest);
    parsedChunks
        .add(singleImportExport..originalPosition = originalPosition.value++);
    return singleImportExport.endToken.next;
  }

  _TokenChunk? knownUnsortableChunk =
      listener.unsortableElementStartToChunk[token];
  if (knownUnsortableChunk != null) {
    outputUnknownChunk(currentUnknown, parsedChunks, originalPosition,
        addMarkerForUnknownForTest);
    parsedChunks
        .add(knownUnsortableChunk..originalPosition = originalPosition.value++);
    return knownUnsortableChunk.endToken.next;
  }

  _TokenChunk? elementChunk = listener.elementStartToChunk[token];
  if (elementChunk != null) {
    outputUnknownChunk(currentUnknown, parsedChunks, originalPosition,
        addMarkerForUnknownForTest);
    parsedChunks.add(elementChunk..originalPosition = originalPosition.value++);
    return elementChunk.endToken.next;
  }

  _MetadataChunk? metadataChunk = listener.metadataStartToChunk[token];
  if (metadataChunk != null) {
    outputUnknownChunk(currentUnknown, parsedChunks, originalPosition,
        addMarkerForUnknownForTest);
    parsedChunks
        .add(metadataChunk..originalPosition = originalPosition.value++);
    return metadataChunk.endToken.next;
  }

  // This token --- and whatever else tokens until we reach a start token we
  // know is an unknown chunk. We don't yet know the end.
  if (currentUnknown.start == null) {
    // Start of unknown chunk.
    currentUnknown.start = token;
    currentUnknown.interimEnd = token;
  } else {
    // Continued unknown chunk.
    currentUnknown.interimEnd = token;
  }
  return token.next;
}

Token _textualizeClass(TextualOutlineListener listener, _ClassChunk classChunk,
    BoxedInt originalPosition, bool addMarkerForUnknownForTest) {
  Token? token = classChunk.startToken;
  // Class header.
  while (token != classChunk.endToken) {
    if (token!.endGroup == classChunk.endToken) {
      break;
    }
    token = token.next;
  }
  classChunk.headerEnd = token;

  if (token == classChunk.endToken) {
    // This for instance happens on named mixins, e.g.
    // class C<T> = Object with A<Function(T)>;
    // or when the class has no content, e.g.
    // class C { }
    // either way, output the end token right away to avoid a weird line break.
  } else {
    token = token!.next;
    // "Normal" class with (possibly) content.
    _UnknownTokenBuilder currentUnknown = new _UnknownTokenBuilder();
    while (token != classChunk.endToken) {
      token = _textualizeTokens(listener, token!, currentUnknown,
          classChunk.content, originalPosition, addMarkerForUnknownForTest);
    }
    outputUnknownChunk(currentUnknown, classChunk.content, originalPosition,
        addMarkerForUnknownForTest);
    classChunk.footerStart = classChunk.endToken;
  }

  return classChunk.endToken.next!;
}

/// Outputs an unknown chunk if one has been started.
///
/// Resets the given builder.
void outputUnknownChunk(
    _UnknownTokenBuilder _currentUnknown,
    List<_Chunk> parsedChunks,
    BoxedInt originalPosition,
    bool addMarkerForUnknownForTest) {
  if (_currentUnknown.start == null) return;
  parsedChunks.add(new _UnknownChunk(addMarkerForUnknownForTest,
      _currentUnknown.start!, _currentUnknown.interimEnd!)
    ..originalPosition = originalPosition.value++);
  _currentUnknown.start = null;
  _currentUnknown.interimEnd = null;
}

void main(List<String> args) {
  File f = new File(args[0]);
  Uint8List data = f.readAsBytesSync();
  ScannerConfiguration scannerConfiguration = new ScannerConfiguration();
  String outline = textualOutline(data, scannerConfiguration,
      throwOnUnexpected: true, performModelling: true)!;
  if (args.length > 1 && args[1] == "--overwrite") {
    f.writeAsStringSync(outline);
  } else if (args.length > 1 && args[1] == "--benchmark") {
    Stopwatch stopwatch = new Stopwatch()..start();
    int numRuns = 100;
    for (int i = 0; i < numRuns; i++) {
      String? outline2 = textualOutline(data, scannerConfiguration,
          throwOnUnexpected: true, performModelling: true);
      if (outline2 != outline) 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++) {
      String? outline2 = textualOutline(data, scannerConfiguration,
          throwOnUnexpected: true, performModelling: true);
      if (outline2 != outline) 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(outline);
  }
}

class TextualOutlineListener extends Listener {
  bool gotError = false;
  final Map<Token, _ClassChunk> classStartToChunk = {};
  final Map<Token, _TokenChunk> elementStartToChunk = {};
  final Map<Token, _MetadataChunk> metadataStartToChunk = {};
  final Map<Token, _SingleImportExportChunk> importExportsStartToChunk = {};
  final Map<Token, _TokenChunk> unsortableElementStartToChunk = {};

  @override
  void endClassMethod(Token? getOrSet, Token beginToken, Token beginParam,
      Token? beginInitializers, Token endToken) {
    elementStartToChunk[beginToken] =
        new _ClassMethodChunk(beginToken, endToken);
  }

  @override
  void endTopLevelMethod(Token beginToken, Token? getOrSet, Token endToken) {
    elementStartToChunk[beginToken] =
        new _TopLevelMethodChunk(beginToken, endToken);
  }

  @override
  void endClassFactoryMethod(
      Token beginToken, Token factoryKeyword, Token endToken) {
    elementStartToChunk[beginToken] =
        new _ClassFactoryMethodChunk(beginToken, endToken);
  }

  @override
  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
    // Allow native functions.
  }

  @override
  void endClassFields(
      Token? abstractToken,
      Token? externalToken,
      Token? staticToken,
      Token? covariantToken,
      Token? lateToken,
      Token? varFinalOrConst,
      int count,
      Token beginToken,
      Token endToken) {
    elementStartToChunk[beginToken] =
        new _ClassFieldsChunk(beginToken, endToken);
  }

  @override
  void endTopLevelFields(
      Token? externalToken,
      Token? staticToken,
      Token? covariantToken,
      Token? lateToken,
      Token? varFinalOrConst,
      int count,
      Token beginToken,
      Token endToken) {
    elementStartToChunk[beginToken] =
        new _TopLevelFieldsChunk(beginToken, endToken);
  }

  @override
  void endFunctionTypeAlias(
      Token typedefKeyword, Token? equals, Token endToken) {
    elementStartToChunk[typedefKeyword] =
        new _FunctionTypeAliasChunk(typedefKeyword, endToken);
  }

  @override
  void endEnum(Token enumKeyword, Token leftBrace, int count) {
    elementStartToChunk[enumKeyword] =
        new _EnumChunk(enumKeyword, leftBrace.endGroup!);
  }

  @override
  void endLibraryName(Token libraryKeyword, Token semicolon) {
    unsortableElementStartToChunk[libraryKeyword] =
        new _LibraryNameChunk(libraryKeyword, semicolon);
  }

  @override
  void endPart(Token partKeyword, Token semicolon) {
    unsortableElementStartToChunk[partKeyword] =
        new _PartChunk(partKeyword, semicolon);
  }

  @override
  void endPartOf(
      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
    unsortableElementStartToChunk[partKeyword] =
        new _PartOfChunk(partKeyword, semicolon);
  }

  @override
  void endMetadata(Token beginToken, Token? periodBeforeName, Token endToken) {
    // Metadata's endToken is the one *after* the actual end of the metadata.
    metadataStartToChunk[beginToken] =
        new _MetadataChunk(beginToken, endToken.previous!);
  }

  @override
  void endClassDeclaration(Token beginToken, Token endToken) {
    classStartToChunk[beginToken] =
        new _ClassDeclarationChunk(beginToken, endToken);
  }

  @override
  void endMixinDeclaration(Token mixinKeyword, Token endToken) {
    classStartToChunk[mixinKeyword] =
        new _MixinDeclarationChunk(mixinKeyword, endToken);
  }

  @override
  void endExtensionDeclaration(Token extensionKeyword, Token? typeKeyword,
      Token onKeyword, Token? showKeyword, Token? hideKeyword, Token endToken) {
    classStartToChunk[extensionKeyword] =
        new _ExtensionDeclarationChunk(extensionKeyword, endToken);
  }

  @override
  void endNamedMixinApplication(Token beginToken, Token classKeyword,
      Token equals, Token? implementsKeyword, Token endToken) {
    classStartToChunk[beginToken] =
        new _NamedMixinApplicationChunk(beginToken, endToken);
  }

  Token? firstShowOrHide;
  List<_NamespaceCombinator>? _combinators;
  List<String>? _combinatorNames;

  @override
  void beginExport(Token export) {
    _combinators = <_NamespaceCombinator>[];
  }

  @override
  void beginImport(Token import) {
    _combinators = <_NamespaceCombinator>[];
  }

  @override
  void beginShow(Token show) {
    if (firstShowOrHide == null) firstShowOrHide = show;
    _combinatorNames = <String>[];
  }

  @override
  void beginHide(Token hide) {
    if (firstShowOrHide == null) firstShowOrHide = hide;
    _combinatorNames = <String>[];
  }

  @override
  void endHide(Token hide) {
    _combinators!.add(new _NamespaceCombinator.hide(_combinatorNames!));
    _combinatorNames = null;
  }

  @override
  void endShow(Token show) {
    _combinators!.add(new _NamespaceCombinator.show(_combinatorNames!));
    _combinatorNames = null;
  }

  @override
  void handleIdentifier(Token token, IdentifierContext context) {
    if (_combinatorNames != null && context == IdentifierContext.combinator) {
      _combinatorNames!.add(token.lexeme);
    }
  }

  @override
  void endImport(Token importKeyword, Token? semicolon) {
    // ignore: unnecessary_null_comparison
    if (importKeyword != null && semicolon != null) {
      importExportsStartToChunk[importKeyword] = new _ImportChunk(
          importKeyword, semicolon, firstShowOrHide, _combinators);
    }
    _combinators = null;
    firstShowOrHide = null;
  }

  @override
  void endExport(Token exportKeyword, Token semicolon) {
    importExportsStartToChunk[exportKeyword] = new _ExportChunk(
        exportKeyword, semicolon, firstShowOrHide, _combinators);
    _combinators = null;
    firstShowOrHide = null;
  }

  @override
  void handleRecoverableError(
      Message message, Token startToken, Token endToken) {
    gotError = true;
  }
}
