// Copyright (c) 2013, 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.

library;

import 'dart:convert' show JsonEncoder, JsonDecoder;

import 'package:compiler/src/js_model/js_strategy.dart';
import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/json_info_codec.dart';
import 'package:dart2js_info/binary_serialization.dart' as dump_info;
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/core_types.dart' as ir;

import '../compiler_api.dart' as api;
import 'common.dart';
import 'common/codegen.dart';
import 'common/elements.dart' show JElementEnvironment;
import 'common/names.dart';
import 'common/tasks.dart' show CompilerTask, Measurer;
import 'common/ram_usage.dart';
import 'constants/values.dart' show ConstantValue;
import 'deferred_load/output_unit.dart' show OutputUnit, deferredPartFileName;
import 'elements/entities.dart';
import 'elements/entity_utils.dart' as entity_utils;
import 'elements/names.dart';
import 'inferrer/abstract_value_domain.dart';
import 'inferrer/types.dart'
    show GlobalTypeInferenceMemberResult, GlobalTypeInferenceResults;
import 'js/js.dart' as js_ast;
import 'js_emitter/code_emitter_task.dart';
import 'js_model/elements.dart';
import 'js_model/js_world.dart' show JClosedWorld;
import 'js_backend/field_analysis.dart';
import 'options.dart';
import 'serialization/serialization.dart';
import 'universe/world_impact.dart' show WorldImpact;

/// Collects data used for the dump info task.
///
/// This registry collects data while JS is being emitted and stores it to be
/// processed by and used in the dump info stage. Since it holds references to
/// AST nodes it should be cleared with [DumpInfoJsAstRegistry.close] as soon
/// as the necessary data for it is extracted.
///
/// See [DumpInfoProgramData.fromEmitterResults] for how this data is processed.
class DumpInfoJsAstRegistry {
  final bool _disabled;
  final CompilerOptions options;

  final Map<Entity, List<CodeSpan>> _entityCode = {};
  final Map<ConstantValue, CodeSpan> _constantCode = {};

  // Contains impacts that will be used immediately (if codegen is being run
  // with this compiler execution) or serialized with partial dump info data.
  // Impacts are not yet transformed by CodegenImpactTransformer.
  final Map<MemberEntity, CodegenImpact> _impactRegistry = {};

  // Contains members whose impacts should be deserialized from codegen results
  // on subsequent dump info execution. Empty when dump info is being executed
  // immediately without serialization.
  final Set<MemberEntity> _serializedImpactMembers = {};

  // Temporary structures used to collect data during the visit process with a
  // low memory footprint.
  final Map<js_ast.Node, ConstantValue> _constantRegistry = {};
  final Map<js_ast.Node, List<Entity>> _entityRegistry = {};
  final List<CodeSpan> _stack = [];
  DataSinkWriter? _dataSinkWriter;
  int _impactCount = 0;

  DumpInfoJsAstRegistry(this.options)
    : _disabled =
          !options.stage.emitsDumpInfo &&
          !options.stage.shouldWriteDumpInfoData;

  bool get useBinaryFormat => options.useDumpInfoBinaryFormat;

  void registerEntityAst(Entity? entity, js_ast.Node code) {
    if (_disabled) return;
    if (entity != null) {
      (_entityRegistry[code] ??= []).add(entity);
    }
  }

  void registerConstantAst(ConstantValue constant, js_ast.Node code) {
    if (_disabled) return;
    assert(
      !_constantRegistry.containsValue(constant) ||
          _constantRegistry[code] == constant,
    );
    _constantRegistry[code] = constant;
  }

  void registerDataSinkWriter(DataSinkWriter dataSinkWriter) {
    _dataSinkWriter = dataSinkWriter..startDeferrable();
  }

  void registerImpact(
    MemberEntity member,
    CodegenImpact impact, {
    required bool isGenerated,
  }) {
    if (_disabled) return;
    if (isGenerated || options.stage.emitsDumpInfo) {
      if (options.stage.shouldWriteDumpInfoData) {
        // Serialize immediately so that we don't have to hold a reference to
        // every impact until the end of the phase.
        _dataSinkWriter!.writeMember(member);
        impact.writeToDataSink(_dataSinkWriter!);
        _impactCount++;
      } else {
        _impactRegistry[member] = impact;
      }
    } else {
      _serializedImpactMembers.add(member);
    }
  }

  bool get shouldEmitText => !useBinaryFormat;

  void enterNode(js_ast.Node node, int start) {
    if (_disabled) return;
    if (!_entityRegistry.containsKey(node) &&
        !_constantRegistry.containsKey(node)) {
      return;
    }
    final data = useBinaryFormat ? CodeSpan() : _CodeData();
    data.start = start;
    _stack.add(data);
  }

  void emit(String string) {
    if (shouldEmitText) {
      // Note: historically we emitted the full body of classes and methods, so
      // instance methods ended up emitted twice.  Once we use a different
      // encoding of dump info, we also plan to remove this duplication.
      for (var f in _stack) {
        (f as _CodeData)._text.write(string);
      }
    }
  }

  void exitNode(js_ast.Node node, int start, int end, int? closing) {
    if (_disabled) return;
    final entities = _entityRegistry.remove(node);
    final constant = _constantRegistry.remove(node);
    if (entities == null && constant == null) return;
    final data = _stack.removeLast();
    data.end = end;
    if (entities != null) {
      for (var e in entities) {
        (_entityCode[e] ??= []).add(data);
      }
    }
    if (constant != null) {
      _constantCode[constant] = data;
    }
  }

  void close() {
    assert(_stack.isEmpty);
    assert(_entityRegistry.isEmpty);
    assert(_constantRegistry.isEmpty);
    _dataSinkWriter?.endDeferrable();
    _entityCode.clear();
    _constantCode.clear();
    _serializedImpactMembers.clear();
    _impactRegistry.clear();
  }
}

/// Only includes entity types stored in [DumpInfoProgramData.entityCode].
enum _EntityType { library, cls, member }

class DumpInfoProgramData {
  final int programSize;
  final Map<OutputUnit, int> outputUnitSizes;
  /* Map<String, Map<String, String?|List<String>>> */
  final Map<String, Map<String, dynamic>> fragmentDeferredMap;
  final Iterable<ClassEntity> neededClasses;
  final Iterable<ClassEntity> neededClassTypes;
  final Map<Entity, List<CodeSpan>> entityCode;
  final Map<Entity, int> entityCodeSize;
  final Map<ConstantValue, CodeSpan> constantCode;

  /// Contains members that are live and whose impacts are serialized in the
  /// codegen results. This will be empty if dump info is being run without
  /// serialization.
  final Set<MemberEntity> serializedImpactMembers;

  /// If dump info is being without serialziation, this will contain impacts for
  /// all live members. Otherwise only contains impacts for members that were
  /// created during the emitter phase and whose impacts are therefore not
  /// included in codegen results.
  final Map<MemberEntity, CodegenImpact> registeredImpacts;

  DumpInfoProgramData._(
    this.programSize,
    this.outputUnitSizes,
    this.fragmentDeferredMap,
    this.entityCode,
    this.entityCodeSize,
    this.constantCode,
    this.serializedImpactMembers,
    this.registeredImpacts, {
    required this.neededClasses,
    required this.neededClassTypes,
  });

  factory DumpInfoProgramData.fromEmitterResults(
    CodeEmitterTask emitterTask,
    DumpInfoJsAstRegistry dumpInfoRegistry,
    CodegenResults codegenResults,
    int programSize,
  ) {
    final outputUnitSizes = emitterTask.emitter.generatedSizes;

    var fragmentsToLoad = emitterTask.emitter.finalizedFragmentsToLoad;
    var fragmentMerger = emitterTask.emitter.fragmentMerger;
    final fragmentDeferredMap = fragmentMerger.computeDeferredMap(
      fragmentsToLoad,
    );
    final neededClasses = emitterTask.neededClasses;
    final neededClassTypes = emitterTask.neededClassTypes;
    final entityCode = Map.of(dumpInfoRegistry._entityCode);
    final entityCodeSize = <Entity, int>{};
    entityCode.forEach((entity, spans) {
      entityCodeSize[entity] = spans.fold(
        0,
        (size, span) => size + (span.end! - span.start!),
      );
    });
    final constantCode = Map.of(dumpInfoRegistry._constantCode);
    return DumpInfoProgramData._(
      programSize,
      outputUnitSizes,
      fragmentDeferredMap,
      entityCode,
      entityCodeSize,
      constantCode,
      Set.from(dumpInfoRegistry._serializedImpactMembers),
      Map.from(dumpInfoRegistry._impactRegistry),
      neededClasses: neededClasses,
      neededClassTypes: neededClassTypes,
    );
  }

  static Entity _readEntity(DataSourceReader source) {
    final entityType = source.readEnum(_EntityType.values);
    switch (entityType) {
      case _EntityType.library:
        return source.readLibrary();
      case _EntityType.cls:
        return source.readClass();
      case _EntityType.member:
        return source.readMember();
    }
  }

  static void _writeEntity(DataSinkWriter sink, Entity entity) {
    if (entity is LibraryEntity) {
      sink.writeEnum(_EntityType.library);
      sink.writeLibrary(entity);
    } else if (entity is ClassEntity) {
      sink.writeEnum(_EntityType.cls);
      sink.writeClass(entity);
    } else if (entity is MemberEntity) {
      sink.writeEnum(_EntityType.member);
      sink.writeMember(entity);
    } else {
      throw UnsupportedError('Unsupported dump info entity: $entity');
    }
  }

