// Copyright (c) 2015, 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:collection' show IterableBase, MapBase;

import '../elements/entities.dart' show ClassEntity;
import '../serialization/serialization.dart';
import '../util/enumset.dart' show EnumSet;

/// Enum for the different kinds of instantiation of a class.
enum Instantiation {
  uninstantiated,
  directlyInstantiated,
  indirectlyInstantiated,
  abstractlyInstantiated,
}

/// Node for [cls] in a tree forming the subclass relation of [ClassEntity]s.
///
/// This is used by the [ClosedWorld] to perform queries on subclass and subtype
/// relations.
///
/// For this class hierarchy:
///
///     class A {}
///     class B extends A {}
///     class C extends A {}
///     class D extends B {}
///     class E extends D {}
///
/// the [ClassHierarchyNode]s form this subclass tree:
///
///       Object
///         |
///         A
///        / \
///       B   C
///       |
///       D
///       |
///       E
///
class ClassHierarchyNode {
  /// Tag used for identifying serialized [ClassHierarchyNode] objects in a
  /// debugging data stream.
  static const String tag = 'class-hierarchy-node';

  /// Enum set for selecting instantiated classes in
  /// [ClassHierarchyNode.subclassesByMask],
  /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
  static final EnumSet<Instantiation> instantiated = EnumSet.fromValues(const [
    Instantiation.directlyInstantiated,
    Instantiation.indirectlyInstantiated,
    Instantiation.abstractlyInstantiated,
  ]);

  /// Enum set for selecting directly and abstractly instantiated classes in
  /// [ClassHierarchyNode.subclassesByMask],
  /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
  static final EnumSet<Instantiation> explicitlyInstantiated =
      EnumSet.fromValues(const [
        Instantiation.directlyInstantiated,
        Instantiation.abstractlyInstantiated,
      ]);

  /// Enum set for selecting all classes in
  /// [ClassHierarchyNode.subclassesByMask],
  /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
  static final EnumSet<Instantiation> all = EnumSet.allValues(
    Instantiation.values,
  );

  /// Creates an enum set for selecting the returned classes in
  /// [ClassHierarchyNode.subclassesByMask],
  /// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
  static EnumSet<Instantiation> createMask({
    bool includeDirectlyInstantiated = true,
    bool includeIndirectlyInstantiated = true,
    bool includeUninstantiated = true,
    bool includeAbstractlyInstantiated = true,
  }) => EnumSet.fromValues([
    if (includeDirectlyInstantiated) Instantiation.directlyInstantiated,
    if (includeIndirectlyInstantiated) Instantiation.indirectlyInstantiated,
    if (includeUninstantiated) Instantiation.uninstantiated,
    if (includeAbstractlyInstantiated) Instantiation.abstractlyInstantiated,
  ]);

  final ClassHierarchyNode? parentNode;
  EnumSet<Instantiation> _mask = EnumSet.fromValues(const [
    Instantiation.uninstantiated,
  ]);
  final ClassEntity cls;

  final int hierarchyDepth;

  ClassEntity? _leastUpperInstantiatedSubclass;
  int _instantiatedSubclassCount = 0;

  /// `true` if [cls] has been directly instantiated.
  ///
  /// For instance `C` but _not_ `B` in:
  ///   class B {}
  ///   class C extends B {}
  ///   main() => C();
  ///
  bool get isDirectlyInstantiated =>
      _mask.contains(Instantiation.directlyInstantiated);

  set isDirectlyInstantiated(bool value) {
    if (value != isDirectlyInstantiated) {
      _updateParentInstantiatedSubclassCount(
        Instantiation.directlyInstantiated,
        add: value,
      );
    }
  }

  /// `true` if [cls] has been abstractly instantiated. This means that at
  /// runtime instances of [cls] or unknown subclasses of [cls] are assumed to
  /// exist.
  ///
  /// This is used to mark native and/or reflectable classes as instantiated.
  /// For native classes we do not know the exact class that instantiates [cls]
  /// so [cls] here represents the root of the subclasses. For reflectable
  /// classes we need event abstract classes to be 'live' even though they
  /// cannot themselves be instantiated.
  bool get isAbstractlyInstantiated =>
      _mask.contains(Instantiation.abstractlyInstantiated);

  set isAbstractlyInstantiated(bool value) {
    if (value != isAbstractlyInstantiated) {
      _updateParentInstantiatedSubclassCount(
        Instantiation.abstractlyInstantiated,
        add: value,
      );
    }
  }

  /// `true` if [cls] is either directly or abstractly instantiated.
  bool get isExplicitlyInstantiated =>
      isDirectlyInstantiated || isAbstractlyInstantiated;

