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

/// Generates the file `api.txt`, which describes a package's public API.
library;

import 'dart:collection';

import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/constant/value.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/file_system/physical_file_system.dart';
import 'package:analyzer_utilities/tools.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart';

/// Computes a list of all targets generated by this code generator for a given
/// package.
List<GeneratedContent> allTargetsForPackage(String pkgName) => [
  GeneratedFile('$pkgName/api.txt', (pkgRoot) async {
    var provider = PhysicalResourceProvider.INSTANCE;
    var collection = AnalysisContextCollection(
      includedPaths: [join(pkgRoot, pkgName)],
      resourceProvider: provider,
    );
    // Use `.single` to make sure that `collection` just contains a single
    // context. This ensures that `publicApi.build` will see all the files in
    // the package.
    var context = collection.contexts.single;
    var publicApi = ApiDescription(pkgName);
    var stringBuffer = StringBuffer();
    _printNodes(stringBuffer, await publicApi.build(context));
    return stringBuffer.toString();
  }),
];

/// Outputs the contents of [nodes] to [sink], prepending [prefix] to every
/// line.
void _printNodes<SortKey extends Comparable<SortKey>>(
  StringSink sink,
  List<(SortKey, Node)> nodes, {
  String prefix = '',
}) {
  for (var entry in nodes.sortedBy((n) => n.$1)) {
    var node = entry.$2;
    sink.writeln('$prefix${node.text.join()}');
    node.printChildren(sink, prefix: '$prefix  ');
  }
}

/// Data structure keeping track of a package's API while walking it to produce
/// `api.txt`.
class ApiDescription {
  final String _pkgName;

  /// Top level elements that have already had their child elements dumped.
  ///
  /// If an element is seen again in a different library, it will be followed
  /// with `(see above)` (rather than having its child elements dumped twice).
  final _dumpedTopLevelElements = <Element>{};

  /// Top level elements that have been referenced so far and haven't yet been
  /// processed by [build].
  ///
  /// This is used to ensure that all elements referred to by the public API
  /// (e.g., by being mentioned in the type of an API element) also show up in
  /// the output.
  final _potentiallyDanglingReferences = Queue<Element>();

  final _uniqueNamer = UniqueNamer();

  /// Cache of values returned by [_getOrComputeImmediateSubinterfaceMap], to
  /// avoid unnecessary recomputation.
  final _immediateSubinterfaceCache =
      <LibraryElement, Map<ClassElement, Set<InterfaceElement>>>{};

  ApiDescription(String pkgName) : _pkgName = pkgName;

  /// Builds a list of [Node] objects representing all the libraries that are
  /// relevant to the package's public API.
  ///
  /// This includes libraries that are in the package's public API as well as
  /// libraries that are referenced by the package's public API (either by being
  /// re-exported as part of the package's public API, or by being used as part
  /// of the type of something in the public API).
  ///
  /// Each library node is pared with a [UriSortKey] indicating the order in
  /// which the nodes should be output.
  Future<List<(UriSortKey, Node)>> build(AnalysisContext context) async {
    var nodes = <Uri, Node<MemberSortKey>>{};
    for (var file in context.contextRoot.analyzedFiles().sorted()) {
      if (!file.endsWith('.dart')) continue;
      var fileResult = context.currentSession.getFile(file) as FileResult;
      var uri = fileResult.uri;
      if (fileResult.isLibrary && uri.isInPublicLibOf(_pkgName)) {
        var resolvedLibraryResult =
            (await context.currentSession.getResolvedLibrary(file))
                as ResolvedLibraryResult;
        var node = nodes[uri] = Node<MemberSortKey>();
        _dumpLibrary(resolvedLibraryResult.element, node);
      }
    }
    // Then dump anything referenced by public libraries.
    while (_potentiallyDanglingReferences.isNotEmpty) {
      var element = _potentiallyDanglingReferences.removeFirst();
      if (!_dumpedTopLevelElements.add(element)) continue;
      var containingLibraryUri = element.library!.uri;
      var childNode = Node<MemberSortKey>()
        ..text.add(_uniqueNamer.name(element));
      _dumpElement(element, childNode);
      (nodes[containingLibraryUri] ??= Node<MemberSortKey>()
            ..text.add('$containingLibraryUri:'))
          .childNodes
          .add((MemberSortKey(element), childNode));
    }
    return [
      for (var entry in nodes.entries)
        (UriSortKey(entry.key, _pkgName), entry.value),
    ];
  }

