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

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/src/dart/analysis/driver_event.dart' as events;
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/library_graph.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/dart/analysis/status.dart';
import 'package:analyzer/src/fine/library_manifest.dart';
import 'package:analyzer/src/fine/lookup_name.dart';
import 'package:analyzer/src/fine/manifest_ast.dart';
import 'package:analyzer/src/fine/manifest_context.dart';
import 'package:analyzer/src/fine/manifest_id.dart';
import 'package:analyzer/src/fine/manifest_item.dart';
import 'package:analyzer/src/fine/manifest_type.dart';
import 'package:analyzer/src/fine/requirement_failure.dart';
import 'package:analyzer/src/fine/requirements.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/utilities/extensions/file_system.dart';
import 'package:analyzer_utilities/testing/tree_string_sink.dart';
import 'package:collection/collection.dart';
import 'package:test/test.dart';

import '../../../util/element_printer.dart';
import '../../summary/element_text.dart';
import '../../summary/resolved_ast_printer.dart';

class BundleRequirementsPrinter {
  final DriverEventsPrinterConfiguration configuration;
  final TreeStringSink sink;
  final IdProvider idProvider;

  BundleRequirementsPrinter({
    required this.configuration,
    required this.sink,
    required this.idProvider,
  });

  void write(RequirementsManifest requirements) {
    sink.writelnWithIndent('requirements');
    sink.withIndent(() {
      var libEntries = requirements.libraries.sorted;

      libEntries.removeWhere((entry) {
        var ignored = configuration.requirements.ignoredLibraries;
        return ignored.contains(entry.key);
      });

      sink.writeElements('libraries', libEntries, (libEntry) {
        var libraryUri = libEntry.key;
        var libraryRequirements = libEntry.value;
        sink.writelnWithIndent('$libraryUri');
        sink.withIndent(() {
          _writeExportedTopLevels(libraryRequirements);
          _writeInstanceItems(libraryRequirements);
          _writeInterfaceItems(libraryRequirements);
          _writeExportedExtensions(libraryRequirements);
        });
      });

      _writeExportRequirements(requirements);
      _writeOpaqueApiUses(requirements);
    });
  }

  void _writeExportCombinators(ExportRequirement requirement) {
    sink.writeElements('combinators', requirement.combinators, (combinator) {
      switch (combinator) {
        case ExportRequirementHideCombinator():
          var baseNames = combinator.hiddenBaseNames.sorted();
          sink.writelnWithIndent('hide ${baseNames.join(', ')}');
        case ExportRequirementShowCombinator():
          var baseNames = combinator.shownBaseNames.sorted();
          sink.writelnWithIndent('show ${baseNames.join(', ')}');
      }
    });
  }

  void _writeExportedExtensions(LibraryRequirements requirements) {
    if (requirements.exportedExtensions case var extensions?) {
      var idListStr = extensions.asString(idProvider);
      if (idListStr.isEmpty) {
        idListStr = '[]';
      }
      sink.writelnWithIndent('exportedExtensions: $idListStr');
    }
  }

  void _writeExportedTopLevels(LibraryRequirements requirements) {
    var entries = requirements.exportedTopLevels.sorted;
    sink.writeElements('exportedTopLevels', entries, (entry) {
      _writeNamedId(entry);
    });
  }

  void _writeExportRequirements(RequirementsManifest requirements) {
    var exportRequirements = requirements.exportRequirements.sortedBy(
      (requirement) => requirement.libraryUri.toString(),
    );

    sink.writeElements('exportRequirements', exportRequirements, (
      libraryRequirements,
    ) {
      sink.writelnWithIndent(libraryRequirements.libraryUri);
      sink.withIndent(() {
        if (libraryRequirements.declaredTopNames.isNotEmpty) {
          var declaredTopNamesStr = libraryRequirements.declaredTopNames
              .map((lookupName) => lookupName.asString)
              .join(' ');
          sink.writelnWithIndent('declaredTopNames: $declaredTopNamesStr');
        }
        sink.writeElements(
          'exports',
          libraryRequirements.exports.sortedBy(
            (export) => export.exportedUri.toString(),
          ),
          (fragment) {
            sink.writelnWithIndent(fragment.exportedUri);
            sink.withIndent(() {
              _writeExportCombinators(fragment);
              for (var entry in fragment.exportedIds.sorted) {
                _writeNamedId(entry);
              }
            });
          },
        );
      });
    });
  }

  void _writeInstanceItems(LibraryRequirements requirements) {
    var instanceEntries = requirements.instances.sorted;
    sink.writeElements('instances', instanceEntries, (instanceEntry) {
      var instanceRequirements = instanceEntry.value;
      sink.writelnWithIndent(instanceEntry.key.asString);

      sink.withIndent(() {
        void writeRequestedDeclared(
          String name,
          Map<LookupName, ManifestItemId?> nameToIdMap,
        ) {
          sink.writeElements(name, nameToIdMap.sorted, _writeNamedId);
        }

        writeRequestedDeclared(
          'requestedDeclaredFields',
          instanceRequirements.requestedDeclaredFields,
        );
        writeRequestedDeclared(
          'requestedDeclaredGetters',
          instanceRequirements.requestedDeclaredGetters,
        );
        writeRequestedDeclared(
          'requestedDeclaredSetters',
          instanceRequirements.requestedDeclaredSetters,
        );
        writeRequestedDeclared(
          'requestedDeclaredMethods',
          instanceRequirements.requestedDeclaredMethods,
        );
      });

      sink.withIndent(() {
        void writeAllDeclared(String name, ManifestItemIdList? idList) {
          if (idList != null && idList.ids.isNotEmpty) {
            var idListStr = idList.asString(idProvider);
            sink.writelnWithIndent('$name: $idListStr');
          }
        }

        writeAllDeclared(
          'allDeclaredFields',
          instanceRequirements.allDeclaredFields,
        );
        writeAllDeclared(
          'allDeclaredGetters',
          instanceRequirements.allDeclaredGetters,
        );
        writeAllDeclared(
          'allDeclaredSetters',
          instanceRequirements.allDeclaredSetters,
        );
        writeAllDeclared(
          'allDeclaredMethods',
          instanceRequirements.allDeclaredMethods,
        );
      });
    });
  }

  void _writeInterfaceItems(LibraryRequirements requirements) {
    var interfaceEntries = requirements.interfaces.sorted;
    sink.writeElements('interfaces', interfaceEntries, (interfaceEntry) {
      sink.writelnWithIndent(interfaceEntry.key.asString);
      sink.withIndent(() {
        var requirements = interfaceEntry.value;
        if (requirements.interfaceId case var id?) {
          var idStr = idProvider.manifestId(id);
          sink.writelnWithIndent('interfaceId: $idStr');
        }
        if (requirements.allConstructors case var allConstructors?) {
          if (allConstructors.ids.isNotEmpty) {
            var idListStr = allConstructors.asString(idProvider);
            sink.writelnWithIndent('allConstructors: $idListStr');
          }
        }
        sink.writeElements(
          'requestedConstructors',
          requirements.requestedConstructors.sorted,
          _writeNamedId,
        );
        sink.writeElements(
          'methods',
          requirements.methods.sorted,
          _writeNamedId,
        );
      });
    });
  }