  void _updateParentInstantiatedSubclassCount(
    Instantiation instantiation, {
    required bool add,
  }) {
    ClassHierarchyNode? parent = parentNode;
    if (add) {
      _mask = _mask.remove(Instantiation.uninstantiated);
      _mask = _mask.add(instantiation);
      while (parent != null) {
        parent._updateInstantiatedSubclassCount(1);
        parent = parent.parentNode;
      }
    } else {
      _mask = _mask.remove(instantiation);
      if (_mask.isEmpty) {
        _mask = _mask.add(Instantiation.uninstantiated);
      }
      while (parent != null) {
        parent._updateInstantiatedSubclassCount(-1);
        parent = parent.parentNode;
      }
    }
  }

  /// `true` if [cls] has been instantiated through subclasses.
  ///
  /// For instance `A` and `B` but _not_ `C` in:
  ///   class A {}
  ///   class B extends A {}
  ///   class C extends B {}
  ///   main() => [B(), C()];
  ///
  bool get isIndirectlyInstantiated => _instantiatedSubclassCount > 0;

  /// The number of strict subclasses that are directly or indirectly
  /// instantiated.
  int get instantiatedSubclassCount => _instantiatedSubclassCount;

  void _updateInstantiatedSubclassCount(int change) {
    bool before = isIndirectlyInstantiated;
    _instantiatedSubclassCount += change;
    bool after = isIndirectlyInstantiated;
    if (before != after) {
      if (after) {
        _mask = _mask.remove(Instantiation.uninstantiated);
        _mask = _mask.add(Instantiation.indirectlyInstantiated);
      } else {
        _mask = _mask.remove(Instantiation.indirectlyInstantiated);
        if (_mask.isEmpty) {
          _mask = _mask.add(Instantiation.uninstantiated);
        }
      }
    }
  }

  /// The nodes for the direct subclasses of [cls].
  final List<ClassHierarchyNode> _directSubclasses = [];

  ClassHierarchyNode(this.parentNode, this.cls, this.hierarchyDepth) {
    if (parentNode != null) {
      parentNode!.addDirectSubclass(this);
    }
  }

  /// Deserializes a [ClassHierarchyNode] object from [source].
  factory ClassHierarchyNode.readFromDataSource(
    DataSourceReader source,
    Map<ClassEntity, ClassHierarchyNode> nodeMap,
  ) {
    source.begin(tag);
    final cls = source.readClass();
    ClassHierarchyNode? parentNode;
    final superclass = source.readClassOrNull();
    if (superclass != null) {
      parentNode = nodeMap[superclass]!;
    }
    int maskValue = source.readInt();
    int hierarchyDepth = source.readInt();
    int instantiatedSubclassCount = source.readInt();
    source.end(tag);
    return ClassHierarchyNode(parentNode, cls, hierarchyDepth)
      .._instantiatedSubclassCount = instantiatedSubclassCount
      .._mask = EnumSet.fromRawBits(maskValue);
  }