  /// Creates a list of objects which, when their string representations are
  /// concatenated, describes [type].
  ///
  /// The reason we use this method rather than [DartType.toString] is to make
  /// sure that (a) every element mentioned by the type is added to
  /// [_potentiallyDanglingReferences], and (b) if an ambiguous name is used,
  /// the ambiguity will be taken care of by [_uniqueNamer].
  List<Object?> _describeType(DartType type) {
    var suffix = switch (type.nullabilitySuffix) {
      NullabilitySuffix.none => '',
      NullabilitySuffix.star => '*',
      NullabilitySuffix.question => '?',
    };
    switch (type) {
      case DynamicType():
        return ['dynamic'];
      case FunctionType(
        :var returnType,
        :var typeParameters,
        :var formalParameters,
      ):
        var params = <List<Object?>>[];
        var optionalParams = <List<Object?>>[];
        var namedParams = <String, List<Object?>>{};
        for (var formalParameter in formalParameters) {
          if (formalParameter.isNamed) {
            namedParams[formalParameter.name!] = [
              if (formalParameter.isDeprecated) 'deprecated ',
              if (formalParameter.isRequired) 'required ',
              ..._describeType(formalParameter.type),
            ];
          } else if (formalParameter.isOptional) {
            optionalParams.add([
              if (formalParameter.isDeprecated) 'deprecated ',
              ..._describeType(formalParameter.type),
            ]);
          } else {
            params.add([
              if (formalParameter.isDeprecated) 'deprecated ',
              ..._describeType(formalParameter.type),
            ]);
          }
        }
        if (optionalParams.isNotEmpty) {
          params.add(optionalParams.separate(prefix: '[', suffix: ']'));
        }
        if (namedParams.isNotEmpty) {
          params.add(
            namedParams.entries
                .sortedBy((e) => e.key)
                .map((e) => [...e.value, ' ${e.key}'])
                .separate(prefix: '{', suffix: '}'),
          );
        }
        return <Object?>[
          ..._describeType(returnType),
          ' Function',
          if (typeParameters.isNotEmpty)
            ...typeParameters
                .map(_describeTypeParameter)
                .separate(prefix: '<', suffix: '>'),
          '(',
          ...params.separate(),
          ')',
          suffix,
        ];
      case InterfaceType(:var element, :var typeArguments):
        _potentiallyDanglingReferences.addLast(element);
        return [
          _uniqueNamer.name(element),
          if (typeArguments.isNotEmpty)
            ...typeArguments
                .map(_describeType)
                .separate(prefix: '<', suffix: '>'),
          suffix,
        ];
      case RecordType(:var positionalFields, :var namedFields):
        if (positionalFields.length == 1 && namedFields.isEmpty) {
          return [
            '(',
            ..._describeType(positionalFields[0].type),
            ',)',
            suffix,
          ];
        }
        return [
          ...[
            for (var positionalField in positionalFields)
              _describeType(positionalField.type),
            if (namedFields.isNotEmpty)
              namedFields
                  .sortedBy((f) => f.name)
                  .map((f) => [..._describeType(f.type), ' ', f.name])
                  .separate(prefix: '{', suffix: '}'),
          ].separate(prefix: '(', suffix: ')'),
          suffix,
        ];
      case TypeParameterType(:var element):
        return [element.name!, suffix];
      case VoidType():
        return ['void'];
      case dynamic(:var runtimeType):
        throw UnimplementedError('Unexpected type: $runtimeType');
    }
  }