  void _writeNamedId(MapEntry<LookupName, ManifestItemId?> entry) {
    if (entry.value case var id?) {
      var idStr = idProvider.manifestId(id);
      sink.writelnWithIndent('${entry.key}: $idStr');
    } else {
      sink.writelnWithIndent('${entry.key}: <null>');
    }
  }

  void _writeOpaqueApiUses(RequirementsManifest requirements) {
    var usages = requirements.opaqueApiUses.sortedBy((e) {
      return '${e.targetRuntimeType}.${e.methodName}';
    });
    sink.writeElements('opaqueApiUses', usages, (usage) {
      sink.writelnWithIndent('${usage.targetRuntimeType}.${usage.methodName}');
      sink.withIndent(() {
        if (usage.targetElementLibraryUri case var libraryUri?) {
          sink.writelnWithIndent('targetElementLibraryUri: $libraryUri');
        }
        if (usage.targetElementName case var elementName?) {
          sink.writelnWithIndent('targetElementName: $elementName');
        }
      });
    });
  }
}

sealed class DriverEvent {}

class DriverEventsPrinter {
  final DriverEventsPrinterConfiguration configuration;
  final TreeStringSink sink;
  final ElementPrinter elementPrinter;
  final IdProvider idProvider;

  DriverEventsPrinter({
    required this.configuration,
    required this.sink,
    required this.elementPrinter,
    required this.idProvider,
  });

  void write(List<DriverEvent> events) {
    for (var event in events) {
      _writeEvent(event);
    }
  }

  void _writeAnalyzeFileEvent(events.AnalyzeFile object) {
    if (!configuration.withAnalyzeFileEvents) {
      return;
    }

    sink.writelnWithIndent('[operation] analyzeFile');
    sink.withIndent(() {
      var file = object.file.resource;
      sink.writelnWithIndent('file: ${file.posixPath}');
      var libraryFile = object.library.file.resource;
      sink.writelnWithIndent('library: ${libraryFile.posixPath}');
    });
  }

  void _writeCheckLibraryDiagnosticsRequirements(
    events.CheckLibraryDiagnosticsRequirements event,
  ) {
    if (configuration.withCheckLibraryDiagnosticsRequirements ||
        event.failure != null) {
      sink.writelnWithIndent('[operation] checkLibraryDiagnosticsRequirements');
      sink.withIndent(() {
        sink.writelnNamedFilePath('library', event.library.file);
        if (event.failure case var failure?) {
          _writeRequirementFailure(failure);
        } else {
          sink.writelnWithIndent('failure: null');
        }
      });
    }
  }

  void _writeCheckLinkedBundleRequirements(
    events.CheckLinkedBundleRequirements event,
  ) {
    if (configuration.withCheckLinkedBundleRequirements ||
        event.failure != null) {
      sink.writelnWithIndent('[operation] checkLinkedBundleRequirements');
      sink.withIndent(() {
        _writeLibraryCycle(event.cycle);
        if (event.failure case var failure?) {
          _writeRequirementFailure(failure);
        } else {
          sink.writelnWithIndent('failure: null');
        }
      });
    }
  }

  void _writeDiagnostic(Diagnostic d) {
    sink.writelnWithIndent('${d.offset} +${d.length} ${d.diagnosticCode.name}');
  }

  void _writeErrorsEvent(GetErrorsEvent event) {
    if (!configuration.withGetErrorsEvents) {
      return;
    }

    _writeGetEvent(event);
    sink.withIndent(() {
      _writeErrorsResult(event.result);
    });
  }

  void _writeErrorsResult(SomeErrorsResult result) {
    switch (result) {
      case ErrorsResultImpl():
        var id = idProvider[result];
        sink.writelnWithIndent('ErrorsResult $id');

        sink.withIndent(() {
          sink.writelnWithIndent('path: ${result.file.posixPath}');
          expect(result.path, result.file.path);

          sink.writelnWithIndent('uri: ${result.uri}');

          sink.writeFlags({
            'isLibrary': result.isLibrary,
            'isPart': result.isPart,
          });

          if (configuration.errorsConfiguration.withContentPredicate(result)) {
            sink.writelnWithIndent('content');
            sink.writeln('---');
            sink.write(result.content);
            sink.writeln('---');
          }

          sink.writeElements('errors', result.diagnostics, _writeDiagnostic);
        });
      case MissingSdkLibraryResultImpl():
        _writeMissingSdkLibraryResult(result);
      default:
        throw UnimplementedError('${result.runtimeType}');
    }
  }

  void _writeEvent(DriverEvent event) {
    switch (event) {
      case GetCachedResolvedUnitEvent():
        _writeGetCachedResolvedUnit(event);
      case GetErrorsEvent():
        _writeErrorsEvent(event);
      case GetIndexEvent():
        _writeIndexEvent(event);
      case GetLibraryByUriEvent():
        _writeGetLibraryByUriEvent(event);
      case GetResolvedLibraryEvent():
        _writeGetResolvedLibrary(event);
      case GetResolvedLibraryByUriEvent():
        _writeGetResolvedLibraryByUri(event);
      case GetResolvedUnitEvent():
        _writeGetResolvedUnit(event);
      case GetUnitElementEvent():
        _writeGetUnitElementEvent(event);
      case ResultStreamEvent():
        _writeResultStreamEvent(event);
      case SchedulerStatusEvent():
        _writeSchedulerStatusEvent(event);
    }
  }

  void _writeGetCachedResolvedUnit(GetCachedResolvedUnitEvent event) {
    _writeGetEvent(event);
    sink.withIndent(() {
      if (event.result case var result?) {
        _writeResolvedUnitResult(result);
      } else {
        sink.writelnWithIndent('null');
      }
    });
  }

  void _writeGetEvent(GetDriverEvent event) {
    sink.writelnWithIndent('[future] ${event.methodName} ${event.name}');
  }

  void _writeGetLibraryByUriEvent(GetLibraryByUriEvent event) {
    if (!configuration.withGetLibraryByUri) {
      return;
    }

    _writeGetEvent(event);
    if (configuration.withGetLibraryByUriElement) {
      sink.withIndent(() {
        _writeLibraryElementResult(event.result);
      });
    }
  }

  void _writeGetResolvedLibrary(GetResolvedLibraryEvent event) {
    _writeGetEvent(event);
    sink.withIndent(() {
      _writeResolvedLibraryResult(event.result);
    });
  }

  void _writeGetResolvedLibraryByUri(GetResolvedLibraryByUriEvent event) {
    _writeGetEvent(event);
    sink.withIndent(() {
      _writeResolvedLibraryResult(event.result);
    });
  }

