// Copyright (c) 2021, 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:convert';

import 'package:_fe_analyzer_shared/src/scanner/token.dart';
import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
    show ScannerConfiguration;
import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_prototype/file_system.dart';
import 'package:front_end/src/base/processed_options.dart';
import 'package:front_end/src/fasta/compiler_context.dart';
import 'package:front_end/src/fasta/uri_translator.dart';
import 'package:front_end/src/fasta/util/parser_ast_helper.dart';
import 'package:front_end/src/fasta/util/textual_outline.dart';
import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
import 'package:kernel/target/targets.dart';

import "parser_ast.dart";
import "abstracted_ast_nodes.dart";

// Overall TODO(s):
// * If entry is given as fileuri but exists as different import uri...
//   Does that matter?
// * Setters vs non-setters with naming conflicts.
// * -> also these might be found on "different levels", e.g. the setter might
//      be in the class and the getter might be in an import.
// * show/hide on imports and exports.
// * Handle importing/exporting non-existing files.
// * Tests.
// * Maybe bypass the direct-from-parser-ast stuff for speed?
// * Probably some of the special classes can be combined if we want to
//   (e.g. Class and Mixin).
// * Extensions --- we currently basically mark all we see.
//    => Could be perhaps only include them if the class they're talking about
//       is included? (or we don't know).
// * E.g. "factory Abc.b() => Abc3();" is the same as
//   "factory Abc.b() { return Abc3(); }" and Abc3 shouldn't be marked by it.
//    -> This is basically a rough edge on the textual outline though.
//    -> Also, the same applies to other instances of "=>".
// * It shouldn't lookup private stuff in other libraries.
// * Could there be made a distinction between for instance
//   `IdentifierContext.typeReference` and `IdentifierContext.expression`?
//   => one might not have to include content of classes that only talk about
//      typeReference I think.

Future<void> main(List<String> args) async {
  if (args.length != 2) {
    throw "Needs 2 arguments: packages file/dir and file to process.";
  }
  Uri packages = Uri.base.resolve(args[0]);
  Uri file = Uri.base.resolve(args[1]);
  for (int i = 0; i < 1; i++) {
    Stopwatch stopwatch = new Stopwatch()..start();
    await extractOutline([file], packages: packages, verbosityLevel: 40);
    print("Finished in ${stopwatch.elapsedMilliseconds} ms "
        "(textual outline was "
        "${latestProcessor!.textualOutlineStopwatch.elapsedMilliseconds} ms)"
        "(get ast was "
        "${latestProcessor!.getAstStopwatch.elapsedMilliseconds} ms)"
        "(extract identifier was "
        "${latestProcessor!.extractIdentifierStopwatch.elapsedMilliseconds} ms)"
        "");
  }
}

_Processor? latestProcessor;

Future<Map<Uri, String>> extractOutline(List<Uri> entryPointUris,
    {Uri? sdk,
    required Uri? packages,
    Uri? platform,
    Target? target,
    int verbosityLevel: 0}) {
  CompilerOptions options = new CompilerOptions()
    ..target = target
    ..packagesFileUri = packages
    ..sdkSummary = platform
    ..sdkRoot = sdk;
  ProcessedOptions pOptions =
      new ProcessedOptions(options: options, inputs: entryPointUris);
  return CompilerContext.runWithOptions(pOptions, (CompilerContext c) async {
    FileSystem fileSystem = c.options.fileSystem;
    UriTranslator uriTranslator = await c.options.getUriTranslator();
    _Processor processor =
        new _Processor(verbosityLevel, fileSystem, uriTranslator);
    latestProcessor = processor;
    List<TopLevel> entryPoints = [];
    for (Uri entryPointUri in entryPointUris) {
      TopLevel entryPoint = await processor.preprocessUri(entryPointUri);
      entryPoints.add(entryPoint);
    }
    return await processor.calculate(entryPoints);
  });
}

class _Processor {
  final FileSystem fileSystem;
  final UriTranslator uriTranslator;
  final int verbosityLevel;

  final Stopwatch textualOutlineStopwatch = new Stopwatch();
  final Stopwatch getAstStopwatch = new Stopwatch();
  final Stopwatch extractIdentifierStopwatch = new Stopwatch();

  Map<Uri, TopLevel> parsed = {};

  _Processor(this.verbosityLevel, this.fileSystem, this.uriTranslator);

  void log(String s) {
    if (verbosityLevel <= 0) return;
    print(s);
  }