  /// Creates a list of objects which, when their string representations are
  /// concatenated, describes [typeParameter].
  List<Object?> _describeTypeParameter(TypeParameterElement typeParameter) {
    return [
      typeParameter.name!,
      if (typeParameter.bound case var bound?) ...[
        ' extends ',
        ..._describeType(bound),
      ],
    ];
  }

  /// Appends information to [node] describing [element].
  void _dumpElement(Element element, Node<MemberSortKey> node) {
    var enclosingElement = element.enclosingElement;
    if (enclosingElement is LibraryElement &&
        !element.isInPublicApiOf(_pkgName)) {
      if (!enclosingElement.uri.isIn(_pkgName)) {
        node.text.add(' (referenced)');
      } else {
        node.text.add(' (non-public)');
      }
      return;
    }
    var parentheticals = <List<Object?>>[];
    switch (element) {
      case TypeAliasElement(:var aliasedType, :var typeParameters):
        List<Object?> description = ['type alias'];
        if (typeParameters.isNotEmpty) {
          description.addAll(
            typeParameters
                .map(_describeTypeParameter)
                .separate(prefix: '<', suffix: '>'),
          );
        }
        description.addAll([' for ', ..._describeType(aliasedType)]);
        parentheticals.add(description);
      case InstanceElement():
        switch (element) {
          case InterfaceElement(
            :var typeParameters,
            :var supertype,
            :var interfaces,
          ):
            List<Object?> instanceDescription = [
              switch (element) {
                ClassElement() => 'class',
                EnumElement() => 'enum',
                MixinElement() => 'mixin',
                dynamic(:var runtimeType) => 'TODO: $runtimeType',
              },
            ];
            if (typeParameters.isNotEmpty) {
              instanceDescription.addAll(
                typeParameters
                    .map(_describeTypeParameter)
                    .separate(prefix: '<', suffix: '>'),
              );
            }
            if (element is! EnumElement && supertype != null) {
              instanceDescription.addAll([
                ' extends ',
                ..._describeType(supertype),
              ]);
            }
            if (element is MixinElement &&
                element.superclassConstraints.isNotEmpty) {
              instanceDescription.addAll(
                element.superclassConstraints
                    .map(_describeType)
                    .separate(prefix: ' on '),
              );
            }
            if (interfaces.isNotEmpty) {
              instanceDescription.addAll(
                interfaces.map(_describeType).separate(prefix: ' implements '),
              );
            }
            parentheticals.add(instanceDescription);
            if (element is ClassElement && element.isSealed) {
              var parenthetical = <Object>['sealed'];
              parentheticals.add(parenthetical);
              if (_getOrComputeImmediateSubinterfaceMap(
                    element.library,
                  )[element]
                  case var subinterfaces?) {
                parenthetical.add(' (immediate subtypes: ');
                // Note: it's tempting to just do
                // `subinterfaces.map(_uniqueNamer.name).join(', ')`, but that
                // won't work, because the names returned by
                // `UniqueName.toString()` aren't finalized until we've visited
                // the entire API and seen if there are class names that need to
                // be disambiguated. So we accumulate the `UniqueName` objects
                // into the `parenthetical` list and rely on `printNodes`
                // converting everything to a string when the final API
                // description is being output.
                var commaNeeded = false;
                for (var subinterface in subinterfaces) {
                  if (commaNeeded) {
                    parenthetical.add(', ');
                  } else {
                    commaNeeded = true;
                  }
                  parenthetical.add(_uniqueNamer.name(subinterface));
                }
                parenthetical.add(')');
              }
            }
          case ExtensionElement(:var extendedType):
            parentheticals.add([
              'extension on ',
              ..._describeType(extendedType),
            ]);
          case dynamic(:var runtimeType):
            throw UnimplementedError('Unexpected element: $runtimeType');
        }
        for (var member in element.children.sortedBy((m) => m.name ?? '')) {
          if (member.name case var name? when name.startsWith('_')) {
            // Ignore private members
            continue;
          }
          if (member is FieldElement) {
            // Ignore fields; we care about the getters and setters they induce.
            continue;
          }
          if (member is ConstructorElement &&
              element is ClassElement &&
              element.isAbstract &&
              (element.isFinal || element.isInterface || element.isSealed)) {
            // The class can't be constructed from outside of the library that
            // declares it, so its constructors aren't part of the public API.
            continue;
          }
          if (member is ConstructorElement && element is EnumElement) {
            // Enum constructors can't be called from outside the enum itself,
            // so they aren't part of the public API.
            continue;
          }
          var childNode = Node<MemberSortKey>();
          childNode.text.add(member.apiName);
          _dumpElement(member, childNode);
          node.childNodes.add((MemberSortKey(member), childNode));
        }
      case TopLevelFunctionElement(:var type):
        parentheticals.add(['function: ', ..._describeType(type)]);
      case ExecutableElement(:var isStatic):
        String maybeStatic = isStatic ? 'static ' : '';
        switch (element) {
          case GetterElement(:var type):
            parentheticals.add([
              '${maybeStatic}getter: ',
              ..._describeType(type.returnType),
            ]);
          case SetterElement(:var type):
            parentheticals.add([
              '${maybeStatic}setter: ',
              ..._describeType(type.formalParameters.single.type),
            ]);
          case MethodElement(:var type):
            parentheticals.add([
              '${maybeStatic}method: ',
              ..._describeType(type),
            ]);
          case ConstructorElement(:var type):
            parentheticals.add(['constructor: ', ..._describeType(type)]);
          case dynamic(:var runtimeType):
            throw UnimplementedError('Unexpected element: $runtimeType');
        }
      case dynamic(:var runtimeType):
        throw UnimplementedError('Unexpected element: $runtimeType');
    }

    // For synthetic elements such as getters/setters induced by top level
    // variables and fields, annotations can be found on the corresponding
    // non-synthetic element.
    var nonSyntheticElement = element.nonSynthetic;
    if (nonSyntheticElement.metadata.hasDeprecated) {
      parentheticals.add(['deprecated']);
    }
    if (nonSyntheticElement.metadata.hasExperimental) {
      parentheticals.add(['experimental']);
    }

    if (parentheticals.isNotEmpty) {
      node.text.addAll(parentheticals.separate(prefix: ' (', suffix: ')'));
    }
    if (node.childNodes.isNotEmpty) {
      node.text.add(':');
    }
  }