  void _writeGetResolvedUnit(GetResolvedUnitEvent event) {
    _writeGetEvent(event);
    sink.withIndent(() {
      _writeResolvedUnitResult(event.result);
    });
  }

  void _writeGetUnitElementEvent(GetUnitElementEvent event) {
    _writeGetEvent(event);
    sink.withIndent(() {
      var result = event.result;
      switch (result) {
        case MissingSdkLibraryResultImpl():
          _writeMissingSdkLibraryResult(result);
        case UnitElementResult():
          _writeUnitElementResult(result);
        default:
          throw UnimplementedError('${result.runtimeType}');
      }
    });
  }

  void _writeIndexEvent(GetIndexEvent event) {
    _writeGetEvent(event);
    sink.withIndent(() {
      if (event.result case var result?) {
        sink.writeElements('strings', result.strings, (str) {
          sink.writelnWithIndent(str);
        });
      }
    });
  }

  void _writeLibraryCycle(LibraryCycle cycle) {
    var uriStrList = cycle.libraries
        .map((library) => library.file.uriStr)
        .sorted();
    for (var uriStr in uriStrList) {
      sink.writelnWithIndent(uriStr);
    }
  }

  void _writeLibraryElementResult(SomeLibraryElementResult result) {
    switch (result) {
      case CannotResolveUriResult():
        sink.writelnWithIndent('CannotResolveUriResult');
      case MissingSdkLibraryResultImpl():
        _writeMissingSdkLibraryResult(result);
      case NotLibraryButPartResult():
        sink.writelnWithIndent('NotLibraryButPartResult');
      case LibraryElementResultImpl():
        writeLibrary(
          sink: sink,
          library: result.element,
          configuration: configuration.elementTextConfiguration,
        );
      default:
        throw UnimplementedError('${result.runtimeType}');
    }
  }

  void _writeLinkLibraryCycle(events.LinkLibraryCycle object) {
    if (!configuration.withLinkLibraryCycle) {
      return;
    }

    const printName = 'linkLibraryCycle';
    if (object.cycle.isSdk) {
      sink.writelnWithIndent('[operation] $printName SDK');
      return;
    }

    sink.writelnWithIndent('[operation] $printName');
    sink.withIndent(() {
      var sortedLibraries = object.cycle.libraries.sortedBy(
        (libraryKind) => libraryKind.file.uriStr,
      );
      for (var libraryKind in sortedLibraries) {
        sink.writelnWithIndent(libraryKind.file.uriStr);
        if (configuration.withLibraryManifest) {
          sink.withIndent(() {
            var libraryElement = object.elementFactory.libraryOfUri2(
              libraryKind.file.uri,
            );
            var manifest = libraryElement.manifest!;
            LibraryManifestPrinter(
              configuration: configuration,
              sink: sink,
              idProvider: idProvider,
            ).write(manifest);
          });
        }
      }
      _writeRequirements(object.requirements);
    });
  }

  void _writeMissingSdkLibraryResult(MissingSdkLibraryResultImpl result) {
    var id = idProvider[result];
    sink.writelnWithIndent('MissingSdkLibraryResult $id');

    sink.withIndent(() {
      sink.writelnWithIndent('missingUri: ${result.missingUri}');
    });
  }

  void _writeRequirementFailure(RequirementFailure failure) {
    switch (failure) {
      case LibraryMissing():
        // TODO(scheglov): Handle this case.
        throw UnimplementedError();
      case ExportCountMismatch():
        sink.writelnWithIndent('exportCountMismatch');
        sink.writeProperties({
          'fragmentUri': failure.fragmentUri,
          'exportedUri': failure.exportedUri,
          'expected': failure.expectedCount,
          'actual': failure.actualCount,
        });
      case ExportIdMismatch():
        sink.writelnWithIndent('exportIdMismatch');
        sink.writeProperties({
          'fragmentUri': failure.fragmentUri,
          'exportedUri': failure.exportedUri,
          'name': failure.name.asString,
          'expectedId': idProvider.manifestId(failure.expectedId),
          'actualId': idProvider.manifestId(failure.actualId),
        });
      case ExportLibraryMissing():
        // TODO(scheglov): Handle this case.
        throw UnimplementedError();
      case ExportedExtensionsMismatch():
        sink.writelnWithIndent('exportedExtensionsMismatch');
        sink.writeProperties({
          'libraryUri': failure.libraryUri,
          'expectedIds': failure.expectedIds.asString(idProvider),
          'actualIds': failure.actualIds.asString(idProvider),
        });
      case InstanceFieldIdMismatch():
        sink.writelnWithIndent('instanceFieldIdMismatch');
        sink.writeProperties({
          'libraryUri': failure.libraryUri,
          'interfaceName': failure.interfaceName.asString,
          'fieldName': failure.fieldName.asString,
          'expectedId': idProvider.manifestId(failure.expectedId),
          'actualId': idProvider.manifestId(failure.actualId),
        });
      case InstanceMethodIdMismatch():
        sink.writelnWithIndent('instanceMethodIdMismatch');
        sink.writeProperties({
          'libraryUri': failure.libraryUri,
          'interfaceName': failure.interfaceName.asString,
          'methodName': failure.methodName.asString,
          'expectedId': idProvider.manifestId(failure.expectedId),
          'actualId': idProvider.manifestId(failure.actualId),
        });
      case InstanceChildrenIdsMismatch():
        sink.writelnWithIndent('instanceChildrenIdsMismatch');
        sink.writeProperties({
          'libraryUri': failure.libraryUri,
          'instanceName': failure.instanceName.asString,
          'childrenPropertyName': failure.childrenPropertyName,
          'expectedIds': failure.expectedIds.asString(idProvider),
          'actualIds': failure.actualIds.asString(idProvider),
        });
      case InterfaceIdMismatch():
        sink.writelnWithIndent('interfaceIdMismatch');
        sink.writeProperties({
          'libraryUri': failure.libraryUri,
          'interfaceName': failure.interfaceName.asString,
          'expectedId': idProvider.manifestId(failure.expectedId),
          'actualId': idProvider.manifestId(failure.actualId),
        });
      case InterfaceChildrenIdsMismatch():
        sink.writelnWithIndent('interfaceChildrenIdsMismatch');
        sink.writeProperties({
          'libraryUri': failure.libraryUri,
          'interfaceName': failure.interfaceName.asString,
          'childrenPropertyName': failure.childrenPropertyName,
          'expectedIds': failure.expectedIds.asString(idProvider),
          'actualIds': failure.actualIds.asString(idProvider),
        });
      case InterfaceConstructorIdMismatch():
        sink.writelnWithIndent('interfaceConstructorIdMismatch');
        sink.writeProperties({
          'libraryUri': failure.libraryUri,
          'interfaceName': failure.interfaceName.asString,
          'constructorName': failure.constructorName.asString,
          'expectedId': idProvider.manifestId(failure.expectedId),
          'actualId': idProvider.manifestId(failure.actualId),
        });
      case TopLevelIdMismatch():
        sink.writelnWithIndent('topLevelIdMismatch');
        sink.writeProperties({
          'libraryUri': failure.libraryUri,
          'name': failure.name.asString,
          'expectedId': idProvider.manifestId(failure.expectedId),
          'actualId': idProvider.manifestId(failure.actualId),
        });
      case TopLevelNotInstance():
        sink.writelnWithIndent('topLevelNotInstance');
        sink.writeProperties({
          'libraryUri': failure.libraryUri,
          'name': failure.name.asString,
        });
      case TopLevelNotInterface():
        // TODO(scheglov): Handle this case.
        throw UnimplementedError();
      case OpaqueApiUseFailure():
        var sortedUses = failure.uses.sortedBy((e) {
          return '${e.targetRuntimeType}.${e.methodName}';
        });
        sink.writeElements('opaqueApiUseFailure', sortedUses, (use) {
          sink.writelnWithIndent('${use.targetRuntimeType}.${use.methodName}');
          sink.withIndent(() {
            if (use.targetElementLibraryUri case var libraryUri?) {
              sink.writelnWithIndent('targetElementLibraryUri: $libraryUri');
            }
            if (use.targetElementName case var elementName?) {
              sink.writelnWithIndent('targetElementName: $elementName');
            }
          });
        });
    }
  }