  /// Serializes this [ClassHierarchyNode] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeClass(cls);
    sink.writeClassOrNull(parentNode?.cls);
    sink.writeInt(_mask.mask.bits);
    sink.writeInt(hierarchyDepth);
    sink.writeInt(_instantiatedSubclassCount);
    sink.end(tag);
  }

  /// Adds [subclass] as a direct subclass of [cls].
  void addDirectSubclass(ClassHierarchyNode subclass) {
    assert(!_directSubclasses.contains(subclass));
    _directSubclasses.add(subclass);
  }

  Iterable<ClassHierarchyNode> get directSubclasses => _directSubclasses;

  /// Returns `true` if [other] is contained in the subtree of this node.
  ///
  /// This means that [other] is a subclass of [cls].
  bool contains(ClassHierarchyNode? other) {
    while (other != null) {
      if (cls == other.cls) return true;
      if (hierarchyDepth >= other.hierarchyDepth) return false;
      other = other.parentNode;
    }
    return false;
  }

  /// Returns `true` if `other.cls` is a subclass of [cls].
  bool hasSubclass(ClassHierarchyNode other) {
    return contains(other);
  }

  /// `true` if [cls] has been directly, indirectly, or abstractly instantiated.
  bool get isInstantiated =>
      isExplicitlyInstantiated || isIndirectlyInstantiated;

  /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
  ///
  /// Subclasses are included if their instantiation properties intersect with
  /// their corresponding [Instantiation] values in [mask]. If [strict] is
  /// `true`, [cls] itself is _not_ returned.
  Iterable<ClassEntity> subclassesByMask(
    EnumSet<Instantiation> mask, {
    bool strict = false,
  }) {
    return ClassHierarchyNodeIterable(this, mask, includeRoot: !strict);
  }

  /// Applies [predicate] to each subclass of [cls] matching the criteria
  /// specified by [mask] and [strict]. If [predicate] returns `true` on a
  /// class, visitation is stopped immediately and the function returns `true`.
  ///
  /// [predicate] is applied to subclasses if their instantiation properties
  /// intersect with their corresponding [Instantiation] values in [mask]. If
  /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
  bool anySubclass(
    bool Function(ClassEntity cls) predicate,
    EnumSet<Instantiation> mask, {
    bool strict = false,
  }) {
    IterationStep wrapper(ClassEntity cls) {
      return predicate(cls) ? IterationStep.stop : IterationStep.continue_;
    }

    return forEachSubclass(wrapper, mask, strict: strict) == IterationStep.stop;
  }

  /// Applies [f] to each subclass of [cls] matching the criteria specified by
  /// [mask] and [strict].
  ///
  /// [f] is a applied to subclasses if their instantiation properties intersect
  /// with their corresponding [Instantiation] values in [mask]. If [strict] is
  /// `true`, [f] is _not_ called on [cls] itself.
  ///
  /// The visitation of subclasses can be cut short by the return value of [f].
  /// If [ForEach.STOP] is returned, no further classes are visited and the
  /// function stops immediately. If [ForEach.SKIP_SUBCLASSES] is returned, the
  /// subclasses of the last visited class are skipped, but visitation
  /// continues. The return value of the function is either [ForEach.STOP], if
  /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
  /// the end.
  IterationStep forEachSubclass(
    ForEachFunction f,
    EnumSet<Instantiation> mask, {
    bool strict = false,
  }) {
    IterationStep? nextStep;
    if (!strict && mask.intersects(_mask)) {
      nextStep = f(cls);
    }
    // Interpret `forEach == null` as `forEach == ForEach.CONTINUE`.
    nextStep ??= IterationStep.continue_;

    if (nextStep == IterationStep.continue_) {
      if (mask.contains(Instantiation.uninstantiated) || isInstantiated) {
        for (ClassHierarchyNode subclass in _directSubclasses) {
          IterationStep subForEach = subclass.forEachSubclass(f, mask);
          if (subForEach == IterationStep.stop) {
            return subForEach;
          }
        }
      }
    }
    if (nextStep == IterationStep.stop) {
      return nextStep;
    }
    return IterationStep.continue_;
  }

  /// Returns the most specific subclass of [cls] (including [cls]) that is
  /// directly instantiated or a superclass of all directly instantiated
  /// subclasses. If [cls] is not instantiated, `null` is returned.
  ClassEntity? getLubOfInstantiatedSubclasses() {
    if (!isInstantiated) return null;
    _leastUpperInstantiatedSubclass ??=
        _computeLeastUpperInstantiatedSubclass();
    return _leastUpperInstantiatedSubclass;
  }

  ClassEntity? _computeLeastUpperInstantiatedSubclass() {
    if (isExplicitlyInstantiated) {
      return cls;
    }
    if (!isInstantiated) {
      return null;
    }
    ClassHierarchyNode? subclass;
    for (ClassHierarchyNode node in _directSubclasses) {
      if (node.isInstantiated) {
        if (subclass == null) {
          subclass = node;
        } else {
          return cls;
        }
      }
    }
    if (subclass != null) {
      return subclass.getLubOfInstantiatedSubclasses();
    }
    return cls;
  }

  void printOn(
    StringBuffer sb,
    String indentation, {
    bool instantiatedOnly = false,
    bool sorted = true,
    ClassEntity? withRespectTo,
  }) {
    bool isRelatedTo(ClassEntity subclass) {
      return true;
      // TODO(johnniwinther): Support this for kernel based elements:
      // return subclass == withRespectTo ||
      //    subclass.implementsInterface(withRespectTo);
    }

    sb.write(indentation);
    if (cls.isAbstract) {
      sb.write('abstract ');
    }
    sb.write('class ${cls.name}:');
    if (isDirectlyInstantiated) {
      sb.write(' directly');
    }
    if (isIndirectlyInstantiated) {
      sb.write(' indirectly');
    }
    if (isAbstractlyInstantiated) {
      sb.write(' abstractly');
    }
    sb.write(' [');
    if (_directSubclasses.isEmpty) {
      sb.write(']');
    } else {
      dynamic subclasses = _directSubclasses;
      if (sorted) {
        subclasses =
            _directSubclasses.toList()..sort((a, b) {
              return a.cls.name.compareTo(b.cls.name);
            });
      }
      bool needsComma = false;
      for (ClassHierarchyNode child in subclasses) {
        if (instantiatedOnly && !child.isInstantiated) {
          continue;
        }
        if (withRespectTo != null &&
            !child.anySubclass(isRelatedTo, ClassHierarchyNode.all)) {
          continue;
        }
        if (needsComma) {
          sb.write(',\n');
        } else {
          sb.write('\n');
        }
        child.printOn(
          sb,
          '$indentation  ',
          instantiatedOnly: instantiatedOnly,
          sorted: sorted,
          withRespectTo: withRespectTo,
        );
        needsComma = true;
      }
      if (needsComma) {
        sb.write('\n');
        sb.write('$indentation]');
      } else {
        sb.write(']');
      }
    }
  }

  String dump({
    String indentation = '',
    bool instantiatedOnly = false,
    ClassEntity? withRespectTo,
  }) {
    StringBuffer sb = StringBuffer();
    printOn(
      sb,
      indentation,
      instantiatedOnly: instantiatedOnly,
      withRespectTo: withRespectTo,
    );
    return sb.toString();
  }

  @override
  String toString() => cls.toString();
}