  /// Appends information to [node] describing [element].
  void _dumpLibrary(LibraryElement library, Node<MemberSortKey> node) {
    var uri = library.uri;
    node.text.addAll([uri, ':']);
    var definedNames = library.exportNamespace.definedNames2;
    for (var key in definedNames.keys.sorted()) {
      var element = definedNames[key]!;
      var childNode = Node<MemberSortKey>()
        ..text.add(_uniqueNamer.name(element));
      if (!_dumpedTopLevelElements.add(element)) {
        childNode.text.add(' (see above)');
      } else {
        _dumpElement(element, childNode);
      }
      node.childNodes.add((MemberSortKey(element), childNode));
    }
  }

  /// Returns a map from each sealed class in [library] to the set of its
  /// immediate sub-interfaces.
  ///
  /// If this method has been called before with the same [library], a cached
  /// map is returned from [_immediateSubinterfaceCache]. Otherwise a fresh map
  /// is computed.
  Map<ClassElement, Set<InterfaceElement>>
  _getOrComputeImmediateSubinterfaceMap(LibraryElement library) {
    if (_immediateSubinterfaceCache[library] case var m?) return m;
    var result = <ClassElement, Set<InterfaceElement>>{};
    for (var interface in [
      ...library.classes,
      ...library.mixins,
      ...library.enums,
      ...library.extensionTypes,
    ]..sortBy((e) => e.name!)) {
      for (var superinterface in [
        interface.supertype,
        ...interface.interfaces,
        ...interface.mixins,
        if (interface is MixinElement) ...interface.superclassConstraints,
      ]) {
        if (superinterface == null) continue;
        var superinterfaceElement = superinterface.element;
        if (superinterfaceElement is ClassElement &&
            superinterfaceElement.isSealed) {
          (result[superinterfaceElement] ??= {}).add(interface);
        }
      }
    }
    _immediateSubinterfaceCache[library] = result;
    return result;
  }
}

