text: //===--- APIDigesterData.cpp - api digester data implementation -----------===//
  //
  // 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
  //
  //===----------------------------------------------------------------------===//
  
  #include "llvm/ADT/StringSet.h"
  #include "llvm/Support/YAMLParser.h"
  #include "llvm/Support/YAMLTraits.h"
  #include "llvm/Support/MemoryBuffer.h"
  #include "swift/Basic/JSONSerialization.h"
  #include "swift/IDE/APIDigesterData.h"
  #include "swift/AST/DiagnosticEngine.h"
  #include "swift/AST/DiagnosticsDriver.h"
  
  using namespace swift;
  using namespace ide;
  using namespace api;
  
  raw_ostream &swift::ide::api::
  operator<<(raw_ostream &Out, const SDKNodeKind Value) {
    switch (Value) {
  #define NODE_KIND(Name, Value) case SDKNodeKind::Name: return Out << #Value;
  #include "swift/IDE/DigesterEnums.def"
    }
    llvm_unreachable("Undefined SDK node kind.");
  }
  
  raw_ostream &swift::ide::api::
  operator<<(raw_ostream &Out, const NodeAnnotation Value) {
  #define NODE_ANNOTATION(X) if (Value == NodeAnnotation::X) { return Out << #X; }
  #include "swift/IDE/DigesterEnums.def"
    llvm_unreachable("Undefined SDK node kind.");
  }
  
  static StringRef getDeclKindStrRaw(const DeclKind Value)  {
    switch (Value) {
  #define DECL(X, PARENT) case DeclKind::X: return #X;
  #include "swift/AST/DeclNodes.def"
    } 
    llvm_unreachable("Unhandled DeclKind in switch.");
  }
  
  StringRef swift::ide::api::getDeclKindStr(const DeclKind Value, bool lower) {
    if (lower) {
      switch (Value) {
  #define DECL(X, PARENT) case DeclKind::X: {                                   \
      static std::string lowered = StringRef(#X).lower();                       \
      return lowered;                                                           \
      }
  #include "swift/AST/DeclNodes.def"
      }
      llvm_unreachable("Unhandled DeclKind in switch.");
    } else {
      return getDeclKindStrRaw(Value);
    }
  }
  
  raw_ostream &swift::ide::api::operator<<(raw_ostream &Out, const DeclKind Value) {
    return Out << getDeclKindStrRaw(Value);
  }
  
  Optional<SDKNodeKind> swift::ide::api::parseSDKNodeKind(StringRef Content) {
    return llvm::StringSwitch<Optional<SDKNodeKind>>(Content)
  #define NODE_KIND(NAME, VALUE) .Case(#VALUE, SDKNodeKind::NAME)
  #include "swift/IDE/DigesterEnums.def"
      .Default(None)
    ;
  }
  
  NodeAnnotation swift::ide::api::parseSDKNodeAnnotation(StringRef Content) {
    return llvm::StringSwitch<NodeAnnotation>(Content)
  #define NODE_ANNOTATION_CHANGE_KIND(NAME) .Case(#NAME, NodeAnnotation::NAME)
  #include "swift/IDE/DigesterEnums.def"
    ;
  }
  
  SpecialCaseId swift::ide::api::parseSpecialCaseId(StringRef Content) {
    return llvm::StringSwitch<SpecialCaseId>(Content)
  #define SPECIAL_CASE_ID(NAME) .Case(#NAME, SpecialCaseId::NAME)
  #include "swift/IDE/DigesterEnums.def"
    ;
  }
  
  swift::ide::api::CommonDiffItem::
  CommonDiffItem(SDKNodeKind NodeKind, NodeAnnotation DiffKind,
                 StringRef ChildIndex, StringRef LeftUsr, StringRef RightUsr,
                 StringRef LeftComment, StringRef RightComment,
                 StringRef ModuleName) : NodeKind(NodeKind),
                   DiffKind(DiffKind), ChildIndex(ChildIndex), LeftUsr(LeftUsr),
                   RightUsr(RightUsr), LeftComment(LeftComment),
                   RightComment(RightComment), ModuleName(ModuleName) {
    assert(!ChildIndex.empty() && "Child index is empty.");
    llvm::SmallVector<StringRef, 4> Pieces;
    ChildIndex.split(Pieces, ":");
    std::transform(Pieces.begin(), Pieces.end(),
                   std::back_inserter(ChildIndexPieces),
                   [](StringRef Piece) { return std::stoi(Piece.str()); });
  }
  
  StringRef swift::ide::api::CommonDiffItem::head() {
    return "SDK_CHANGE";
  }
  
  bool swift::ide::api::CommonDiffItem::operator<(CommonDiffItem Other) const {
    if (auto UsrCompare = LeftUsr.compare(Other.LeftUsr))
        return UsrCompare < 0;
    if (NodeKind != Other.NodeKind)
      return NodeKind < Other.NodeKind;
    if (DiffKind != Other.DiffKind)
      return DiffKind < Other.DiffKind;
    if (auto ChildCompare = ChildIndex.compare(Other.ChildIndex))
      return ChildCompare < 0;
    return false;
  }
  
  void swift::ide::api::CommonDiffItem::describe(llvm::raw_ostream &os) {
    os << "#ifndef " << head() << "\n";
    os << "#define " << head() << "(NODE_KIND, DIFF_KIND, CHILD_INDEX, LEFT_USR, "
                                  "RIGHT_USR, LEFT_COMMENT, RIGHT_COMMENT, "
                                  "MODULENAME)\n";
    os << "#endif\n";
  }
  
  void swift::ide::api::CommonDiffItem::undef(llvm::raw_ostream &os) {
    os << "#undef " << head() << "\n";
  }
  
  void swift::ide::api::CommonDiffItem::streamDef(llvm::raw_ostream &S) const {
    S << head() << "(" << NodeKind << ", " << DiffKind << ", \"" << ChildIndex
      << "\", \"" << LeftUsr << "\", \"" << RightUsr << "\", \""
      << LeftComment << "\", \"" << RightComment
      << "\", \"" << ModuleName << "\")";
  }
  
  StringRef swift::ide::api::TypeMemberDiffItem::head() {
    return "SDK_CHANGE_TYPE_MEMBER";
  }
  
  TypeMemberDiffItemSubKind
  swift::ide::api::TypeMemberDiffItem::getSubKind() const {
    DeclNameViewer OldName = getOldName();
    DeclNameViewer NewName = getNewName();
    if (!OldName.isFunction()) {
      assert(!NewName.isFunction());
      if (oldTypeName.empty())
        return TypeMemberDiffItemSubKind::SimpleReplacement;
      else
        return TypeMemberDiffItemSubKind::QualifiedReplacement;
    }
    assert(OldName.isFunction());
    bool ToProperty = !NewName.isFunction();
    if (selfIndex) {
      if (removedIndex) {
        if (ToProperty)
          llvm_unreachable("unknown situation");
        else {
          assert(NewName.argSize() + 2 == OldName.argSize());
          return TypeMemberDiffItemSubKind::HoistSelfAndRemoveParam;
        }
      } else if (ToProperty) {
        assert(OldName.argSize() == 1);
        return TypeMemberDiffItemSubKind::HoistSelfAndUseProperty;
      } else if (oldTypeName.empty()) {
        assert(NewName.argSize() + 1 == OldName.argSize());
        return TypeMemberDiffItemSubKind::HoistSelfOnly;
      } else {
        assert(NewName.argSize() == OldName.argSize());
        return TypeMemberDiffItemSubKind::QualifiedReplacement;
      }
    } else if (ToProperty) {
      assert(OldName.argSize() == 0);
      assert(!removedIndex);
      return TypeMemberDiffItemSubKind::GlobalFuncToStaticProperty;
    } else if (oldTypeName.empty()) {
      // we can handle this as a simple function rename.
      assert(NewName.argSize() == OldName.argSize());
      return TypeMemberDiffItemSubKind::FuncRename;
    } else {
      assert(NewName.argSize() == OldName.argSize());
      return TypeMemberDiffItemSubKind::QualifiedReplacement;
    }
  }
  
  void swift::ide::api::TypeMemberDiffItem::describe(llvm::raw_ostream &os) {
    os << "#ifndef " << head() << "\n";
    os << "#define " << head() << "(USR, NEW_TYPE_NAME, NEW_PRINTED_NAME, "
                                  "SELF_INDEX, OLD_PRINTED_NAME)\n";
    os << "#endif\n";
  }
  
  void swift::ide::api::TypeMemberDiffItem::undef(llvm::raw_ostream &os) {
    os << "#undef " << head() << "\n";
  }
  
  void swift::ide::api::TypeMemberDiffItem::streamDef(llvm::raw_ostream &os) const {
    std::string IndexContent = selfIndex.hasValue() ?
      std::to_string(selfIndex.getValue()) : "";
    os << head() << "("
       << "\"" << usr << "\"" << ", "
       << "\"" << newTypeName << "\"" << ", "
       << "\"" << newPrintedName << "\"" << ", "
       << "\"" << IndexContent << "\"" << ", "
       << "\"" << oldPrintedName << "\""
       << ")";
  }
  
  bool swift::ide::api::TypeMemberDiffItem::
  operator<(TypeMemberDiffItem Other) const {
    return usr.compare(Other.usr) < 0;
  }
  
  StringRef swift::ide::api::NoEscapeFuncParam::head() {
    return "NOESCAPE_FUNC_PARAM";
  }
  
  void swift::ide::api::NoEscapeFuncParam::describe(llvm::raw_ostream &os) {
    os << "#ifndef " << head() << "\n";
    os << "#define " << head() << "(USR, Index)\n";
    os << "#endif\n";
  }
  
  void swift::ide::api::NoEscapeFuncParam::undef(llvm::raw_ostream &os) {
    os << "#undef " << head() << "\n";
  }
  
  void swift::ide::api::NoEscapeFuncParam::
  streamDef(llvm::raw_ostream &os) const {
    os << head() << "(" << "\"" << Usr << "\"" << ", "
       << "\"" << Index << "\"" << ")";
  }
  
  bool swift::ide::api::NoEscapeFuncParam::
  operator<(NoEscapeFuncParam Other) const {
    if (Usr != Other.Usr)
      return Usr.compare(Other.Usr) < 0;
    return Index < Other.Index;
  }
  
  StringRef swift::ide::api::OverloadedFuncInfo::head() {
    return "OVERLOAD_FUNC_TRAILING_CLOSURE";
  }
  
  void swift::ide::api::OverloadedFuncInfo::describe(llvm::raw_ostream &os) {
    os << "#ifndef " << head() << "\n";
    os << "#define " << head() << "(USR)\n";
    os << "#endif\n";
  }
  
  void swift::ide::api::OverloadedFuncInfo::undef(llvm::raw_ostream &os) {
    os << "#undef " << head() << "\n";
  }
  
  void swift::ide::api::OverloadedFuncInfo::
  streamDef(llvm::raw_ostream &os) const {
    os << head() << "(" << "\"" << Usr << "\"" << ")";
  }
  
  bool swift::ide::api::OverloadedFuncInfo::
  operator<(OverloadedFuncInfo Other) const {
    return Usr.compare(Other.Usr) < 0;
  }
  
  #define DIFF_ITEM_KIND(NAME)                                                   \
  bool swift::ide::api::NAME::classof(const APIDiffItem *D) {                    \
    return D->getKind() == APIDiffItemKind::ADK_##NAME;                          \
  }
  #include "swift/IDE/DigesterEnums.def"
  
  bool APIDiffItem::operator==(const APIDiffItem &Other) const {
    if (getKind() != Other.getKind())
      return false;
    if (getKey() != Other.getKey())
      return false;
    switch(getKind()) {
    case APIDiffItemKind::ADK_CommonDiffItem: {
      auto *Left = static_cast<const CommonDiffItem*>(this);
      auto *Right = static_cast<const CommonDiffItem*>(&Other);
      return
        Left->DiffKind == Right->DiffKind &&
        Left->ChildIndex == Right->ChildIndex;
    }
    case APIDiffItemKind::ADK_NoEscapeFuncParam: {
      auto *Left = static_cast<const NoEscapeFuncParam*>(this);
      auto *Right = static_cast<const NoEscapeFuncParam*>(&Other);
      return Left->Index == Right->Index;
    }
    case APIDiffItemKind::ADK_TypeMemberDiffItem:
    case APIDiffItemKind::ADK_OverloadedFuncInfo:
    case APIDiffItemKind::ADK_SpecialCaseDiffItem:
      return true;
    }
    llvm_unreachable("unhandled kind");
  }
  
  namespace {
  enum class DiffItemKeyKind {
  #define DIFF_ITEM_KEY_KIND(NAME) KK_##NAME,
  #include "swift/IDE/DigesterEnums.def"
  };
  
  static const char* getKeyContent(DiffItemKeyKind KK) {
    switch (KK) {
  #define DIFF_ITEM_KEY_KIND(NAME) case DiffItemKeyKind::KK_##NAME: return #NAME;
  #include "swift/IDE/DigesterEnums.def"
    }
    llvm_unreachable("unhandled kind");
  }
  
  static DiffItemKeyKind parseKeyKind(StringRef Content) {
    return llvm::StringSwitch<DiffItemKeyKind>(Content)
  #define DIFF_ITEM_KEY_KIND(NAME) .Case(#NAME, DiffItemKeyKind::KK_##NAME)
  #include "swift/IDE/DigesterEnums.def"
    ;
  }
  
  static APIDiffItemKind parseDiffItemKind(StringRef Content) {
    return llvm::StringSwitch<APIDiffItemKind>(Content)
  #define DIFF_ITEM_KIND(NAME) .Case(#NAME, APIDiffItemKind::ADK_##NAME)
  #include "swift/IDE/DigesterEnums.def"
    ;
  }
  
  static StringRef getScalarString(llvm::yaml::Node *N) {
    auto WithQuote = cast<llvm::yaml::ScalarNode>(N)->getRawValue();
    return WithQuote.substr(1, WithQuote.size() - 2);
  };
  
  static int getScalarInt(llvm::yaml::Node *N) {
    return std::stoi(cast<llvm::yaml::ScalarNode>(N)->getRawValue().str());
  };
  
  static APIDiffItem*
  serializeDiffItem(llvm::BumpPtrAllocator &Alloc,
                    llvm::yaml::MappingNode* Node) {
  #define DIFF_ITEM_KEY_KIND_STRING(NAME) StringRef NAME;
  #define DIFF_ITEM_KEY_KIND_INT(NAME) Optional<int> NAME;
  #include "swift/IDE/DigesterEnums.def"
    for (auto &Pair : *Node) {
      switch(parseKeyKind(getScalarString(Pair.getKey()))) {
  #define DIFF_ITEM_KEY_KIND_STRING(NAME)                                       \
      case DiffItemKeyKind::KK_##NAME:                                          \
        NAME = getScalarString(Pair.getValue()); break;
  #define DIFF_ITEM_KEY_KIND_INT(NAME)                                          \
      case DiffItemKeyKind::KK_##NAME:                                          \
        NAME = getScalarInt(Pair.getValue()); break;
  #include "swift/IDE/DigesterEnums.def"
      }
    }
    switch (parseDiffItemKind(DiffItemKind)) {
    case APIDiffItemKind::ADK_CommonDiffItem: {
      return new (Alloc.Allocate<CommonDiffItem>())
        CommonDiffItem(*parseSDKNodeKind(NodeKind),
                       parseSDKNodeAnnotation(NodeAnnotation), ChildIndex,
                       LeftUsr, RightUsr, LeftComment, RightComment, ModuleName);
    }
    case APIDiffItemKind::ADK_TypeMemberDiffItem: {
      Optional<uint8_t> SelfIndexShort;
      Optional<uint8_t> RemovedIndexShort;
      if (SelfIndex)
        SelfIndexShort = SelfIndex.getValue();
      if (RemovedIndex)
        RemovedIndexShort = RemovedIndex.getValue();
      return new (Alloc.Allocate<TypeMemberDiffItem>())
        TypeMemberDiffItem(Usr, NewTypeName, NewPrintedName, SelfIndexShort,
                           RemovedIndexShort, OldTypeName, OldPrintedName);
    }
    case APIDiffItemKind::ADK_NoEscapeFuncParam: {
      return new (Alloc.Allocate<NoEscapeFuncParam>())
        NoEscapeFuncParam(Usr, Index.getValue());
    }
    case APIDiffItemKind::ADK_OverloadedFuncInfo: {
      return new (Alloc.Allocate<OverloadedFuncInfo>()) OverloadedFuncInfo(Usr);
    }
    case APIDiffItemKind::ADK_SpecialCaseDiffItem: {
      return new (Alloc.Allocate<SpecialCaseDiffItem>())
        SpecialCaseDiffItem(Usr, SpecialCaseId);
    }
    }
    llvm_unreachable("unhandled kind");
  }
  } // end anonymous namespace
  
  namespace swift {
  namespace json {
  template<>
  struct ScalarEnumerationTraits<APIDiffItemKind> {
    static void enumeration(Output &out, APIDiffItemKind &value) {
  #define DIFF_ITEM_KIND(X) out.enumCase(value, #X, APIDiffItemKind::ADK_##X);
  #include "swift/IDE/DigesterEnums.def"
    }
  };
  
  template<>
  struct ScalarEnumerationTraits<NodeAnnotation> {
    static void enumeration(Output &out, NodeAnnotation &value) {
  #define NODE_ANNOTATION(X) out.enumCase(value, #X, NodeAnnotation::X);
  #include "swift/IDE/DigesterEnums.def"
    }
  };
  template<>
  struct ObjectTraits<APIDiffItem*> {
    static void mapping(Output &out, APIDiffItem *&value) {
      switch (value->getKind()) {
      case APIDiffItemKind::ADK_CommonDiffItem: {
        CommonDiffItem *Item = cast<CommonDiffItem>(value);
        auto ItemKind = Item->getKind();
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_DiffItemKind), ItemKind);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_NodeKind),
                        Item->NodeKind);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_NodeAnnotation),
                        Item->DiffKind);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_ChildIndex),
                        Item->ChildIndex);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_LeftUsr),
                        Item->LeftUsr);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_LeftComment),
                        Item->LeftComment);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_RightUsr),
                        Item->RightUsr);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_RightComment),
                        Item->RightComment);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_ModuleName),
                        Item->ModuleName);
        return;
      }
      case APIDiffItemKind::ADK_TypeMemberDiffItem: {
        TypeMemberDiffItem *Item = cast<TypeMemberDiffItem>(value);
        auto ItemKind = Item->getKind();
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_DiffItemKind),
                        ItemKind);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_Usr), Item->usr);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_OldPrintedName),
                        Item->oldPrintedName);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_OldTypeName),
                        Item->oldTypeName);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_NewPrintedName),
                        Item->newPrintedName);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_NewTypeName),
                        Item->newTypeName);
        out.mapOptional(getKeyContent(DiffItemKeyKind::KK_SelfIndex),
                        Item->selfIndex);
        return;
      }
      case APIDiffItemKind::ADK_NoEscapeFuncParam: {
        NoEscapeFuncParam *Item = cast<NoEscapeFuncParam>(value);
        auto ItemKind = Item->getKind();
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_DiffItemKind), ItemKind);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_Usr), Item->Usr);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_Index), Item->Index);
        return;
      }
      case APIDiffItemKind::ADK_OverloadedFuncInfo: {
        OverloadedFuncInfo *Item = cast<OverloadedFuncInfo>(value);
        auto ItemKind = Item->getKind();
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_DiffItemKind), ItemKind);
        out.mapRequired(getKeyContent(DiffItemKeyKind::KK_Usr), Item->Usr);
        return;
      }
      case APIDiffItemKind::ADK_SpecialCaseDiffItem:
        llvm_unreachable("This entry should be authored only.");
      }
    }
  };
  template<>
  struct ArrayTraits<ArrayRef<APIDiffItem*>> {
    static size_t size(Output &out, ArrayRef<APIDiffItem *> &seq) {
      return seq.size();
    }
    static APIDiffItem *&element(Output &, ArrayRef<APIDiffItem *> &seq,
                                 size_t index) {
      return const_cast<APIDiffItem *&>(seq[index]);
    }
  };
  
  template<>
  struct ObjectTraits<NameCorrectionInfo> {
    static void mapping(Output &out, NameCorrectionInfo &value) {
      out.mapRequired(getKeyContent(DiffItemKeyKind::KK_OldPrintedName),value.OriginalName);
      out.mapRequired(getKeyContent(DiffItemKeyKind::KK_NewPrintedName), value.CorrectedName);
      out.mapRequired(getKeyContent(DiffItemKeyKind::KK_ModuleName), value.ModuleName);
    }
  };
  template<>
  struct ArrayTraits<ArrayRef<NameCorrectionInfo>> {
    static size_t size(Output &out, ArrayRef<NameCorrectionInfo> &seq) {
      return seq.size();
    }
    static NameCorrectionInfo &element(Output &, ArrayRef<NameCorrectionInfo> &seq,
                                       size_t index) {
      return const_cast<NameCorrectionInfo&>(seq[index]);
    }
  };
  } // namespace json
  } // namespace swift
  
  void swift::ide::api::APIDiffItemStore::
  serialize(llvm::raw_ostream &os, ArrayRef<APIDiffItem*> Items) {
    json::Output yout(os);
    yout << Items;
  }
  
  void swift::ide::api::APIDiffItemStore::
  serialize(llvm::raw_ostream &os, ArrayRef<NameCorrectionInfo> Items) {
    json::Output yout(os);
    yout << Items;
  }
  
  struct swift::ide::api::APIDiffItemStore::Implementation {
  private:
    DiagnosticEngine &Diags;
    llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 2> AllBuffer;
    llvm::BumpPtrAllocator Allocator;
  
    static bool shouldInclude(APIDiffItem *Item) {
      if (auto *CI = dyn_cast<CommonDiffItem>(Item)) {
        if (CI->rightCommentUnderscored())
          return false;
  
        // Ignore constructor's return value rewritten.
        if (CI->DiffKind == NodeAnnotation::TypeRewritten &&
            CI->NodeKind == SDKNodeKind::DeclConstructor &&
            CI->getChildIndices().front() == 0) {
          return false;
        }
      }
      return true;
    }
  
  public:
    Implementation(DiagnosticEngine &Diags): Diags(Diags) {}
    llvm::StringMap<std::vector<APIDiffItem*>> Data;
    bool PrintUsr;
    std::vector<APIDiffItem*> AllItems;
    llvm::StringSet<> PrintedUsrs;
    void addStorePath(StringRef FileName) {
      llvm::MemoryBuffer *pMemBuffer = nullptr;
      {
        auto FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(FileName);
        if (!FileBufOrErr) {
          Diags.diagnose(SourceLoc(), diag::cannot_find_migration_script,
            FileName);
          return;
        }
        pMemBuffer = FileBufOrErr->get();
        AllBuffer.push_back(std::move(FileBufOrErr.get()));
      }
      assert(pMemBuffer);
      StringRef Buffer = pMemBuffer->getBuffer();
      llvm::SourceMgr SM;
      llvm::yaml::Stream Stream(Buffer, SM);
      for (auto DI = Stream.begin(); DI != Stream.end(); ++ DI) {
        auto Array = cast<llvm::yaml::SequenceNode>(DI->getRoot());
        for (auto It = Array->begin(); It != Array->end(); ++ It) {
          APIDiffItem *Item = serializeDiffItem(Allocator,
            cast<llvm::yaml::MappingNode>(&*It));
          auto &Bag = Data[Item->getKey()];
          if (shouldInclude(Item) && std::find_if(Bag.begin(), Bag.end(),
              [&](APIDiffItem* I) { return *Item == *I; }) == Bag.end()) {
            Bag.push_back(Item);
            AllItems.push_back(Item);
          }
        }
      }
    }
  };
  
  ArrayRef<APIDiffItem*> swift::ide::api::APIDiffItemStore::
  getDiffItems(StringRef Key) const {
    if (Impl.PrintUsr && !Impl.PrintedUsrs.count(Key)) {
      llvm::outs() << Key << "\n";
      Impl.PrintedUsrs.insert(Key);
    }
    return Impl.Data[Key];
  }
  
  ArrayRef<APIDiffItem*> swift::ide::api::APIDiffItemStore::
  getAllDiffItems() const { return Impl.AllItems; }
  
  swift::ide::api::APIDiffItemStore::APIDiffItemStore(DiagnosticEngine &Diags) :
    Impl(*new Implementation(Diags)) {}
  
  swift::ide::api::APIDiffItemStore::~APIDiffItemStore() { delete &Impl; }
  
  void swift::ide::api::APIDiffItemStore::addStorePath(StringRef Path) {
    Impl.addStorePath(Path);
  }
  
  void swift::ide::api::APIDiffItemStore::printIncomingUsr(bool print) {
    Impl.PrintUsr = print;
  }
  