  Future<TopLevel> preprocessUri(Uri importUri, {Uri? partOf}) async {
    if (verbosityLevel >= 20) log("$importUri =>");
    Uri fileUri = importUri;
    if (importUri.scheme == "package") {
      fileUri = uriTranslator.translate(importUri)!;
    }
    if (verbosityLevel >= 20) log("$fileUri");
    final List<int> bytes =
        await fileSystem.entityForUri(fileUri).readAsBytes();
    // TODO: Support updating the configuration; also default it to match
    // the package version.
    final ScannerConfiguration configuration = new ScannerConfiguration(
        enableExtensionMethods: true,
        enableNonNullable: true,
        enableTripleShift: true);
    textualOutlineStopwatch.start();
    final String? outlined = textualOutline(bytes, configuration);
    textualOutlineStopwatch.stop();
    if (outlined == null) throw "Textual outline returned null";
    final List<int> bytes2 = utf8.encode(outlined);
    getAstStopwatch.start();
    List<Token> languageVersionsSeen = [];
    final ParserAstNode ast = getAST(bytes2,
        enableExtensionMethods: configuration.enableExtensionMethods,
        enableNonNullable: configuration.enableNonNullable,
        enableTripleShift: configuration.enableTripleShift,
        languageVersionsSeen: languageVersionsSeen);
    getAstStopwatch.stop();

    _ParserAstVisitor visitor = new _ParserAstVisitor(
        verbosityLevel, outlined, importUri, partOf, ast, languageVersionsSeen);
    TopLevel topLevel = visitor.currentContainer as TopLevel;
    if (parsed[importUri] != null) throw "$importUri already set?!?";
    parsed[importUri] = topLevel;
    visitor.accept(ast);
    topLevel.buildScope();

    _IdentifierExtractor identifierExtractor = new _IdentifierExtractor();
    extractIdentifierStopwatch.start();
    identifierExtractor.extract(ast);
    extractIdentifierStopwatch.stop();
    for (IdentifierHandle identifier in identifierExtractor.identifiers) {
      if (identifier.context == IdentifierContext.typeVariableDeclaration) {
        // Hack: Put type variable declarations into scope so any overlap in
        // name doesn't mark usages (e.g. a class E shouldn't be marked if we're
        // talking about the type variable E).
        ParserAstNode content = identifier;
        AstNode? nearestAstNode = visitor.map[content];
        while (nearestAstNode == null && content.parent != null) {
          content = content.parent!;
          nearestAstNode = visitor.map[content];
        }
        if (nearestAstNode == null) {
          content = identifier;
          nearestAstNode = visitor.map[content];
          while (nearestAstNode == null && content.parent != null) {
            content = content.parent!;
            nearestAstNode = visitor.map[content];
          }

          StringBuffer sb = new StringBuffer();
          Token t = identifier.token;
          // for(int i = 0; i < 10; i++) {
          //   t = t.previous!;
          // }
          for (int i = 0; i < 20; i++) {
            sb.write("$t ");
            t = t.next!;
          }
          throw "$fileUri --- couldn't even find nearest ast node for "
              "${identifier.token} :( -- context $sb";
        }
        (nearestAstNode.scope[identifier.token.lexeme] ??= [])
            .add(nearestAstNode);
      }
    }

    return topLevel;
  }

  Future<void> _premarkTopLevel(List<_TopLevelAndAstNode> worklist,
      Set<TopLevel> closed, TopLevel entrypointish) async {
    if (!closed.add(entrypointish)) return;

    for (AstNode child in entrypointish.children) {
      child.marked = Coloring.Marked;
      worklist.add(new _TopLevelAndAstNode(entrypointish, child));

      if (child is Part) {
        if (child.uri.scheme != "dart") {
          TopLevel partTopLevel = parsed[child.uri] ??
              await preprocessUri(child.uri, partOf: entrypointish.uri);
          await _premarkTopLevel(worklist, closed, partTopLevel);
        }
      } else if (child is Export) {
        for (Uri importedUri in child.uris) {
          if (importedUri.scheme != "dart") {
            TopLevel exportTopLevel =
                parsed[importedUri] ?? await preprocessUri(importedUri);
            await _premarkTopLevel(worklist, closed, exportTopLevel);
          }
        }
      }
    }
  }