/// Element categorization used by [MemberSortKey].
enum MemberCategory {
  constructor,
  propertyAccessor,
  topLevelFunctionOrMethod,
  interface,
  extension,
  typeAlias,
}

/// Sort key used to sort elements in the output.
class MemberSortKey implements Comparable<MemberSortKey> {
  final bool _isInstanceMember;
  final MemberCategory _category;
  final String _name;

  MemberSortKey(Element element)
    : _isInstanceMember = _computeIsInstanceMember(element),
      _category = _computeCategory(element),
      _name = element.name!;

  @override
  int compareTo(MemberSortKey other) {
    if ((_isInstanceMember ? 1 : 0).compareTo(other._isInstanceMember ? 1 : 0)
        case var value when value != 0) {
      return value;
    }
    if (_category.index.compareTo(other._category.index) case var value
        when value != 0) {
      return value;
    }
    return _name.compareTo(other._name);
  }

  static MemberCategory _computeCategory(Element element) => switch (element) {
    ConstructorElement() => MemberCategory.constructor,
    PropertyAccessorElement() => MemberCategory.propertyAccessor,
    TopLevelFunctionElement() => MemberCategory.topLevelFunctionOrMethod,
    MethodElement() => MemberCategory.topLevelFunctionOrMethod,
    InterfaceElement() => MemberCategory.interface,
    ExtensionElement() => MemberCategory.extension,
    TypeAliasElement() => MemberCategory.typeAlias,
    dynamic(:var runtimeType) => throw UnimplementedError(
      'Unexpected element: $runtimeType',
    ),
  };

  static bool _computeIsInstanceMember(Element element) =>
      element.enclosingElement is InstanceElement &&
      switch (element) {
        ExecutableElement(:var isStatic) => !isStatic,
        dynamic(:var runtimeType) => throw UnimplementedError(
          'Unexpected element: $runtimeType',
        ),
      };
}

/// A node to be printed to the output.
class Node<ChildSortKey extends Comparable<ChildSortKey>> {
  /// A list of objects which, when their string representations are
  /// concatenated, is the text that should be displayed on the first line of
  /// the node.
  ///
  /// The reason this is a list rather than a single string is to allow elements
  /// of the list to be [UniqueName] objects, which may acquire a disambiguation
  /// suffix at a later time.
  final text = <Object?>[];

  /// A list of child nodes, paired with a sort key indicating the order in
  /// which they should be output.
  final childNodes = <(ChildSortKey, Node)>[];

  /// Outputs [childNodes], prepending [prefix] to every line.
  void printChildren(StringSink sink, {required String prefix}) {
    _printNodes(sink, childNodes, prefix: prefix);
  }
}

/// Object that will have a unique string representation within the context of a
/// given [UniqueNamer] instance.
///
/// If two or more [UniqueName] objects are constructed with reference to the
/// same [UniqueNamer], and they have the same [_nameHint], then all such
/// objects' [toString] methods will append a unique suffix of the form
/// `@INTEGER`, so that the resulting strings are unique.
class UniqueName {
  /// The name that will be returned by [toString] if no disambiguation is
  /// needed.
  final String _nameHint;

  /// If not `Null`, the integer that [toString] will use to disambiguate this
  /// [UniqueName] from other ones with the same [_nameHint].
  int? _disambiguator;