/// Object holding the subclass and subtype relation for a single
/// [ClassEntity].
///
/// The subclass relation for a class `C` is modelled through a reference to
/// the [ClassHierarchyNode] for `C` in the global [ClassHierarchyNode] tree
/// computed in [World].
///
/// The subtype relation for a class `C` is modelled through a collection of
/// disjoint [ClassHierarchyNode] subtrees. The subclasses of `C`, modelled
/// through the aforementioned [ClassHierarchyNode] pointer, are extended with
/// the subtypes that do not extend `C` through a list of additional
/// [ClassHierarchyNode] nodes. This list is normalized to contain only the
/// nodes for the topmost subtypes and is furthermore ordered in increasing
/// hierarchy depth order.
///
/// For this class hierarchy:
///
///     class A {}
///     class B extends A {}
///     class C implements B {}
///     class D implements A {}
///     class E extends D {}
///     class F implements D {}
///
/// the [ClassHierarchyNode] tree is
///
///       Object
///      / |  | \
///     A  C  D  F
///     |     |
///     B     E
///
/// and the [ClassSet] for `A` holds these [ClassHierarchyNode] nodes:
///
///      A  ->  [C, D, F]
///
/// The subtypes `B` and `E` are not directly modeled because they are implied
/// by their subclass relation to `A` and `D`, respectively. This can be seen
/// if we expand the subclass subtrees:
///
///      A  ->  [C, D, F]
///      |          |
///      B          E
///
class ClassSet {
  /// Tag used for identifying serialized [ClassSet] objects in a debugging
  /// data stream.
  static const String tag = 'class-set';

  final ClassHierarchyNode node;
  ClassEntity? _leastUpperInstantiatedSubtype;

  /// A list of the class hierarchy nodes for the subtypes that declare a
  /// subtype relationship to [cls] either directly or indirectly.
  ///
  /// For instance
  ///
  ///     class A {}
  ///     class B extends A {}
  ///     class C implements B {}
  ///     class D implements A {}
  ///     class E extends D {}
  ///
  /// The class hierarchy nodes for classes `C` and `D` are in [_subtypes]. `C`
  /// because it implements `A` through `B` and `D` because it implements `A`
  /// directly. `E` also implements `A` through its extension of `D` and it is
  /// therefore included through the class hierarchy node for `D`.
  ///
  List<ClassHierarchyNode>? _subtypes;

  /// A list of the class hierarchy nodes for the class that directly mix in
  /// [cls].
  ///
  /// For instance
  ///
  ///     class A {}
  ///     class B extends Object with A {}
  ///     class C = Object with A;
  ///     class D extends B {}
  ///     class E extends C {}
  ///
  /// The class hierarchy nodes for the unnamed mixin application `Object+A` and
  /// the named mixin application `C` are in [_mixinApplications].
  ///
  List<ClassHierarchyNode>? _mixinApplications;

  ClassSet(this.node);

  /// Deserializes a [ClassSet] object from [source].
  factory ClassSet.readFromDataSource(
    DataSourceReader source,
    Map<ClassEntity, ClassHierarchyNode> nodeMap,
  ) {
    source.begin(tag);
    ClassHierarchyNode node = nodeMap[source.readClass()]!;
    List<ClassHierarchyNode>? subtypes = source.readListOrNull(() {
      return nodeMap[source.readClass()]!;
    });
    List<ClassHierarchyNode>? mixinApplications = source.readListOrNull(() {
      return nodeMap[source.readClass()]!;
    });
    source.end(tag);
    return ClassSet(node)
      .._subtypes = subtypes
      .._mixinApplications = mixinApplications;
  }