  Future<List<TopLevel>> _preprocessImportsAsNeeded(
      Map<TopLevel, List<TopLevel>> imports, TopLevel topLevel) async {
    List<TopLevel>? imported = imports[topLevel];
    if (imported == null) {
      // Process all imports.
      imported = [];
      imports[topLevel] = imported;
      for (AstNode child in topLevel.children) {
        if (child is Import) {
          child.marked = Coloring.Marked;
          for (Uri importedUri in child.uris) {
            if (importedUri.scheme != "dart") {
              TopLevel importedTopLevel =
                  parsed[importedUri] ?? await preprocessUri(importedUri);
              imported.add(importedTopLevel);
            }
          }
        } else if (child is PartOf) {
          child.marked = Coloring.Marked;
          if (child.partOfUri.scheme != "dart") {
            TopLevel part = parsed[child.partOfUri]!;
            List<TopLevel> importsFromPart =
                await _preprocessImportsAsNeeded(imports, part);
            imported.addAll(importsFromPart);
          }
        }
      }
    }
    return imported;
  }

  Future<Map<Uri, String>> calculate(List<TopLevel> entryPoints) async {
    List<_TopLevelAndAstNode> worklist = [];
    Map<TopLevel, List<TopLevel>> imports = {};

    // Mark all top-level in entry point. Also include parts and exports (and
    // exports exports etc) of the entry point.
    Set<TopLevel> closed = {};
    for (TopLevel entryPoint in entryPoints) {
      await _premarkTopLevel(worklist, closed, entryPoint);
    }

    Map<TopLevel, Set<String>> lookupsAll = {};
    Map<TopLevel, List<String>> lookupsWorklist = {};
    while (worklist.isNotEmpty || lookupsWorklist.isNotEmpty) {
      while (worklist.isNotEmpty) {
        _TopLevelAndAstNode entry = worklist.removeLast();
        if (verbosityLevel >= 20) {
          log("\n-----\nProcessing ${entry.entry.node.toString()}");
        }
        _IdentifierExtractor identifierExtractor = new _IdentifierExtractor();
        identifierExtractor.extract(entry.entry.node);
        if (verbosityLevel >= 20) {
          log("Found ${identifierExtractor.identifiers}");
        }
        List<AstNode>? prevLookupResult;
        nextIdentifier:
        for (IdentifierHandle identifier in identifierExtractor.identifiers) {
          ParserAstNode content = identifier;
          AstNode? nearestAstNode = entry.topLevel.map[content];
          while (nearestAstNode == null && content.parent != null) {
            content = content.parent!;
            nearestAstNode = entry.topLevel.map[content];
          }
          if (nearestAstNode == null) {
            throw "couldn't even find nearest ast node for "
                "${identifier.token} :(";
          }

          if (identifier.context == IdentifierContext.typeReference ||
              identifier.context == IdentifierContext.prefixedTypeReference ||
              identifier.context ==
                  IdentifierContext.typeReferenceContinuation ||
              identifier.context == IdentifierContext.constructorReference ||
              identifier.context ==
                  IdentifierContext.constructorReferenceContinuation ||
              identifier.context == IdentifierContext.expression ||
              identifier.context == IdentifierContext.expressionContinuation ||
              identifier.context == IdentifierContext.metadataReference ||
              identifier.context == IdentifierContext.metadataContinuation) {
            bool lookupInThisScope = true;
            if (!identifier.context.isContinuation) {
              prevLookupResult = null;
            } else if (prevLookupResult != null) {
              // In continuation.
              // either 0 or all should be imports.
              for (AstNode prevResult in prevLookupResult) {
                if (prevResult is Import) {
                  lookupInThisScope = false;
                } else {
                  continue nextIdentifier;
                }
              }
            } else {
              // Still in continuation --- but prev lookup didn't yield
              // anything. We shouldn't search for the continuation part in this
              // scope (and thus skip looking in imports).
              lookupInThisScope = false;
            }
            if (verbosityLevel >= 20) {
              log("${identifier.token} (${identifier.context})");
            }

            // Now we need parts at this point. Either we're in the entry point
            // in which case parts was read by [_premarkTopLevel], or we're here
            // via lookups on an import, where parts were read too.
            List<AstNode>? lookedUp;
            if (lookupInThisScope) {
              lookedUp = findInScope(
                  identifier.token.lexeme, nearestAstNode, entry.topLevel);
              prevLookupResult = lookedUp;
            }
            if (lookedUp != null) {
              for (AstNode found in lookedUp) {
                if (verbosityLevel >= 20) log(" => found $found");
                if (found.marked == Coloring.Untouched) {
                  found.marked = Coloring.Marked;
                  TopLevel foundTopLevel = entry.topLevel;
                  if (found.parent is TopLevel) {
                    foundTopLevel = found.parent as TopLevel;
                  }
                  worklist.add(new _TopLevelAndAstNode(foundTopLevel, found));
                }
              }
            } else {
              if (verbosityLevel >= 20) {
                log("=> Should find this via an import probably?");
              }

              List<TopLevel> imported =
                  await _preprocessImportsAsNeeded(imports, entry.topLevel);

              Set<Uri>? wantedImportUrls;
              if (!lookupInThisScope && prevLookupResult != null) {
                for (AstNode castMeAsImport in prevLookupResult) {
                  Import import = castMeAsImport as Import;
                  assert(import.asName != null);
                  (wantedImportUrls ??= {}).addAll(import.uris);
                }
              }

              for (TopLevel other in imported) {
                if (!lookupInThisScope && prevLookupResult != null) {
                  assert(wantedImportUrls != null);
                  if (!wantedImportUrls!.contains(other.uri)) continue;
                }

                Set<String> lookupStrings = lookupsAll[other] ??= {};
                if (lookupStrings.add(identifier.token.lexeme)) {
                  List<String> lookupStringsWorklist =
                      lookupsWorklist[other] ??= [];
                  lookupStringsWorklist.add(identifier.token.lexeme);
                }
              }
            }
          } else {
            if (verbosityLevel >= 30) {
              log("Ignoring ${identifier.token} as it's a "
                  "${identifier.context}");
            }
          }
        }
      }
      Map<TopLevel, List<String>> lookupsWorklistTmp = {};
      for (MapEntry<TopLevel, List<String>> lookups
          in lookupsWorklist.entries) {
        TopLevel topLevel = lookups.key;
        // We have to make the same lookups in parts and exports too.
        for (AstNode child in topLevel.children) {
          TopLevel? other;
          if (child is Part) {
            child.marked = Coloring.Marked;
            // do stuff to part.
            if (child.uri.scheme != "dart") {
              other = parsed[child.uri] ??
                  await preprocessUri(child.uri, partOf: topLevel.uri);
            }
          } else if (child is Export) {
            child.marked = Coloring.Marked;
            // do stuff to export.
            for (Uri importedUri in child.uris) {
              if (importedUri.scheme != "dart") {
                other = parsed[importedUri] ?? await preprocessUri(importedUri);
              }
            }
          } else if (child is Extension) {
            // TODO: Maybe put on a list to process later and only include if
            // the on-class is included?
            if (child.marked == Coloring.Untouched) {
              child.marked = Coloring.Marked;
              worklist.add(new _TopLevelAndAstNode(topLevel, child));
            }
          }
          if (other != null) {
            Set<String> lookupStrings = lookupsAll[other] ??= {};
            for (String identifier in lookups.value) {
              if (lookupStrings.add(identifier)) {
                List<String> lookupStringsWorklist =
                    lookupsWorklistTmp[other] ??= [];
                lookupStringsWorklist.add(identifier);
              }
            }
          }
        }

        for (String identifier in lookups.value) {
          List<AstNode>? foundInScope = topLevel.findInScope(identifier);
          if (foundInScope != null) {
            for (AstNode found in foundInScope) {
              if (found.marked == Coloring.Untouched) {
                found.marked = Coloring.Marked;
                worklist.add(new _TopLevelAndAstNode(topLevel, found));
              }
              if (verbosityLevel >= 20) {
                log(" => found $found via import (${found.marked})");
              }
            }
          }
        }
      }
      lookupsWorklist = lookupsWorklistTmp;
    }

    if (verbosityLevel >= 40) {
      log("\n\n---------\n\n");
      log(parsed.toString());
      log("\n\n---------\n\n");
    }

    // Extract.
    int count = 0;
    Map<Uri, String> result = {};
    // We only read imports if we need to lookup in them, but if a import
    // statement is included in the output the file has to exist if it actually
    // exists to not get a compilation error.
    Set<Uri> imported = {};
    for (MapEntry<Uri, TopLevel> entry in parsed.entries) {
      if (verbosityLevel >= 40) log("${entry.key}:");
      StringBuffer sb = new StringBuffer();
      for (AstNode child in entry.value.children) {
        if (child.marked == Coloring.Marked) {
          String substring = entry.value.sourceText.substring(
              child.startInclusive.charOffset, child.endInclusive.charEnd);
          sb.writeln(substring);
          if (verbosityLevel >= 40) {
            log(substring);
          }
          if (child is Import) {
            for (Uri importedUri in child.uris) {
              if (importedUri.scheme != "dart") {
                imported.add(importedUri);
              }
            }
          }
        }
      }
      if (sb.isNotEmpty) count++;
      Uri uri = entry.key;
      Uri fileUri = uri;
      if (uri.scheme == "package") {
        fileUri = uriTranslator.translate(uri)!;
      }
      result[fileUri] = sb.toString();
    }
    for (Uri uri in imported) {
      TopLevel? topLevel = parsed[uri];
      if (topLevel != null) continue;
      // uri imports a file we haven't read. Check if it exists and include it
      // as an empty file if it does.
      Uri fileUri = uri;
      if (uri.scheme == "package") {
        fileUri = uriTranslator.translate(uri)!;
      }
      if (await fileSystem.entityForUri(fileUri).exists()) {
        result[fileUri] = "";
      }
    }

    print("=> Long story short got it to $count non-empty files...");

    return result;
  }

