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

import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/error/correct_override.dart';
import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:meta/meta.dart';

/// Failure because of there is no most specific signature in [candidates].
class CandidatesConflict extends Conflict {
  /// The list has at least two items, because the only item is always valid.
  final List<ExecutableElement> candidates;

  CandidatesConflict({
    @required Name name,
    @required this.candidates,
  }) : super(name);
}

/// Failure to find a valid signature from superinterfaces.
class Conflict {
  /// The name for which we failed to find a valid signature.
  final Name name;

  Conflict(this.name);
}

/// Failure because of a getter and a method from direct superinterfaces.
class GetterMethodConflict extends Conflict {
  final ExecutableElement getter;
  final ExecutableElement method;

  GetterMethodConflict({
    @required Name name,
    @required this.getter,
    @required this.method,
  }) : super(name);
}

/// Manages knowledge about interface types and their members.
class InheritanceManager3 {
  static final _noSuchMethodName = Name(null, 'noSuchMethod');

  /// Cached instance interfaces for [ClassElement].
  final Map<ClassElement, Interface> _interfaces = {};

  /// The set of classes that are currently being processed, used to detect
  /// self-referencing cycles.
  final Set<ClassElement> _processingClasses = <ClassElement>{};

  /// Return the result of [getInherited2] with [type] substitution.
  ExecutableElement getInherited(InterfaceType type, Name name) {
    var rawElement = getInherited2(type.element, name);
    if (rawElement == null) {
      return null;
    }

    return ExecutableMember.from2(
      rawElement,
      Substitution.fromInterfaceType(type),
    );
  }

  /// Return the most specific signature of the member with the given [name]
  /// that [element] inherits from the mixins, superclasses, or interfaces;
  /// or `null` if no member is inherited because the member is not declared
  /// at all, or because there is no the most specific signature.
  ///
  /// This is equivalent to `getInheritedMap2(type)[name]`.
  ExecutableElement getInherited2(ClassElement element, Name name) {
    return getInheritedMap2(element)[name];
  }

  /// Return signatures of all concrete members that the given [type] inherits
  /// from the superclasses and mixins.
  @Deprecated('Use getInheritedConcreteMap2')
  Map<Name, ExecutableElement> getInheritedConcreteMap(InterfaceType type) {
    var result = <Name, ExecutableElement>{};

    var substitution = Substitution.fromInterfaceType(type);
    var rawMap = getInheritedConcreteMap2(type.element);
    for (var rawEntry in rawMap.entries) {
      result[rawEntry.key] = ExecutableMember.from2(
        rawEntry.value,
        substitution,
      );
    }

    return result;
  }

  /// Return signatures of all concrete members that the given [element] inherits
  /// from the superclasses and mixins.
  Map<Name, ExecutableElement> getInheritedConcreteMap2(ClassElement element) {
    var interface = getInterface(element);
    return interface._superImplemented.last;
  }

  /// Return the mapping from names to most specific signatures of members
  /// inherited from the super-interfaces (superclasses, mixins, and
  /// interfaces).  If there is no most specific signature for a name, the
  /// corresponding name will not be included.
  @Deprecated('Use getInheritedMap2')
  Map<Name, ExecutableElement> getInheritedMap(InterfaceType type) {
    var result = <Name, ExecutableElement>{};

    var substitution = Substitution.fromInterfaceType(type);
    var rawMap = getInheritedMap2(type.element);
    for (var rawEntry in rawMap.entries) {
      result[rawEntry.key] = ExecutableMember.from2(
        rawEntry.value,
        substitution,
      );
    }

    return result;
  }

  /// Return the mapping from names to most specific signatures of members
  /// inherited from the super-interfaces (superclasses, mixins, and
  /// interfaces).  If there is no most specific signature for a name, the
  /// corresponding name will not be included.
  Map<Name, ExecutableElement> getInheritedMap2(ClassElement element) {
    var interface = getInterface(element);
    if (interface._inheritedMap == null) {
      interface._inheritedMap = {};
      _findMostSpecificFromNamedCandidates(
        element,
        interface._inheritedMap,
        interface._overridden,
        doTopMerge: false,
      );
    }
    return interface._inheritedMap;
  }