  /// Serializes this [ClassSet] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeClass(node.cls);
    sink.writeListOrNull(_subtypes, (ClassHierarchyNode node) {
      sink.writeClass(node.cls);
    });
    sink.writeListOrNull(_mixinApplications, (ClassHierarchyNode node) {
      sink.writeClass(node.cls);
    });
    sink.end(tag);
  }

  ClassEntity get cls => node.cls;

  /// Returns `true` if `other.cls` is a subclass of [cls].
  bool hasSubclass(ClassHierarchyNode other) => node.hasSubclass(other);

  /// Returns `true` if `other.cls` is a subtype of [cls].
  bool hasSubtype(ClassHierarchyNode other) {
    if (hasSubclass(other)) return true;
    if (_subtypes != null) {
      for (ClassHierarchyNode subtypeNode in _subtypes!) {
        if (subtypeNode.hasSubclass(other)) return true;
      }
    }
    return false;
  }

  /// Returns the number of directly instantiated subtypes of [cls].
  int get instantiatedSubtypeCount {
    int count = node.instantiatedSubclassCount;
    if (_subtypes != null) {
      for (ClassHierarchyNode subtypeNode in _subtypes!) {
        if (subtypeNode.isExplicitlyInstantiated) {
          count++;
        }
        count += subtypeNode.instantiatedSubclassCount;
      }
    }
    return count;
  }

  /// Returns `true` if all instantiated subtypes of [cls] are subclasses of
  /// [cls].
  bool get hasOnlyInstantiatedSubclasses {
    if (_subtypes != null) {
      for (ClassHierarchyNode subtypeNode in _subtypes!) {
        if (subtypeNode.isInstantiated) {
          return false;
        }
      }
    }
    return true;
  }

  /// Returns an [Iterable] of the classes that implement [cls] directly or
  /// through supertypes.
  ///
  /// A class that implements [cls] through its superclasses is not included in
  /// the iterable.
  Iterable<ClassHierarchyNode> get subtypeNodes {
    return _subtypes ?? const [];
  }

  /// Returns an [Iterable] of the classes that mix in [cls] directly.
  Iterable<ClassHierarchyNode> get mixinApplicationNodes {
    return _mixinApplications ?? const [];
  }

  /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
  ///
  /// Subclasses are included if their instantiation properties intersect with
  /// their corresponding [Instantiation] values in [mask]. If [strict] is
  /// `true`, [cls] itself is _not_ returned.
  Iterable<ClassEntity> subclassesByMask(
    EnumSet<Instantiation> mask, {
    bool strict = false,
  }) {
    return node.subclassesByMask(mask, strict: strict);
  }

  /// Returns an [Iterable] of the subtypes of [cls] possibly including [cls].
  ///
  /// The directly instantiated, indirectly instantiated and uninstantiated
  /// subtypes of [cls] are returned if [includeDirectlyInstantiated],
  /// [includeIndirectlyInstantiated], and [includeUninstantiated] are `true`,
  /// respectively. If [strict] is `true`, [cls] itself is _not_ returned.
  Iterable<ClassEntity> subtypes({
    bool includeDirectlyInstantiated = true,
    bool includeIndirectlyInstantiated = true,
    bool includeUninstantiated = true,
    bool strict = false,
  }) {
    EnumSet<Instantiation> mask = ClassHierarchyNode.createMask(
      includeDirectlyInstantiated: includeDirectlyInstantiated,
      includeIndirectlyInstantiated: includeIndirectlyInstantiated,
      includeUninstantiated: includeUninstantiated,
    );
    return subtypesByMask(mask, strict: strict);
  }

  /// Returns an [Iterable] of the subtypes of [cls] possibly including [cls].
  ///
  /// Subtypes are included if their instantiation properties intersect with
  /// their corresponding [Instantiation] values in [mask]. If [strict] is
  /// `true`, [cls] itself is _not_ returned.
  Iterable<ClassEntity> subtypesByMask(
    EnumSet<Instantiation> mask, {
    bool strict = false,
  }) {
    if (_subtypes == null) {
      return node.subclassesByMask(mask, strict: strict);
    }

    return SubtypesIterable.subtypesIterator(this, mask, includeRoot: !strict);
  }

  /// Applies [predicate] to each subclass of [cls] matching the criteria
  /// specified by [mask] and [strict]. If [predicate] returns `true` on a
  /// class, visitation is stopped immediately and the function returns `true`.
  ///
  /// [predicate] is applied to subclasses if their instantiation properties
  /// intersect with their corresponding [Instantiation] values in [mask]. If
  /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
  bool anySubclass(
    bool Function(ClassEntity cls) predicate,
    EnumSet<Instantiation> mask, {
    bool strict = false,
  }) {
    return node.anySubclass(predicate, mask, strict: strict);
  }

  /// Applies [f] to each subclass of [cls] matching the criteria specified by
  /// [mask] and [strict].
  ///
  /// [f] is a applied to subclasses if their instantiation properties intersect
  /// with their corresponding [Instantiation] values in [mask]. If [strict] is
  /// `true`, [f] is _not_ called on [cls] itself.
  ///
  /// The visitation of subclasses can be cut short by the return value of [f].
  /// If [ForEach.STOP] is returned, no further classes are visited and the
  /// function stops immediately. If [ForEach.SKIP_SUBCLASSES] is returned, the
  /// subclasses of the last visited class are skipped, but visitation
  /// continues. The return value of the function is either [ForEach.STOP], if
  /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
  /// the end.
  IterationStep forEachSubclass(
    ForEachFunction f,
    EnumSet<Instantiation> mask, {
    bool strict = false,
  }) {
    return node.forEachSubclass(f, mask, strict: strict);
  }

  /// Applies [predicate] to each subtype of [cls] matching the criteria
  /// specified by [mask] and [strict]. If [predicate] returns `true` on a
  /// class, visitation is stopped immediately and the function returns `true`.
  ///
  /// [predicate] is applied to subtypes if their instantiation properties
  /// intersect with their corresponding [Instantiation] values in [mask]. If
  /// [strict] is `true`, [predicate] is _not_ called on [cls] itself.
  bool anySubtype(
    bool Function(ClassEntity cls) predicate,
    EnumSet<Instantiation> mask, {
    bool strict = false,
  }) {
    IterationStep wrapper(ClassEntity cls) {
      return predicate(cls) ? IterationStep.stop : IterationStep.continue_;
    }

    return forEachSubtype(wrapper, mask, strict: strict) == IterationStep.stop;
  }

  /// Applies [f] to each subtype of [cls] matching the criteria specified by
  /// [mask] and [strict].
  ///
  /// [f] is a applied to subtypes if their instantiation properties intersect
  /// with their corresponding [Instantiation] values in [mask]. If [strict] is
  /// `true`, [f] is _not_ called on [cls] itself.
  ///
  /// The visitation of subtypes can be cut short by the return value of [f].
  /// If [ForEach.STOP] is returned, no further classes are visited and the
  /// function stops immediately. If [ForEach.SKIP_SUBCLASSES] is returned, the
  /// subclasses of the last visited class are skipped, but visitation
  /// continues. The return value of the function is either [ForEach.STOP], if
  /// visitation was stopped, or [ForEach.CONTINUE] if visitation continued to
  /// the end.
  IterationStep forEachSubtype(
    ForEachFunction f,
    EnumSet<Instantiation> mask, {
    bool strict = false,
  }) {
    IterationStep nextStep = node.forEachSubclass(f, mask, strict: strict);
    if (nextStep == IterationStep.continue_ && _subtypes != null) {
      for (ClassHierarchyNode subclass in _subtypes!) {
        IterationStep subForEach = subclass.forEachSubclass(f, mask);
        if (subForEach == IterationStep.stop) {
          return subForEach;
        }
      }
    }
    assert(nextStep != IterationStep.skipSubclasses);
    return nextStep;
  }

  /// Adds [subtype] as a subtype of [cls].
  void addSubtype(ClassHierarchyNode subtype) {
    if (node.contains(subtype)) {
      return;
    }
    if (_subtypes == null) {
      _subtypes = [subtype];
    } else {
      int hierarchyDepth = subtype.hierarchyDepth;
      List<ClassHierarchyNode> newSubtypes = [];
      bool added = false;
      for (ClassHierarchyNode otherSubtype in _subtypes!) {
        int otherHierarchyDepth = otherSubtype.hierarchyDepth;
        if (hierarchyDepth == otherHierarchyDepth) {
          if (subtype == otherSubtype) {
            return;
          } else {
            // [otherSubtype] is unrelated to [subtype].
            newSubtypes.add(otherSubtype);
          }
        } else if (hierarchyDepth > otherSubtype.hierarchyDepth) {
          // [otherSubtype] could be a superclass of [subtype].
          if (otherSubtype.contains(subtype)) {
            // [subtype] is already in this set.
            return;
          } else {
            // [otherSubtype] is unrelated to [subtype].
            newSubtypes.add(otherSubtype);
          }
        } else {
          if (!added) {
            // Insert [subtype] before other subtypes of higher hierarchy depth.
            newSubtypes.add(subtype);
            added = true;
          }
          // [subtype] could be a superclass of [otherSubtype].
          if (subtype.contains(otherSubtype)) {
            // Replace [otherSubtype].
          } else {
            newSubtypes.add(otherSubtype);
          }
        }
      }
      if (!added) {
        newSubtypes.add(subtype);
      }
      _subtypes = newSubtypes;
    }
  }

  /// Adds [mixinApplication] as a class that mixes in [cls].
  void addMixinApplication(ClassHierarchyNode mixinApplication) {
    (_mixinApplications ??= []).add(mixinApplication);
  }

  /// Returns the most specific subtype of [cls] (including [cls]) that is
  /// directly instantiated or a superclass of all directly instantiated
  /// subtypes. If no subtypes of [cls] are instantiated, `null` is returned.
  ClassEntity? getLubOfInstantiatedSubtypes() {
    return _leastUpperInstantiatedSubtype ??=
        _computeLeastUpperInstantiatedSubtype();
  }

  ClassEntity? _computeLeastUpperInstantiatedSubtype() {
    if (node.isExplicitlyInstantiated) {
      return cls;
    }
    if (_subtypes == null) {
      return node.getLubOfInstantiatedSubclasses();
    }
    ClassHierarchyNode? subtype;
    if (node.isInstantiated) {
      subtype = node;
    }
    for (ClassHierarchyNode subnode in _subtypes!) {
      if (subnode.isInstantiated) {
        if (subtype == null) {
          subtype = subnode;
        } else {
          return cls;
        }
      }
    }
    if (subtype != null) {
      return subtype.getLubOfInstantiatedSubclasses();
    }
    return null;
  }

  @override
  String toString() {
    StringBuffer sb = StringBuffer();
    sb.write('[\n');
    node.printOn(sb, '  ');
    sb.write('\n');
    if (_subtypes != null) {
      sb.write('  subtypes:\n');
      for (ClassHierarchyNode node in _subtypes!) {
        node.printOn(sb, '  ');
        sb.write('\n');
      }
    }
    if (_mixinApplications != null) {
      sb.write('  mixin-applications:\n');
      for (ClassHierarchyNode node in _mixinApplications!) {
        node.printOn(sb, '  ');
        sb.write('\n');
      }
    }
    sb.write(']');
    return sb.toString();
  }
}