  static CodeSpan _readCodeSpan(DataSourceReader source, bool includeText) {
    final start = source.readInt();
    final end = source.readInt();
    final savedText = source.readStringOrNull();
    final text = includeText ? savedText : null;
    return CodeSpan(start: start, end: end, text: text);
  }

  static void _writeCodeSpan(DataSinkWriter sink, CodeSpan codeSpan) {
    sink.writeInt(codeSpan.start!);
    sink.writeInt(codeSpan.end!);
    sink.writeStringOrNull(codeSpan.text);
  }

  factory DumpInfoProgramData.readFromDataSource(
    DataSourceReader source, {
    required bool includeCodeText,
  }) {
    late int impactCount;
    final registeredImpactsDeferrable = source.readDeferrable((
      DataSourceReader source,
    ) {
      final impacts = <MemberEntity, CodegenImpact>{};
      for (var i = 0; i < impactCount; i++) {
        final member = source.readMember();
        final impact = CodegenImpact.readFromDataSource(source);
        impacts[member] = impact;
      }
      return impacts;
    });
    impactCount = source.readInt();
    final programSize = source.readInt();
    final outputUnitSizesLength = source.readInt();
    final outputUnitSizes = <OutputUnit, int>{};
    for (int i = 0; i < outputUnitSizesLength; i++) {
      final outputUnit = source.readOutputUnitReference();
      final size = source.readInt();
      outputUnitSizes[outputUnit] = size;
    }
    final fragmentDeferredMap = source.readStringMap(
      () => source.readStringMap(
        () => JsonDecoder().convert(source.readString()),
      ),
    );
    final neededClasses = source.readList(source.readClass);
    final neededClassTypes = source.readList(source.readClass);
    final entityCodeLength = source.readInt();
    final entityCode = <Entity, List<CodeSpan>>{};
    final entityCodeSize = <Entity, int>{};
    for (int i = 0; i < entityCodeLength; i++) {
      final entity = _readEntity(source);
      final size = source.readInt();
      final codeSpans = source.readList(
        () => _readCodeSpan(source, includeCodeText),
      );
      entityCode[entity] = codeSpans;
      entityCodeSize[entity] = size;
    }
    final constantCode = <ConstantValue, CodeSpan>{};
    final costantCodeLength = source.readInt();
    for (int i = 0; i < costantCodeLength; i++) {
      final constant = source.readConstant();
      final codeSpan = _readCodeSpan(source, includeCodeText);
      constantCode[constant] = codeSpan;
    }
    final serializedImpactMembers = source.readMembers().toSet();
    return DumpInfoProgramData._(
      programSize,
      outputUnitSizes,
      fragmentDeferredMap,
      entityCode,
      entityCodeSize,
      constantCode,
      serializedImpactMembers,
      registeredImpactsDeferrable.loaded(),
      neededClasses: neededClasses,
      neededClassTypes: neededClassTypes,
    );
  }

  void writeToDataSink(DataSinkWriter sink, DumpInfoJsAstRegistry registry) {
    sink.writeInt(registry._impactCount);
    sink.writeInt(programSize);
    sink.writeInt(outputUnitSizes.length);
    outputUnitSizes.forEach((outputUnit, size) {
      sink.writeOutputUnitReference(outputUnit);
      sink.writeInt(size);
    });
    sink.writeStringMap(fragmentDeferredMap, (Map<String, dynamic> innerMap) {
      sink.writeStringMap(
        innerMap,
        (value) => sink.writeString(JsonEncoder().convert(value)),
      );
    });
    sink.writeList(neededClasses, sink.writeClass);
    sink.writeList(neededClassTypes, sink.writeClass);
    assert(entityCode.length == entityCodeSize.length);
    sink.writeInt(entityCode.length);
    entityCode.forEach((entity, codeSpans) {
      final size = entityCodeSize[entity]!;
      _writeEntity(sink, entity);
      sink.writeInt(size);
      sink.writeList(
        codeSpans,
        (CodeSpan codeSpan) => _writeCodeSpan(sink, codeSpan),
      );
    });
    sink.writeInt(constantCode.length);
    constantCode.forEach((constant, codeSpan) {
      sink.writeConstant(constant);
      _writeCodeSpan(sink, codeSpan);
    });
    sink.writeMembers(serializedImpactMembers);
  }
}

class ElementInfoCollector {
  final CompilerOptions options;
  final JClosedWorld closedWorld;
  final GlobalTypeInferenceResults _globalInferenceResults;
  final DumpInfoTask dumpInfoTask;

  JElementEnvironment get environment => closedWorld.elementEnvironment;

  final state = DumpInfoStateData();

  ElementInfoCollector(
    this.options,
    this.dumpInfoTask,
    this.closedWorld,
    this._globalInferenceResults,
  );

  void run() {
    dumpInfoTask._dumpInfoData.constantCode.forEach((constant, span) {
      // TODO(sigmund): add dependencies on other constants
      var info = ConstantInfo(
        size: span.end! - span.start!,
        code: [span],
        outputUnit: _unitInfoForConstant(constant),
      );
      state.constantToInfo[constant] = info;
      state.info.constants.add(info);
    });
    environment.libraries.forEach(visitLibrary);
  }

  /// Whether to emit information about [entity].
  ///
  /// By default we emit information for any entity that contributes to the
  /// output size. Either because it is a function being emitted or inlined,
  /// or because it is an entity that holds dependencies to other entities.
  bool shouldKeep(Entity entity) {
    return dumpInfoTask.impacts.containsKey(entity) ||
        dumpInfoTask.inlineCount.containsKey(entity);
  }

  LibraryInfo? visitLibrary(LibraryEntity lib) {
    String libname = environment.getLibraryName(lib);
    if (libname.isEmpty) {
      libname = '<unnamed>';
    }
    int size = dumpInfoTask.sizeOf(lib);
    LibraryInfo info = LibraryInfo(libname, lib.canonicalUri, null, size);
    state.entityToInfo[lib] = info;

    environment.forEachLibraryMember(lib, (MemberEntity member) {
      if (member.isFunction || member.isGetter || member.isSetter) {
        final functionInfo = visitFunction(member as FunctionEntity);
        if (functionInfo != null) {
          info.topLevelFunctions.add(functionInfo);
          functionInfo.parent = info;
        }
      } else if (member is FieldEntity) {
        final fieldInfo = visitField(member);
        if (fieldInfo != null) {
          info.topLevelVariables.add(fieldInfo);
          fieldInfo.parent = info;
        }
      }
    });

    environment.forEachClass(lib, (ClassEntity clazz) {
      final classTypeInfo = visitClassType(clazz);
      if (classTypeInfo != null) {
        info.classTypes.add(classTypeInfo);
        classTypeInfo.parent = info;
      }

      final classInfo = visitClass(clazz);
      if (classInfo != null) {
        info.classes.add(classInfo);
        classInfo.parent = info;
      }
    });

    if (info.isEmpty && !shouldKeep(lib)) return null;
    state.info.libraries.add(info);
    return info;
  }

  GlobalTypeInferenceMemberResult _resultOfMember(MemberEntity e) =>
      _globalInferenceResults.resultOfMember(e);

  AbstractValue _resultOfParameter(Local e) =>
      _globalInferenceResults.resultOfParameter(e);

  FieldInfo? visitField(FieldEntity field) {
    AbstractValue inferredType = _resultOfMember(field).type;
    // If a field has an empty inferred type it is never used.
    if (closedWorld.abstractValueDomain
        .isEmpty(inferredType)
        .isDefinitelyTrue) {
      return null;
    }

    int size = dumpInfoTask.sizeOf(field);
    List<CodeSpan> code = dumpInfoTask.codeOf(field);

    // TODO(het): Why doesn't `size` account for the code size already?
    size += code.length;

    FieldInfo info = FieldInfo(
      name: field.name!,
      type: '${environment.getFieldType(field)}',
      inferredType: '$inferredType',
      code: code,
      outputUnit: _unitInfoForMember(field),
      isConst: field.isConst,
    );
    state.entityToInfo[field] = info;
    final fieldData = closedWorld.fieldAnalysis.getFieldData(field as JField);
    if (fieldData.initialValue != null) {
      info.initializer =
          state.constantToInfo[fieldData.initialValue] as ConstantInfo?;
    }

    if (options.experimentCallInstrumentation) {
      // We use field.hashCode because it is globally unique and it is
      // available while we are doing codegen.
      info.coverageId = '${field.hashCode}';
    }

    int closureSize = _addClosureInfo(info, field);
    info.size = size + closureSize;

    state.info.fields.add(info);
    return info;
  }

  ClassTypeInfo? visitClassType(ClassEntity clazz) {
    // Omit class type if it is not needed.
    ClassTypeInfo classTypeInfo = ClassTypeInfo(
      name: clazz.name,
      outputUnit: _unitInfoForClassType(clazz),
    );

    // TODO(joshualitt): Get accurate size information for class types.
    classTypeInfo.size = 0;

    bool isNeeded = dumpInfoTask._dumpInfoData.neededClassTypes.contains(clazz);
    if (!isNeeded) {
      return null;
    }

    state.info.classTypes.add(classTypeInfo);
    return classTypeInfo;
  }

  /// Returns all immediately extended, implemented, or mixed-in types of
  /// [clazz].
  List<ClassEntity> getImmediateSupers(ClassEntity clazz) {
    final superclass = environment.getSuperClass(
      clazz,
      skipUnnamedMixinApplications: true,
    );
    // Ignore 'Object' to reduce overhead.
    return [
      if (superclass != null &&
          superclass != closedWorld.commonElements.objectClass)
        superclass,
      ...closedWorld.dartTypes.getInterfaces(clazz).map((i) => i.element),
    ];
  }

