text: //===--- Edge.h - Symbol Graph Edge ---------------------------------------===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
  // Licensed under Apache License v2.0 with Runtime Library Exception
  //
  // See https://swift.org/LICENSE.txt for license information
  // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef SWIFT_SYMBOLGRAPHGEN_EDGE_H
  #define SWIFT_SYMBOLGRAPHGEN_EDGE_H
  
  #include "llvm/Support/JSON.h"
  #include "swift/AST/Decl.h"
  #include "swift/AST/Type.h"
  #include "swift/Basic/LLVM.h"
  
  #include "JSON.h"
  #include "Symbol.h"
  
  namespace swift {
  namespace symbolgraphgen {
  
  struct SymbolGraph;
    
  /// The kind of relationship, tagging an edge in the graph.
  struct RelationshipKind {
    StringRef Name;
    
    RelationshipKind(llvm::StringRef Name) : Name(Name) {}
    
    /**
     A symbol A is a member of another symbol B.
     
     For example, a method or field of a class would be a member of that class.
     
     The implied inverse of this relationship is a symbol B is the owner
     of a member symbol A.
     */
    static inline RelationshipKind MemberOf() {
      return RelationshipKind { "memberOf" };
    }
  
    /**
     A symbol A conforms to an interface/protocol symbol B.
     
     For example, a class `C` that conforms to protocol `P` in Swift would use
     this relationship.
     
     The implied inverse of this relationship is a symbol B that has
     a conformer A.
     */
    static inline RelationshipKind ConformsTo() {
      return RelationshipKind { "conformsTo" };
    }
    /**
     A symbol A inherits from another symbol B.
     
     For example, a derived class inherits from a base class, or a protocol
     that refines another protocol would use this relationship.
     
     The implied inverse of this relationship is a symbol B is a base
     of another symbol A.
     */
    static inline RelationshipKind InheritsFrom() {
      return RelationshipKind { "inheritsFrom" };
    }
    /**
     A symbol A serves as a default implementation of an interface requirement B.
     
     The implied inverse of this relationship is an interface requirement B
     has a default implementation of A.
     */
    static inline RelationshipKind DefaultImplementationOf() {
      return RelationshipKind { "defaultImplementationOf" };
    }
    /**
     A symbol A overrides another symbol B, such as through inheritance.
     
     The implied inverse of this relationship is a symbol A is the base
     of symbol B.
     */
    static inline RelationshipKind Overrides() {
      return RelationshipKind { "overrides" };
    }
    /**
     A symbol A is a requirement of interface B.
     
     The implied inverse of this relationship is an interface B
     has a requirement of A.
     */
    static inline RelationshipKind RequirementOf() {
      return RelationshipKind { "requirementOf" };
    }
    /**
     A symbol A is an optional requirement of interface B.
     
     The implied inverse of this relationship is an interface B
     has an optional requirement of A.
     */
    static inline RelationshipKind OptionalRequirementOf() {
      return RelationshipKind { "optionalRequirementOf" };
    }
    
    bool operator==(const RelationshipKind &Other) const {
      return Name == Other.Name;
    }
  
    bool operator<(const RelationshipKind &Other) const {
      return Name < Other.Name;
    }
  };
  
  /// A relationship between two symbols: an edge in a directed graph.
  struct Edge {
    SymbolGraph *Graph;
  
    /// The kind of relationship this edge represents.
    RelationshipKind Kind;
  
    /// The precise identifier of the source symbol node.
    Symbol Source;
    
    /// The precise identifier of the target symbol node.
    Symbol Target;
  
    /// If this is a conformsTo relationship, the extension that defined
    /// the conformance.
    const ExtensionDecl *ConformanceExtension;
    
    void serialize(llvm::json::OStream &OS) const;
  };
    
  } // end namespace symbolgraphgen 
  } // end namespace swift
  
  namespace llvm {
  using SymbolGraph = swift::symbolgraphgen::SymbolGraph;
  using Symbol = swift::symbolgraphgen::Symbol;
  using Edge = swift::symbolgraphgen::Edge;
  using ExtensionDecl = swift::ExtensionDecl;
  template <> struct DenseMapInfo<Edge> {
    static inline Edge getEmptyKey() {
      return {
        DenseMapInfo<SymbolGraph *>::getEmptyKey(),
        { "Empty" },
        DenseMapInfo<Symbol>::getEmptyKey(),
        DenseMapInfo<Symbol>::getEmptyKey(),
        DenseMapInfo<const ExtensionDecl *>::getEmptyKey(),
      };
    }
    static inline Edge getTombstoneKey() {
      return {
        nullptr,
        { "Tombstone" },
        DenseMapInfo<Symbol>::getTombstoneKey(),
        DenseMapInfo<Symbol>::getTombstoneKey(),
        DenseMapInfo<const ExtensionDecl *>::getTombstoneKey(),
      };
    }
    static unsigned getHashValue(const Edge E) {
      unsigned H = 0;
      H ^= DenseMapInfo<StringRef>::getHashValue(E.Kind.Name);
      H ^= DenseMapInfo<Symbol>::getHashValue(E.Source);
      H ^= DenseMapInfo<Symbol>::getHashValue(E.Target);
      H ^= DenseMapInfo<const ExtensionDecl *>::
           getHashValue(E.ConformanceExtension);
      return H;
    }
    static bool isEqual(const Edge LHS, const Edge RHS) {
      return LHS.Kind == RHS.Kind &&
        DenseMapInfo<Symbol>::isEqual(LHS.Source, RHS.Source) &&
        DenseMapInfo<Symbol>::isEqual(LHS.Target, RHS.Target) &&
        DenseMapInfo<const ExtensionDecl *>::isEqual(LHS.ConformanceExtension,
                                                     RHS.ConformanceExtension);
    }
  };
  } // end namespace llvm
  
  #endif // SWIFT_SYMBOLGRAPHGEN_EDGE_H
  