  void _writeRequirements(RequirementsManifest? requirements) {
    if (!configuration.withResultRequirements) {
      return;
    }

    if (requirements == null) {
      return;
    }

    BundleRequirementsPrinter(
      configuration: configuration,
      sink: sink,
      idProvider: idProvider,
    ).write(requirements);
  }

  void _writeResolvedLibraryResult(SomeResolvedLibraryResult result) {
    switch (result) {
      case CannotResolveUriResult():
        sink.writelnWithIndent('CannotResolveUriResult');
      case MissingSdkLibraryResultImpl():
        _writeMissingSdkLibraryResult(result);
      case NotLibraryButPartResult():
        sink.writelnWithIndent('NotLibraryButPartResult');
      case ResolvedLibraryResult():
        ResolvedLibraryResultPrinter(
          configuration: configuration.libraryConfiguration,
          sink: sink,
          idProvider: idProvider,
          elementPrinter: ElementPrinter(
            sink: sink,
            configuration: ElementPrinterConfiguration(),
          ),
        ).write(result);
      default:
        throw UnimplementedError('${result.runtimeType}');
    }
  }

  void _writeResolvedUnitResult(SomeResolvedUnitResult result) {
    switch (result) {
      case MissingSdkLibraryResultImpl():
        _writeMissingSdkLibraryResult(result);
      case ResolvedUnitResultImpl():
        ResolvedUnitResultPrinter(
          configuration: configuration.libraryConfiguration.unitConfiguration,
          sink: sink,
          elementPrinter: elementPrinter,
          idProvider: idProvider,
          libraryElement: null,
        ).write(result);
      default:
        throw UnimplementedError('${result.runtimeType}');
    }
  }

  void _writeResultStreamEvent(ResultStreamEvent event) {
    var object = event.object;
    switch (object) {
      case events.AnalyzeFile():
        _writeAnalyzeFileEvent(object);
      case events.AnalyzedLibrary():
        sink.writelnWithIndent('[operation] analyzedLibrary');
        sink.withIndent(() {
          var libraryFile = object.library.file;
          sink.writelnWithIndent('file: ${libraryFile.resource.posixPath}');
          _writeRequirements(object.requirements);
        });
      case events.CheckLibraryDiagnosticsRequirements():
        _writeCheckLibraryDiagnosticsRequirements(object);
      case events.CheckLinkedBundleRequirements():
        _writeCheckLinkedBundleRequirements(object);
      case events.LinkLibraryCycle():
        _writeLinkLibraryCycle(object);
      case events.ReuseLinkedBundle():
        _writeReuseLinkedBundle(object);
      case ErrorsResult():
        sink.writelnWithIndent('[stream]');
        sink.withIndent(() {
          _writeErrorsResult(object);
        });
      case events.GetErrorsFromBytes():
        sink.writelnWithIndent('[operation] getErrorsFromBytes');
        sink.withIndent(() {
          var file = object.file.resource;
          sink.writelnWithIndent('file: ${file.posixPath}');
          var libraryFile = object.library.file.resource;
          sink.writelnWithIndent('library: ${libraryFile.posixPath}');
        });
      case ResolvedUnitResult():
        if (!configuration.withStreamResolvedUnitResults) {
          return;
        }
        sink.writelnWithIndent('[stream]');
        sink.withIndent(() {
          _writeResolvedUnitResult(object);
        });
      default:
        throw UnimplementedError('${object.runtimeType}');
    }
  }

  void _writeReuseLinkedBundle(events.ReuseLinkedBundle event) {
    const printName = 'reuseLinkedBundle';
    if (event.cycle.isSdk) {
      sink.writelnWithIndent('[operation] $printName SDK');
    } else {
      sink.writelnWithIndent('[operation] $printName');
      sink.withIndent(() {
        _writeLibraryCycle(event.cycle);
      });
    }
  }

  void _writeSchedulerStatusEvent(SchedulerStatusEvent event) {
    if (!configuration.withSchedulerStatus) {
      return;
    }

    sink.writeIndentedLine(() {
      sink.write('[status] ');
      switch (event.status) {
        case AnalysisStatusIdle():
          sink.write('idle');
        case AnalysisStatusWorking():
          sink.write('working');
      }
    });
  }

  void _writeUnitElementResult(UnitElementResult result) {
    sink.writelnWithIndent('path: ${result.file.posixPath}');
    expect(result.path, result.file.path);

    sink.writelnWithIndent('uri: ${result.uri}');

    sink.writeFlags({'isLibrary': result.isLibrary, 'isPart': result.isPart});

    var libraryFragment = result.fragment;

    elementPrinter.writeNamedFragment(
      'enclosing',
      libraryFragment.enclosingFragment,
    );

    var elementsToWrite = configuration.unitElementConfiguration
        .elementSelector(libraryFragment);
    elementPrinter.writeElementList2('selectedElements', elementsToWrite);
  }
}

class DriverEventsPrinterConfiguration {
  var libraryConfiguration = ResolvedLibraryResultPrinterConfiguration();
  var unitElementConfiguration = UnitElementPrinterConfiguration();
  var errorsConfiguration = ErrorsResultPrinterConfiguration();
  var elementTextConfiguration = ElementTextConfiguration();
  var requirements = RequirementPrinterConfiguration();

  var withAnalyzeFileEvents = true;
  var withCheckLibraryDiagnosticsRequirements = false;
  var withCheckLinkedBundleRequirements = false;
  var withElementManifests = false;
  var withGetErrorsEvents = true;
  var withGetLibraryByUri = true;
  var withGetLibraryByUriElement = true;
  var withLibraryManifest = false;
  var withLinkLibraryCycle = false;
  var withResultRequirements = false;
  var withSchedulerStatus = true;
  var withStreamResolvedUnitResults = true;