  List<AstNode>? findInScope(
      String name, AstNode nearestAstNode, TopLevel topLevel,
      {Set<TopLevel>? visited}) {
    List<AstNode>? result;
    result = nearestAstNode.findInScope(name);
    if (result != null) return result;
    for (AstNode child in topLevel.children) {
      if (child is Part) {
        visited ??= {topLevel};
        TopLevel partTopLevel = parsed[child.uri]!;
        if (visited.add(partTopLevel)) {
          result =
              findInScope(name, partTopLevel, partTopLevel, visited: visited);
          if (result != null) return result;
        }
      } else if (child is PartOf) {
        visited ??= {topLevel};
        TopLevel partOwnerTopLevel = parsed[child.partOfUri]!;
        if (visited.add(partOwnerTopLevel)) {
          result = findInScope(name, partOwnerTopLevel, partOwnerTopLevel,
              visited: visited);
          if (result != null) return result;
        }
      }
    }
  }
}

class _TopLevelAndAstNode {
  final TopLevel topLevel;
  final AstNode entry;

  _TopLevelAndAstNode(this.topLevel, this.entry);
}

class _IdentifierExtractor {
  List<IdentifierHandle> identifiers = [];

  void extract(ParserAstNode ast) {
    if (ast is IdentifierHandle) {
      identifiers.add(ast);
    }
    List<ParserAstNode>? children = ast.children;
    if (children != null) {
      for (ParserAstNode child in children) {
        extract(child);
      }
    }
  }
}

