// 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/direct_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 "direct_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 DirectParserASTContent 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 (DirectParserASTContentIdentifierHandle 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).
        DirectParserASTContent 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 (DirectParserASTContentIdentifierHandle identifier
            in identifierExtractor.identifiers) {
          DirectParserASTContent 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<DirectParserASTContentIdentifierHandle> identifiers = [];

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

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

  _ParserAstVisitor(
      this.verbosityLevel,
      String sourceText,
      this.uri,
      this.partOfUri,
      DirectParserASTContent rootAst,
      this.languageVersionsSeen) {
    currentContainer = new TopLevel(sourceText, uri, rootAst, map);
    if (languageVersionsSeen.isNotEmpty) {
      // Use first one.
      Token languageVersion = languageVersionsSeen.first;
      DirectParserASTContent dummyNode =
          new DirectParserASTContentNoInitializersHandle(
              DirectParserASTType.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(DirectParserASTContentClassDeclarationEnd node,
      Token startInclusive, Token endInclusive) {
    DirectParserASTContentTopLevelDeclarationEnd parent =
        node.parent! as DirectParserASTContentTopLevelDeclarationEnd;
    DirectParserASTContentIdentifierHandle 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(DirectParserASTContentClassConstructorEnd node,
      Token startInclusive, Token endInclusive) {
    assert(currentContainer is Class);
    List<DirectParserASTContentIdentifierHandle> 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(DirectParserASTContentClassFactoryMethodEnd node,
      Token startInclusive, Token endInclusive) {
    assert(currentContainer is Class);
    List<DirectParserASTContentIdentifierHandle> 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(DirectParserASTContentClassFieldsEnd 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(DirectParserASTContentClassMethodEnd 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(DirectParserASTContentEnumEnd node, Token startInclusive,
      Token endInclusive) {
    List<DirectParserASTContentIdentifierHandle> 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(DirectParserASTContentExportEnd 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(DirectParserASTContentExtensionDeclarationEnd node,
      Token startInclusive, Token endInclusive) {
    DirectParserASTContentExtensionDeclarationBegin begin =
        node.children!.first as DirectParserASTContentExtensionDeclarationBegin;
    DirectParserASTContentTopLevelDeclarationEnd parent =
        node.parent! as DirectParserASTContentTopLevelDeclarationEnd;
    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(
      DirectParserASTContentExtensionConstructorEnd node,
      Token startInclusive,
      Token endInclusive) {
    // TODO: implement visitExtensionConstructor
    throw node;
  }

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

  @override
  void visitExtensionFields(DirectParserASTContentExtensionFieldsEnd 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(DirectParserASTContentExtensionMethodEnd 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(DirectParserASTContentImportEnd node, Token startInclusive,
      Token? endInclusive) {
    DirectParserASTContentIdentifierHandle? 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(DirectParserASTContentLibraryNameEnd node,
      Token startInclusive, Token endInclusive) {
    LibraryName name = new LibraryName(node, startInclusive, endInclusive);
    name.marked = Coloring.Marked;
    currentContainer.addChild(name, map);
  }

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

  @override
  void visitMixin(DirectParserASTContentMixinDeclarationEnd node,
      Token startInclusive, Token endInclusive) {
    DirectParserASTContentTopLevelDeclarationEnd parent =
        node.parent! as DirectParserASTContentTopLevelDeclarationEnd;
    DirectParserASTContentIdentifierHandle 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(DirectParserASTContentMixinFieldsEnd 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(DirectParserASTContentMixinMethodEnd 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(DirectParserASTContentNamedMixinApplicationEnd node,
      Token startInclusive, Token endInclusive) {
    DirectParserASTContentTopLevelDeclarationEnd parent =
        node.parent! as DirectParserASTContentTopLevelDeclarationEnd;
    DirectParserASTContentIdentifierHandle 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(DirectParserASTContentPartEnd 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(DirectParserASTContentPartOfEnd 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(DirectParserASTContentTopLevelFieldsEnd 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(DirectParserASTContentTopLevelMethodEnd 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(DirectParserASTContentTypedefEnd 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);
  }
}