  ClassInfo? visitClass(ClassEntity clazz) {
    // True if [info] can be safely removed from the output.
    bool filterClassInfo(ClassInfo info) =>
        !dumpInfoTask._dumpInfoData.neededClasses.contains(clazz) &&
        info.fields.isEmpty &&
        info.functions.isEmpty;

    ClassInfo? classInfo = state.entityToInfo[clazz] as ClassInfo?;
    if (classInfo != null) {
      return filterClassInfo(classInfo) ? null : classInfo;
    }
    final supers = <ClassInfo>[];
    getImmediateSupers(clazz).forEach((superInterface) {
      final superclass = environment.lookupClass(
        superInterface.library,
        superInterface.name,
      );
      if (superclass == null) return;
      final classInfo = visitClass(superclass);
      if (classInfo == null) return;
      supers.add(classInfo);
    });
    classInfo = ClassInfo(
      name: clazz.name,
      isAbstract: clazz.isAbstract,
      supers: supers,
      outputUnit: _unitInfoForClass(clazz),
    );
    state.entityToInfo[clazz] = classInfo;

    int size = dumpInfoTask.sizeOf(clazz);
    environment.forEachLocalClassMember(clazz, (member) {
      if (member.isFunction || member.isGetter || member.isSetter) {
        final functionInfo = visitFunction(member as FunctionEntity);
        if (functionInfo != null) {
          classInfo!.functions.add(functionInfo);
          functionInfo.parent = classInfo;
          for (var closureInfo in functionInfo.closures) {
            size += closureInfo.size;
          }
        }
      } else if (member is FieldEntity) {
        final fieldInfo = visitField(member);
        if (fieldInfo != null) {
          classInfo!.fields.add(fieldInfo);
          fieldInfo.parent = classInfo;
          for (var closureInfo in fieldInfo.closures) {
            size += closureInfo.size;
          }
        }
      } else {
        throw StateError('Class member not a function or field');
      }
    });
    environment.forEachConstructor(clazz, (constructor) {
      final functionInfo = visitFunction(constructor);
      if (functionInfo != null) {
        classInfo!.functions.add(functionInfo);
        functionInfo.parent = classInfo;
        for (var closureInfo in functionInfo.closures) {
          size += closureInfo.size;
        }
      }
    });

    classInfo.size = size;

    if (filterClassInfo(classInfo)) {
      return null;
    }

    state.info.classes.add(classInfo);
    return classInfo;
  }

  ClosureInfo? visitClosureClass(ClassEntity element) {
    ClosureInfo closureInfo = ClosureInfo(
      name: element.name,
      outputUnit: _unitInfoForClass(element),
      size: dumpInfoTask.sizeOf(element),
    );
    state.entityToInfo[element] = closureInfo;

    final callMethod = closedWorld.elementEnvironment.lookupClassMember(
      element,
      Names.call,
    );

    final functionInfo = visitFunction(callMethod as FunctionEntity);
    if (functionInfo == null) return null;
    closureInfo.function = functionInfo;
    functionInfo.parent = closureInfo;

    state.info.closures.add(closureInfo);
    return closureInfo;
  }

  FunctionInfo? visitFunction(FunctionEntity function) {
    int size = dumpInfoTask.sizeOf(function);
    // TODO(sigmund): consider adding a small info to represent unreachable
    // code here.
    if (size == 0 && !shouldKeep(function)) return null;

    // TODO(het): use 'toString' instead of 'text'? It will add '=' for setters
    String name = function.memberName.text;
    int? kind;
    if (function.isStatic || function.isTopLevel) {
      kind = FunctionInfo.TOP_LEVEL_FUNCTION_KIND;
    } else if (function.enclosingClass != null) {
      kind = FunctionInfo.METHOD_FUNCTION_KIND;
    }

    if (function is ConstructorEntity) {
      name =
          name == ""
              ? function.enclosingClass.name
              : "${function.enclosingClass.name}.${function.name}";
      kind = FunctionInfo.CONSTRUCTOR_FUNCTION_KIND;
    }

    FunctionModifiers modifiers = FunctionModifiers(
      isStatic: function.isStatic,
      isConst: function.isConst,
      isFactory:
          function is ConstructorEntity ? function.isFactoryConstructor : false,
      isExternal: function.isExternal,
    );
    List<CodeSpan> code = dumpInfoTask.codeOf(function);

    List<ParameterInfo> parameters = <ParameterInfo>[];
    List<String> inferredParameterTypes = <String>[];

    closedWorld.elementEnvironment.forEachParameterAsLocal(
      _globalInferenceResults.globalLocalsMap,
      function,
      (parameter) {
        inferredParameterTypes.add('${_resultOfParameter(parameter)}');
      },
    );
    int parameterIndex = 0;
    closedWorld.elementEnvironment.forEachParameter(function, (type, name, _) {
      // Synthesized parameters have no name. This can happen on parameters of
      // setters derived from lowering late fields.
      parameters.add(
        ParameterInfo(
          name ?? '#t$parameterIndex',
          inferredParameterTypes[parameterIndex++],
          '$type',
        ),
      );
    });

    final functionType = environment.getFunctionType(function);
    String returnType = '${functionType.returnType}';

    String inferredReturnType = '${_resultOfMember(function).returnType}';
    String sideEffects =
        '${_globalInferenceResults.inferredData.getSideEffectsOfElement(function)}';

    int inlinedCount = dumpInfoTask.inlineCount[function] ?? 0;

    FunctionInfo info = FunctionInfo(
      name: name,
      functionKind: kind!,
      modifiers: modifiers,
      returnType: returnType,
      inferredReturnType: inferredReturnType,
      parameters: parameters,
      sideEffects: sideEffects,
      inlinedCount: inlinedCount,
      code: code,
      type: functionType.toString(),
      outputUnit: _unitInfoForMember(function),
    );
    state.entityToInfo[function] = info;

    int closureSize = _addClosureInfo(info, function);
    size += closureSize;

    if (options.experimentCallInstrumentation) {
      // We use function.hashCode because it is globally unique and it is
      // available while we are doing codegen.
      info.coverageId = '${function.hashCode}';
    }

    info.size = size;

    state.info.functions.add(info);
    return info;
  }

  /// Adds closure information to [info], using all nested closures in [member].
  ///
  /// Returns the total size of the nested closures, to add to the info size.
  int _addClosureInfo(Info info, MemberEntity member) {
    assert(info is FunctionInfo || info is FieldInfo);
    int size = 0;
    List<ClosureInfo> nestedClosures = <ClosureInfo>[];
    environment.forEachNestedClosure(member, (closure) {
      final closureInfo = visitClosureClass(closure.enclosingClass!);
      if (closureInfo != null) {
        closureInfo.parent = info;
        nestedClosures.add(closureInfo);
        size += closureInfo.size;
      }
    });
    if (info is FunctionInfo) info.closures = nestedClosures;
    if (info is FieldInfo) info.closures = nestedClosures;

    return size;
  }

  OutputUnitInfo _infoFromOutputUnit(OutputUnit outputUnit) {
    return state.outputToInfo.putIfAbsent(outputUnit, () {
      // Dump-info currently only works with the full emitter. If another
      // emitter is used it will fail here.
      final filename =
          outputUnit.isMainOutput
              ? (options.outputUri?.pathSegments.last ?? 'out')
              : deferredPartFileName(options, outputUnit.name);
      OutputUnitInfo info = OutputUnitInfo(
        filename,
        outputUnit.name,
        dumpInfoTask._dumpInfoData.outputUnitSizes[outputUnit]!,
      );
      info.imports.addAll(
        closedWorld.outputUnitData.getImportNames(outputUnit),
      );
      state.info.outputUnits.add(info);
      return info;
    });
  }

  OutputUnitInfo _unitInfoForMember(MemberEntity entity) {
    return _infoFromOutputUnit(
      closedWorld.outputUnitData.outputUnitForMember(entity),
    );
  }

  OutputUnitInfo _unitInfoForClass(ClassEntity entity) {
    return _infoFromOutputUnit(
      closedWorld.outputUnitData.outputUnitForClass(entity, allowNull: true),
    );
  }

  OutputUnitInfo _unitInfoForClassType(ClassEntity entity) {
    return _infoFromOutputUnit(
      closedWorld.outputUnitData.outputUnitForClassType(
        entity,
        allowNull: true,
      ),
    );
  }

  OutputUnitInfo _unitInfoForConstant(ConstantValue constant) {
    final outputUnit = closedWorld.outputUnitData.outputUnitForConstant(
      constant,
    );
    return _infoFromOutputUnit(outputUnit);
  }
}

class KernelInfoCollector {
  final ir.Component component;
  final CompilerOptions options;
  final JClosedWorld closedWorld;
  final DumpInfoTask dumpInfoTask;
  final state = DumpInfoStateData();
  final ir.CoreTypes coreTypes;

  JElementEnvironment get environment => closedWorld.elementEnvironment;

  KernelInfoCollector(
    this.component,
    this.options,
    this.dumpInfoTask,
    this.closedWorld,
  ) : coreTypes = ir.CoreTypes(component);

  void run() {
    // TODO(markzipan): Add CFE constants to `state.info.constants`.
    component.libraries.forEach(visitLibrary);
  }