class _ParserAstVisitor extends ParserAstVisitor {
  final Uri uri;
  final Uri? partOfUri;
  late Container currentContainer;
  final Map<ParserAstNode, AstNode> map = {};
  final int verbosityLevel;
  final List<Token> languageVersionsSeen;

  _ParserAstVisitor(this.verbosityLevel, String sourceText, this.uri,
      this.partOfUri, ParserAstNode rootAst, this.languageVersionsSeen) {
    currentContainer = new TopLevel(sourceText, uri, rootAst, map);
    if (languageVersionsSeen.isNotEmpty) {
      // Use first one.
      Token languageVersion = languageVersionsSeen.first;
      ParserAstNode dummyNode = new NoInitializersHandle(ParserAstType.HANDLE);
      LanguageVersion version =
          new LanguageVersion(dummyNode, languageVersion, languageVersion);
      version.marked = Coloring.Marked;
      currentContainer.addChild(version, map);
    }
  }

  void log(String s) {
    if (verbosityLevel <= 0) return;
    Container? x = currentContainer.parent;
    int level = 0;
    while (x != null) {
      level++;
      x = x.parent;
    }
    print(" " * level + s);
  }

  @override
  void visitClass(
      ClassDeclarationEnd node, Token startInclusive, Token endInclusive) {
    TopLevelDeclarationEnd parent = node.parent! as TopLevelDeclarationEnd;
    IdentifierHandle identifier = parent.getIdentifier();

    log("Hello from class ${identifier.token}");

    Class cls = new Class(
        parent, identifier.token.lexeme, startInclusive, endInclusive);
    currentContainer.addChild(cls, map);

    Container previousContainer = currentContainer;
    currentContainer = cls;
    super.visitClass(node, startInclusive, endInclusive);
    currentContainer = previousContainer;
  }