  /// Return the interface of the given [element].  It might include
  /// private members, not necessary accessible in all libraries.
  Interface getInterface(ClassElement element) {
    if (element == null) {
      return Interface._empty;
    }

    var result = _interfaces[element];
    if (result != null) {
      return result;
    }
    _interfaces[element] = Interface._empty;

    if (!_processingClasses.add(element)) {
      return Interface._empty;
    }

    try {
      if (element.isMixin) {
        result = _getInterfaceMixin(element);
      } else {
        result = _getInterfaceClass(element);
      }
    } finally {
      _processingClasses.remove(element);
    }

    _interfaces[element] = result;
    return result;
  }

  /// Return the result of [getMember2] with [type] substitution.
  ExecutableElement getMember(
    InterfaceType type,
    Name name, {
    bool concrete = false,
    int forMixinIndex = -1,
    bool forSuper = false,
  }) {
    var rawElement = getMember2(
      type.element,
      name,
      concrete: concrete,
      forMixinIndex: forMixinIndex,
      forSuper: forSuper,
    );
    if (rawElement == null) {
      return null;
    }

    var substitution = Substitution.fromInterfaceType(type);
    return ExecutableMember.from2(rawElement, substitution);
  }

  /// Return the member with the given [name].
  ///
  /// If [concrete] is `true`, the the concrete implementation is returned,
  /// from the given [element], or its superclass.
  ///
  /// If [forSuper] is `true`, then [concrete] is implied, and only concrete
  /// members from the superclass are considered.
  ///
  /// If [forMixinIndex] is specified, only the nominal superclass, and the
  /// given number of mixins after it are considered.  For example for `1` in
  /// `class C extends S with M1, M2, M3`, only `S` and `M1` are considered.
  ExecutableElement getMember2(
    ClassElement element,
    Name name, {
    bool concrete = false,
    int forMixinIndex = -1,
    bool forSuper = false,
  }) {
    var interface = getInterface(element);
    if (forSuper) {
      var superImplemented = interface._superImplemented;
      if (forMixinIndex >= 0) {
        return superImplemented[forMixinIndex][name];
      }
      if (superImplemented.isNotEmpty) {
        return superImplemented.last[name];
      } else {
        assert(element.name == 'Object');
        return null;
      }
    }
    if (concrete) {
      return interface.implemented[name];
    }
    return interface.map[name];
  }

  /// Return all members of mixins, superclasses, and interfaces that a member
  /// with the given [name], defined in the [type], would override; or `null`
  /// if no members would be overridden.
  @Deprecated('Use getOverridden2')
  List<ExecutableElement> getOverridden(InterfaceType type, Name name) {
    return getOverridden2(type.element, name);
  }

  /// Return all members of mixins, superclasses, and interfaces that a member
  /// with the given [name], defined in the [element], would override; or `null`
  /// if no members would be overridden.
  List<ExecutableElement> getOverridden2(ClassElement element, Name name) {
    var interface = getInterface(element);
    return interface._overridden[name];
  }

  void _addCandidates({
    @required Map<Name, List<ExecutableElement>> namedCandidates,
    @required Substitution substitution,
    @required Interface interface,
    @required bool isNonNullableByDefault,
  }) {
    var map = interface.map;
    for (var name in map.keys) {
      var candidate = map[name];

      candidate = ExecutableMember.from2(candidate, substitution);

      if (!isNonNullableByDefault) {
        candidate = Member.legacy(candidate);
      }

      var candidates = namedCandidates[name];
      if (candidates == null) {
        candidates = <ExecutableElement>[];
        namedCandidates[name] = candidates;
      }

      candidates.add(candidate);
    }
  }

  void _addImplemented(
    Map<Name, ExecutableElement> implemented,
    ClassElement element,
  ) {
    var libraryUri = element.librarySource.uri;

    void addMember(ExecutableElement member) {
      if (!member.isAbstract && !member.isStatic) {
        var name = Name(libraryUri, member.name);
        implemented[name] = member;
      }
    }

    element.methods.forEach(addMember);
    element.accessors.forEach(addMember);
  }