  LibraryInfo? visitLibrary(ir.Library lib) {
    final libEntity = environment.lookupLibrary(lib.importUri);
    if (libEntity == null) return null;

    String? libname = lib.name;
    if (libname == null || libname.isEmpty) {
      libname = '${lib.importUri}';
    }
    LibraryInfo info = LibraryInfo(libname, lib.importUri, null, 0);

    for (var member in lib.members) {
      final memberEntity = environment.lookupLibraryMember(
        libEntity,
        member.name.text,
      );
      if (memberEntity == null) continue;
      final function = member.function;
      if (function != null) {
        final functionInfo = visitFunction(
          function,
          functionEntity: memberEntity as FunctionEntity,
        );
        if (functionInfo != null) {
          info.topLevelFunctions.add(functionInfo);
          functionInfo.parent = info;
        }
      } else {
        final fieldInfo = visitField(
          member as ir.Field,
          fieldEntity: memberEntity as FieldEntity,
        );
        if (fieldInfo != null) {
          info.topLevelVariables.add(fieldInfo);
          fieldInfo.parent = info;
        }
      }
    }

    for (var clazz in lib.classes) {
      final classEntity = environment.lookupClass(libEntity, clazz.name);
      if (classEntity == null) continue;

      final classTypeInfo = visitClassType(clazz);
      if (classTypeInfo != null) {
        info.classTypes.add(classTypeInfo);
        classTypeInfo.parent = info;
      }

      final classInfo = visitClass(clazz, classEntity: classEntity);
      if (classInfo != null) {
        info.classes.add(classInfo);
        classInfo.parent = info;
      }
    }

    state.info.libraries.add(info);
    return info;
  }

  FieldInfo? visitField(ir.Field field, {required FieldEntity fieldEntity}) {
    FieldInfo info = FieldInfo.fromKernel(
      name: field.name.text,
      type: field.type.toStringInternal(),
      isConst: field.isConst,
    );

    if (options.experimentCallInstrumentation) {
      // We use field.hashCode because it is globally unique and it is
      // available while we are doing codegen.
      info.coverageId = '${field.hashCode}';
    }

    _addClosureInfo(
      info,
      field,
      libraryEntity: fieldEntity.library,
      memberEntity: fieldEntity,
    );

    state.info.fields.add(info);
    return info;
  }

  ClassTypeInfo? visitClassType(ir.Class clazz) {
    ClassTypeInfo classTypeInfo = ClassTypeInfo(name: clazz.name);
    state.info.classTypes.add(classTypeInfo);
    return classTypeInfo;
  }

  ClassInfo? visitClass(ir.Class clazz, {required ClassEntity classEntity}) {
    if (state.entityToInfo[classEntity] != null) {
      return state.entityToInfo[classEntity] as ClassInfo?;
    }

    final supers = <ClassInfo>[];
    for (var supertype in clazz.supers) {
      final superclass = supertype.classNode;
      // Ignore 'Object' to reduce overhead.
      if (superclass == coreTypes.objectClass) {
        continue;
      }
      final superclassLibrary =
          environment.lookupLibrary(superclass.enclosingLibrary.importUri)!;
      final superclassEntity = environment.lookupClass(
        superclassLibrary,
        superclass.name,
      );
      if (superclassEntity == null) continue;
      final classInfo = visitClass(superclass, classEntity: superclassEntity);
      if (classInfo != null) supers.add(classInfo);
    }

    ClassInfo classInfo = ClassInfo.fromKernel(
      name: clazz.name,
      isAbstract: clazz.isAbstract,
      supers: supers,
    );
    state.entityToInfo[classEntity] = classInfo;

    for (var member in clazz.members) {
      final isSetter = member is ir.Procedure && member.isSetter;
      // clazz.members includes constructors
      final name = Name(
        member.name.text,
        member.name.isPrivate ? member.name.library!.importUri : null,
        isSetter: isSetter,
      );
      final memberEntity =
          environment.lookupLocalClassMember(classEntity, name) ??
          environment.lookupConstructor(classEntity, member.name.text);
      if (memberEntity == null) continue;

      final function = member.function;
      if (function != null) {
        // Multiple kernel members can map to single JWorld member
        // (e.g., when one of a getter/field pair are tree-shaken),
        // so avoid duplicating the downstream info object.
        if (memberEntity is FunctionEntity) {
          final functionInfo = visitFunction(
            function,
            functionEntity: memberEntity,
          );
          if (functionInfo != null) {
            classInfo.functions.add(functionInfo);
            functionInfo.parent = classInfo;
          }
        }
      } else {
        final fieldInfo = visitField(
          member as ir.Field,
          fieldEntity: memberEntity as FieldEntity,
        );
        if (fieldInfo != null) {
          classInfo.fields.add(fieldInfo);
          fieldInfo.parent = classInfo;
        }
      }
    }

    state.info.classes.add(classInfo);
    return classInfo;
  }

  FunctionInfo? visitFunction(
    ir.FunctionNode function, {
    required FunctionEntity functionEntity,
    LocalFunctionInfo? localFunctionInfo,
  }) {
    final parent = function.parent;
    bool isClosureCallMethod = parent is ir.LocalFunction;
    String name = isClosureCallMethod ? 'call' : parent!.toStringInternal();
    bool isConstructor = parent is ir.Constructor;
    bool isFactory = parent is ir.Procedure && parent.isFactory;
    // Kernel `isStatic` refers to static members, constructors, and top-level
    // members.
    bool isTopLevel =
        (parent is ir.Field && parent.isStatic) ||
        (parent is ir.Procedure && parent.isStatic) ||
        (parent is ir.Member && parent.enclosingClass == null);
    bool isStaticMember =
        ((parent is ir.Field && parent.isStatic) ||
            (parent is ir.Procedure && parent.isStatic)) &&
        (parent is ir.Member && parent.enclosingClass != null) &&
        !isConstructor &&
        !isFactory;
    bool isConst = parent is ir.Member && parent.isConst;
    bool isExternal = parent is ir.Member && parent.isExternal;
    bool isMethod =
        isClosureCallMethod ||
        (parent is ir.Member && parent.enclosingClass != null);
    bool isGetter = parent is ir.Procedure && parent.isGetter;
    bool isSetter = parent is ir.Procedure && parent.isSetter;
    late int kind;
    if (isStaticMember || isTopLevel) {
      kind = FunctionInfo.TOP_LEVEL_FUNCTION_KIND;
    } else if (isMethod) {
      kind = FunctionInfo.METHOD_FUNCTION_KIND;
    }
    if (isConstructor || isFactory) {
      kind = FunctionInfo.CONSTRUCTOR_FUNCTION_KIND;
      String functionName = function.toStringInternal();
      name = functionName.isEmpty ? name : '$name$functionName';
    } else {
      if (parent!.parent is ir.Class && name.contains('.')) {
        name = name.split('.')[1];
      }
    }
    if (name.endsWith('.')) name = name.substring(0, name.length - 1);

    FunctionModifiers modifiers = FunctionModifiers(
      isStatic: isStaticMember,
      isConst: isConst,
      isFactory: isFactory,
      isExternal: isExternal,
      isGetter: isGetter,
      isSetter: isSetter,
    );

    // TODO(markzipan): Determine if it's safe to default to nonNullable here.
    final nullability =
        parent is ir.Member
            ? parent.enclosingLibrary.nonNullable
            : ir.Nullability.nonNullable;
    final functionType = function.computeFunctionType(nullability);

    FunctionInfo info = FunctionInfo.fromKernel(
      name: name,
      functionKind: kind,
      modifiers: modifiers,
      returnType: function.returnType.toStringInternal(),
      type: functionType.toStringInternal(),
    );

    final functionParent = function.parent;
    if (functionParent is ir.Member) {
      _addClosureInfo(
        info,
        functionParent,
        libraryEntity: functionEntity.library,
        memberEntity: functionEntity,
      );
    } else {
      // This branch is only reached when function is a 'call' method.
      // TODO(markzipan): Ensure call methods never have children.
      info.closures = [];
    }

    if (options.experimentCallInstrumentation) {
      // We use function.hashCode because it is globally unique and it is
      // available while we are doing codegen.
      info.coverageId = '${function.hashCode}';
    }

    state.info.functions.add(info);
    return info;
  }

  /// Adds closure information to [info], using all nested closures in [member].
  void _addClosureInfo(
    Info info,
    ir.Member member, {
    required LibraryEntity libraryEntity,
    required MemberEntity memberEntity,
  }) {
    final localFunctionInfoCollector = LocalFunctionInfoCollector();
    member.accept(localFunctionInfoCollector);
    List<ClosureInfo> nestedClosures = <ClosureInfo>[];
    localFunctionInfoCollector.localFunctions.forEach((key, value) {
      late FunctionEntity closureEntity;
      int closureOrder = value.order;
      environment.forEachNestedClosure(memberEntity, (closure) {
        if (closure.enclosingClass!.name == value.name &&
            (closureOrder-- == 0)) {
          closureEntity = closure;
        }
      });
      final closureClassEntity = closureEntity.enclosingClass!;
      final closureInfo = ClosureInfo.fromKernel(name: value.disambiguatedName);

      final callMethod = closedWorld.elementEnvironment.lookupClassMember(
        closureClassEntity,
        Names.call,
      );
      final functionInfo = visitFunction(
        key.function,
        functionEntity: callMethod as FunctionEntity,
        localFunctionInfo: value,
      );

      closureInfo.function = functionInfo!;
      functionInfo.parent = closureInfo;
      state.info.closures.add(closureInfo);

      closureInfo.parent = info;
      nestedClosures.add(closureInfo);
    });
    if (info is FunctionInfo) info.closures = nestedClosures;
    if (info is FieldInfo) info.closures = nestedClosures;
  }
}

/// Maps JWorld Entity objects to disambiguated names in order to map them
/// to/from Kernel.
///
/// This is primarily used for naming closure objects, which rely on Entity
/// object identity to determine uniqueness.
///
/// Note: this relies on the Kernel traversal order to determine order, which
/// may change in the future.
class EntityDisambiguator {
  final nameFrequencies = <String, int>{};
  final entityNames = <Entity, String>{};