  var ignoredManifestInstanceMemberNames = <String>{
    '==',
    'hashCode',
    'noSuchMethod',
    'runtimeType',
    'toString',
    'new',
  };

  void includeDefaultConstructors() {
    ignoredManifestInstanceMemberNames.remove('new');
  }
}

class ErrorsResultPrinterConfiguration {
  bool Function(FileResult) withContentPredicate = (_) => false;
}

/// The result of `getCachedResolvedUnit`.
final class GetCachedResolvedUnitEvent extends GetDriverEvent {
  final SomeResolvedUnitResult? result;

  GetCachedResolvedUnitEvent({required super.name, required this.result});

  @override
  String get methodName => 'getCachedResolvedUnit';
}

sealed class GetDriverEvent extends DriverEvent {
  final String name;

  GetDriverEvent({required this.name});

  String get methodName;
}

/// The result of `getErrors`.
final class GetErrorsEvent extends GetDriverEvent {
  final SomeErrorsResult result;

  GetErrorsEvent({required super.name, required this.result});

  @override
  String get methodName => 'getErrors';
}

/// The result of `getIndex`.
final class GetIndexEvent extends GetDriverEvent {
  final AnalysisDriverUnitIndex? result;

  GetIndexEvent({required super.name, required this.result});

  @override
  String get methodName => 'getIndex';
}

/// The result of `getLibraryByUri`.
final class GetLibraryByUriEvent extends GetDriverEvent {
  final SomeLibraryElementResult result;

  GetLibraryByUriEvent({required super.name, required this.result});

  @override
  String get methodName => 'getLibraryByUri';
}

/// The result of `getResolvedLibraryByUri`.
final class GetResolvedLibraryByUriEvent extends GetDriverEvent {
  final SomeResolvedLibraryResult result;

  GetResolvedLibraryByUriEvent({required super.name, required this.result});

  @override
  String get methodName => 'getResolvedLibraryByUri';
}

/// The result of `getResolvedLibrary`.
final class GetResolvedLibraryEvent extends GetDriverEvent {
  final SomeResolvedLibraryResult result;

  GetResolvedLibraryEvent({required super.name, required this.result});

  @override
  String get methodName => 'getResolvedLibrary';
}

/// The result of `getResolvedUnit`.
final class GetResolvedUnitEvent extends GetDriverEvent {
  final SomeResolvedUnitResult result;

  GetResolvedUnitEvent({required super.name, required this.result});

  @override
  String get methodName => 'getResolvedUnit';
}

/// The result of `getUnitElement`.
final class GetUnitElementEvent extends GetDriverEvent {
  final SomeUnitElementResult result;

  GetUnitElementEvent({required super.name, required this.result});

  @override
  String get methodName => 'getUnitElement';
}

class IdProvider {
  final Map<Object, String> _map = Map.identity();
  final Map<ManifestItemId, String> _manifestIdMap = {};

  String operator [](Object object) {
    return _map[object] ??= '#${_map.length}';
  }

  String? existing(Object object) {
    return _map[object];
  }

  String manifestId(ManifestItemId? id) {
    if (id == null) return '<null>';
    return _manifestIdMap[id] ??= '#M${_manifestIdMap.length}';
  }
}

class LibraryManifestPrinter {
  final DriverEventsPrinterConfiguration configuration;
  final TreeStringSink sink;
  final IdProvider idProvider;

  LibraryManifestPrinter({
    required this.configuration,
    required this.sink,
    required this.idProvider,
  });

  void write(LibraryManifest manifest) {
    var classEntries = manifest.declaredClasses.sorted;
    sink.writeElements('declaredClasses', classEntries, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeClassItem(item);
    });