  void _addMixinMembers({
    @required Map<Name, ExecutableElement> implemented,
    @required Substitution substitution,
    @required Interface mixin,
    @required bool isNonNullableByDefault,
  }) {
    for (var entry in mixin.implemented.entries) {
      var executable = entry.value;
      if (executable.isAbstract) {
        continue;
      }

      var class_ = executable.enclosingElement;
      if (class_ is ClassElement && class_.isDartCoreObject) {
        continue;
      }

      executable = ExecutableMember.from2(executable, substitution);

      if (!isNonNullableByDefault) {
        executable = Member.legacy(executable);
      }

      implemented[entry.key] = executable;
    }
  }

  /// Check that all [candidates] for the given [name] have the same kind, all
  /// getters, all methods, or all setter.  If a conflict found, return the
  /// new [Conflict] instance that describes it.
  Conflict _checkForGetterMethodConflict(
      Name name, List<ExecutableElement> candidates) {
    assert(candidates.length > 1);

    bool allGetters = true;
    bool allMethods = true;
    bool allSetters = true;
    for (var candidate in candidates) {
      var kind = candidate.kind;
      if (kind != ElementKind.GETTER) {
        allGetters = false;
      }
      if (kind != ElementKind.METHOD) {
        allMethods = false;
      }
      if (kind != ElementKind.SETTER) {
        allSetters = false;
      }
    }

    if (allGetters || allMethods || allSetters) {
      return null;
    }

    ExecutableElement getter;
    ExecutableElement method;
    for (var candidate in candidates) {
      var kind = candidate.kind;
      if (kind == ElementKind.GETTER) {
        getter ??= candidate;
      }
      if (kind == ElementKind.METHOD) {
        method ??= candidate;
      }
    }
    return GetterMethodConflict(name: name, getter: getter, method: method);
  }

  /// The given [namedCandidates] maps names to candidates from direct
  /// superinterfaces.  Find the most specific signature, and put it into the
  /// [map], if there is no one yet (from the class itself).  If there is no
  /// such single most specific signature (i.e. no valid override), then add a
  /// new conflict description.
  List<Conflict> _findMostSpecificFromNamedCandidates(
    ClassElement targetClass,
    Map<Name, ExecutableElement> map,
    Map<Name, List<ExecutableElement>> namedCandidates, {
    @required bool doTopMerge,
  }) {
    TypeSystemImpl typeSystem = targetClass.library.typeSystem;

    List<Conflict> conflicts;

    for (var name in namedCandidates.keys) {
      if (map.containsKey(name)) {
        continue;
      }

      var candidates = namedCandidates[name];

      // If just one candidate, it is always valid.
      if (candidates.length == 1) {
        map[name] = candidates[0];
        continue;
      }

      // Check for a getter/method conflict.
      var conflict = _checkForGetterMethodConflict(name, candidates);
      if (conflict != null) {
        conflicts ??= <Conflict>[];
        conflicts.add(conflict);
      }

      var validOverrides = <ExecutableElement>[];
      for (var i = 0; i < candidates.length; i++) {
        var validOverride = candidates[i];
        var overrideHelper = CorrectOverrideHelper(
          library: targetClass.library,
          thisMember: validOverride,
        );
        for (var j = 0; j < candidates.length; j++) {
          var candidate = candidates[j];
          if (!overrideHelper.isCorrectOverrideOf(superMember: candidate)) {
            validOverride = null;
            break;
          }
        }
        if (validOverride != null) {
          validOverrides.add(validOverride);
        }
      }

      if (validOverrides.isEmpty) {
        conflicts ??= <Conflict>[];
        conflicts.add(
          CandidatesConflict(
            name: name,
            candidates: candidates,
          ),
        );
        continue;
      }

      if (doTopMerge) {
        map[name] = _topMerge(typeSystem, targetClass, validOverrides);
      } else {
        map[name] = validOverrides.first;
      }
    }

    return conflicts;
  }