  String name(Entity entity) {
    final disambiguatedName = entityNames[entity];
    if (disambiguatedName != null) {
      return disambiguatedName;
    }
    final entityName = entity.name!;
    nameFrequencies[entityName] = (nameFrequencies[entityName] ?? -1) + 1;
    final order = nameFrequencies[entityName]!;
    entityNames[entity] = order == 0 ? entityName : '$entityName%${order - 1}';

    return entityNames[entity]!;
  }
}

/// Annotates [KernelInfoCollector] with info extracted from closed-world
/// analysis.
class DumpInfoAnnotator {
  final KernelInfoCollector kernelInfo;
  final CompilerOptions options;
  final JClosedWorld closedWorld;
  final GlobalTypeInferenceResults _globalInferenceResults;
  final DumpInfoTask dumpInfoTask;
  final entityDisambiguator = EntityDisambiguator();

  JElementEnvironment get environment => closedWorld.elementEnvironment;

  DumpInfoAnnotator(
    this.kernelInfo,
    this.options,
    this.dumpInfoTask,
    this.closedWorld,
    this._globalInferenceResults,
  );

  void run() {
    dumpInfoTask._dumpInfoData.constantCode.forEach((constant, span) {
      // TODO(sigmund): add dependencies on other constants
      var info = ConstantInfo(
        size: span.end! - span.start!,
        code: [span],
        outputUnit: _unitInfoForConstant(constant),
      );
      kernelInfo.state.constantToInfo[constant] = info;
      info.treeShakenStatus = TreeShakenStatus.Live;
      kernelInfo.state.info.constants.add(info);
    });
    environment.libraries.forEach(visitLibrary);
  }

  /// Whether to emit information about [entity].
  ///
  /// By default we emit information for any entity that contributes to the
  /// output size. Either because it is a function being emitted or inlined,
  /// or because it is an entity that holds dependencies to other entities.
  bool shouldKeep(Entity entity) {
    return dumpInfoTask.impacts.containsKey(entity) ||
        dumpInfoTask.inlineCount.containsKey(entity);
  }

  LibraryInfo? visitLibrary(LibraryEntity lib) {
    var kLibraryInfos = kernelInfo.state.info.libraries.where(
      (i) => '${i.uri}' == '${lib.canonicalUri}',
    );
    assert(
      kLibraryInfos.length == 1,
      'Ambiguous library resolution. '
      'Expected singleton, found $kLibraryInfos',
    );
    var kLibraryInfo = kLibraryInfos.first;
    kernelInfo.state.entityToInfo[lib] = kLibraryInfo;

    String libname = environment.getLibraryName(lib);
    if (libname.isEmpty) {
      libname = '${lib.canonicalUri}';
    }
    assert(kLibraryInfo.name == libname);
    kLibraryInfo.size = dumpInfoTask.sizeOf(lib);

    environment.forEachLibraryMember(lib, (MemberEntity member) {
      if (member.isFunction || member.isGetter || member.isSetter) {
        visitFunction(member as FunctionEntity, libname);
      } else if (member is FieldEntity) {
        visitField(member, libname);
      } else {
        throw StateError('Class member not a function or field');
      }
    });

    environment.forEachClass(lib, (ClassEntity clazz) {
      visitClassType(clazz, libname);
      visitClass(clazz, libname);
    });

    bool hasLiveFields = [
      ...kLibraryInfo.topLevelFunctions,
      ...kLibraryInfo.topLevelVariables,
      ...kLibraryInfo.classes,
      ...kLibraryInfo.classTypes,
    ].any((i) => i.treeShakenStatus == TreeShakenStatus.Live);
    if (!hasLiveFields && !shouldKeep(lib)) return null;
    kLibraryInfo.treeShakenStatus = TreeShakenStatus.Live;
    return kLibraryInfo;
  }

  GlobalTypeInferenceMemberResult _resultOfMember(MemberEntity e) =>
      _globalInferenceResults.resultOfMember(e);

  AbstractValue _resultOfParameter(Local e) =>
      _globalInferenceResults.resultOfParameter(e);

  // TODO(markzipan): [parentName] is used for disambiguation, but this might
  // not always be valid. Check and validate later.
  FieldInfo? visitField(FieldEntity field, String parentName) {
    final inferredType = _resultOfMember(field).type;
    // If a field has an empty inferred type it is never used.
    if (closedWorld.abstractValueDomain
        .isEmpty(inferredType)
        .isDefinitelyTrue) {
      return null;
    }

    final kFieldInfos =
        kernelInfo.state.info.fields
            .where(
              (f) =>
                  f.name == field.name &&
                  fullyResolvedNameForInfo(f.parent) == parentName,
            )
            .toList();
    assert(
      kFieldInfos.length == 1,
      'Ambiguous field resolution. '
      'Expected singleton, found $kFieldInfos',
    );
    final kFieldInfo = kFieldInfos.first;
    kernelInfo.state.entityToInfo[field] = kFieldInfo;

    int size = dumpInfoTask.sizeOf(field);
    List<CodeSpan> code = dumpInfoTask.codeOf(field);

    // TODO(het): Why doesn't `size` account for the code size already?
    size += code.length;

    kFieldInfo.outputUnit = _unitInfoForMember(field);
    kFieldInfo.inferredType = '$inferredType';
    kFieldInfo.code = code;
    kFieldInfo.treeShakenStatus = TreeShakenStatus.Live;

    FieldAnalysisData fieldData = closedWorld.fieldAnalysis.getFieldData(
      field as JField,
    );
    if (fieldData.initialValue != null) {
      kFieldInfo.initializer =
          kernelInfo.state.constantToInfo[fieldData.initialValue]
              as ConstantInfo?;
    }

    int closureSize = _addClosureInfo(kFieldInfo, field);
    kFieldInfo.size = size + closureSize;
    return kFieldInfo;
  }

  // TODO(markzipan): [parentName] is used for disambiguation, but this might
  // not always be valid. Check and validate later.
  ClassTypeInfo? visitClassType(ClassEntity clazz, String parentName) {
    var kClassTypeInfos = kernelInfo.state.info.classTypes.where(
      (i) => i.name == clazz.name && i.parent!.name == parentName,
    );
    assert(
      kClassTypeInfos.length == 1,
      'Ambiguous class type resolution. '
      'Expected singleton, found $kClassTypeInfos',
    );
    var kClassTypeInfo = kClassTypeInfos.first;

    // TODO(joshualitt): Get accurate size information for class types.
    kClassTypeInfo.size = 0;

    // Omit class type if it is not needed.
    bool isNeeded = dumpInfoTask._dumpInfoData.neededClassTypes.contains(clazz);
    if (!isNeeded) return null;

    assert(kClassTypeInfo.name == clazz.name);
    kClassTypeInfo.outputUnit = _unitInfoForClassType(clazz);
    kClassTypeInfo.treeShakenStatus = TreeShakenStatus.Live;
    return kClassTypeInfo;
  }

  // TODO(markzipan): [parentName] is used for disambiguation, but this might
  // not always be valid. Check and validate later.
  ClassInfo? visitClass(ClassEntity clazz, String parentName) {
    final kClassInfos =
        kernelInfo.state.info.classes
            .where(
              (i) =>
                  i.name == clazz.name &&
                  fullyResolvedNameForInfo(i.parent) == parentName,
            )
            .toList();
    assert(
      kClassInfos.length == 1,
      'Ambiguous class resolution. '
      'Expected singleton, found $kClassInfos',
    );
    final kClassInfo = kClassInfos.first;
    kernelInfo.state.entityToInfo[clazz] = kClassInfo;

    /// Add synthetically injected superclasses like `Interceptor` and
    /// `LegacyJavaScriptObject`.
    final syntheticSuperclass = closedWorld.commonElements.getDefaultSuperclass(
      clazz,
      closedWorld.nativeData,
    );
    if (syntheticSuperclass != closedWorld.commonElements.objectClass) {
      final classInfo = kernelInfo.state.entityToInfo[syntheticSuperclass];
      if (classInfo != null) {
        kClassInfo.supers.add(classInfo as ClassInfo);
      }
    }

    int size = dumpInfoTask.sizeOf(clazz);
    final disambiguatedMemberName = '$parentName/${clazz.name}';
    environment.forEachLocalClassMember(clazz, (member) {
      // Skip certain incongruent locals that during method alias installation.
      if (member is JMethod && member.enclosingClass!.name != clazz.name) {
        return;
      }
      if (member.isFunction || member.isGetter || member.isSetter) {
        final functionInfo = visitFunction(
          member as FunctionEntity,
          disambiguatedMemberName,
        );
        if (functionInfo != null) {
          for (var closureInfo in functionInfo.closures) {
            size += closureInfo.size;
          }
        }
      } else if (member is FieldEntity) {
        final fieldInfo = visitField(member, disambiguatedMemberName);
        if (fieldInfo != null) {
          for (var closureInfo in fieldInfo.closures) {
            size += closureInfo.size;
          }
        }
      } else {
        throw StateError('Class member not a function or field');
      }
    });
    environment.forEachConstructor(clazz, (constructor) {
      final functionInfo = visitFunction(constructor, disambiguatedMemberName);
      if (functionInfo != null) {
        for (var closureInfo in functionInfo.closures) {
          size += closureInfo.size;
        }
      }
    });
    kClassInfo.size = size;

    bool hasLiveFields = [
      ...kClassInfo.fields,
      ...kClassInfo.functions,
    ].any((i) => i.treeShakenStatus == TreeShakenStatus.Live);
    if (!dumpInfoTask._dumpInfoData.neededClasses.contains(clazz) &&
        !hasLiveFields) {
      return null;
    }

    kClassInfo.outputUnit = _unitInfoForClass(clazz);
    kClassInfo.treeShakenStatus = TreeShakenStatus.Live;
    return kClassInfo;
  }