/// Iterable for subclasses of a [ClassHierarchyNode].
class ClassHierarchyNodeIterable extends IterableBase<ClassEntity> {
  final ClassHierarchyNode root;
  final EnumSet<Instantiation> mask;
  final bool includeRoot;

  ClassHierarchyNodeIterable(this.root, this.mask, {this.includeRoot = true});

  @override
  ClassHierarchyNodeIterator get iterator {
    return ClassHierarchyNodeIterator(this);
  }
}

/// Iterator for subclasses of a [ClassHierarchyNode].
///
/// Classes are returned in pre-order DFS fashion.
class ClassHierarchyNodeIterator implements Iterator<ClassEntity> {
  final ClassHierarchyNodeIterable iterable;

  /// The class node holding the [current] class.
  ///
  /// This is `null` before the first call to [moveNext] and at the end of
  /// iteration, i.e. after [moveNext] has returned `false`.
  ClassHierarchyNode? currentNode;

  /// Stack of pending class nodes.
  ///
  /// This is `null` before the first call to [moveNext].
  List<ClassHierarchyNode>? stack;

  ClassHierarchyNodeIterator(this.iterable);

  ClassHierarchyNode get root => iterable.root;

  bool get includeRoot => iterable.includeRoot;

  EnumSet<Instantiation> get mask => iterable.mask;