  Interface _getInterfaceClass(ClassElement element) {
    var classLibrary = element.library;
    var isNonNullableByDefault = classLibrary.isNonNullableByDefault;

    var namedCandidates = <Name, List<ExecutableElement>>{};
    var superImplemented = <Map<Name, ExecutableElement>>[];
    var implemented = <Name, ExecutableElement>{};

    Interface superTypeInterface;
    var superType = element.supertype;
    if (superType != null) {
      var substitution = Substitution.fromInterfaceType(superType);
      superTypeInterface = getInterface(superType.element);
      _addCandidates(
        namedCandidates: namedCandidates,
        substitution: substitution,
        interface: superTypeInterface,
        isNonNullableByDefault: isNonNullableByDefault,
      );

      for (var entry in superTypeInterface.implemented.entries) {
        var executable = entry.value;
        executable = ExecutableMember.from2(executable, substitution);
        if (!isNonNullableByDefault) {
          executable = Member.legacy(executable);
        }
        implemented[entry.key] = executable;
      }

      superImplemented.add(implemented);
    }

    // TODO(scheglov) Handling of members for super and mixins is not
    // optimal. We always have just one member for each name in super,
    // multiple candidates happen only when we merge super and multiple
    // interfaces. Consider using `Map<Name, ExecutableElement>` here.
    var mixinsConflicts = <List<Conflict>>[];
    for (var mixin in element.mixins) {
      var mixinElement = mixin.element;
      var substitution = Substitution.fromInterfaceType(mixin);
      var mixinInterface = getInterface(mixinElement);
      // `class X extends S with M1, M2 {}` is semantically a sequence of:
      //     class S&M1 extends S implements M1 {
      //       // declared M1 members
      //     }
      //     class S&M2 extends S&M1 implements M2 {
      //       // declared M2 members
      //     }
      //     class X extends S&M2 {
      //       // declared X members
      //     }
      // So, each mixin always replaces members in the interface.
      // And there are individual override conflicts for each mixin.
      var candidatesFromSuperAndMixin = <Name, List<ExecutableElement>>{};
      var mixinConflicts = <Conflict>[];
      for (var name in mixinInterface.map.keys) {
        var candidate = ExecutableMember.from2(
          mixinInterface.map[name],
          substitution,
        );

        var currentList = namedCandidates[name];
        if (currentList == null) {
          namedCandidates[name] = [
            isNonNullableByDefault ? candidate : Member.legacy(candidate),
          ];
          continue;
        }

        var current = currentList.single;
        if (candidate.enclosingElement == mixinElement) {
          namedCandidates[name] = [
            isNonNullableByDefault ? candidate : Member.legacy(candidate),
          ];
          if (current.kind != candidate.kind) {
            var currentIsGetter = current.kind == ElementKind.GETTER;
            mixinConflicts.add(
              GetterMethodConflict(
                name: name,
                getter: currentIsGetter ? current : candidate,
                method: currentIsGetter ? candidate : current,
              ),
            );
          }
        } else {
          candidatesFromSuperAndMixin[name] = [current, candidate];
        }
      }

      // Merge members from the superclass and the mixin interface.
      {
        var map = <Name, ExecutableElement>{};
        _findMostSpecificFromNamedCandidates(
          element,
          map,
          candidatesFromSuperAndMixin,
          doTopMerge: true,
        );
        for (var entry in map.entries) {
          namedCandidates[entry.key] = [
            isNonNullableByDefault ? entry.value : Member.legacy(entry.value),
          ];
        }
      }

      mixinsConflicts.add(mixinConflicts);

      implemented = Map.of(implemented);
      _addMixinMembers(
        implemented: implemented,
        substitution: substitution,
        mixin: mixinInterface,
        isNonNullableByDefault: isNonNullableByDefault,
      );

      superImplemented.add(implemented);
    }

    for (var interface in element.interfaces) {
      _addCandidates(
        namedCandidates: namedCandidates,
        substitution: Substitution.fromInterfaceType(interface),
        interface: getInterface(interface.element),
        isNonNullableByDefault: isNonNullableByDefault,
      );
    }

    implemented = Map.of(implemented);
    _addImplemented(implemented, element);

    // If a class declaration has a member declaration, the signature of that
    // member declaration becomes the signature in the interface.
    var declared = _getTypeMembers(element);

    // If a class declaration does not have a member declaration with a
    // particular name, but some super-interfaces do have a member with that
    // name, it's a compile-time error if there is no signature among the
    // super-interfaces that is a valid override of all the other
    // super-interface signatures with the same name. That "most specific"
    // signature becomes the signature of the class's interface.
    var interface = Map.of(declared);
    List<Conflict> conflicts = _findMostSpecificFromNamedCandidates(
      element,
      interface,
      namedCandidates,
      doTopMerge: true,
    );

    var noSuchMethodForwarders = <Name>{};
    if (element.isAbstract) {
      if (superTypeInterface != null) {
        noSuchMethodForwarders = superTypeInterface._noSuchMethodForwarders;
      }
    } else {
      var noSuchMethod = implemented[_noSuchMethodName];
      if (noSuchMethod != null && !_isDeclaredInObject(noSuchMethod)) {
        var superForwarders = superTypeInterface?._noSuchMethodForwarders;
        for (var name in interface.keys) {
          if (!implemented.containsKey(name) ||
              superForwarders != null && superForwarders.contains(name)) {
            implemented[name] = interface[name];
            noSuchMethodForwarders.add(name);
          }
        }
      }
    }

    /// TODO(scheglov) Instead of merging conflicts we could report them on
    /// the corresponding mixins applied in the class.
    for (var mixinConflicts in mixinsConflicts) {
      if (mixinConflicts.isNotEmpty) {
        conflicts ??= [];
        conflicts.addAll(mixinConflicts);
      }
    }

    return Interface._(
      interface,
      declared,
      implemented,
      noSuchMethodForwarders,
      namedCandidates,
      superImplemented,
      conflicts ?? const [],
    );
  }