  UniqueName(UniqueNamer uniqueNamer, this._nameHint) {
    // The uniqueness guarantee depends on `_nameHint` not containing an `@`.
    assert(!_nameHint.contains('@'));
    var conflicts = uniqueNamer._conflicts[_nameHint] ??= [];
    if (conflicts.length == 1) {
      conflicts[0]._disambiguator = 1;
    }
    conflicts.add(this);
    if (conflicts.length > 1) {
      _disambiguator = conflicts.length;
    }
  }

  @override
  String toString() => [
    _nameHint,
    if (_disambiguator case var disambiguator?) '@$disambiguator',
  ].join();
}

/// Manager of unique names for elements.
class UniqueNamer {
  final _names = <Element, UniqueName>{};
  final _conflicts = <String, List<UniqueName>>{};

  /// Returns a [UniqueName] object whose [toString] method will produce a
  /// unique name for [element].
  UniqueName name(Element element) =>
      _names[element] ??= UniqueName(this, element.apiName);
}

/// URI categorization used by [UriSortKey].
enum UriCategory { inPackage, notInPackage }

/// Sort key used to sort libraries in the output.
///
/// Libraries in the specified package will be output first (sorted by URI),
/// followed by libraries not in the package.
class UriSortKey implements Comparable<UriSortKey> {
  final UriCategory _category;
  final String _uriString;

  UriSortKey(Uri uri, String pkgName)
    : _category = uri.isIn(pkgName)
          ? UriCategory.inPackage
          : UriCategory.notInPackage,
      _uriString = uri.toString();

  @override
  int compareTo(UriSortKey other) {
    if (_category.index.compareTo(other._category.index) case var value
        when value != 0) {
      return value;
    }
    return _uriString.compareTo(other._uriString);
  }
}

extension on Iterable<Iterable<Object?>> {
  /// Forms a list containing [prefix], followed by the elements of `this`
  /// (separated by [separator]), followed by [suffix].
  List<Object?> separate({
    String separator = ', ',
    String prefix = '',
    String suffix = '',
  }) {
    var result = <Object?>[prefix];
    var first = true;
    for (var item in this) {
      if (first) {
        first = false;
      } else {
        result.add(separator);
      }
      result.addAll(item);
    }
    result.add(suffix);
    return result;
  }
}

extension on Element {
  /// Returns the appropriate name for describing the element in `api.txt`.
  ///
  /// The name is the same as [name], but with `=` appended for setters.
  String get apiName {
    var apiName = name!;
    if (this is SetterElement) {
      apiName += '=';
    }
    return apiName;
  }

  bool isInPublicApiOf(String packageName) {
    if (this case PropertyAccessorElement(
      isSynthetic: true,
      :var variable,
    ) when variable.isInPublicApiOf(packageName)) {
      return true;
    }
    if (packageName == 'analyzer') {
      // Any element annotated with `@analyzerPublicApi` is considered to be
      // part of the public API of the analyzer package.
      if (metadata.annotations.any(_isPublicApiAnnotation)) {
        return true;
      }
    }
    if (name case var name? when !name.isPublic) return false;
    if (library!.uri.isInPublicLibOf(packageName)) return true;
    return false;
  }

  bool _isPublicApiAnnotation(ElementAnnotation annotation) {
    if (annotation.computeConstantValue() case DartObject(
      type: InterfaceType(element: InterfaceElement(name: 'AnalyzerPublicApi')),
    )) {
      return true;
    } else {
      return false;
    }
  }
}

extension on FormalParameterElement {
  bool get isDeprecated {
    // TODO(paulberry): add this to the analyzer public API
    return metadata.hasDeprecated;
  }
}

extension on String {
  bool get isPublic => !startsWith('_');
}

extension on Uri {
  bool isIn(String packageName) =>
      scheme == 'package' &&
      pathSegments.isNotEmpty &&
      pathSegments[0] == packageName;

  bool isInPublicLibOf(String packageName) =>
      scheme == 'package' &&
      pathSegments.length > 1 &&
      pathSegments[0] == packageName &&
      pathSegments[1] != 'src';
}