    var enumEntries = manifest.declaredEnums.sorted;
    sink.writeElements('declaredEnums', enumEntries, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeEnumItem(item);
    });

    var extensionEntries = manifest.declaredExtensions.sorted;
    sink.writeElements('declaredExtensions', extensionEntries, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeExtensionItem(item);
    });

    var extensionTypeEntries = manifest.declaredExtensionTypes.sorted;
    sink.writeElements('declaredExtensionTypes', extensionTypeEntries, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeExtensionTypeItem(item);
    });

    var mixinEntries = manifest.declaredMixins.sorted;
    sink.writeElements('declaredMixins', mixinEntries, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeMixinItem(item);
    });

    var typeAliasEntries = manifest.declaredTypeAliases.sorted;
    sink.writeElements('declaredTypeAliases', typeAliasEntries, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeTypeAliasItem(item);
    });

    var getterEntries = manifest.declaredGetters.sorted;
    sink.writeElements('declaredGetters', getterEntries, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeTopLevelGetterItem(item);
    });

    var setterEntries = manifest.declaredSetters.sorted;
    sink.writeElements('declaredSetters', setterEntries, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeTopLevelSetterItem(item);
    });

    var functionEntries = manifest.declaredFunctions;
    sink.writeElements('declaredFunctions', functionEntries.sorted, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeTopLevelFunctionItem(item);
    });

    var variableEntries = manifest.declaredVariables;
    sink.writeElements('declaredVariables', variableEntries.sorted, (entry) {
      var item = entry.value;
      _writeNamedId(entry.key, item.id);
      _writeTopLevelVariableItem(item);
    });

    var reExportEntries = manifest.reExportMap.sorted;
    if (reExportEntries.isNotEmpty) {
      sink.writelnWithIndent('reExportMap');
      sink.withIndent(() {
        for (var entry in reExportEntries) {
          _writeNamedId(entry.key, entry.value);
        }
      });
    }

    var exportedExtensionIds = manifest.exportedExtensions;
    if (exportedExtensionIds.ids.isNotEmpty) {
      var idListStr = exportedExtensionIds.asString(idProvider);
      sink.writelnWithIndent('exportedExtensions: $idListStr');
    }
  }

  void _writeClassItem(ClassItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        sink.writeFlags({
          'isAbstract': item.isAbstract,
          'isBase': item.isBase,
          'isFinal': item.isFinal,
          'isInterface': item.isInterface,
          'isMixinApplication': item.isMixinApplication,
          'isMixinClass': item.isMixinClass,
          'isSealed': item.isSealed,
        });
        _writeMetadata(item);
        _writeTypeParameters(item.typeParameters);
        _writeNamedType('supertype', item.supertype);
        _writeTypeList('mixins', item.mixins);
        _writeTypeList('interfaces', item.interfaces);
      });
    }

    sink.withIndent(() {
      _writeInstanceItemMembers(item);
      _writeInterfaceItemInterface(item);
    });
  }

  void _writeEnumItem(EnumItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        _writeMetadata(item);
        _writeTypeParameters(item.typeParameters);
        _writeTypeList('mixins', item.mixins);
        _writeTypeList('interfaces', item.interfaces);
      });
    }

    sink.withIndent(() {
      _writeInstanceItemMembers(item);
      _writeInterfaceItemInterface(item);
    });
  }

  void _writeExtensionItem(ExtensionItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        _writeMetadata(item);
        _writeTypeParameters(item.typeParameters);
        _writeNamedType('extendedType', item.extendedType);
      });
    }

    sink.withIndent(() {
      _writeInstanceItemMembers(item);
    });
  }

  void _writeExtensionTypeItem(ExtensionTypeItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        sink.writeFlags({
          'hasImplementsSelfReference': item.hasImplementsSelfReference,
          'hasRepresentationSelfReference': item.hasRepresentationSelfReference,
        });
        _writeMetadata(item);
        _writeTypeParameters(item.typeParameters);
        _writeNamedType('representationType', item.representationType);
        _writeNamedType('typeErasure', item.typeErasure);
        _writeTypeList('interfaces', item.interfaces);
      });
    }

    sink.withIndent(() {
      _writeInstanceItemMembers(item);
      _writeInterfaceItemInterface(item);
    });
  }

  void _writeInstanceItemMembers(InstanceItem item) {
    var ignored = configuration.ignoredManifestInstanceMemberNames;

    void writeDeclaredDuplicateNames() {
      var conflicts = item.declaredConflicts.sorted;
      if (conflicts.isNotEmpty) {
        sink.writelnWithIndent('declaredConflicts');
        sink.withIndent(() {
          for (var entry in conflicts) {
            var name = entry.key.asString;
            var idStr = idProvider.manifestId(entry.value);
            sink.writelnWithIndent('$name: $idStr');
          }
        });
      }
    }

    void writeDeclaredFields() {
      var declaredFields = item.declaredFields.sorted.whereNot((entry) {
        return ignored.contains(entry.key.asString);
      }).toList();

      if (declaredFields.isNotEmpty) {
        sink.writelnWithIndent('declaredFields');
        sink.withIndent(() {
          for (var entry in declaredFields) {
            var name = entry.key.asString;
            var item = entry.value;
            var idStr = idProvider.manifestId(item.id);
            sink.writelnWithIndent('$name: $idStr');
            if (configuration.withElementManifests) {
              sink.withIndent(() {
                _writeMetadata(item);
                _writeNamedType('type', item.type);
                _writeNode('constInitializer', item.constInitializer);
              });
            }
          }
        });
      }
    }

    void writeDeclaredGetters() {
      var declaredGetters = item.declaredGetters.sorted.whereNot((entry) {
        return ignored.contains(entry.key.asString);
      }).toList();

      if (declaredGetters.isNotEmpty) {
        sink.writelnWithIndent('declaredGetters');
        sink.withIndent(() {
          for (var entry in declaredGetters) {
            var name = entry.key.asString;
            var item = entry.value;
            var idStr = idProvider.manifestId(item.id);
            sink.writelnWithIndent('$name: $idStr');
            if (configuration.withElementManifests) {
              sink.withIndent(() {
                _writeMetadata(item);
                _writeNamedType('returnType', item.returnType);
              });
            }
          }
        });
      }
    }

    void writeDeclaredSetters() {
      var declaredSetters = item.declaredSetters.sorted.whereNot((entry) {
        return ignored.contains(entry.key.asString);
      }).toList();

      if (declaredSetters.isNotEmpty) {
        sink.writelnWithIndent('declaredSetters');
        sink.withIndent(() {
          for (var entry in declaredSetters) {
            var name = entry.key.asString;
            var item = entry.value;
            var idStr = idProvider.manifestId(item.id);
            sink.writelnWithIndent('$name: $idStr');
            if (configuration.withElementManifests) {
              sink.withIndent(() {
                _writeMetadata(item);
                _writeNamedType('functionType', item.functionType);
              });
            }
          }
        });
      }
    }

    void writeDeclaredMethods() {
      var declaredMethods = item.declaredMethods.sorted.whereNot((entry) {
        return ignored.contains(entry.key.asString);
      }).toList();

      if (declaredMethods.isNotEmpty) {
        sink.writelnWithIndent('declaredMethods');
        sink.withIndent(() {
          for (var entry in declaredMethods) {
            var name = entry.key.asString;
            var item = entry.value;
            var idStr = idProvider.manifestId(item.id);
            sink.writelnWithIndent('$name: $idStr');
            if (configuration.withElementManifests) {
              sink.withIndent(() {
                _writeMetadata(item);
                _writeNamedType('functionType', item.functionType);
              });
            }
          }
        });
      }
    }

    void writeDeclaredConstructors() {
      var declaredConstructors = item.declaredConstructors.sorted.whereNot((
        entry,
      ) {
        return ignored.contains(entry.key.asString);
      }).toList();

      if (declaredConstructors.isNotEmpty) {
        sink.writelnWithIndent('declaredConstructors');
        sink.withIndent(() {
          for (var entry in declaredConstructors) {
            var name = entry.key.asString;
            var item = entry.value;
            var idStr = idProvider.manifestId(item.id);
            sink.writelnWithIndent('$name: $idStr');
            if (configuration.withElementManifests) {
              sink.withIndent(() {
                sink.withIndent(() {
                  _writeMetadata(item);
                  _writeNamedType('functionType', item.functionType);
                });
              });
            }
          }
        });
      }
    }

    void writeInheritedConstructors() {
      var inheritedConstructors = item.inheritedConstructors.sorted.whereNot((
        entry,
      ) {
        return ignored.contains(entry.key.asString);
      }).toList();

      if (inheritedConstructors.isNotEmpty) {
        sink.writelnWithIndent('inheritedConstructors');
        sink.withIndent(() {
          for (var entry in inheritedConstructors) {
            var name = entry.key.asString;
            var idStr = idProvider.manifestId(entry.value);
            sink.writelnWithIndent('$name: $idStr');
          }
        });
      }
    }

    writeDeclaredDuplicateNames();
    writeDeclaredFields();
    writeDeclaredGetters();
    writeDeclaredSetters();
    writeDeclaredMethods();
    writeDeclaredConstructors();
    writeInheritedConstructors();
  }

  void _writeInterfaceItemInterface(InterfaceItem item) {
    var ignored = configuration.ignoredManifestInstanceMemberNames;

    List<MapEntry<LookupName, V>> notIgnored<V>(Map<LookupName, V> map) {
      return map.sorted.whereNot((entry) {
        return ignored.contains(entry.key.asString);
      }).toList();
    }

    var interface = item.interface;
    var idStr = idProvider.manifestId(interface.id);
    sink.writelnWithIndent('interface: $idStr');

    var mapEntries = notIgnored(interface.map);
    if (mapEntries.isNotEmpty) {
      sink.withIndent(() {
        if (mapEntries.isNotEmpty) {
          sink.writelnWithIndent('map');
          sink.withIndent(() {
            for (var entry in mapEntries) {
              _writeNamedId(entry.key, entry.value);
            }
          });
        }

        var combinedIds = interface.combinedIds;
        if (combinedIds.isNotEmpty) {
          sink.writelnWithIndent('combinedIds');
          sink.withIndent(() {
            for (var entry in combinedIds.entries) {
              var idListStr = entry.key.ids
                  .map((id) => idProvider.manifestId(id))
                  .join(', ');
              var idStr = idProvider.manifestId(entry.value);
              sink.writelnWithIndent('[$idListStr]: $idStr');
            }
          });
        }
      });
    }
  }

  void _writelnElement(ManifestElement element) {
    var parts = [
      element.libraryUri,
      element.kind.name,
      element.topLevelName,
      if (element.memberName case var memberName?) memberName,
    ];
    var idStr = idProvider.manifestId(element.id);
    sink.writeln('(${parts.join(', ')}) $idStr');
  }

  void _writeMetadata(ManifestItem item) {
    if (configuration.withElementManifests) {
      sink.writeElements(
        'metadata',
        item.metadata.annotations.indexed.toList(),
        (indexed) {
          _writeNode('[${indexed.$1}]', indexed.$2.ast);
        },
      );
    }
  }

  void _writeMixinItem(MixinItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        _writeMetadata(item);
        _writeTypeParameters(item.typeParameters);
        _writeTypeList('superclassConstraints', item.superclassConstraints);
        _writeTypeList('interfaces', item.interfaces);
      });
    }

    sink.withIndent(() {
      _writeInstanceItemMembers(item);
      _writeInterfaceItemInterface(item);
    });
  }

  void _writeNamedId(LookupName name, ManifestItemId id) {
    var idStr = idProvider.manifestId(id);
    sink.writelnWithIndent('$name: $idStr');
  }

  void _writeNamedType(String name, ManifestType? type) {
    sink.writeWithIndent('$name: ');
    if (type != null) {
      _writeType(type);
    } else {
      sink.writeln('<null>');
    }
  }

  void _writeNode(String name, ManifestNode? node) {
    if (node != null) {
      sink.writelnWithIndent(name);
      sink.withIndent(() {
        if (node.isValid) {
          sink.writelnWithIndent('tokenBuffer: ${node.tokenBuffer}');
          sink.writelnWithIndent('tokenLengthList: ${node.tokenLengthList}');

          if (node.elements.isNotEmpty) {
            sink.writelnWithIndent('elements');
            sink.withIndent(() {
              for (var (index, element) in node.elements.indexed) {
                sink.writeWithIndent('[$index] ');
                _writelnElement(element);
              }
            });
          }

          if (node.elementIndexList.isNotEmpty) {
            sink.writeElements('elementIndexList', node.elementIndexList, (
              index,
            ) {
              var (kind, rawIndex) = ManifestAstElementKind.decode(index);
              switch (kind) {
                case ManifestAstElementKind.null_:
                  sink.writelnWithIndent('$index = null');
                case ManifestAstElementKind.dynamic_:
                  sink.writelnWithIndent('$index = dynamic');
                case ManifestAstElementKind.multiplyDefined:
                  sink.writelnWithIndent('$index = multiplyDefined');
                case ManifestAstElementKind.formalParameter:
                  sink.writelnWithIndent('$index = formalParameter $rawIndex');
                case ManifestAstElementKind.importPrefix:
                  sink.writelnWithIndent('$index = importPrefix');
                case ManifestAstElementKind.typeParameter:
                  sink.writelnWithIndent('$index = typeParameter $rawIndex');
                case ManifestAstElementKind.regular:
                  sink.writelnWithIndent('$index = element $rawIndex');
              }
            });
          }
        } else {
          sink.writelnWithIndent('isValid: ${node.isValid}');
        }
      });
    }
  }

  void _writeTopLevelFunctionItem(TopLevelFunctionItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        _writeMetadata(item);
        _writeNamedType('functionType', item.functionType);
      });
    }
  }

  void _writeTopLevelGetterItem(TopLevelGetterItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        _writeMetadata(item);
        _writeNamedType('returnType', item.returnType);
      });
    }
  }

  void _writeTopLevelSetterItem(TopLevelSetterItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        _writeMetadata(item);
        _writeNamedType('valueType', item.valueType);
      });
    }
  }

  void _writeTopLevelVariableItem(TopLevelVariableItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        _writeMetadata(item);
        _writeNamedType('type', item.type);
        _writeNode('constInitializer', item.constInitializer);
      });
    }
  }

  void _writeType(ManifestType type) {
    void writeNullabilitySuffix() {
      if (type.nullabilitySuffix == NullabilitySuffix.question) {
        sink.write('?');
      }
    }

    switch (type) {
      case ManifestDynamicType():
        sink.writeln('dynamic');
      case ManifestFunctionType():
        sink.writeln('FunctionType');
        sink.withIndent(() {
          _writeTypeParameters(type.typeParameters);
          sink.writeElements('positional', type.positional, (field) {
            sink.writeIndent();
            if (field.isRequired) {
              sink.write('required ');
            }
            _writeType(field.type);
          });
          sink.writeElements('named', type.named, (field) {
            sink.writeWithIndent('${field.name}: ');
            if (field.isRequired) {
              sink.write('required ');
            }
            _writeType(field.type);
          });
          _writeNamedType('returnType', type.returnType);
        });
      case ManifestInterfaceType():
        var element = type.element;
        sink.write(element.topLevelName);
        writeNullabilitySuffix();
        sink.write(' @ ');
        sink.writeln(element.libraryUri);
        sink.withIndent(() {
          for (var argument in type.arguments) {
            sink.writeIndent();
            _writeType(argument);
          }
        });
      case ManifestInvalidType():
        sink.writeln('InvalidType');
      case ManifestNeverType():
        sink.write('Never');
        writeNullabilitySuffix();
        sink.writeln();
      case ManifestRecordType():
        sink.writeln('RecordType');
        sink.withIndent(() {
          sink.writeElements('positional', type.positionalFields, (field) {
            sink.writeIndentedLine(() {
              _writeType(field);
            });
          });
          sink.writeElements('named', type.namedFields, (field) {
            sink.writeIndentedLine(() {
              sink.write('${field.name}: ');
              _writeType(field.type);
            });
          });
        });
      case ManifestTypeParameterType():
        sink.write('typeParameter#${type.index}');
        writeNullabilitySuffix();
        sink.writeln();
      case ManifestVoidType():
        sink.writeln('void');
    }
  }

  void _writeTypeAliasItem(TypeAliasItem item) {
    if (configuration.withElementManifests) {
      sink.withIndent(() {
        _writeMetadata(item);
        _writeTypeParameters(item.typeParameters);
        _writeNamedType('aliasedType', item.aliasedType);
      });
    }
  }

  void _writeTypeList(String name, List<ManifestType> types) {
    sink.writeElements(name, types, (type) {
      sink.writeIndent();
      _writeType(type);
    });
  }

  void _writeTypeParameters(List<ManifestTypeParameter> typeParameters) {
    var indexed = typeParameters.indexed.toList();
    sink.writeElements('typeParameters', indexed, (pair) {
      var typeParameter = pair.$2;
      sink.writeIndentedLine(() {
        sink.write('#${pair.$1} ');
        sink.write(typeParameter.variance.name);
      });
      sink.withIndent(() {
        _writeNamedType('bound', typeParameter.bound);
      });
    });
  }
}