  Interface _getInterfaceMixin(ClassElement element) {
    var classLibrary = element.library;
    var isNonNullableByDefault = classLibrary.isNonNullableByDefault;

    var superCandidates = <Name, List<ExecutableElement>>{};
    for (var constraint in element.superclassConstraints) {
      var substitution = Substitution.fromInterfaceType(constraint);
      var interfaceObj = getInterface(constraint.element);
      _addCandidates(
        namedCandidates: superCandidates,
        substitution: substitution,
        interface: interfaceObj,
        isNonNullableByDefault: isNonNullableByDefault,
      );
    }

    // `mixin M on S1, S2 {}` can call using `super` any instance member
    // from its superclass constraints, whether it is abstract or concrete.
    var superInterface = <Name, ExecutableElement>{};
    var superConflicts = _findMostSpecificFromNamedCandidates(
      element,
      superInterface,
      superCandidates,
      doTopMerge: true,
    );

    var interfaceCandidates = Map.of(superCandidates);
    for (var interface in element.interfaces) {
      _addCandidates(
        namedCandidates: interfaceCandidates,
        substitution: Substitution.fromInterfaceType(interface),
        interface: getInterface(interface.element),
        isNonNullableByDefault: isNonNullableByDefault,
      );
    }

    var declared = _getTypeMembers(element);

    var interface = Map.of(declared);
    var interfaceConflicts = _findMostSpecificFromNamedCandidates(
      element,
      interface,
      interfaceCandidates,
      doTopMerge: true,
    );

    var implemented = <Name, ExecutableElement>{};
    _addImplemented(implemented, element);

    return Interface._(
      interface,
      declared,
      implemented,
      {},
      interfaceCandidates,
      [superInterface],
      <Conflict>[...?superConflicts, ...?interfaceConflicts],
    );
  }

  /// Given one or more [validOverrides], merge them into a single resulting
  /// signature. This signature always exists.
  ExecutableElement _topMerge(
    TypeSystemImpl typeSystem,
    ClassElement targetClass,
    List<ExecutableElement> validOverrides,
  ) {
    var first = validOverrides[0];

    if (validOverrides.length == 1) {
      return first;
    }

    if (!typeSystem.isNonNullableByDefault) {
      return first;
    }

    var firstType = first.type;
    var allTypesEqual = true;
    for (var executable in validOverrides) {
      if (executable.type != firstType) {
        allTypesEqual = false;
        break;
      }
    }

    if (allTypesEqual) {
      return first;
    }

    FunctionType resultType;
    for (var executable in validOverrides) {
      var type = executable.type;
      var normalizedType = typeSystem.normalize(type);
      if (resultType == null) {
        resultType = normalizedType;
      } else {
        resultType = typeSystem.topMerge(resultType, normalizedType);
      }
    }

    for (var executable in validOverrides) {
      if (executable.type == resultType) {
        return executable;
      }
    }

    if (first is MethodElement) {
      var firstMethod = first;
      var result = MethodElementImpl(firstMethod.name, -1);
      result.enclosingElement = targetClass;
      result.typeParameters = resultType.typeFormals;
      result.returnType = resultType.returnType;
      result.parameters = resultType.parameters;
      return result;
    } else {
      var firstAccessor = first as PropertyAccessorElement;
      var result = PropertyAccessorElementImpl(firstAccessor.name, -1);
      result.enclosingElement = targetClass;
      result.getter = firstAccessor.isGetter;
      result.returnType = resultType.returnType;
      result.parameters = resultType.parameters;
      return result;
    }
  }