  ClosureInfo? visitClosureClass(ClassEntity element) {
    final disambiguatedElementName = entityDisambiguator.name(element);
    final kClosureInfos =
        kernelInfo.state.info.closures
            .where((info) => info.name == disambiguatedElementName)
            .toList();
    assert(
      kClosureInfos.length == 1,
      'Ambiguous closure resolution. '
      'Expected singleton, found $kClosureInfos',
    );
    final kClosureInfo = kClosureInfos.first;
    kernelInfo.state.entityToInfo[element] = kClosureInfo;

    kClosureInfo.outputUnit = _unitInfoForClass(element);
    kClosureInfo.size = dumpInfoTask.sizeOf(element);

    final callMethod = closedWorld.elementEnvironment.lookupClassMember(
      element,
      Names.call,
    );

    final functionInfo = visitFunction(
      callMethod as FunctionEntity,
      disambiguatedElementName,
      isClosure: true,
    );
    if (functionInfo == null) return null;

    kClosureInfo.treeShakenStatus = TreeShakenStatus.Live;
    return kClosureInfo;
  }

  // TODO(markzipan): [parentName] is used for disambiguation, but this might
  // not always be valid. Check and validate later.
  FunctionInfo? visitFunction(
    FunctionEntity function,
    String parentName, {
    bool isClosure = false,
  }) {
    int size = dumpInfoTask.sizeOf(function);
    if (size == 0 && !shouldKeep(function)) return null;

    var compareName = function.name;
    if (function is ConstructorEntity) {
      compareName =
          compareName == ""
              ? function.enclosingClass.name
              : "${function.enclosingClass.name}.${function.name}";
    }

    // Multiple kernel members can sometimes map to a single JElement.
    // [isSetter] and [isGetter] are required for disambiguating these cases.
    final kFunctionInfos =
        kernelInfo.state.info.functions
            .where(
              (i) =>
                  i.name == compareName &&
                  (isClosure
                          ? i.parent!.name
                          : fullyResolvedNameForInfo(i.parent)) ==
                      parentName &&
                  !(function.isGetter ^ i.modifiers.isGetter) &&
                  !(function.isSetter ^ i.modifiers.isSetter),
            )
            .toList();
    assert(
      kFunctionInfos.length <= 1,
      'Ambiguous function resolution. '
      'Expected single or none, found $kFunctionInfos',
    );
    if (kFunctionInfos.isEmpty) return null;
    final kFunctionInfo = kFunctionInfos.first;
    kernelInfo.state.entityToInfo[function] = kFunctionInfo;

    List<CodeSpan> code = dumpInfoTask.codeOf(function);
    List<ParameterInfo> parameters = <ParameterInfo>[];
    List<String> inferredParameterTypes = <String>[];

    closedWorld.elementEnvironment.forEachParameterAsLocal(
      _globalInferenceResults.globalLocalsMap,
      function,
      (parameter) {
        inferredParameterTypes.add('${_resultOfParameter(parameter)}');
      },
    );
    int parameterIndex = 0;
    closedWorld.elementEnvironment.forEachParameter(function, (type, name, _) {
      // Synthesized parameters have no name. This can happen on parameters of
      // setters derived from lowering late fields.
      parameters.add(
        ParameterInfo(
          name ?? '#t$parameterIndex',
          inferredParameterTypes[parameterIndex++],
          '$type',
        ),
      );
    });

    String inferredReturnType = '${_resultOfMember(function).returnType}';
    String sideEffects =
        '${_globalInferenceResults.inferredData.getSideEffectsOfElement(function)}';
    int inlinedCount = dumpInfoTask.inlineCount[function] ?? 0;

    kFunctionInfo.inferredReturnType = inferredReturnType;
    kFunctionInfo.sideEffects = sideEffects;
    kFunctionInfo.inlinedCount = inlinedCount;
    kFunctionInfo.code = code;
    kFunctionInfo.parameters = parameters;
    kFunctionInfo.outputUnit = _unitInfoForMember(function);

    int closureSize = _addClosureInfo(kFunctionInfo, function);
    kFunctionInfo.size = size + closureSize;

    kFunctionInfo.treeShakenStatus = TreeShakenStatus.Live;
    return kFunctionInfo;
  }

  /// Adds closure information to [info], using all nested closures in [member].
  ///
  /// Returns the total size of the nested closures, to add to the info size.
  int _addClosureInfo(BasicInfo info, MemberEntity member) {
    assert(info is FunctionInfo || info is FieldInfo);
    int size = 0;
    environment.forEachNestedClosure(member, (closure) {
      final closureInfo = visitClosureClass(closure.enclosingClass!);
      if (closureInfo != null) {
        closureInfo.treeShakenStatus = TreeShakenStatus.Live;
        size += closureInfo.size;
      }
    });
    return size;
  }

  OutputUnitInfo _infoFromOutputUnit(OutputUnit outputUnit) {
    return kernelInfo.state.outputToInfo.putIfAbsent(outputUnit, () {
      // Dump-info currently only works with the full emitter. If another
      // emitter is used it will fail here.
      final filename =
          outputUnit.isMainOutput
              ? (options.outputUri?.pathSegments.last ?? 'out')
              : deferredPartFileName(options, outputUnit.name);
      OutputUnitInfo info = OutputUnitInfo(
        filename,
        outputUnit.name,
        dumpInfoTask._dumpInfoData.outputUnitSizes[outputUnit]!,
      );
      info.treeShakenStatus = TreeShakenStatus.Live;
      info.imports.addAll(
        closedWorld.outputUnitData.getImportNames(outputUnit),
      );
      kernelInfo.state.info.outputUnits.add(info);
      return info;
    });
  }

  OutputUnitInfo _unitInfoForMember(MemberEntity entity) {
    return _infoFromOutputUnit(
      closedWorld.outputUnitData.outputUnitForMember(entity),
    );
  }

  OutputUnitInfo _unitInfoForClass(ClassEntity entity) {
    return _infoFromOutputUnit(
      closedWorld.outputUnitData.outputUnitForClass(entity, allowNull: true),
    );
  }

  OutputUnitInfo _unitInfoForClassType(ClassEntity entity) {
    return _infoFromOutputUnit(
      closedWorld.outputUnitData.outputUnitForClassType(
        entity,
        allowNull: true,
      ),
    );
  }

  OutputUnitInfo _unitInfoForConstant(ConstantValue constant) {
    OutputUnit outputUnit = closedWorld.outputUnitData.outputUnitForConstant(
      constant,
    );
    return _infoFromOutputUnit(outputUnit);
  }
}

class Selection {
  final Entity selectedEntity;
  final Object? receiverConstraint;
  Selection(this.selectedEntity, this.receiverConstraint);
}

/// Interface used to record information from different parts of the compiler so
/// we can emit them in the dump-info task.
// TODO(sigmund,het): move more features here. Ideally the dump-info task
// shouldn't reach into internals of other parts of the compiler. For example,
// we currently reach into the full emitter and as a result we don't support
// dump-info when using the startup-emitter (issue #24190).
abstract class InfoReporter {
  void reportInlined(FunctionEntity element, MemberEntity inlinedFrom);
}

class DumpInfoTask extends CompilerTask implements InfoReporter {
  final CompilerOptions options;
  final api.CompilerOutput outputProvider;
  final DiagnosticReporter reporter;
  final Measurer measurer;
  final bool useBinaryFormat;

  DumpInfoTask(this.options, this.measurer, this.outputProvider, this.reporter)
    : useBinaryFormat = options.useDumpInfoBinaryFormat,
      super(measurer);

  @override
  String get name => "Dump Info";

  /// The size of the generated output.
  late DumpInfoProgramData _dumpInfoData;

  final Map<Entity, int> inlineCount = <Entity, int>{};

  // A mapping from an entity to a list of entities that are
  // inlined inside of it.
  final Map<Entity, List<Entity>> inlineMap = <Entity, List<Entity>>{};

  final Map<MemberEntity, WorldImpact> impacts = {};

  /// Register the size of the generated output.
  void registerDumpInfoProgramData(DumpInfoProgramData dumpInfoData) {
    _dumpInfoData = dumpInfoData;
  }

  @override
  void reportInlined(FunctionEntity element, MemberEntity inlinedFrom) {
    inlineCount.update(element, (i) => i + 1, ifAbsent: () => 1);
    inlineMap.putIfAbsent(inlinedFrom, () => <Entity>[]);
    inlineMap[inlinedFrom]!.add(element);
  }

  void unregisterImpact(MemberEntity impactSource) {
    impacts.remove(impactSource);
  }

  /// Returns an iterable of [Selection]s that are used by [entity]. Each
  /// [Selection] contains an entity that is used and the selector that
  /// selected the entity.
  Iterable<Selection> getRetaining(
    MemberEntity entity,
    JClosedWorld closedWorld,
  ) {
    final impact = impacts[entity];
    if (impact == null) return const <Selection>[];

    var selections = <Selection>[];
    impact.forEachDynamicUse((_, dynamicUse) {
      final mask = dynamicUse.receiverConstraint as AbstractValue?;
      selections.addAll(
        closedWorld
            // TODO(het): Handle `call` on `Closure` through
            // `world.includesClosureCall`.
            .locateMembers(dynamicUse.selector, mask)
            .map((MemberEntity e) => Selection(e, mask)),
      );
    });
    impact.forEachStaticUse((_, staticUse) {
      selections.add(Selection(staticUse.element, null));
    });
    unregisterImpact(entity);
    return selections;
  }