  bool get includeUninstantiated {
    return mask.contains(Instantiation.uninstantiated);
  }

  @override
  ClassEntity get current {
    // The [Iterator] spec allows for any behavior if current is not set yet
    // (i.e. the iterator is in an invalid state). Therefore we can assert not
    // null and allow this to throw.
    return currentNode!.cls;
  }

  @override
  bool moveNext() {
    if (stack == null) {
      // First call to moveNext
      stack = [root];
      return _findNext();
    } else {
      // Initialized state.
      if (currentNode == null) return false;
      return _findNext();
    }
  }

  /// Find the next class using the [stack].
  bool _findNext() {
    while (true) {
      if (stack!.isEmpty) {
        // No more classes. Set [currentNode] to `null` to signal the end of
        // iteration.
        currentNode = null;
        return false;
      }
      currentNode = stack!.removeLast();
      if (!includeUninstantiated && !currentNode!.isInstantiated) {
        // We're only iterating instantiated classes so there is no use in
        // visiting the current node and its subtree.
        continue;
      }
      // Add direct subclasses in reverse order so will visit them in the list
      // order.
      for (int i = currentNode!._directSubclasses.length - 1; i >= 0; i--) {
        stack!.add(currentNode!._directSubclasses[i]);
      }
      if (_isValid(currentNode!)) {
        return true;
      }
    }
  }