  @override
  void visitClassConstructor(
      ClassConstructorEnd node, Token startInclusive, Token endInclusive) {
    assert(currentContainer is Class);
    List<IdentifierHandle> ids = node.getIdentifiers();
    if (ids.length == 1) {
      ClassConstructor classConstructor = new ClassConstructor(
          node, ids.single.token.lexeme, startInclusive, endInclusive);
      currentContainer.addChild(classConstructor, map);
      log("Hello from constructor ${ids.single.token}");
    } else if (ids.length == 2) {
      ClassConstructor classConstructor = new ClassConstructor(node,
          "${ids.first.token}.${ids.last.token}", startInclusive, endInclusive);
      map[node] = classConstructor;
      currentContainer.addChild(classConstructor, map);
      log("Hello from constructor ${ids.first.token}.${ids.last.token}");
    } else {
      throw "Unexpected identifiers in class constructor";
    }

    super.visitClassConstructor(node, startInclusive, endInclusive);
  }

  @override
  void visitClassFactoryMethod(
      ClassFactoryMethodEnd node, Token startInclusive, Token endInclusive) {
    assert(currentContainer is Class);
    List<IdentifierHandle> ids = node.getIdentifiers();
    if (ids.length == 1) {
      ClassFactoryMethod classFactoryMethod = new ClassFactoryMethod(
          node, ids.single.token.lexeme, startInclusive, endInclusive);
      currentContainer.addChild(classFactoryMethod, map);
      log("Hello from factory method ${ids.single.token}");
    } else if (ids.length == 2) {
      ClassFactoryMethod classFactoryMethod = new ClassFactoryMethod(node,
          "${ids.first.token}.${ids.last.token}", startInclusive, endInclusive);
      map[node] = classFactoryMethod;
      currentContainer.addChild(classFactoryMethod, map);
      log("Hello from factory method ${ids.first.token}.${ids.last.token}");
    } else {
      Container findTopLevel = currentContainer;
      while (findTopLevel is! TopLevel) {
        findTopLevel = findTopLevel.parent!;
      }
      String src = findTopLevel.sourceText
          .substring(startInclusive.charOffset, endInclusive.charEnd);
      throw "Unexpected identifiers in class factory method: $ids "
          "(${ids.map((e) => e.token.lexeme).toList()}) --- "
          "error on source ${src} --- "
          "${node.children}";
    }

    super.visitClassFactoryMethod(node, startInclusive, endInclusive);
  }

  @override
  void visitClassFields(
      ClassFieldsEnd node, Token startInclusive, Token endInclusive) {
    assert(currentContainer is Class);
    List<String> fields =
        node.getFieldIdentifiers().map((e) => e.token.lexeme).toList();
    ClassFields classFields =
        new ClassFields(node, fields, startInclusive, endInclusive);
    currentContainer.addChild(classFields, map);
    log("Hello from class fields ${fields.join(", ")}");
    super.visitClassFields(node, startInclusive, endInclusive);
  }

  @override
  void visitClassMethod(
      ClassMethodEnd node, Token startInclusive, Token endInclusive) {
    assert(currentContainer is Class);

    String identifier;
    try {
      identifier = node.getNameIdentifier();
    } catch (e) {
      Container findTopLevel = currentContainer;
      while (findTopLevel is! TopLevel) {
        findTopLevel = findTopLevel.parent!;
      }
      String src = findTopLevel.sourceText
          .substring(startInclusive.charOffset, endInclusive.charEnd);
      throw "Unexpected identifiers in visitClassMethod --- "
          "error on source ${src} --- "
          "${node.children}";
    }
    ClassMethod classMethod =
        new ClassMethod(node, identifier, startInclusive, endInclusive);
    currentContainer.addChild(classMethod, map);
    log("Hello from class method $identifier");
    super.visitClassMethod(node, startInclusive, endInclusive);
  }

  @override
  void visitEnum(EnumEnd node, Token startInclusive, Token endInclusive) {
    List<IdentifierHandle> ids = node.getIdentifiers();

    Enum e = new Enum(
        node,
        ids.first.token.lexeme,
        ids.skip(1).map((e) => e.token.lexeme).toList(),
        startInclusive,
        endInclusive);
    currentContainer.addChild(e, map);

    log("Hello from enum ${ids.first.token} with content "
        "${ids.skip(1).map((e) => e.token).join(", ")}");
    super.visitEnum(node, startInclusive, endInclusive);
  }