  /// Returns the size of the source code that was generated for an entity.
  /// If no source code was produced, return 0.
  int sizeOf(Entity entity) {
    return _dumpInfoData.entityCodeSize[entity] ?? 0;
  }

  List<CodeSpan> codeOf(MemberEntity entity) {
    return _dumpInfoData.entityCode[entity] ?? const [];
  }

  void _populateImpacts(
    JClosedWorld closedWorld,
    CodegenResults codegenResults,
    JsBackendStrategy backendStrategy,
  ) {
    backendStrategy.initialize(closedWorld, codegenResults.codegenInputs);

    _dumpInfoData.registeredImpacts.forEach((member, impact) {
      impacts[member] = backendStrategy.transformCodegenImpact(impact);
    });
    for (final member in _dumpInfoData.serializedImpactMembers) {
      final (:result, :isGenerated) = codegenResults.getCodegenResults(member);
      assert(!isGenerated, 'Should not be generating impact: $member');
      impacts[member] = backendStrategy.transformCodegenImpact(result.impact);
    }
  }

  Future<DumpInfoStateData> dumpInfo(
    JClosedWorld closedWorld,
    GlobalTypeInferenceResults globalInferenceResults,
    CodegenResults codegenResults,
    JsBackendStrategy backendStrategy,
  ) async {
    late DumpInfoStateData dumpInfoState;
    await measure(() async {
      _populateImpacts(closedWorld, codegenResults, backendStrategy);

      ElementInfoCollector elementInfoCollector = ElementInfoCollector(
        options,
        this,
        closedWorld,
        globalInferenceResults,
      )..run();

      dumpInfoState = await buildDumpInfoData(
        closedWorld,
        elementInfoCollector,
      );
      if (useBinaryFormat) {
        dumpInfoBinary(dumpInfoState.info);
      } else {
        dumpInfoJson(dumpInfoState.info);
      }
      return;
    });
    return dumpInfoState;
  }

  Future<DumpInfoStateData> dumpInfoNew(
    ir.Component component,
    JClosedWorld closedWorld,
    GlobalTypeInferenceResults globalInferenceResults,
    CodegenResults codegenResults,
    JsBackendStrategy backendStrategy,
  ) async {
    late DumpInfoStateData dumpInfoState;
    await measure(() async {
      _populateImpacts(closedWorld, codegenResults, backendStrategy);

      KernelInfoCollector kernelInfoCollector = KernelInfoCollector(
        component,
        options,
        this,
        closedWorld,
      )..run();

      DumpInfoAnnotator(
        kernelInfoCollector,
        options,
        this,
        closedWorld,
        globalInferenceResults,
      ).run();

      dumpInfoState = await buildDumpInfoDataNew(
        closedWorld,
        kernelInfoCollector,
      );
      TreeShakingInfoVisitor().filter(dumpInfoState.info);

      if (useBinaryFormat) {
        dumpInfoBinary(dumpInfoState.info);
      } else {
        dumpInfoJson(dumpInfoState.info);
      }
    });
    return dumpInfoState;
  }

  void dumpInfoJson(AllInfo data) {
    JsonEncoder encoder = const JsonEncoder.withIndent('  ');
    final name = (options.outputUri?.pathSegments.last ?? 'out');
    final outputSink = outputProvider.createOutputSink(
      name,
      'info.json',
      api.OutputType.dumpInfo,
    );
    final sink = encoder.startChunkedConversion(
      _BufferedStringOutputSink(outputSink),
    );
    sink.add(AllInfoJsonCodec(isBackwardCompatible: true).encode(data));
    reporter.reportInfoMessage(noLocationSpannable, MessageKind.generic, {
      'text':
          'Learn how to process the dumped .info.json file at '
          'https://dart.dev/go/dart2js-info',
    });
  }

  void dumpInfoBinary(AllInfo data) {
    final name = "${options.outputUri?.pathSegments.last ?? 'out'}.info.data";
    Sink<List<int>> sink = outputProvider.createBinarySink(
      options.outputUri!.resolve(name),
    );
    dump_info.encode(data, sink);
    reporter.reportInfoMessage(noLocationSpannable, MessageKind.generic, {
      'text':
          'Learn how to parse and process the dumped .info.data file at '
          'https://dart.dev/go/dart2js-info',
    });
  }

  Future<DumpInfoStateData> buildDumpInfoData(
    JClosedWorld closedWorld,
    ElementInfoCollector infoCollector,
  ) async {
    Stopwatch stopwatch = Stopwatch();
    stopwatch.start();

    DumpInfoStateData result = infoCollector.state;

    // Recursively build links to function uses
    final functionEntities =
        infoCollector.state.entityToInfo.keys.whereType<FunctionEntity>();
    for (final entity in functionEntities) {
      final info = infoCollector.state.entityToInfo[entity] as FunctionInfo;
      Iterable<Selection> uses = getRetaining(entity, closedWorld);
      // Don't bother recording an empty list of dependencies.
      for (Selection selection in uses) {
        // Don't register dart2js builtin functions that are not recorded.
        final useInfo =
            infoCollector.state.entityToInfo[selection.selectedEntity];
        if (useInfo == null) continue;
        info.uses.add(
          DependencyInfo(useInfo, selection.receiverConstraint?.toString()),
        );
      }
    }

    // Recursively build links to field uses
    final fieldEntity =
        infoCollector.state.entityToInfo.keys.whereType<FieldEntity>();
    for (final entity in fieldEntity) {
      final info = infoCollector.state.entityToInfo[entity] as FieldInfo;
      Iterable<Selection> uses = getRetaining(entity, closedWorld);
      // Don't bother recording an empty list of dependencies.
      for (Selection selection in uses) {
        final useInfo =
            infoCollector.state.entityToInfo[selection.selectedEntity];
        if (useInfo == null) continue;
        info.uses.add(
          DependencyInfo(useInfo, selection.receiverConstraint?.toString()),
        );
      }
    }

    // Track dependencies that come from inlining.
    for (Entity entity in inlineMap.keys) {
      final outerInfo = infoCollector.state.entityToInfo[entity] as CodeInfo?;
      if (outerInfo == null) continue;
      for (final inlined in inlineMap[entity]!) {
        final inlinedInfo = infoCollector.state.entityToInfo[inlined];
        if (inlinedInfo == null) continue;
        outerInfo.uses.add(DependencyInfo(inlinedInfo, 'inlined'));
      }
    }

    result.info.deferredFiles = _dumpInfoData.fragmentDeferredMap;
    stopwatch.stop();

    result.info.program = ProgramInfo(
      entrypoint:
          infoCollector.state.entityToInfo[closedWorld
                  .elementEnvironment
                  .mainFunction]
              as FunctionInfo,
      size: _dumpInfoData.programSize,
      ramUsage: await currentHeapCapacityInMb(),
      dart2jsVersion: options.hasBuildId ? options.buildId : null,
      compilationMoment: DateTime.now(),
      compilationDuration: measurer.elapsedWallClock,
      toJsonDuration: Duration(milliseconds: stopwatch.elapsedMilliseconds),
      dumpInfoDuration: Duration(milliseconds: timing),
      noSuchMethodEnabled: closedWorld.backendUsage.isNoSuchMethodUsed,
      isRuntimeTypeUsed: closedWorld.backendUsage.isRuntimeTypeUsed,
      isIsolateInUse: false,
      isFunctionApplyUsed: closedWorld.backendUsage.isFunctionApplyUsed,
      minified: options.enableMinification,
    );

    return result;
  }

  Future<DumpInfoStateData> buildDumpInfoDataNew(
    JClosedWorld closedWorld,
    KernelInfoCollector infoCollector,
  ) async {
    Stopwatch stopwatch = Stopwatch();
    stopwatch.start();

    DumpInfoStateData result = infoCollector.state;

    // Recursively build links to function uses
    final functionEntities =
        infoCollector.state.entityToInfo.keys.whereType<FunctionEntity>();
    for (final entity in functionEntities) {
      final info = infoCollector.state.entityToInfo[entity] as FunctionInfo;
      Iterable<Selection> uses = getRetaining(entity, closedWorld);
      // Don't bother recording an empty list of dependencies.
      for (Selection selection in uses) {
        // Don't register dart2js builtin functions that are not recorded.
        final useInfo =
            infoCollector.state.entityToInfo[selection.selectedEntity];
        if (useInfo == null) continue;
        if (useInfo.treeShakenStatus != TreeShakenStatus.Live) continue;
        info.uses.add(
          DependencyInfo(useInfo, selection.receiverConstraint?.toString()),
        );
      }
    }

    // Recursively build links to field uses
    final fieldEntity =
        infoCollector.state.entityToInfo.keys.whereType<FieldEntity>();
    for (final entity in fieldEntity) {
      final info = infoCollector.state.entityToInfo[entity] as FieldInfo;
      Iterable<Selection> uses = getRetaining(entity, closedWorld);
      // Don't bother recording an empty list of dependencies.
      for (Selection selection in uses) {
        final useInfo =
            infoCollector.state.entityToInfo[selection.selectedEntity];
        if (useInfo == null) continue;
        if (useInfo.treeShakenStatus != TreeShakenStatus.Live) continue;
        info.uses.add(
          DependencyInfo(useInfo, selection.receiverConstraint?.toString()),
        );
      }
    }

    // Track dependencies that come from inlining.
    for (Entity entity in inlineMap.keys) {
      final outerInfo = infoCollector.state.entityToInfo[entity] as CodeInfo?;
      if (outerInfo == null) continue;
      for (final inlined in inlineMap[entity]!) {
        final inlinedInfo = infoCollector.state.entityToInfo[inlined];
        if (inlinedInfo == null) continue;
        if (inlinedInfo.treeShakenStatus != TreeShakenStatus.Live) continue;
        outerInfo.uses.add(DependencyInfo(inlinedInfo, 'inlined'));
      }
    }

    result.info.deferredFiles = _dumpInfoData.fragmentDeferredMap;
    stopwatch.stop();

    result.info.program = ProgramInfo(
      entrypoint:
          infoCollector.state.entityToInfo[closedWorld
                  .elementEnvironment
                  .mainFunction]
              as FunctionInfo,
      size: _dumpInfoData.programSize,
      ramUsage: await currentHeapCapacityInMb(),
      dart2jsVersion: options.hasBuildId ? options.buildId : null,
      compilationMoment: DateTime.now(),
      compilationDuration: measurer.elapsedWallClock,
      toJsonDuration: Duration(milliseconds: stopwatch.elapsedMilliseconds),
      dumpInfoDuration: Duration(milliseconds: timing),
      noSuchMethodEnabled: closedWorld.backendUsage.isNoSuchMethodUsed,
      isRuntimeTypeUsed: closedWorld.backendUsage.isRuntimeTypeUsed,
      isIsolateInUse: false,
      isFunctionApplyUsed: closedWorld.backendUsage.isFunctionApplyUsed,
      minified: options.enableMinification,
    );

    return result;
  }
}