class RequirementPrinterConfiguration {
  var ignoredLibraries = <Uri>{Uri.parse('dart:core')};
}

class ResolvedLibraryResultPrinter {
  final ResolvedLibraryResultPrinterConfiguration configuration;
  final TreeStringSink sink;
  final ElementPrinter elementPrinter;
  final IdProvider idProvider;

  late final LibraryElement _libraryElement;

  ResolvedLibraryResultPrinter({
    required this.configuration,
    required this.sink,
    required this.elementPrinter,
    required this.idProvider,
  });

  void write(SomeResolvedLibraryResult result) {
    switch (result) {
      case ResolvedLibraryResult():
        _writeResolvedLibraryResult(result);
      default:
        throw UnimplementedError('${result.runtimeType}');
    }
  }

  void _writeResolvedLibraryResult(ResolvedLibraryResult result) {
    if (idProvider.existing(result) case var id?) {
      sink.writelnWithIndent('ResolvedLibraryResult $id');
      return;
    }

    _libraryElement = result.element;

    var id = idProvider[result];
    sink.writelnWithIndent('ResolvedLibraryResult $id');

    sink.withIndent(() {
      elementPrinter.writeNamedElement2('element', result.element);
      sink.writeElements('units', result.units, _writeResolvedUnitResult);
    });
  }