  static Map<Name, ExecutableElement> _getTypeMembers(ClassElement element) {
    var declared = <Name, ExecutableElement>{};
    var libraryUri = element.librarySource.uri;

    var methods = element.methods;
    for (var i = 0; i < methods.length; i++) {
      var method = methods[i];
      if (!method.isStatic) {
        var name = Name(libraryUri, method.name);
        declared[name] = method;
      }
    }

    var accessors = element.accessors;
    for (var i = 0; i < accessors.length; i++) {
      var accessor = accessors[i];
      if (!accessor.isStatic) {
        var name = Name(libraryUri, accessor.name);
        declared[name] = accessor;
      }
    }

    return declared;
  }

  static bool _isDeclaredInObject(ExecutableElement element) {
    var enclosing = element.enclosingElement;
    return enclosing is ClassElement &&
        enclosing.supertype == null &&
        !enclosing.isMixin;
  }
}

/// The instance interface of an [InterfaceType].
class Interface {
  static final _empty = Interface._(
    const {},
    const {},
    const {},
    <Name>{},
    const {},
    const [{}],
    const [],
  );

  /// The map of names to their signature in the interface.
  final Map<Name, ExecutableElement> map;

  /// The map of declared names to their signatures.
  final Map<Name, ExecutableElement> declared;

  /// The map of names to their concrete implementations.
  final Map<Name, ExecutableElement> implemented;

  /// The set of names that are `noSuchMethod` forwarders in [implemented].
  final Set<Name> _noSuchMethodForwarders;

  /// The map of names to their signatures from the mixins, superclasses,
  /// or interfaces.
  final Map<Name, List<ExecutableElement>> _overridden;

  /// Each item of this list maps names to their concrete implementations.
  /// The first item of the list is the nominal superclass, next the nominal
  /// superclass plus the first mixin, etc. So, for the class like
  /// `class C extends S with M1, M2`, we get `[S, S&M1, S&M1&M2]`.
  final List<Map<Name, ExecutableElement>> _superImplemented;

  /// The list of conflicts between superinterfaces - the nominal superclass,
  /// mixins, and interfaces.  Does not include conflicts with the declared
  /// members of the class.
  final List<Conflict> conflicts;

  /// The map of names to the most specific signatures from the mixins,
  /// superclasses, or interfaces.
  Map<Name, ExecutableElement> _inheritedMap;

  Interface._(
    this.map,
    this.declared,
    this.implemented,
    this._noSuchMethodForwarders,
    this._overridden,
    this._superImplemented,
    this.conflicts,
  );

  /// Return `true` if the [name] is implemented in the supertype.
  bool isSuperImplemented(Name name) {
    return _superImplemented.last.containsKey(name);
  }
}

/// A public name, or a private name qualified by a library URI.
class Name {
  /// If the name is private, the URI of the defining library.
  /// Otherwise, it is `null`.
  final Uri libraryUri;

  /// The name of this name object.
  /// If the name starts with `_`, then the name is private.
  /// Names of setters end with `=`.
  final String name;

  /// Precomputed
  final bool isPublic;

  /// The cached, pre-computed hash code.
  @override
  final int hashCode;

  factory Name(Uri libraryUri, String name) {
    if (name.startsWith('_')) {
      var hashCode = JenkinsSmiHash.hash2(libraryUri.hashCode, name.hashCode);
      return Name._internal(libraryUri, name, false, hashCode);
    } else {
      return Name._internal(null, name, true, name.hashCode);
    }
  }

  Name._internal(this.libraryUri, this.name, this.isPublic, this.hashCode);

  @override
  bool operator ==(other) {
    return other is Name &&
        name == other.name &&
        libraryUri == other.libraryUri;
  }

  bool isAccessibleFor(Uri libraryUri) {
    return isPublic || this.libraryUri == libraryUri;
  }

  @override
  String toString() => libraryUri != null ? '$libraryUri::$name' : name;
}