  /// Returns `true` if the class of [node] is a valid result for this iterator.
  bool _isValid(ClassHierarchyNode node) {
    if (!includeRoot && node == root) return false;
    return mask.intersects(node._mask);
  }
}

/// Iterable for the subtypes in a [ClassSet].
class SubtypesIterable extends IterableBase<ClassEntity> {
  final ClassSet subtypeSet;
  final EnumSet<Instantiation> mask;
  final bool includeRoot;

  SubtypesIterable.subtypesIterator(
    this.subtypeSet,
    this.mask, {
    this.includeRoot = true,
  });

  @override
  Iterator<ClassEntity> get iterator => SubtypesIterator(this);
}

/// Iterator for the subtypes in a [ClassSet].
class SubtypesIterator implements Iterator<ClassEntity> {
  final SubtypesIterable iterable;
  Iterator<ClassEntity>? elements;
  Iterator<ClassHierarchyNode>? hierarchyNodes;

  SubtypesIterator(this.iterable);

  bool get includeRoot => iterable.includeRoot;

  EnumSet<Instantiation> get mask => iterable.mask;

  @override
  ClassEntity get current {
    // The [Iterator] spec says that the behavior is unspecified if current is
    // unset because moveNext() has been called 0 times or too many times.
    return elements!.current;
  }

  @override
  bool moveNext() {
    if (elements == null && hierarchyNodes == null) {
      // Initial state. Iterate through subclasses.
      elements =
          iterable.subtypeSet.node
              .subclassesByMask(mask, strict: !includeRoot)
              .iterator;
    }
    if (elements != null && elements!.moveNext()) {
      return true;
    }
    hierarchyNodes ??= iterable.subtypeSet._subtypes!.iterator;
    while (hierarchyNodes!.moveNext()) {
      elements = hierarchyNodes!.current.subclassesByMask(mask).iterator;
      if (elements!.moveNext()) {
        return true;
      }
    }
    return false;
  }
}

/// Enum values returned from the [ForEachFunction] provided to the `forEachX`
/// functions of [ClassHierarchyNode] and [ClassSet]. The value is used to
/// control the continued iteration.
enum IterationStep {
  /// Iteration continues.
  continue_,

  /// Iteration stops immediately.
  stop,

  /// Iteration skips the subclasses of the current class.
  skipSubclasses,
}

/// Visiting function used for the `forEachX` functions of [ClassHierarchyNode]
/// and [ClassSet]. The return value controls the continued iteration. If `null`
/// is returned, iteration continues to the end.
typedef ForEachFunction = IterationStep Function(ClassEntity cls);

/// Singleton map implemented as a field on the key.
class ClassHierarchyNodesMap extends MapBase<ClassEntity, ClassHierarchyNode> {
  @override
  ClassHierarchyNode? operator [](Object? cls) {
    // TODO(sra): Change the key type to `covariant ClassHierarchyNodesMapKey`.
    if (cls is ClassHierarchyNodesMapKey) {
      return cls._classHierarchyNode;
    }
    throw UnimplementedError('ClassHierarchyNodesMap for $cls');
  }

  @override
  operator []=(Object cls, ClassHierarchyNode node) {
    // TODO(sra): Change the key type to `covariant ClassHierarchyNodesMapKey`.
    if (cls is ClassHierarchyNodesMapKey) {
      cls._classHierarchyNode = node;
      return;
    }
    throw UnimplementedError('ClassHierarchyNodesMap for $cls');
  }

  @override
  ClassHierarchyNode putIfAbsent(
    ClassEntity key,
    ClassHierarchyNode Function() ifAbsent,
  ) {
    return this[key] ??= ifAbsent();
  }

  @override
  Iterable<ClassEntity> get keys {
    throw UnimplementedError('ClassHierarchyNodesMap.keys');
  }

  @override
  ClassHierarchyNode remove(Object? key) {
    throw UnimplementedError('ClassHierarchyNodesMap.remove');
  }

  @override
  void clear() {
    throw UnimplementedError('ClassHierarchyNodesMap.clear');
  }
}

mixin ClassHierarchyNodesMapKey implements ClassEntity {
  ClassHierarchyNode? _classHierarchyNode;
}