class _BufferedStringOutputSink implements Sink<String> {
  StringBuffer buffer = StringBuffer();
  final Sink<String> outputSink;
  static const int _maxLength = 1024 * 1024 * 500;

  _BufferedStringOutputSink(this.outputSink);

  @override
  void add(String data) {
    buffer.write(data);
    if (buffer.length > _maxLength) {
      outputSink.add(buffer.toString());
      buffer.clear();
    }
  }

  @override
  void close() {
    outputSink.add(buffer.toString());
    outputSink.close();
  }
}

/// Helper class to store what dump-info will show for a piece of code.
// TODO(sigmund): delete once we no longer emit text by default.
class _CodeData extends CodeSpan {
  final StringBuffer _text = StringBuffer();

  @override
  String get text => '$_text';
  int get length => end! - start!;
}

/// Holds dump-info's mutable state.
class DumpInfoStateData {
  final AllInfo info = AllInfo();
  final Map<Entity, Info> entityToInfo = <Entity, Info>{};
  final Map<ConstantValue, Info> constantToInfo = <ConstantValue, Info>{};
  final Map<OutputUnit, OutputUnitInfo> outputToInfo = {};

  DumpInfoStateData();
}

class LocalFunctionInfo {
  final ir.LocalFunction localFunction;
  final String name;
  final int order;
  bool isInvoked = false;

  LocalFunctionInfo(this.localFunction, this.name, this.order);

  String get disambiguatedName => order == 0 ? name : '$name%${order - 1}';
}

class LocalFunctionInfoCollector extends ir.RecursiveVisitor {
  final localFunctions = <ir.LocalFunction, LocalFunctionInfo>{};
  final localFunctionNameCount = <String, int>{};

  LocalFunctionInfo generateLocalFunctionInfo(ir.LocalFunction localFunction) {
    final name = _computeClosureName(localFunction);
    localFunctionNameCount[name] = (localFunctionNameCount[name] ?? -1) + 1;
    return LocalFunctionInfo(
      localFunction,
      name,
      localFunctionNameCount[name]!,
    );
  }

  @override
  void visitFunctionExpression(ir.FunctionExpression node) {
    assert(!localFunctions.containsKey(node));
    localFunctions[node] = generateLocalFunctionInfo(node);
    defaultExpression(node);
  }

  @override
  void visitFunctionDeclaration(ir.FunctionDeclaration node) {
    assert(!localFunctions.containsKey(node));
    localFunctions[node] = generateLocalFunctionInfo(node);
    defaultStatement(node);
  }

  @override
  void visitLocalFunctionInvocation(ir.LocalFunctionInvocation node) {
    if (localFunctions[node.localFunction] == null) {
      visitFunctionDeclaration(node.localFunction);
    }
    localFunctions[node.localFunction]!.isInvoked = true;
  }
}

// Returns a non-unique name for the given closure element.
//
// Must be kept logically identical to js_model/element_map_impl.dart.
String _computeClosureName(ir.TreeNode treeNode) {
  String reconstructConstructorName(ir.Member node) {
    String className = node.enclosingClass!.name;
    return node.name.text == '' ? className : '$className\$${node.name.text}';
  }

  var parts = <String>[];
  // First anonymous is called 'closure', outer ones called '' to give a
  // compound name where increasing nesting level corresponds to extra
  // underscores.
  var anonymous = 'closure';
  ir.TreeNode? current = treeNode;
  while (current != null) {
    var node = current;
    if (node is ir.FunctionExpression) {
      parts.add(anonymous);
      anonymous = '';
    } else if (node is ir.FunctionDeclaration) {
      final name = node.variable.name;
      if (name != null && name != "") {
        parts.add(entity_utils.operatorNameToIdentifier(name)!);
      } else {
        parts.add(anonymous);
        anonymous = '';
      }
    } else if (node is ir.Class) {
      parts.add(node.name);
      break;
    } else if (node is ir.Procedure) {
      if (node.kind == ir.ProcedureKind.Factory) {
        parts.add(reconstructConstructorName(node));
      } else {
        parts.add(entity_utils.operatorNameToIdentifier(node.name.text)!);
      }
    } else if (node is ir.Constructor) {
      parts.add(reconstructConstructorName(node));
      break;
    } else if (node is ir.Field) {
      // Add the field name for closures in field initializers.
      String name = node.name.text;
      parts.add(name);
    }
    current = current.parent;
  }
  return parts.reversed.join('_');
}

/// Filters dead code from Dart2JS [Info] trees.
class TreeShakingInfoVisitor extends InfoVisitor<void> {
  List<T> filterDeadInfo<T extends Info>(List<T> infos) {
    return infos
        .where((info) => info.treeShakenStatus == TreeShakenStatus.Live)
        .toList();
  }

  void filter(AllInfo info) {
    info.program = info.program;
    info.libraries = filterDeadInfo<LibraryInfo>(info.libraries);
    info.functions = filterDeadInfo<FunctionInfo>(info.functions);
    info.typedefs = filterDeadInfo<TypedefInfo>(info.typedefs);
    info.typedefs = filterDeadInfo<TypedefInfo>(info.typedefs);
    info.classes = filterDeadInfo<ClassInfo>(info.classes);
    info.classTypes = filterDeadInfo<ClassTypeInfo>(info.classTypes);
    info.fields = filterDeadInfo<FieldInfo>(info.fields);
    info.constants = filterDeadInfo<ConstantInfo>(info.constants);
    info.closures = filterDeadInfo<ClosureInfo>(info.closures);
    info.outputUnits = filterDeadInfo<OutputUnitInfo>(info.outputUnits);
    info.deferredFiles = info.deferredFiles;
    // TODO(markzipan): 'dependencies' is always empty. Revisit this if/when
    // this holds meaningful information.
    info.dependencies = info.dependencies;
    info.accept(this);
  }

  @override
  void visitAll(AllInfo info) {
    info.libraries = filterDeadInfo<LibraryInfo>(info.libraries);
    info.constants = filterDeadInfo<ConstantInfo>(info.constants);

    info.libraries.forEach(visitLibrary);
    info.constants.forEach(visitConstant);
  }

  @override
  void visitProgram(ProgramInfo info) {}

  @override
  void visitLibrary(LibraryInfo info) {
    info.topLevelFunctions = filterDeadInfo<FunctionInfo>(
      info.topLevelFunctions,
    );
    info.topLevelVariables = filterDeadInfo<FieldInfo>(info.topLevelVariables);
    info.classes = filterDeadInfo<ClassInfo>(info.classes);
    info.classTypes = filterDeadInfo<ClassTypeInfo>(info.classTypes);
    info.typedefs = filterDeadInfo<TypedefInfo>(info.typedefs);

    info.topLevelFunctions.forEach(visitFunction);
    info.topLevelVariables.forEach(visitField);
    info.classes.forEach(visitClass);
    info.classTypes.forEach(visitClassType);
    info.typedefs.forEach(visitTypedef);
  }

  @override
  void visitClass(ClassInfo info) {
    info.functions = filterDeadInfo<FunctionInfo>(info.functions);
    info.fields = filterDeadInfo<FieldInfo>(info.fields);
    info.supers = filterDeadInfo<ClassInfo>(info.supers);

    info.functions.forEach(visitFunction);
    info.fields.forEach(visitField);
    info.supers.forEach(visitClass);
  }

  @override
  void visitClassType(ClassTypeInfo info) {}

  @override
  void visitField(FieldInfo info) {
    info.closures = filterDeadInfo<ClosureInfo>(info.closures);

    info.closures.forEach(visitClosure);
  }

  @override
  void visitConstant(ConstantInfo info) {}

  @override
  void visitFunction(FunctionInfo info) {
    info.closures = filterDeadInfo<ClosureInfo>(info.closures);

    info.closures.forEach(visitClosure);
  }

  @override
  void visitTypedef(TypedefInfo info) {}
  @override
  void visitOutput(OutputUnitInfo info) {}
  @override
  void visitClosure(ClosureInfo info) {
    visitFunction(info.function);
  }
}

/// Returns a fully resolved name for [info] for disambiguation.
String fullyResolvedNameForInfo(Info? info) {
  if (info == null) return '';
  var name = info.name;
  var currentInfo = info;
  while (currentInfo.parent != null) {
    currentInfo = currentInfo.parent!;
    name = '${currentInfo.name}/$name';
  }
  return name;
}