  @override
  void visitExport(ExportEnd node, Token startInclusive, Token endInclusive) {
    String uriString = node.getExportUriString();
    Uri exportUri = uri.resolve(uriString);
    List<String>? conditionalUriStrings = node.getConditionalExportUriStrings();
    List<Uri>? conditionalUris;
    if (conditionalUriStrings != null) {
      conditionalUris = [];
      for (String conditionalUri in conditionalUriStrings) {
        conditionalUris.add(uri.resolve(conditionalUri));
      }
    }
    // TODO: Use 'show' and 'hide' stuff.
    Export e = new Export(
        node, exportUri, conditionalUris, startInclusive, endInclusive);
    currentContainer.addChild(e, map);
    log("Hello export");
  }

  @override
  void visitExtension(
      ExtensionDeclarationEnd node, Token startInclusive, Token endInclusive) {
    ExtensionDeclarationBegin begin =
        node.children!.first as ExtensionDeclarationBegin;
    TopLevelDeclarationEnd parent = node.parent! as TopLevelDeclarationEnd;
    log("Hello from extension ${begin.name}");
    Extension extension =
        new Extension(parent, begin.name?.lexeme, startInclusive, endInclusive);
    currentContainer.addChild(extension, map);

    Container previousContainer = currentContainer;
    currentContainer = extension;
    super.visitExtension(node, startInclusive, endInclusive);
    currentContainer = previousContainer;
  }

  @override
  void visitExtensionConstructor(
      ExtensionConstructorEnd node, Token startInclusive, Token endInclusive) {
    // TODO: implement visitExtensionConstructor
    throw node;
  }

  @override
  void visitExtensionFactoryMethod(ExtensionFactoryMethodEnd node,
      Token startInclusive, Token endInclusive) {
    // TODO: implement visitExtensionFactoryMethod
    throw node;
  }

  @override
  void visitExtensionFields(
      ExtensionFieldsEnd node, Token startInclusive, Token endInclusive) {
    assert(currentContainer is Extension);
    List<String> fields =
        node.getFieldIdentifiers().map((e) => e.token.lexeme).toList();
    ExtensionFields classFields =
        new ExtensionFields(node, fields, startInclusive, endInclusive);
    currentContainer.addChild(classFields, map);
    log("Hello from extension fields ${fields.join(", ")}");
    super.visitExtensionFields(node, startInclusive, endInclusive);
  }

  @override
  void visitExtensionMethod(
      ExtensionMethodEnd node, Token startInclusive, Token endInclusive) {
    assert(currentContainer is Extension);
    ExtensionMethod extensionMethod = new ExtensionMethod(
        node, node.getNameIdentifier(), startInclusive, endInclusive);
    currentContainer.addChild(extensionMethod, map);
    log("Hello from extension method ${node.getNameIdentifier()}");
    super.visitExtensionMethod(node, startInclusive, endInclusive);
  }

  @override
  void visitImport(ImportEnd node, Token startInclusive, Token? endInclusive) {
    IdentifierHandle? prefix = node.getImportPrefix();
    String uriString = node.getImportUriString();
    Uri importUri = uri.resolve(uriString);
    List<String>? conditionalUriStrings = node.getConditionalImportUriStrings();
    List<Uri>? conditionalUris;
    if (conditionalUriStrings != null) {
      conditionalUris = [];
      for (String conditionalUri in conditionalUriStrings) {
        conditionalUris.add(uri.resolve(conditionalUri));
      }
    }
    // TODO: Use 'show' and 'hide' stuff.

    // endInclusive can be null on syntax errors and there's recovery of the
    // import. For now we'll ignore this.
    Import i = new Import(node, importUri, conditionalUris,
        prefix?.token.lexeme, startInclusive, endInclusive!);
    currentContainer.addChild(i, map);
    if (prefix == null) {
      log("Hello import");
    } else {
      log("Hello import as '${prefix.token}'");
    }
  }

  @override
  void visitLibraryName(
      LibraryNameEnd node, Token startInclusive, Token endInclusive) {
    LibraryName name = new LibraryName(node, startInclusive, endInclusive);
    name.marked = Coloring.Marked;
    currentContainer.addChild(name, map);
  }

  @override
  void visitMetadata(
      MetadataEnd node, Token startInclusive, Token endInclusive) {
    Metadata m = new Metadata(node, startInclusive, endInclusive);
    currentContainer.addChild(m, map);
  }