  void _writeResolvedUnitResult(ResolvedUnitResult result) {
    // TODO(scheglov): remove the cast
    result as ResolvedUnitResultImpl;
    ResolvedUnitResultPrinter(
      configuration: configuration.unitConfiguration,
      sink: sink,
      elementPrinter: elementPrinter,
      libraryElement: _libraryElement,
      idProvider: idProvider,
    ).write(result);
  }
}

class ResolvedLibraryResultPrinterConfiguration {
  var unitConfiguration = ResolvedUnitResultPrinterConfiguration();
}

class ResolvedUnitResultPrinter {
  final ResolvedUnitResultPrinterConfiguration configuration;
  final TreeStringSink sink;
  final ElementPrinter elementPrinter;
  final LibraryElement? libraryElement;
  final IdProvider idProvider;

  ResolvedUnitResultPrinter({
    required this.configuration,
    required this.sink,
    required this.elementPrinter,
    required this.libraryElement,
    required this.idProvider,
  });

  void write(ResolvedUnitResultImpl result) {
    _writeResolvedUnitResult(result);
  }

  void _writeDiagnostic(Diagnostic d) {
    sink.writelnWithIndent('${d.offset} +${d.length} ${d.diagnosticCode.name}');
  }

  void _writeResolvedUnitResult(ResolvedUnitResultImpl result) {
    if (idProvider.existing(result) case var id?) {
      sink.writelnWithIndent('ResolvedUnitResult $id');
      return;
    }

    var id = idProvider[result];
    sink.writelnWithIndent('ResolvedUnitResult $id');

    sink.withIndent(() {
      sink.writelnWithIndent('path: ${result.file.posixPath}');
      expect(result.path, result.file.path);

      sink.writelnWithIndent('uri: ${result.uri}');

      // Don't write, just check.
      if (libraryElement != null) {
        expect(result.libraryElement, same(libraryElement));
      }

      sink.writeFlags({
        'exists': result.exists,
        'isLibrary': result.isLibrary,
        'isPart': result.isPart,
      });

      if (configuration.withContentPredicate(result)) {
        sink.writelnWithIndent('content');
        sink.writeln('---');
        sink.write(result.content);
        sink.writeln('---');
      }

      sink.writeElements('errors', result.diagnostics, _writeDiagnostic);

      var nodeToWrite = configuration.nodeSelector(result);
      if (nodeToWrite != null) {
        sink.writeWithIndent('selectedNode: ');
        nodeToWrite.accept(
          ResolvedAstPrinter(
            sink: sink,
            elementPrinter: elementPrinter,
            configuration: configuration.nodeConfiguration,
          ),
        );
      }

      var typesToWrite = configuration.typesSelector(result);
      sink.writeElements('selectedTypes', typesToWrite.entries.toList(), (
        entry,
      ) {
        sink.writeIndent();
        sink.write('${entry.key}: ');
        elementPrinter.writeType(entry.value);
      });

      var variableTypesToWrite = configuration.variableTypesSelector(result);
      sink.writeElements('selectedVariableTypes', variableTypesToWrite, (
        variable,
      ) {
        sink.writeIndent();
        sink.write('${variable.name}: ');
        if (variable is LocalVariableElement) {
          elementPrinter.writeType(variable.type);
        } else if (variable is TopLevelVariableElement) {
          elementPrinter.writeType(variable.type);
        }
      });
    });
  }
}

class ResolvedUnitResultPrinterConfiguration {
  var nodeConfiguration = ResolvedNodeTextConfiguration();
  AstNode? Function(ResolvedUnitResult) nodeSelector = (_) => null;
  Map<String, DartType> Function(ResolvedUnitResult) typesSelector = (_) => {};
  List<Element> Function(ResolvedUnitResult) variableTypesSelector = (_) => [];
  bool Function(FileResult) withContentPredicate = (_) => false;
}

/// The event of received an object into the `results` stream.
final class ResultStreamEvent extends DriverEvent {
  final Object object;

  ResultStreamEvent({required this.object});
}

final class SchedulerStatusEvent extends DriverEvent {
  final AnalysisStatus status;

  SchedulerStatusEvent(this.status);
}

class UnitElementPrinterConfiguration {
  List<Element> Function(LibraryFragment) elementSelector = (_) => [];
}

extension on ManifestItemIdList {
  String asString(IdProvider idProvider) {
    return ids.map((id) => idProvider.manifestId(id)).join(' ');
  }
}

extension on LibraryCycle {
  bool get isSdk {
    return libraries.any((library) => library.file.uri.isScheme('dart'));
  }
}

extension<V> on Map<LookupName, V> {
  List<MapEntry<LookupName, V>> get sorted {
    return entries.sortedByCompare((entry) => entry.key, LookupName.compare);
  }
}

extension<V> on Map<Uri, V> {
  List<MapEntry<Uri, V>> get sorted {
    return entries.sortedBy((entry) => entry.key.toString());
  }
}

extension on TreeStringSink {
  void writelnNamedFilePath(String name, FileState fileState) {
    writelnWithIndent('$name: ${fileState.resource.posixPath}');
  }
}