  @override
  void visitMixin(
      MixinDeclarationEnd node, Token startInclusive, Token endInclusive) {
    TopLevelDeclarationEnd parent = node.parent! as TopLevelDeclarationEnd;
    IdentifierHandle identifier = parent.getIdentifier();
    log("Hello from mixin ${identifier.token}");

    Mixin mixin = new Mixin(
        parent, identifier.token.lexeme, startInclusive, endInclusive);
    currentContainer.addChild(mixin, map);

    Container previousContainer = currentContainer;
    currentContainer = mixin;
    super.visitMixin(node, startInclusive, endInclusive);
    currentContainer = previousContainer;
  }

  @override
  void visitMixinFields(
      MixinFieldsEnd node, Token startInclusive, Token endInclusive) {
    assert(currentContainer is Mixin);
    List<String> fields =
        node.getFieldIdentifiers().map((e) => e.token.lexeme).toList();
    MixinFields mixinFields =
        new MixinFields(node, fields, startInclusive, endInclusive);
    currentContainer.addChild(mixinFields, map);
    log("Hello from mixin fields ${fields.join(", ")}");
    super.visitMixinFields(node, startInclusive, endInclusive);
  }

  @override
  void visitMixinMethod(
      MixinMethodEnd node, Token startInclusive, Token endInclusive) {
    assert(currentContainer is Mixin);
    MixinMethod classMethod = new MixinMethod(
        node, node.getNameIdentifier(), startInclusive, endInclusive);
    currentContainer.addChild(classMethod, map);
    log("Hello from mixin method ${node.getNameIdentifier()}");
    super.visitMixinMethod(node, startInclusive, endInclusive);
  }

  @override
  void visitNamedMixin(
      NamedMixinApplicationEnd node, Token startInclusive, Token endInclusive) {
    TopLevelDeclarationEnd parent = node.parent! as TopLevelDeclarationEnd;
    IdentifierHandle identifier = parent.getIdentifier();
    log("Hello from named mixin ${identifier.token}");

    Mixin mixin = new Mixin(
        parent, identifier.token.lexeme, startInclusive, endInclusive);
    currentContainer.addChild(mixin, map);

    Container previousContainer = currentContainer;
    currentContainer = mixin;
    super.visitNamedMixin(node, startInclusive, endInclusive);
    currentContainer = previousContainer;
  }

  @override
  void visitPart(PartEnd node, Token startInclusive, Token endInclusive) {
    String uriString = node.getPartUriString();
    Uri partUri = uri.resolve(uriString);

    Part i = new Part(node, partUri, startInclusive, endInclusive);
    currentContainer.addChild(i, map);
    log("Hello part");
  }

  @override
  void visitPartOf(PartOfEnd node, Token startInclusive, Token endInclusive) {
    // We'll assume we've gotten here via a "part" so we'll ignore that for now.
    // TODO: partOfUri could - in an error case - be null.
    PartOf partof = new PartOf(node, partOfUri!, startInclusive, endInclusive);
    partof.marked = Coloring.Marked;
    currentContainer.addChild(partof, map);
  }

  @override
  void visitTopLevelFields(
      TopLevelFieldsEnd node, Token startInclusive, Token endInclusive) {
    List<String> fields =
        node.getFieldIdentifiers().map((e) => e.token.lexeme).toList();
    TopLevelFields f =
        new TopLevelFields(node, fields, startInclusive, endInclusive);
    currentContainer.addChild(f, map);
    log("Hello from top level fields ${fields.join(", ")}");
    super.visitTopLevelFields(node, startInclusive, endInclusive);
  }

  @override
  void visitTopLevelMethod(
      TopLevelMethodEnd node, Token startInclusive, Token endInclusive) {
    TopLevelMethod m = new TopLevelMethod(node,
        node.getNameIdentifier().token.lexeme, startInclusive, endInclusive);
    currentContainer.addChild(m, map);
    log("Hello from top level method ${node.getNameIdentifier().token}");
    super.visitTopLevelMethod(node, startInclusive, endInclusive);
  }

  @override
  void visitTypedef(TypedefEnd node, Token startInclusive, Token endInclusive) {
    Typedef t = new Typedef(node, node.getNameIdentifier().token.lexeme,
        startInclusive, endInclusive);
    currentContainer.addChild(t, map);
    log("Hello from typedef ${node.getNameIdentifier().token}");
    super.visitTypedef(node, startInclusive, endInclusive);
  }
}
