//===--- swift-api-digester.cpp - API change detector ---------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// swift-api-digester is a test utility to detect source-breaking API changes
// during the evolution of a Swift library. The tool works on two phases:
// (1) dumping library contents as a JSON file, and (2) comparing two JSON
// files textually to report interesting changes.
//
// During phase (1), the api-digester looks up every declarations inside
// a module and outputs a singly-rooted tree that encloses interesting
// details of the API level.
//
// During phase (2), api-digester applies structure-information comparison
// algorithms on two given singly root trees, trying to figure out, as
// precise as possible, the branches/leaves in the trees that differ from
// each other. Further analysis decides whether the changed leaves/branches
// can be reflected as source-breaking changes for API users. If they are,
// the output of api-digester will include such changes.

#include "swift/AST/DiagnosticsModuleDiffer.h"
#include "swift/IDE/APIDigesterData.h"
#include <functional>
#include "ModuleAnalyzerNodes.h"
#include "ModuleDiagsConsumer.h"

using namespace swift;
using namespace ide;
using namespace api;

namespace  {
  enum class ActionType {
    None,
    DumpSDK,
    DumpSwiftModules,
    CompareSDKs,
    DiagnoseSDKs,
    // The following two are for testing purposes
    DeserializeDiffItems,
    DeserializeSDK,
    GenerateNameCorrectionTemplate,
    FindUsr,
  };
} // end anonymous namespace

namespace options {

static llvm::cl::opt<bool>
IncludeAllModules("include-all", llvm::cl::desc("Include all modules from the SDK"));

static llvm::cl::list<std::string>
ModuleNames("module", llvm::cl::ZeroOrMore, llvm::cl::desc("Names of modules"));

static llvm::cl::opt<std::string>
ModuleList("module-list-file",
           llvm::cl::desc("File containing a new-line separated list of modules"));

static llvm::cl::opt<std::string>
ProtReqWhiteList("protocol-requirement-white-list",
           llvm::cl::desc("File containing a new-line separated list of protocol names"));

static llvm::cl::opt<std::string>
OutputFile("o", llvm::cl::desc("Output file"));

static llvm::cl::opt<std::string>
SDK("sdk", llvm::cl::desc("path to the SDK to build against"));

static llvm::cl::opt<std::string>
Triple("target", llvm::cl::desc("target triple"));

static llvm::cl::opt<std::string>
ModuleCachePath("module-cache-path", llvm::cl::desc("Clang module cache path"));

static llvm::cl::opt<std::string>
ResourceDir("resource-dir",
            llvm::cl::desc("The directory that holds the compiler resource files"));

static llvm::cl::list<std::string>
FrameworkPaths("F", llvm::cl::desc("add a directory to the framework search path"));

static llvm::cl::list<std::string>
ModuleInputPaths("I", llvm::cl::desc("add a module for input"));

static llvm::cl::list<std::string>
CCSystemFrameworkPaths("iframework",
  llvm::cl::desc("add a directory to the clang importer system framework search path"));

static llvm::cl::opt<bool>
AbortOnModuleLoadFailure("abort-on-module-fail",
                        llvm::cl::desc("Abort if a module failed to load"));

static llvm::cl::opt<bool>
Verbose("v", llvm::cl::desc("Verbose"));

static llvm::cl::opt<bool>
Abi("abi", llvm::cl::desc("Dumping ABI interface"),  llvm::cl::init(false));

static llvm::cl::opt<bool>
SwiftOnly("swift-only",
          llvm::cl::desc("Only include APIs defined from Swift source"),
          llvm::cl::init(false));

static llvm::cl::opt<bool>
PrintModule("print-module", llvm::cl::desc("Print module names in diagnostics"));

static llvm::cl::opt<ActionType>
Action(llvm::cl::desc("Mode:"), llvm::cl::init(ActionType::None),
      llvm::cl::values(
          clEnumValN(ActionType::DumpSDK,
                     "dump-sdk",
                     "Dump SDK content to JSON file"),
          clEnumValN(ActionType::DumpSwiftModules,
                     "dump-swift",
                     "dump swift modules in SDK"),
          clEnumValN(ActionType::CompareSDKs,
                     "compare-sdk",
                     "Compare SDK content in JSON file"),
          clEnumValN(ActionType::DiagnoseSDKs,
                     "diagnose-sdk",
                     "Diagnose SDK content in JSON file"),
          clEnumValN(ActionType::DeserializeDiffItems,
                     "deserialize-diff",
                     "Deserialize diff items in a JSON file"),
          clEnumValN(ActionType::DeserializeSDK,
                     "deserialize-sdk",
                     "Deserialize sdk digester in a JSON file"),
          clEnumValN(ActionType::FindUsr,
                     "find-usr",
                     "Find USR for decls by given condition"),
          clEnumValN(ActionType::GenerateNameCorrectionTemplate,
                     "generate-name-correction",
                     "Generate name correction template")));

static llvm::cl::list<std::string>
SDKJsonPaths("input-paths",
            llvm::cl::desc("The SDK contents under comparison"));

static llvm::cl::list<std::string>
ApisPrintUsrs("api-usrs",
              llvm::cl::desc("The name of APIs to print their usrs, "
                             "e.g. Type::Function"));

static llvm::cl::opt<std::string>
IgnoreRemovedDeclUSRs("ignored-usrs",
                      llvm::cl::desc("the file containing USRs of removed decls "
                                     "that the digester should ignore"));

static llvm::cl::opt<std::string>
SwiftVersion("swift-version",
             llvm::cl::desc("The Swift compiler version to invoke"));

static llvm::cl::opt<bool>
OutputInJson("json", llvm::cl::desc("Print output in JSON format."));

static llvm::cl::opt<bool>
AvoidLocation("avoid-location",
              llvm::cl::desc("Avoid serializing the file paths of SDK nodes."));

static llvm::cl::opt<std::string>
LocationFilter("location",
              llvm::cl::desc("Filter nodes with the given location."));
} // namespace options

namespace {

using swift::ide::api::KnownProtocolKind;

// A node matcher will traverse two trees of SDKNode and find matched nodes
struct NodeMatcher {
  virtual void match() = 0;
  virtual ~NodeMatcher() = default;
};

// During the matching phase, any matched node will be reported using this API.
// For update Node left = {Node before change} Right = {Node after change};
// For added Node left = {NilNode} Right = {Node after change};
// For removed Node left = {Node before change} Right = {NilNode}
struct MatchedNodeListener {
  virtual void foundMatch(NodePtr Left, NodePtr Right, NodeMatchReason Reason) = 0;
  virtual ~MatchedNodeListener() = default;
};

template<typename T>
bool contains(std::vector<T*> &container, T *instance) {
  return std::find(container.begin(), container.end(), instance) != container.end();
}

template<typename T>
bool contains(ArrayRef<T> container, T instance) {
  return std::find(container.begin(), container.end(), instance) != container.end();
}

// Given two NodeVector, this matches SDKNode by the order of their appearance
// in the respective NodeVector. We use this in the order-sensitive cases, such
// as parameters in a function decl.
class SequentialNodeMatcher : public NodeMatcher {
  ArrayRef<SDKNode*> Left;
  ArrayRef<SDKNode*> Right;
  MatchedNodeListener &Listener;
public:
  SequentialNodeMatcher(ArrayRef<SDKNode*> Left,
                        ArrayRef<SDKNode*> Right,
                        MatchedNodeListener &Listener) :
                          Left(Left), Right(Right), Listener(Listener) {}

  void match() override {
    for (unsigned long i = 0; i < std::max(Left.size(), Right.size()); i ++) {
      auto L = i < Left.size() ? Left[i] : nullptr;
      auto R = i < Right.size() ? Right[i] : nullptr;
      if (L && R && *L == *R)
        continue;
      if (!L || !R)
        Listener.foundMatch(L, R,
          L ? NodeMatchReason::Removed : NodeMatchReason::Added);
      else
        Listener.foundMatch(L, R, NodeMatchReason::Sequential);
    }
  }
};
struct NodeMatch {
  NodePtr Left;
  NodePtr Right;
};

class BestMatchMatcher : public NodeMatcher {
  NodeVector &Left;
  NodeVector &Right;
  llvm::function_ref<bool(NodePtr, NodePtr)> CanMatch;
  llvm::function_ref<bool(NodeMatch, NodeMatch)> IsFirstMatchBetter;
  NodeMatchReason Reason;
  MatchedNodeListener &Listener;
  llvm::SmallPtrSet<NodePtr, 16> MatchedRight;

  bool internalCanMatch(NodePtr L, NodePtr R) {
    return MatchedRight.count(R) == 0 && CanMatch(L, R);
  }

  Optional<NodePtr> findBestMatch(NodePtr Pin, NodeVector& Candidates) {
    Optional<NodePtr> Best;
    for (auto Can : Candidates) {
      if (!internalCanMatch(Pin, Can))
        continue;
      if (!Best.hasValue() ||
          IsFirstMatchBetter({Pin, Can}, {Pin, Best.getValue()}))
        Best = Can;
    }
    return Best;
  }

public:
  BestMatchMatcher(NodeVector &Left, NodeVector &Right,
                   llvm::function_ref<bool(NodePtr, NodePtr)> CanMatch,
                   llvm::function_ref<bool(NodeMatch, NodeMatch)> IsFirstMatchBetter,
                   NodeMatchReason Reason,
                   MatchedNodeListener &Listener) : Left(Left), Right(Right),
  CanMatch(CanMatch),
  IsFirstMatchBetter(IsFirstMatchBetter), Reason(Reason),
  Listener(Listener){}

  void match() override {
    for (auto L : Left) {
      if (auto Best = findBestMatch(L, Right)) {
        MatchedRight.insert(Best.getValue());
        Listener.foundMatch(L, Best.getValue(), Reason);
      }
    }
  }
};

class RemovedAddedNodeMatcher : public NodeMatcher, public MatchedNodeListener {
  NodeVector &Removed;
  NodeVector &Added;
  MatchedNodeListener &Listener;

  NodeVector RemovedMatched;
  NodeVector AddedMatched;

  void handleUnmatch(NodeVector &Matched, NodeVector &All, bool Left) {
    for (auto A : All) {
      if (contains(Matched, A))
        continue;
      if (Left)
        Listener.foundMatch(A, nullptr, NodeMatchReason::Removed);
      else
        Listener.foundMatch(nullptr, A, NodeMatchReason::Added);
    }
  }

  bool detectFuncToProperty(SDKNode *R, SDKNode *A) {
    if (R->getKind() == SDKNodeKind::DeclFunction) {
      if (A->getKind() == SDKNodeKind::DeclVar) {
        if (A->getName().compare_lower(R->getName()) == 0) {
          R->annotate(NodeAnnotation::GetterToProperty);
        } else if (R->getName().startswith("get") &&
                   R->getName().substr(3).compare_lower(A->getName()) == 0) {
          R->annotate(NodeAnnotation::GetterToProperty);
        } else if (R->getName().startswith("set") &&
                   R->getName().substr(3).compare_lower(A->getName()) == 0) {
          R->annotate(NodeAnnotation::SetterToProperty);
        } else {
          return false;
        }
        R->annotate(NodeAnnotation::PropertyName, A->getPrintedName());
        foundMatch(R, A, NodeMatchReason::FuncToProperty);
        return true;
      }
    }
    return false;
  }

  static bool isAnonymousEnum(SDKNodeDecl *N) {
    return N->getKind() == SDKNodeKind::DeclVar &&
      N->getUsr().startswith("c:@Ea@");
  }

  static bool isNominalEnum(SDKNodeDecl *N) {
    return N->getKind() == SDKNodeKind::DeclType &&
    N->getUsr().startswith("c:@E@");
  }

  static Optional<StringRef> getLastPartOfUsr(SDKNodeDecl *N) {
    auto LastPartIndex = N->getUsr().find_last_of('@');
    if (LastPartIndex == StringRef::npos)
      return None;
    return N->getUsr().substr(LastPartIndex + 1);
  }

  bool detectTypeAliasChange(SDKNodeDecl *R, SDKNodeDecl *A) {
    if (R->getPrintedName() != A->getPrintedName())
      return false;
    if (R->getKind() == SDKNodeKind::DeclType &&
        A->getKind() == SDKNodeKind::DeclTypeAlias) {
      foundMatch(R, A, NodeMatchReason::TypeToTypeAlias);
      return true;
    } else {
      return false;
    }
  }

  bool detectModernizeEnum(SDKNodeDecl *R, SDKNodeDecl *A) {
    if (!isAnonymousEnum(R) || !isNominalEnum(A))
      return false;

    auto LastPartOfR = getLastPartOfUsr(R);
    if (!LastPartOfR)
      return false;

    for (auto Child : A->getChildren()) {
      if (auto VC = dyn_cast<SDKNodeDeclVar>(Child)) {
      auto LastPartOfA = getLastPartOfUsr(VC);
        if (LastPartOfA && LastPartOfR.getValue() == LastPartOfA.getValue()) {
          std::string FullName = (llvm::Twine(A->getName()) + "." +
            Child->getName()).str();
          R->annotate(NodeAnnotation::ModernizeEnum,
                      R->getSDKContext().buffer(FullName));
          foundMatch(R, A, NodeMatchReason::ModernizeEnum);
          return true;
        }
      }
    }
    return false;
  }

  bool detectSameAnonymousEnum(SDKNodeDecl *R, SDKNodeDecl *A) {
    if (!isAnonymousEnum(R) || !isAnonymousEnum(A))
      return false;
    auto LastR = getLastPartOfUsr(R);
    auto LastA = getLastPartOfUsr(A);
    if (LastR && LastA && LastR.getValue() == LastA.getValue()) {
      foundMatch(R, A, NodeMatchReason::Name);
      return true;
    }
    return false;
  }

  static bool isNameTooSimple(StringRef N) {
    static std::vector<std::string> SimpleNames = {"unit", "data", "log", "coding",
      "url", "name", "date", "datecomponents", "notification", "urlrequest",
      "personnamecomponents", "measurement", "dateinterval", "indexset"};
    return std::find(SimpleNames.begin(), SimpleNames.end(), N) !=
      SimpleNames.end();
  }

  static bool isSimilarName(StringRef L, StringRef R) {
    auto LL = L.lower();
    auto RR = R.lower();
    if (isNameTooSimple(LL) || isNameTooSimple(RR))
      return false;
    if (((StringRef)LL).startswith(RR) || ((StringRef)RR).startswith(LL))
      return true;
    if (((StringRef)LL).startswith((llvm::Twine("ns") + RR).str()) ||
        ((StringRef)RR).startswith((llvm::Twine("ns") + LL).str()))
      return true;
    if (((StringRef)LL).endswith(RR) || ((StringRef)RR).endswith(LL))
      return true;
    return false;
  }

  /// Whether two decls of different decl kinds can be considered as rename.
  static bool isDeclKindCrossable(DeclKind DK1, DeclKind DK2, bool First) {
    if (DK1 == DK2)
      return true;
    if (DK1 == DeclKind::Var && DK2 == DeclKind::EnumElement)
      return true;
    return First && isDeclKindCrossable(DK2, DK1, false);
  }

  static bool isRename(NodePtr L, NodePtr R) {
    if (L->getKind() != R->getKind())
      return false;
    if (isa<SDKNodeDeclConstructor>(L))
      return false;
    if (auto LD = dyn_cast<SDKNodeDecl>(L)) {
      auto *RD = R->getAs<SDKNodeDecl>();
      return isDeclKindCrossable(LD->getDeclKind(), RD->getDeclKind(), true) &&
        isSimilarName(LD->getName(), RD->getName());
    }
    return false;
  }

  static bool isBetterMatch(NodeMatch Match1, NodeMatch Match2) {
    assert(Match1.Left == Match2.Left);
    auto Left = Match1.Left;
    auto *M1Right = Match1.Right->getAs<SDKNodeDecl>();
    auto *M2Right = Match2.Right->getAs<SDKNodeDecl>();

    // Consider non-deprecated nodes better matches.
    auto Dep1 = M1Right->isDeprecated();
    auto Dep2 = M2Right->isDeprecated();
    if (Dep1 ^ Dep2) {
      return Dep2;
    }

    // If two names are identical, measure whose printed names is closer.
    if (M1Right->getName() == M2Right->getName()) {
      return
        M1Right->getPrintedName().edit_distance(Left->getPrintedName()) <
        M2Right->getPrintedName().edit_distance(Left->getPrintedName());
    }

#define DIST(A, B) (std::max(A, B) - std::min(A, B))
    return
      DIST(Left->getName().size(), Match1.Right->getName().size()) <
      DIST(Left->getName().size(), Match2.Right->getName().size());
#undef DIST
  }

  void foundMatch(NodePtr R, NodePtr A, NodeMatchReason Reason) override {
    Listener.foundMatch(R, A, Reason);
    RemovedMatched.push_back(R);
    AddedMatched.push_back(A);
  }

public:
  RemovedAddedNodeMatcher(NodeVector &Removed, NodeVector &Added,
                          MatchedNodeListener &Listener) : Removed(Removed),
                            Added(Added), Listener(Listener) {}

  void match() override {
    auto IsDecl = [](NodePtr P) { return isa<SDKNodeDecl>(P); };
    for (auto R : SDKNodeVectorViewer(Removed, IsDecl)) {
      for (auto A : SDKNodeVectorViewer(Added, IsDecl)) {
        auto RD = R->getAs<SDKNodeDecl>();
        auto AD = A->getAs<SDKNodeDecl>();
        if (detectFuncToProperty(RD, AD) || detectModernizeEnum(RD, AD) ||
            detectSameAnonymousEnum(RD, AD) || detectTypeAliasChange(RD, AD)) {
          break;
        }
      }
    }

    // Rename detection starts.
    NodeVector RenameLeft;
    NodeVector RenameRight;

    for (auto Remain : Removed) {
      if (!contains(RemovedMatched, Remain))
        RenameLeft.push_back(Remain);
    }

    for (auto Remain : Added) {
      if (!contains(AddedMatched, Remain))
        RenameRight.push_back(Remain);
    }

    BestMatchMatcher RenameMatcher(RenameLeft, RenameRight, isRename,
                                   isBetterMatch, NodeMatchReason::Name, *this);
    RenameMatcher.match();
    // Rename detection ends.

    handleUnmatch(RemovedMatched, Removed, true);
    handleUnmatch(AddedMatched, Added, false);
  }
};

// Given two NodeVector, this matches SDKNode by the their names; only Nodes with
// the identical names will be matched. We use this in name-sensitive but
// order-insensitive cases, such as matching types in a module.
class SameNameNodeMatcher : public NodeMatcher {
  ArrayRef<SDKNode*> Left;
  ArrayRef<SDKNode*> Right;
  MatchedNodeListener &Listener;

  enum class NameMatchKind {
    USR,
    PrintedName,
    PrintedNameAndUSR,
  };

  static bool isUSRSame(SDKNode *L, SDKNode *R) {
    auto *LD = dyn_cast<SDKNodeDecl>(L);
    auto *RD = dyn_cast<SDKNodeDecl>(R);
    if (!LD || !RD)
      return false;
    return LD->getUsr() == RD->getUsr();
  }

  // Given two SDK nodes, figure out the reason for why they have the same name.
  Optional<NameMatchKind> getNameMatchKind(SDKNode *L, SDKNode *R) {
    if (L->getKind() != R->getKind())
      return None;
    auto NameEqual = L->getPrintedName() == R->getPrintedName();
    auto UsrEqual = isUSRSame(L, R);
    if (NameEqual && UsrEqual)
      return NameMatchKind::PrintedNameAndUSR;
    else if (NameEqual)
      return NameMatchKind::PrintedName;
    else if (UsrEqual)
      return NameMatchKind::USR;
    else
      return None;
  }

  struct NameMatchCandidate {
    SDKNode *Node;
    NameMatchKind Kind;
  };

  // Get the priority for the favored name match kind. Favored name match kind
  // locats before less favored ones.
  ArrayRef<NameMatchKind> getNameMatchKindPriority(SDKNodeKind Kind) {
    if (Kind == SDKNodeKind::DeclFunction) {
      static NameMatchKind FuncPriority[] = { NameMatchKind::PrintedNameAndUSR,
                                              NameMatchKind::USR,
                                              NameMatchKind::PrintedName };
      return FuncPriority;
    } else {
      static NameMatchKind OtherPriority[] = { NameMatchKind::PrintedNameAndUSR,
                                               NameMatchKind::PrintedName,
                                               NameMatchKind::USR };
      return OtherPriority;
    }
  }

  // Given a list and a priority, find the best matched candidate SDK node.
  SDKNode* findBestNameMatch(ArrayRef<NameMatchCandidate> Candidates,
                             ArrayRef<NameMatchKind> Kinds) {
    for (auto Kind : Kinds)
      for (auto &Can : Candidates)
        if (Kind == Can.Kind)
          return Can.Node;
    return nullptr;
  }

public:
  SameNameNodeMatcher(ArrayRef<SDKNode*> Left, ArrayRef<SDKNode*> Right,
                      MatchedNodeListener &Listener) : Left(Left), Right(Right),
                                                       Listener(Listener) {}
  void match() override ;
};

void SameNameNodeMatcher::match() {
  NodeVector MatchedRight;
  NodeVector Removed;
  NodeVector Added;

  for (auto *LN : Left) {

    // This collects all the candidates that can match with LN.
    std::vector<NameMatchCandidate> Candidates;
    for (auto *RN : Right) {

      // If RN has matched before, ignore it.
      if (contains(MatchedRight, RN))
        continue;

      // If LN and RN have the same name for some reason, keep track of RN.
      if (auto Kind = getNameMatchKind(LN, RN))
        Candidates.push_back({RN, Kind.getValue()});
    }

    // Try to find the best match among all the candidates by the priority name
    // match kind list.
    if (auto Match = findBestNameMatch(Candidates,
                                    getNameMatchKindPriority(LN->getKind()))) {
      Listener.foundMatch(LN, Match, NodeMatchReason::Name);
      MatchedRight.push_back(Match);
    } else {
      Removed.push_back(LN);
    }
  }
  for (auto &R : Right) {
    if (!contains(MatchedRight, R)) {
      Added.push_back(R);
    }
  }
  RemovedAddedNodeMatcher RAMatcher(Removed, Added, Listener);
  RAMatcher.match();
}

// The recursive version of sequential matcher. We do not only match two vectors
// of NodePtr but also their descendents.
class SequentialRecursiveMatcher : public NodeMatcher {
  NodePtr &Left;
  NodePtr &Right;
  MatchedNodeListener &Listener;

  void matchInternal(NodePtr L, NodePtr R) {
    Listener.foundMatch(L, R, NodeMatchReason::Sequential);
    if (!L || !R)
      return;
    for (unsigned I = 0; I < std::max(L->getChildrenCount(),
                                      R->getChildrenCount()); ++ I) {
      auto Left = I < L->getChildrenCount() ? L->childAt(I) : nullptr;
      auto Right = I < R->getChildrenCount() ? R->childAt(I): nullptr;
      matchInternal(Left, Right);
    }
  }

public:
  SequentialRecursiveMatcher(NodePtr &Left, NodePtr &Right,
                             MatchedNodeListener &Listener) : Left(Left),
                              Right(Right), Listener(Listener) {}
  void match() override {
    matchInternal(Left, Right);
  }
};


// This is the interface of all passes on the given trees rooted at Left and Right.
class SDKTreeDiffPass {
public:
  virtual void pass(NodePtr Left, NodePtr Right) = 0;
  virtual ~SDKTreeDiffPass() {}
};

static void detectRename(SDKNode *L, SDKNode *R) {
  if (L->getKind() == R->getKind() && isa<SDKNodeDecl>(L) &&
      L->getPrintedName() != R->getPrintedName()) {
    L->annotate(NodeAnnotation::Rename);
    L->annotate(NodeAnnotation::RenameOldName, L->getPrintedName());
    L->annotate(NodeAnnotation::RenameNewName, R->getPrintedName());
  }
}

static bool isOwnershipEquivalent(ReferenceOwnership Left,
                                  ReferenceOwnership Right) {
  if (Left == Right)
    return true;
  if (Left == ReferenceOwnership::Unowned && Right == ReferenceOwnership::Weak)
    return true;
  if (Left == ReferenceOwnership::Weak && Right == ReferenceOwnership::Unowned)
    return true;
  return false;
}
}// End of anonymous namespace

void swift::ide::api::SDKNodeDeclType::diagnose(SDKNode *Right) {
  SDKNodeDecl::diagnose(Right);
  auto *R = dyn_cast<SDKNodeDeclType>(Right);
  if (!R)
    return;
  auto &Diags = Ctx.getDiags();

  if (getDeclKind() != R->getDeclKind()) {
    Diags.diagnose(SourceLoc(), diag::decl_kind_changed, getScreenInfo(),
                   getDeclKindStr(R->getDeclKind()));
    return;
  }

  assert(getDeclKind() == R->getDeclKind());
  auto DKind = getDeclKind();
  switch (DKind) {
  case DeclKind::Class: {
    auto LSuperClass = getSuperClassName();
    auto RSuperClass = R->getSuperClassName();
    if (!LSuperClass.empty() && LSuperClass != RSuperClass) {
      if (RSuperClass.empty()) {
        Diags.diagnose(SourceLoc(), diag::super_class_removed, getScreenInfo(),
                       LSuperClass);
      } else if (!contains(R->getClassInheritanceChain(), LSuperClass)) {
        Diags.diagnose(SourceLoc(), diag::super_class_changed, getScreenInfo(),
                       LSuperClass, RSuperClass);
      }
    }
    break;
  }
  default:
    break;
  }
}

void swift::ide::api::SDKNodeDeclAbstractFunc::diagnose(SDKNode *Right) {
  SDKNodeDecl::diagnose(Right);
  auto *R = dyn_cast<SDKNodeDeclAbstractFunc>(Right);
  if (!R)
    return;
  auto &Diags = Ctx.getDiags();

  if (!isThrowing() && R->isThrowing()) {
    Diags.diagnose(SourceLoc(), diag::decl_new_attr, getScreenInfo(),
                   Ctx.buffer("throwing"));
  }
}

void swift::ide::api::SDKNodeDeclFunction::diagnose(SDKNode *Right) {
  SDKNodeDeclAbstractFunc::diagnose(Right);
  auto *R = dyn_cast<SDKNodeDeclFunction>(Right);
  if (!R)
    return;
  auto &Diags = Ctx.getDiags();
  if (getSelfAccessKind() != R->getSelfAccessKind()) {
    Diags.diagnose(SourceLoc(), diag::func_self_access_change, getScreenInfo(),
                   getSelfAccessKind(), R->getSelfAccessKind());
  }
  if (Ctx.checkingABI()) {
    if (hasFixedBinaryOrder() != R->hasFixedBinaryOrder()) {
      Ctx.getDiags().diagnose(SourceLoc(), diag::func_has_fixed_order_change,
                              getScreenInfo(), hasFixedBinaryOrder());
    }
  }
}

void swift::ide::api::SDKNodeDeclSubscript::diagnose(SDKNode *Right) {
  SDKNodeDeclAbstractFunc::diagnose(Right);
  auto *R = dyn_cast<SDKNodeDeclSubscript>(Right);
  if (!R)
    return;
  if (hasSetter() && !R->hasSetter()) {
    Ctx.getDiags().diagnose(SourceLoc(), diag::removed_setter,
                            getScreenInfo());
  }
}

void swift::ide::api::SDKNodeDecl::diagnose(SDKNode *Right) {
  SDKNode::diagnose(Right);
  auto *RD = dyn_cast<SDKNodeDecl>(Right);
  if (!RD)
    return;
  auto &Diags = Ctx.getDiags();
  detectRename(this, RD);
  if (isOpen() && !RD->isOpen()) {
    Diags.diagnose(SourceLoc(), diag::no_longer_open, getScreenInfo());
  }

  // Diagnose static attribute change.
  if (isStatic() ^ RD->isStatic()) {
    Diags.diagnose(SourceLoc(), diag::decl_new_attr, getScreenInfo(),
                   Ctx.buffer(isStatic() ? "not static" : "static"));
  }

  // Diagnose ownership change.
  if (!isOwnershipEquivalent(getReferenceOwnership(),
                             RD->getReferenceOwnership())) {
    auto getOwnershipDescription = [&](swift::ReferenceOwnership O) {
      if (O == ReferenceOwnership::Strong)
        return Ctx.buffer("strong");
      return keywordOf(O);
    };
    Diags.diagnose(SourceLoc(), diag::decl_attr_change, getScreenInfo(),
                   getOwnershipDescription(getReferenceOwnership()),
                   getOwnershipDescription(RD->getReferenceOwnership()));
  }
  // Diagnose generic signature change
  if (getGenericSignature() != RD->getGenericSignature()) {
    Diags.diagnose(SourceLoc(), diag::generic_sig_change, getScreenInfo(),
                   getGenericSignature(), RD->getGenericSignature());
  }
  if (isOptional() != RD->isOptional()) {
    if (Ctx.checkingABI()) {
      // Both adding/removing optional is ABI-breaking.
      Diags.diagnose(SourceLoc(), diag::optional_req_changed,
                     getScreenInfo(), isOptional());
    } else if (isOptional()) {
      // Removing optional is source-breaking.
      Diags.diagnose(SourceLoc(), diag::optional_req_changed,
                     getScreenInfo(), isOptional());
    }
  }

  // Check if some attributes with ABI/API-impact have been added/removed.
  for (auto &Info: Ctx.getBreakingAttributeInfo()) {
    if (hasDeclAttribute(Info.Kind) != RD->hasDeclAttribute(Info.Kind)) {
      auto Desc = hasDeclAttribute(Info.Kind) ?
      Ctx.buffer((llvm::Twine("without ") + Info.Content).str()):
      Ctx.buffer((llvm::Twine("with ") + Info.Content).str());
      Diags.diagnose(SourceLoc(), diag::decl_new_attr, getScreenInfo(),
                     Desc);
    }
  }

  if (Ctx.checkingABI()) {
    if (hasFixedBinaryOrder() && RD->hasFixedBinaryOrder() &&
        getFixedBinaryOrder() != RD->getFixedBinaryOrder()) {
      Ctx.getDiags().diagnose(SourceLoc(), diag::decl_reorder,
                              getScreenInfo(),
                              getFixedBinaryOrder(),
                              RD->getFixedBinaryOrder());
    }
  }
}

void swift::ide::api::SDKNodeDeclOperator::diagnose(SDKNode *Right) {
  SDKNodeDecl::diagnose(Right);
  auto *RO = dyn_cast<SDKNodeDeclOperator>(Right);
  if (!RO)
    return;
  if (getDeclKind() != RO->getDeclKind()) {
    Ctx.getDiags().diagnose(SourceLoc(), diag::decl_kind_changed, getScreenInfo(),
                            getDeclKindStr(RO->getDeclKind()));
  }
}

void swift::ide::api::SDKNodeDeclVar::diagnose(SDKNode *Right) {
  SDKNodeDecl::diagnose(Right);
  auto *RV = dyn_cast<SDKNodeDeclVar>(Right);
  if (!RV)
    return;
  if (getSetter() && !RV->getSetter()) {
    Ctx.getDiags().diagnose(SourceLoc(), diag::removed_setter,
                            getScreenInfo());
  }
  if (Ctx.checkingABI()) {
    if (hasFixedBinaryOrder() != RV->hasFixedBinaryOrder()) {
      Ctx.getDiags().diagnose(SourceLoc(), diag::var_has_fixed_order_change,
                              getScreenInfo(), hasFixedBinaryOrder());
    }
    if (isLet() != RV->isLet()) {
      Ctx.getDiags().diagnose(SourceLoc(), diag::var_let_changed,
                              getScreenInfo(),
                              isLet());
    }
  }
}

static bool shouldDiagnoseType(SDKNodeType *T) {
  return T->isTopLevelType();
}

void swift::ide::api::SDKNodeType::diagnose(SDKNode *Right) {
  SDKNode::diagnose(Right);
  auto &Diags = Ctx.getDiags();
  auto *RT = dyn_cast<SDKNodeType>(Right);
  if (!RT || !shouldDiagnoseType(this))
    return;
  assert(isTopLevelType());

  // Diagnose type witness changes when diagnosing ABI breakages.
  if (auto *Wit = dyn_cast<SDKNodeTypeWitness>(getParent())) {
    auto *Conform = Wit->getParent()->getAs<SDKNodeConformance>();
    if (Ctx.checkingABI() && getPrintedName() != RT->getPrintedName()) {
      Diags.diagnose(SourceLoc(), diag::type_witness_change,
                     Conform->getNominalTypeDecl()->getScreenInfo(),
                     Wit->getWitnessedTypeName(),
                     getPrintedName(), RT->getPrintedName());
    }
    return;
  }

  StringRef Descriptor = getTypeRoleDescription();
  assert(isa<SDKNodeDecl>(getParent()));
  auto LParent = cast<SDKNodeDecl>(getParent());
  assert(LParent->getKind() == RT->getParent()->getAs<SDKNodeDecl>()->getKind());

  if (getPrintedName() != RT->getPrintedName()) {
    Diags.diagnose(SourceLoc(), diag::decl_type_change, LParent->getScreenInfo(),
                   Descriptor, getPrintedName(), RT->getPrintedName());
  }

  if (hasDefaultArgument() && !RT->hasDefaultArgument()) {
    Diags.diagnose(SourceLoc(), diag::default_arg_removed,
                   LParent->getScreenInfo(), Descriptor);
  }
  if (getParamValueOwnership() != RT->getParamValueOwnership()) {
    Diags.diagnose(SourceLoc(), diag::param_ownership_change,
                   getParent()->getAs<SDKNodeDecl>()->getScreenInfo(),
                   getTypeRoleDescription(),
                   getParamValueOwnership(),
                   RT->getParamValueOwnership());
  }
}

void swift::ide::api::SDKNodeTypeFunc::diagnose(SDKNode *Right) {
  SDKNode::diagnose(Right);
  auto &Diags = Ctx.getDiags();
  auto *RT = dyn_cast<SDKNodeTypeFunc>(Right);
  if (!RT || !shouldDiagnoseType(this))
    return;
  assert(isTopLevelType());
  if (Ctx.checkingABI() && isEscaping() != RT->isEscaping()) {
    Diags.diagnose(SourceLoc(), diag::func_type_escaping_changed,
                   getParent()->getAs<SDKNodeDecl>()->getScreenInfo(),
                   getTypeRoleDescription(),
                   isEscaping());
  }
}

namespace {
// This is first pass on two given SDKNode trees. This pass removes the common part
// of two versions of SDK, leaving only the changed part.
class PrunePass : public MatchedNodeListener, public SDKTreeDiffPass {

  static void removeCommon(NodeVector &Left, NodeVector &Right) {
    NodeVector LeftMinusRight, RightMinusLeft;
    nodeSetDifference(Left, Right, LeftMinusRight, RightMinusLeft);
    Left = LeftMinusRight;
    Right = RightMinusLeft;
  }

  static void removeCommonChildren(NodePtr Left, NodePtr Right) {
    removeCommon(Left->getChildren(), Right->getChildren());
  }

  SDKContext &Ctx;
  UpdatedNodesMap &UpdateMap;
  llvm::StringSet<> ProtocolReqWhitelist;

  static void printSpaces(llvm::raw_ostream &OS, SDKNode *N) {
    assert(N);
    for (auto P = N; !isa<SDKNodeRoot>(P); P = P->getParent())
      OS << "        ";
  }

  static void debugMatch(SDKNode *Left, SDKNode *Right, NodeMatchReason Reason,
                         llvm::raw_ostream &OS) {
    if (Left && !isa<SDKNodeDecl>(Left))
      return;
    if (Right && !isa<SDKNodeDecl>(Right))
      return;
    StringRef Arrow = "  <-------->  ";
    switch (Reason) {
    case NodeMatchReason::Added:
      printSpaces(OS, Right);
      OS << "<NULL>" << Arrow << Right->getPrintedName() << "\n";
      return;
    case NodeMatchReason::Removed:
      printSpaces(OS, Left);
      OS << Left->getPrintedName() << Arrow << "<NULL>\n";
      return;
    default:
      printSpaces(OS, Left);
      OS << Left->getPrintedName() << Arrow << Right->getPrintedName() << "\n";
      return;
    }
  }

public:
  PrunePass(SDKContext &Ctx): Ctx(Ctx), UpdateMap(Ctx.getNodeUpdateMap()) {}
  PrunePass(SDKContext &Ctx, llvm::StringSet<> prWhitelist):
    Ctx(Ctx),
    UpdateMap(Ctx.getNodeUpdateMap()),
    ProtocolReqWhitelist(std::move(prWhitelist)) {}

  void foundMatch(NodePtr Left, NodePtr Right, NodeMatchReason Reason) override {
    if (options::Verbose)
      debugMatch(Left, Right, Reason, llvm::errs());
    switch (Reason) {
    case NodeMatchReason::Added:
      assert(!Left);
      Right->annotate(NodeAnnotation::Added);
      if (Ctx.checkingABI()) {
        // Any order-important decl added to a non-resilient type breaks ABI.
        if (auto *D = dyn_cast<SDKNodeDecl>(Right)) {
          if (D->hasFixedBinaryOrder()) {
            Ctx.getDiags().diagnose(SourceLoc(), diag::decl_added,
                                    D->getScreenInfo());
          }
        }
      }
      // Complain about added protocol requirements
      if (auto *D = dyn_cast<SDKNodeDecl>(Right)) {
        if (D->isNonOptionalProtocolRequirement()) {
          bool ShouldComplain = !D->isOverriding();
          // We should allow added associated types with default.
          if (auto ATD = dyn_cast<SDKNodeDeclAssociatedType>(D)) {
            if (ATD->getDefault())
              ShouldComplain = false;
          }
          if (ShouldComplain &&
              ProtocolReqWhitelist.count(D->getParent()->getAs<SDKNodeDecl>()->getFullyQualifiedName())) {
            // Ignore protocol requirement additions if the protocol has been added
            // to the whitelist.
            ShouldComplain = false;
          }
          if (ShouldComplain)
            Ctx.getDiags().diagnose(SourceLoc(), diag::protocol_req_added,
                                    D->getScreenInfo());
        }
      }
      // Diagnose an inherited protocol has been added.
      if (auto *Conf = dyn_cast<SDKNodeConformance>(Right)) {
        auto *TD = Conf->getNominalTypeDecl();
        if (TD->isProtocol()) {
          Ctx.getDiags().diagnose(SourceLoc(), diag::conformance_added,
                                  TD->getScreenInfo(),
                                  Conf->getName());
        }
      }

      return;
    case NodeMatchReason::Removed:
      assert(!Right);
      Left->annotate(NodeAnnotation::Removed);
      if (auto *LT = dyn_cast<SDKNodeType>(Left)) {
        if (auto *AT = dyn_cast<SDKNodeDeclAssociatedType>(LT->getParent())) {
          Ctx.getDiags().diagnose(SourceLoc(),
                                  diag::default_associated_type_removed,
                                  AT->getScreenInfo(), LT->getPrintedName());
        }
      }
      // Diagnose a protocol conformance has been removed.
      if (auto *Conf = dyn_cast<SDKNodeConformance>(Left)) {
        auto *TD = Conf->getNominalTypeDecl();
        Ctx.getDiags().diagnose(SourceLoc(), diag::conformance_removed,
                                TD->getScreenInfo(), Conf->getName(),
                                TD->isProtocol());
      }
      return;
    case NodeMatchReason::FuncToProperty:
    case NodeMatchReason::ModernizeEnum:
    case NodeMatchReason::TypeToTypeAlias:
      Left->annotate(NodeAnnotation::Removed);
      Right->annotate(NodeAnnotation::Added);
      return;
    case NodeMatchReason::Root:
    case NodeMatchReason::Name:
    case NodeMatchReason::Sequential:
      break;
    }
    assert(Left && Right);
    Left->annotate(NodeAnnotation::Updated);
    Right->annotate(NodeAnnotation::Updated);
    // Push the updated node to the map for future reference.
    UpdateMap.insert(Left, Right);

    Left->diagnose(Right);
    if (Left->getKind() != Right->getKind()) {
      assert(isa<SDKNodeType>(Left) && isa<SDKNodeType>(Right) &&
        "only type nodes can match across kinds.");
      return;
    }
    assert(Left->getKind() == Right->getKind());
    SDKNodeKind Kind = Left->getKind();
    assert(Kind == SDKNodeKind::Root || *Left != *Right);
    switch(Kind) {
    case SDKNodeKind::DeclType: {
      // Remove common conformances and diagnose conformance changes.
      auto LConf = cast<SDKNodeDeclType>(Left)->getConformances();
      auto RConf = cast<SDKNodeDeclType>(Right)->getConformances();
      removeCommon(LConf, RConf);
      SameNameNodeMatcher(LConf, RConf, *this).match();
      LLVM_FALLTHROUGH;
    }
    case SDKNodeKind::Conformance:
    case SDKNodeKind::Root: {
      // If the matched nodes are both modules, remove the contained
      // type decls that are identical. If the matched nodes are both type decls,
      // remove the contained function decls that are identical.
      removeCommonChildren(Left, Right);
      SameNameNodeMatcher SNMatcher(Left->getChildren(), Right->getChildren(), *this);
      SNMatcher.match();
      break;
    }
    case SDKNodeKind::TypeWitness:
    case SDKNodeKind::DeclOperator:
    case SDKNodeKind::DeclSubscript:
    case SDKNodeKind::DeclAssociatedType:
    case SDKNodeKind::DeclFunction:
    case SDKNodeKind::DeclSetter:
    case SDKNodeKind::DeclGetter:
    case SDKNodeKind::DeclConstructor:
    case SDKNodeKind::DeclTypeAlias:
    case SDKNodeKind::TypeFunc:
    case SDKNodeKind::TypeNominal:
    case SDKNodeKind::TypeAlias: {
      // If matched nodes are both function/var/TypeAlias decls, mapping their
      // parameters sequentially.
      SequentialNodeMatcher SNMatcher(Left->getChildren(), Right->getChildren(),
                                      *this);
      SNMatcher.match();
      break;
    }

    case SDKNodeKind::DeclVar: {
      auto &LC = *Left->getAs<SDKNodeDeclVar>()->getType();
      auto &RC = *Right->getAs<SDKNodeDeclVar>()->getType();
      if (LC != RC)
        foundMatch(&LC, &RC, NodeMatchReason::Sequential);
      break;
    }
    }
  }

  void pass(NodePtr Left, NodePtr Right) override {
    foundMatch(Left, Right, NodeMatchReason::Root);
  }
};


// Class to build up a diff of structurally different nodes, based on the given
// USR map for the left (original) side of the diff, based on parent types.
class TypeMemberDiffFinder : public SDKNodeVisitor {
  friend class SDKNode; // for visit()

  SDKNodeRoot *diffAgainst;

  // Vector of {givenNodePtr, diffAgainstPtr}
  NodePairVector TypeMemberDiffs;

  void visit(NodePtr node) override {
    // Skip nodes that we don't have a correlate for
    auto declNode = dyn_cast<SDKNodeDecl>(node);
    if (!declNode)
      return;
    auto usr = declNode->getUsr();
    auto &usrName = usr;

    // If we can find no nodes in the other tree with the same usr, abort.
    auto candidates = diffAgainst->getDescendantsByUsr(usrName);
    if (candidates.empty())
      return;

    // If any of the candidates has the same kind and name with the node, we
    // shouldn't continue.
    for (auto Can : candidates) {
      if (Can->getKind() == declNode->getKind() &&
          Can->getAs<SDKNodeDecl>()->getFullyQualifiedName() ==
            declNode->getFullyQualifiedName())
        return;
    }

    auto diffNode = candidates.front();
    assert(node && diffNode && "nullptr visited?");
    auto nodeParent = node->getParent();
    auto diffParent = diffNode->getParent();
    assert(nodeParent && diffParent && "trying to check Root?");

    // Move from global variable to a member variable.
    if (nodeParent->getKind() == SDKNodeKind::DeclType &&
        diffParent->getKind() == SDKNodeKind::Root)
      TypeMemberDiffs.insert({diffNode, node});

    // Move from a member variable to global variable.
    if (nodeParent->getKind() == SDKNodeKind::Root &&
        diffParent->getKind() == SDKNodeKind::DeclType)
      TypeMemberDiffs.insert({diffNode, node});

    // Move from a member variable to another member variable
    if (nodeParent->getKind() == SDKNodeKind::DeclType &&
        diffParent->getKind() == SDKNodeKind::DeclType &&
        declNode->isStatic())
      TypeMemberDiffs.insert({diffNode, node});
    // Move from a getter/setter function to a property
    else if (node->getKind() == SDKNodeKind::DeclGetter &&
             diffNode->getKind() == SDKNodeKind::DeclFunction &&
             node->isNameValid()) {
      diffNode->annotate(NodeAnnotation::Rename);
      diffNode->annotate(NodeAnnotation::RenameOldName,
                         diffNode->getPrintedName());
      diffNode->annotate(NodeAnnotation::RenameNewName,
                         node->getParent()->getPrintedName());
    }
  }

public:
  TypeMemberDiffFinder(SDKNodeRoot *diffAgainst):
    diffAgainst(diffAgainst) {}

  void findDiffsFor(NodePtr ptr) { SDKNode::preorderVisit(ptr, *this); }

  const NodePairVector &getDiffs() const {
    return TypeMemberDiffs;
  }

  void dump(llvm::raw_ostream &) const;
  void dump() const { dump(llvm::errs()); }

private:
  TypeMemberDiffFinder(const TypeMemberDiffFinder &) = delete;
  TypeMemberDiffFinder &operator=(const TypeMemberDiffFinder &) = delete;

};

/// This is to find type alias of raw types being changed to RawRepresentable.
/// e.g. AttributeName was a typealias of String in the old SDK however it becomes
/// a RawRepresentable struct in the new SDK.
/// This happens typically when we use apinotes to preserve API stability by
/// using SwiftWrapper:none in the old SDK.
class TypeAliasDiffFinder: public SDKNodeVisitor {
  SDKNodeRoot *leftRoot;
  SDKNodeRoot *rightRoot;
  NodeMap &result;

  static bool checkTypeMatch(const SDKNodeType* aliasType,
      const SDKNodeType* rawType) {
    StringRef Left = aliasType->getPrintedName();
    StringRef Right = rawType->getPrintedName();
    if (Left == "NSString" && Right == "String")
      return true;
    if (Left == "String" && Right == "String")
      return true;
    if (Left == "Int" && Right == "Int")
      return true;
    if (Left == "UInt" && Right == "UInt")
      return true;
    return false;
  }

  void visit(NodePtr node) override {
    auto alias = dyn_cast<SDKNodeDeclTypeAlias>(node);
    if (!alias)
      return;
    const SDKNodeType* aliasType = alias->getUnderlyingType();
    for (auto *counter: rightRoot->getDescendantsByUsr(alias->getUsr())) {
      if (auto DT = dyn_cast<SDKNodeDeclType>(counter)) {
        if (auto *rawType = DT->getRawValueType()) {
          if (checkTypeMatch(aliasType, rawType)) {
            result.insert({alias, DT});
            return;
          }
        }
      }
    }
  }
public:
  TypeAliasDiffFinder(SDKNodeRoot *leftRoot, SDKNodeRoot *rightRoot,
    NodeMap &result): leftRoot(leftRoot), rightRoot(rightRoot),
      result(result) {}

  void search() {
    SDKNode::preorderVisit(leftRoot, *this);
  }
};

// Given a condition, search whether a node satisfies that condition exists
// in a tree.
class SearchVisitor : public SDKNodeVisitor {
  bool isFound = false;
  llvm::function_ref<bool(NodePtr)> Predicate;

public:
  SearchVisitor(llvm::function_ref<bool(NodePtr)> Predicate) :
    Predicate(Predicate) {}

  void visit(NodePtr Node) override {
    isFound |= Predicate(Node);
  }

  bool search(NodePtr Node) {
    SDKNode::preorderVisit(Node, *this);
    return isFound;
  }
};

class InterfaceTypeChangeDetector {
  bool IsVisitingLeft;

#define ANNOTATE(Node, Counter, X, Y)                                          \
  auto ToAnnotate = IsVisitingLeft ? Node : Counter;                           \
  ToAnnotate->annotate(IsVisitingLeft ? X : Y);

  bool detectWrapOptional(SDKNodeType *Node, SDKNodeType *Counter) {
    if (Node->getTypeKind() != KnownTypeKind::Optional &&
        Node->getTypeKind() != KnownTypeKind::ImplicitlyUnwrappedOptional &&
        Counter->getTypeKind() == KnownTypeKind::Optional &&
        *Node == *Counter->getOnlyChild()) {
      ANNOTATE(Node, Counter, NodeAnnotation::WrapOptional,
               NodeAnnotation::UnwrapOptional)
      return true;
    }
    return false;
  }

  bool detectWrapImplicitOptional(SDKNodeType *Node, SDKNodeType *Counter) {
    if (Node->getTypeKind() != KnownTypeKind::Optional &&
        Node->getTypeKind() != KnownTypeKind::ImplicitlyUnwrappedOptional &&
        Counter->getTypeKind() == KnownTypeKind::ImplicitlyUnwrappedOptional &&
        *Node == *Counter->getOnlyChild()) {
      ANNOTATE(Node, Counter, NodeAnnotation::WrapImplicitOptional,
               NodeAnnotation::UnwrapOptional)
      return true;
    }

    return false;
  }

  bool detectOptionalUpdate(SDKNodeType *Node, SDKNodeType *Counter) {
    if (Node->getTypeKind() == KnownTypeKind::Optional &&
        Counter->getTypeKind() == KnownTypeKind::ImplicitlyUnwrappedOptional &&
        *Node->getOnlyChild() == *Counter->getOnlyChild()) {
      ANNOTATE(Node, Counter,
               NodeAnnotation::OptionalToImplicitOptional,
               NodeAnnotation::ImplicitOptionalToOptional)
      return true;
    }
    return false;
  }

  bool detectUnmanagedUpdate(SDKNodeType *Node, SDKNodeType *Counter) {
    if (IsVisitingLeft && Node->getTypeKind() == KnownTypeKind::Unmanaged &&
        Counter->getTypeKind() != KnownTypeKind::Unmanaged &&
        *Node->getOnlyChild() == *Counter) {
      Node->annotate(NodeAnnotation::UnwrapUnmanaged);
      return true;
    }
    return false;
  }

#undef ANNOTATE

  bool detectTypeRewritten(SDKNodeType *Node, SDKNodeType *Counter) {
    if (IsVisitingLeft &&
        Node->getPrintedName() != Counter->getPrintedName() &&
        (Node->getName() != Counter->getName() ||
         Node->getChildrenCount() != Counter->getChildrenCount())) {
      Node->annotate(NodeAnnotation::TypeRewritten);
      Node->annotate(NodeAnnotation::TypeRewrittenLeft, Node->getPrintedName());
      Node->annotate(NodeAnnotation::TypeRewrittenRight, 
                     Counter->getPrintedName());
      return true;
    }
    return false;
  }

  static bool isRawType(const SDKNodeType *T, StringRef &Raw) {
    if (auto Alias = dyn_cast<SDKNodeTypeAlias>(T)) {
      // In case this type is an alias of the raw type.
      return isRawType(Alias->getUnderlyingType(), Raw);
    }
    switch(T->getTypeKind()) {
    case KnownTypeKind::String:
    case KnownTypeKind::Int:
      Raw = T->getName();
      return true;
    default:
      return false;
    }
  }

  static StringRef getStringRepresentableChange(SDKNode *L, SDKNode *R,
                                                StringRef &Raw) {
    if (!isRawType(L->getAs<SDKNodeType>(), Raw))
      return StringRef();
    auto* RKey = dyn_cast<SDKNodeTypeNominal>(R);
    if (!RKey)
      return StringRef();
    if (Raw.empty())
      return StringRef();
    auto Results = RKey->getRootNode()->getDescendantsByUsr(RKey->getUsr());
    if (Results.empty())
      return StringRef();
    if (auto DT = dyn_cast<SDKNodeDeclType>(Results.front())) {
      if (DT->isConformingTo(KnownProtocolKind::RawRepresentable)) {
        return DT->getFullyQualifiedName();
      }
    }
    return StringRef();
  }

  static StringRef detectDictionaryKeyChangeInternal(SDKNodeType *L,
                                                     SDKNodeType *R,
                                                     StringRef &Raw) {
    if (L->getTypeKind() != KnownTypeKind::Dictionary ||
        R->getTypeKind() != KnownTypeKind::Dictionary)
      return StringRef();
    auto *Left = dyn_cast<SDKNodeTypeNominal>(L);
    auto *Right = dyn_cast<SDKNodeTypeNominal>(R);
    assert(Left && Right);
    assert(Left->getChildrenCount() == 2);
    assert(Right->getChildrenCount() == 2);
    return getStringRepresentableChange(*Left->getChildBegin(),
      *Right->getChildBegin(), Raw);
  }

  bool detectDictionaryKeyChange(SDKNodeType *L, SDKNodeType *R) {
    // We only care if this the top-level type node.
    if (!L->isTopLevelType() || !R->isTopLevelType())
      return false;
    StringRef Raw;
    StringRef KeyChangedTo;
    bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
      R->getTypeKind() == KnownTypeKind::Optional;
    if (HasOptional) {
      // Detect [String: Any]? to [StringRepresentableStruct: Any]? Chnage
      KeyChangedTo =
        detectDictionaryKeyChangeInternal(L->getOnlyChild()->getAs<SDKNodeType>(),
                                          R->getOnlyChild()->getAs<SDKNodeType>(),
                                          Raw);
    } else {
      // Detect [String: Any] to [StringRepresentableStruct: Any] Chnage
      KeyChangedTo = detectDictionaryKeyChangeInternal(L, R, Raw);
    }
    if (!KeyChangedTo.empty()) {
      if (IsVisitingLeft) {
        L->annotate(HasOptional ?
                    NodeAnnotation::OptionalDictionaryKeyUpdate :
                    NodeAnnotation::DictionaryKeyUpdate);
        L->annotate(NodeAnnotation::RawTypeLeft, Raw);
        L->annotate(NodeAnnotation::RawTypeRight, KeyChangedTo);
      } else {
        R->annotate(HasOptional ?
                    NodeAnnotation::RevertOptionalDictionaryKeyUpdate :
                    NodeAnnotation::RevertDictionaryKeyUpdate);
        R->annotate(NodeAnnotation::RawTypeLeft, KeyChangedTo);
        R->annotate(NodeAnnotation::RawTypeRight, Raw);
      }
      return true;
    }
    return false;
  }

  static StringRef detectArrayMemberChangeInternal(SDKNodeType *L,
      SDKNodeType *R, StringRef &Raw) {
    if (L->getTypeKind() != KnownTypeKind::Array ||
        R->getTypeKind() != KnownTypeKind::Array)
      return StringRef();
    auto *Left = dyn_cast<SDKNodeTypeNominal>(L);
    auto *Right = dyn_cast<SDKNodeTypeNominal>(R);
    assert(Left && Right);
    assert(Left->getChildrenCount() == 1);
    assert(Right->getChildrenCount() == 1);
    return getStringRepresentableChange(Left->getOnlyChild(),
      Right->getOnlyChild(), Raw);
  }

  bool detectArrayMemberChange(SDKNodeType* L, SDKNodeType *R) {
    // We only care if this the top-level type node.
    if (!L->isTopLevelType() || !R->isTopLevelType())
      return false;
    StringRef Raw;
    StringRef KeyChangedTo;
    bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
      R->getTypeKind() == KnownTypeKind::Optional;
    if (HasOptional) {
      // Detect [String]? to [StringRepresentableStruct]? Chnage
      KeyChangedTo =
        detectArrayMemberChangeInternal(L->getOnlyChild()->getAs<SDKNodeType>(),
                                        R->getOnlyChild()->getAs<SDKNodeType>(),
                                        Raw);
    } else {
      // Detect [String] to [StringRepresentableStruct] Chnage
      KeyChangedTo = detectArrayMemberChangeInternal(L, R, Raw);
    }
    if (!KeyChangedTo.empty()) {
      if (IsVisitingLeft) {
        L->annotate(HasOptional ?
                    NodeAnnotation::OptionalArrayMemberUpdate :
                    NodeAnnotation::ArrayMemberUpdate);
        L->annotate(NodeAnnotation::RawTypeLeft, Raw);
        L->annotate(NodeAnnotation::RawTypeRight, KeyChangedTo);
      } else {
        R->annotate(HasOptional ?
                    NodeAnnotation::RevertOptionalArrayMemberUpdate :
                    NodeAnnotation::RevertArrayMemberUpdate);
        R->annotate(NodeAnnotation::RawTypeLeft, KeyChangedTo);
        R->annotate(NodeAnnotation::RawTypeRight, Raw);
      }
      return true;
    }
    return false;
  }

  bool detectSimpleStringRepresentableUpdate(SDKNodeType *L, SDKNodeType *R) {
    if (!L->isTopLevelType() || !R->isTopLevelType())
      return false;
    StringRef KeyChangedTo;
    StringRef Raw;
    bool HasOptional = L->getTypeKind() == KnownTypeKind::Optional &&
        R->getTypeKind() == KnownTypeKind::Optional;
    if (HasOptional) {
      // Detect String? changes to StringRepresentableStruct? change.
      KeyChangedTo =
        getStringRepresentableChange(L->getOnlyChild()->getAs<SDKNodeType>(),
                                     R->getOnlyChild()->getAs<SDKNodeType>(),
                                     Raw);
    } else {
      // Detect String changes to StringRepresentableStruct change.
      KeyChangedTo = getStringRepresentableChange(L, R, Raw);
    }
    if (!KeyChangedTo.empty()) {
      if (IsVisitingLeft) {
        L->annotate(NodeAnnotation::RawTypeLeft, Raw);
        L->annotate(NodeAnnotation::RawTypeRight, KeyChangedTo);
        L->annotate(HasOptional ?
                    NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
                    NodeAnnotation::SimpleStringRepresentableUpdate);
      } else {
        R->annotate(NodeAnnotation::RawTypeLeft, KeyChangedTo);
        R->annotate(NodeAnnotation::RawTypeRight, Raw);
        R->annotate(HasOptional ?
                    NodeAnnotation::RevertSimpleOptionalStringRepresentableUpdate:
                    NodeAnnotation::RevertSimpleStringRepresentableUpdate);
      }
      return true;
    }
    return false;
  }

  bool isUnhandledCase(SDKNodeType *Node, SDKNodeType *Counter) {
    return Node->getTypeKind() == KnownTypeKind::Void ||
           Counter->getTypeKind() == KnownTypeKind::Void;
  }

  static void clearTypeRewritten(SDKNode *N) {
    if (!N->isAnnotatedAs(NodeAnnotation::TypeRewritten))
      return;
    N->removeAnnotate(NodeAnnotation::TypeRewritten);
    N->removeAnnotate(NodeAnnotation::TypeRewrittenLeft);
    N->removeAnnotate(NodeAnnotation::TypeRewrittenRight);
  }

public:
  InterfaceTypeChangeDetector(bool IsVisitingLeft):
    IsVisitingLeft(IsVisitingLeft) {}
  void detect(SDKNode *Left, SDKNode *Right) {
    auto *Node = dyn_cast<SDKNodeType>(Left);
    auto *Counter = dyn_cast<SDKNodeType>(Right);
    if (!Node || !Counter || isUnhandledCase(Node, Counter))
      return;
    if (detectWrapOptional(Node, Counter) ||
        detectOptionalUpdate(Node, Counter) ||
        detectWrapImplicitOptional(Node, Counter) ||
        detectUnmanagedUpdate(Node, Counter)) {

      // we may have detected type rewritten before (when visiting left),
      // so clear the annotation here.
      clearTypeRewritten(Node);
      clearTypeRewritten(Counter);
    } else {
      // Detect type re-written then.
      detectTypeRewritten(Node, Counter);
    }
    // The raw representable changes can co-exist with above attributes.
    auto Result = detectDictionaryKeyChange(Node, Counter) ||
      detectArrayMemberChange(Node, Counter) ||
      detectSimpleStringRepresentableUpdate(Node, Counter);
    (void) Result;
    return;
  }
};

class ChangeRefinementPass : public SDKTreeDiffPass, public SDKNodeVisitor {
  UpdatedNodesMap &UpdateMap;
  InterfaceTypeChangeDetector LeftDetector;
  InterfaceTypeChangeDetector RightDetector;
  InterfaceTypeChangeDetector *Detector;

public:
  ChangeRefinementPass(UpdatedNodesMap &UpdateMap) : UpdateMap(UpdateMap),
    LeftDetector(true), RightDetector(false), Detector(nullptr) {}

  void pass(NodePtr Left, NodePtr Right) override {

    // Post-order visit is necessary since we propagate annotations bottom-up
    Detector = &LeftDetector;
    SDKNode::postorderVisit(Left, *this);
    Detector = &RightDetector;
    SDKNode::postorderVisit(Right, *this);
  }

  void visit(NodePtr Node) override {
    assert(Detector);
    if (!Node || !Node->isAnnotatedAs(NodeAnnotation::Updated))
      return;
    auto *Counter = UpdateMap.findUpdateCounterpart(Node);
    Detector->detect(Node, Counter);
    return;
  }
};
} // end anonymous namespace

static void findTypeMemberDiffs(NodePtr leftSDKRoot, NodePtr rightSDKRoot,
                                TypeMemberDiffVector &out);

static void printNode(llvm::raw_ostream &os, NodePtr node) {
  os << "{" << node->getName() << " " << node->getKind() << " "
            << node->getPrintedName();
  if (auto F = dyn_cast<SDKNodeDeclAbstractFunc>(node)) {
    if (F->hasSelfIndex()) {
      os << " selfIndex: ";
      os << F->getSelfIndex();
    }
  }
  os << "}";
}

void TypeMemberDiffFinder::dump(llvm::raw_ostream &os) const {
  for (auto pair : getDiffs()) {
    os << " - ";
    printNode(os, pair.first);
    os << " parent: ";
    printNode(os, pair.first->getParent());

    os << "\n + ";
    printNode(os, pair.second);
    os << " parent: ";
    printNode(os, pair.second->getParent());
    os << "\n\n";
  }
}

namespace {

template<typename T>
void removeRedundantAndSort(std::vector<T> &Diffs) {
  std::set<T> DiffSet(Diffs.begin(), Diffs.end());
  Diffs.assign(DiffSet.begin(), DiffSet.end());
  std::sort(Diffs.begin(), Diffs.end());
}

template<typename T>
void serializeDiffs(llvm::raw_ostream &Fs, std::vector<T> &Diffs) {
  if (Diffs.empty())
    return;
  Fs << "\n";
  T::describe(Fs);
  for (auto &Diff : Diffs) {
    Diff.streamDef(Fs);
    Fs << "\n";
  }
  T::undef(Fs);
  Fs << "\n";
}

static bool isTypeChangeInterestedFuncNode(NodePtr Decl) {
  switch(Decl->getKind()) {
    case SDKNodeKind::DeclConstructor:
    case SDKNodeKind::DeclFunction:
      return true;
    default:
      return false;
  }
}

class DiffItemEmitter : public SDKNodeVisitor {
  DiffVector &AllItems;

  static bool isInterested(SDKNodeDecl* Decl, NodeAnnotation Anno) {
    switch (Anno) {
      case NodeAnnotation::WrapOptional:
      case NodeAnnotation::UnwrapOptional:
      case NodeAnnotation::ImplicitOptionalToOptional:
      case NodeAnnotation::OptionalToImplicitOptional:
      case NodeAnnotation::UnwrapUnmanaged:
      case NodeAnnotation::TypeRewritten:
        return isTypeChangeInterestedFuncNode(Decl) &&
        Decl->getParent()->getKind() == SDKNodeKind::DeclType;
      default:
        return true;
    }
  }

  bool doesAncestorHaveTypeRewritten() {
    return std::find_if(Ancestors.begin(), Ancestors.end(),[](NodePtr N) {
      return N->isAnnotatedAs(NodeAnnotation::TypeRewritten);
    }) != Ancestors.end();
  }

  static StringRef getLeftComment(NodePtr Node, NodeAnnotation Anno) {
    switch(Anno) {
      case NodeAnnotation::ArrayMemberUpdate:
      case NodeAnnotation::OptionalArrayMemberUpdate:
      case NodeAnnotation::DictionaryKeyUpdate:
      case NodeAnnotation::OptionalDictionaryKeyUpdate:
      case NodeAnnotation::SimpleStringRepresentableUpdate:
      case NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
      case NodeAnnotation::RevertArrayMemberUpdate:
      case NodeAnnotation::RevertOptionalArrayMemberUpdate:
      case NodeAnnotation::RevertDictionaryKeyUpdate:
      case NodeAnnotation::RevertOptionalDictionaryKeyUpdate:
      case NodeAnnotation::RevertSimpleStringRepresentableUpdate:
      case NodeAnnotation::RevertSimpleOptionalStringRepresentableUpdate:
        return Node->getAnnotateComment(NodeAnnotation::RawTypeLeft);
      case NodeAnnotation::TypeRewritten:
        return Node->getAnnotateComment(NodeAnnotation::TypeRewrittenLeft);
      case NodeAnnotation::Rename:
        return Node->getAnnotateComment(NodeAnnotation::RenameOldName);
      default:
        return StringRef();
    }
  }

  static StringRef getRightComment(NodePtr Node, NodeAnnotation Anno) {
    switch (Anno) {
      case NodeAnnotation::ArrayMemberUpdate:
      case NodeAnnotation::OptionalArrayMemberUpdate:
      case NodeAnnotation::DictionaryKeyUpdate:
      case NodeAnnotation::OptionalDictionaryKeyUpdate:
      case NodeAnnotation::SimpleStringRepresentableUpdate:
      case NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
      case NodeAnnotation::RevertArrayMemberUpdate:
      case NodeAnnotation::RevertOptionalArrayMemberUpdate:
      case NodeAnnotation::RevertDictionaryKeyUpdate:
      case NodeAnnotation::RevertOptionalDictionaryKeyUpdate:
      case NodeAnnotation::RevertSimpleStringRepresentableUpdate:
      case NodeAnnotation::RevertSimpleOptionalStringRepresentableUpdate:
        return Node->getAnnotateComment(NodeAnnotation::RawTypeRight);
      case NodeAnnotation::TypeRewritten:
        return Node->getAnnotateComment(NodeAnnotation::TypeRewrittenRight);
      case NodeAnnotation::ModernizeEnum:
        return Node->getAnnotateComment(NodeAnnotation::ModernizeEnum);
      case NodeAnnotation::Rename:
        return Node->getAnnotateComment(NodeAnnotation::RenameNewName);
      case NodeAnnotation::GetterToProperty:
      case NodeAnnotation::SetterToProperty:
        return Node->getAnnotateComment(NodeAnnotation::PropertyName);
      default:
        return StringRef();
    }
  }

  void handleAnnotations(NodePtr Node, SDKNodeDecl *NonTypeParent,
                         StringRef Index, ArrayRef<NodeAnnotation> Annotations) {
    for (auto Anno: Annotations) {
      if (isInterested(NonTypeParent, Anno) && Node->isAnnotatedAs(Anno)) {
        auto Kind = NonTypeParent->getKind();
        StringRef LC = getLeftComment(Node, Anno);
        StringRef RC = getRightComment(Node, Anno);
        AllItems.emplace_back(Kind, Anno, Index,
                              NonTypeParent->getUsr(), StringRef(), LC, RC,
                              NonTypeParent->getModuleName());
      }
    }
  }

  void visit(NodePtr Node) override {
    auto *Parent = dyn_cast<SDKNodeDecl>(Node);
    if (!Parent) {
      if (auto TN = dyn_cast<SDKNodeType>(Node)) {
        Parent = TN->getClosestParentDecl();
      }
    }

    if (!Parent)
      return;
    if (doesAncestorHaveTypeRewritten())
      return;

    handleAnnotations(Node, Parent,
                      isa<SDKNodeType>(Node) ? getIndexString(Node) : "0",
                      {
#define NODE_ANNOTATION_CHANGE_KIND(NAME) NodeAnnotation::NAME,
#include "swift/IDE/DigesterEnums.def"
                      });
  }

  StringRef getIndexString(NodePtr Node) {
    llvm::SmallString<32> Builder;
    std::vector<int> Indexes;
    collectIndexes(Node, Indexes);
    auto First = true;
    for (auto I : Indexes) {
      if (!First)
        Builder.append(":");
      else
        First = false;
      Builder.append(std::to_string(I));
    }
    return Node->getSDKContext().buffer(Builder.str());
  }

  void collectIndexes(NodePtr Node, std::vector<int> &Indexes) {
    for (unsigned I = Ancestors.size(); I > 0 && (I == Ancestors.size() ||
        isa<SDKNodeType>(Ancestors[I])); -- I) {
      auto Child = I == Ancestors.size() ? Node : Ancestors[I];
      auto Parent = Ancestors[I - 1];
      Indexes.insert(Indexes.begin(), Parent->getChildIndex(Child));
    }
  }
  DiffItemEmitter(DiffVector &AllItems) : AllItems(AllItems) {}

public:
  static void collectDiffItems(NodePtr Root, DiffVector &DV) {
    DiffItemEmitter Emitter(DV);
    SDKNode::postorderVisit(Root, Emitter);
  }
};

class DiagnosisEmitter : public SDKNodeVisitor {
  void handle(const SDKNodeDecl *D, NodeAnnotation Anno);
  void visitDecl(SDKNodeDecl *D);
  void visit(NodePtr Node) override;
  SDKNodeDecl *findAddedDecl(const SDKNodeDecl *Node);
  bool findTypeAliasDecl(const SDKNodeDecl *Node);
  static void collectAddedDecls(NodePtr Root, std::set<SDKNodeDecl*> &Results);

  std::set<SDKNodeDecl*> AddedDecls;

  UpdatedNodesMap &UpdateMap;
  NodeMap &TypeAliasUpdateMap;
  TypeMemberDiffVector &MemberChanges;
  DiagnosticEngine &Diags;
  DiagnosisEmitter(SDKContext &Ctx):
    UpdateMap(Ctx.getNodeUpdateMap()),
    TypeAliasUpdateMap(Ctx.getTypeAliasUpdateMap()),
    MemberChanges(Ctx.getTypeMemberDiffs()), Diags(Ctx.getDiags()) {}

public:
  static void diagnosis(NodePtr LeftRoot, NodePtr RightRoot,
                        SDKContext &Ctx);
};

void DiagnosisEmitter::collectAddedDecls(NodePtr Root,
                                         std::set<SDKNodeDecl*> &Results) {
  if (auto *D = dyn_cast<SDKNodeDecl>(Root)) {
    if (Root->isAnnotatedAs(NodeAnnotation::Added))
      Results.insert(D);
  }
  for (auto &C : Root->getChildren())
    collectAddedDecls(C, Results);
}

SDKNodeDecl *DiagnosisEmitter::findAddedDecl(const SDKNodeDecl *Root) {
  for (auto *Added : AddedDecls) {
    if (Root->getKind() == Added->getKind() &&
        Root->getPrintedName() == Added->getPrintedName() &&
        Root->getUsr() == Added->getUsr())
      return Added;
  }
  return nullptr;
}

bool DiagnosisEmitter::findTypeAliasDecl(const SDKNodeDecl *Node) {
  if (Node->getKind() != SDKNodeKind::DeclType)
    return false;
  return std::any_of(AddedDecls.begin(), AddedDecls.end(),
      [&](SDKNodeDecl *Added) {
    return Added->getKind() == SDKNodeKind::DeclTypeAlias &&
           Added->getPrintedName() == Node->getPrintedName();
  });
}

void DiagnosisEmitter::diagnosis(NodePtr LeftRoot, NodePtr RightRoot,
                                 SDKContext &Ctx) {
  DiagnosisEmitter Emitter(Ctx);
  collectAddedDecls(RightRoot, Emitter.AddedDecls);
  SDKNode::postorderVisit(LeftRoot, Emitter);
}

void DiagnosisEmitter::handle(const SDKNodeDecl *Node, NodeAnnotation Anno) {
  assert(Node->isAnnotatedAs(Anno));
  auto &Ctx = Node->getSDKContext();
  switch(Anno) {
  case NodeAnnotation::Removed: {
    // If we can find a type alias decl with the same name of this type, we
    // consider the type is not removed.
    if (findTypeAliasDecl(Node))
      return;
    if (auto *Added = findAddedDecl(Node)) {
      if (Node->getDeclKind() != DeclKind::Constructor) {
        Diags.diagnose(SourceLoc(), diag::moved_decl, Node->getScreenInfo(),
          Ctx.buffer((Twine(getDeclKindStr(Added->getDeclKind())) + " " +
            Added->getFullyQualifiedName()).str()));
        return;
      }
    }

    // If we can find a hoisted member for this removed delcaration, we
    // emit the diagnostics as rename instead of removal.
    auto It = std::find_if(MemberChanges.begin(), MemberChanges.end(),
      [&](TypeMemberDiffItem &Item) { return Item.usr == Node->getUsr(); });
    if (It != MemberChanges.end()) {
      Diags.diagnose(SourceLoc(), diag::renamed_decl, Node->getScreenInfo(),
        Ctx.buffer((Twine(getDeclKindStr(Node->getDeclKind())) + " " +
          It->newTypeName + "." + It->newPrintedName).str()));
      return;
    }

    // If a type alias of a raw type has been changed to a struct/enum that
    // conforms to RawRepresentable in the later version of SDK, we show the
    // refine diagnostics message instead of showing the type alias has been
    // removed.
    if (TypeAliasUpdateMap.find((SDKNode*)Node) != TypeAliasUpdateMap.end()) {
      Diags.diagnose(SourceLoc(), diag::raw_type_change, Node->getScreenInfo(),
        Node->getAs<SDKNodeDeclTypeAlias>()->getUnderlyingType()->getPrintedName(),
        TypeAliasUpdateMap[(SDKNode*)Node]->getAs<SDKNodeDeclType>()->
          getRawValueType()->getPrintedName());
      return;
    }

    // We should exlude those declarations that are pulled up to the super classes.
    bool FoundInSuperclass = false;
    if (auto PD = dyn_cast<SDKNodeDecl>(Node->getParent())) {
      if (PD->isAnnotatedAs(NodeAnnotation::Updated)) {
        // Get the updated counterpart of the parent decl.
        if (auto RTD = dyn_cast<SDKNodeDeclType>(UpdateMap.
            findUpdateCounterpart(PD))) {
          // Look up by the printed name in the counterpart.
          FoundInSuperclass =
            RTD->lookupChildByPrintedName(Node->getPrintedName()).hasValue();
        }
      }
    }
    if (FoundInSuperclass)
      return;
    Diags.diagnose(SourceLoc(), diag::removed_decl, Node->getScreenInfo(),
      Node->isDeprecated());
    return;
  }
  case NodeAnnotation::Rename: {
    auto *Count = UpdateMap.findUpdateCounterpart(Node)->getAs<SDKNodeDecl>();
    Diags.diagnose(SourceLoc(), diag::renamed_decl, Node->getScreenInfo(),
        Ctx.buffer((Twine(getDeclKindStr(Count->getDeclKind())) + " " +
          Count->getFullyQualifiedName()).str()));
    return;
  }
  default:
    return;
  }
}

void DiagnosisEmitter::visitDecl(SDKNodeDecl *Node) {
  std::vector<NodeAnnotation> Scratch;
  for (auto Anno : Node->getAnnotations(Scratch))
    handle(Node, Anno);
}

void DiagnosisEmitter::visit(NodePtr Node) {
  if (auto *DNode = dyn_cast<SDKNodeDecl>(Node)) {
    visitDecl(DNode);
  }
}

typedef std::vector<NoEscapeFuncParam> NoEscapeFuncParamVector;

class NoEscapingFuncEmitter : public SDKNodeVisitor {
  NoEscapeFuncParamVector &AllItems;
  NoEscapingFuncEmitter(NoEscapeFuncParamVector &AllItems) : AllItems(AllItems) {}

  void visit(NodePtr Node) override {
    if (Node->getKind() != SDKNodeKind::TypeFunc)
      return;
    if (Node->getAs<SDKNodeTypeFunc>()->isEscaping())
      return;
    auto Parent = Node->getParent();
    if (auto ParentFunc = dyn_cast<SDKNodeDeclAbstractFunc>(Parent)) {
      if (ParentFunc->isObjc()) {
        unsigned Index = ParentFunc->getChildIndex(Node);
        AllItems.emplace_back(ParentFunc->getUsr(), Index);
      }
    }
  }

public:
  static void collectDiffItems(NodePtr Root, NoEscapeFuncParamVector &DV) {
    NoEscapingFuncEmitter Emitter(DV);
    SDKNode::postorderVisit(Root, Emitter);
  }
};
} // end anonymous namespace

namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;

class RenameDetectorForMemberDiff : public MatchedNodeListener {
  InterfaceTypeChangeDetector LeftDetector;
  InterfaceTypeChangeDetector RightDetector;
public:
  RenameDetectorForMemberDiff(): LeftDetector(true), RightDetector(false) {}
  void foundMatch(NodePtr Left, NodePtr Right, NodeMatchReason Reason) override {
    if (!Left || !Right)
      return;
    detectRename(Left, Right);
    LeftDetector.detect(Left, Right);
    RightDetector.detect(Right, Left);
  }
  void workOn(NodePtr Left, NodePtr Right) {
    if (Left->getKind() == Right->getKind() &&
        Left->getKind() == SDKNodeKind::DeclType) {
      SameNameNodeMatcher SNMatcher(Left->getChildren(), Right->getChildren(),
                                    *this);
      SNMatcher.match();
    }
    if (Left->getKind() == Right->getKind() &&
        Left->getKind() == SDKNodeKind::DeclVar) {
      SequentialNodeMatcher Matcher(Left->getChildren(),
                                    Right->getChildren(), *this);
      Matcher.match();
    }
  }
};

static Optional<uint8_t> findSelfIndex(SDKNode* Node) {
  if (auto func = dyn_cast<SDKNodeDeclAbstractFunc>(Node)) {
    return func->getSelfIndexOptional();
  } else if (auto vd = dyn_cast<SDKNodeDeclVar>(Node)) {
    for (auto &C : vd->getChildren()) {
      if (isa<SDKNodeDeclAbstractFunc>(C)) {
        if (auto Result = findSelfIndex(C))
          return Result;
      }
    }
  }
  return None;
}

/// Find cases where a diff is due to a change to being a type member
static void findTypeMemberDiffs(NodePtr leftSDKRoot, NodePtr rightSDKRoot,
                                TypeMemberDiffVector &out) {
  TypeMemberDiffFinder diffFinder(cast<SDKNodeRoot>(leftSDKRoot));
  diffFinder.findDiffsFor(rightSDKRoot);
  RenameDetectorForMemberDiff Detector;
  for (auto pair : diffFinder.getDiffs()) {
    auto left = pair.first;
    auto leftParent = left->getParent();
    auto right = pair.second;
    auto rightParent = right->getParent();

    // SDK_CHANGE_TYPE_MEMBER(USR, new type context name, new printed name, self
    // index, old printed name)
    TypeMemberDiffItem item = {
        right->getAs<SDKNodeDecl>()->getUsr(),
        rightParent->getKind() == SDKNodeKind::Root ?
          StringRef() : rightParent->getAs<SDKNodeDecl>()->getFullyQualifiedName(),
        right->getPrintedName(), findSelfIndex(right), None,
        leftParent->getKind() == SDKNodeKind::Root ?
          StringRef() : leftParent->getAs<SDKNodeDecl>()->getFullyQualifiedName(),
        left->getPrintedName()
    };
    out.emplace_back(item);
    Detector.workOn(left, right);
  }
}

static int diagnoseModuleChange(StringRef LeftPath, StringRef RightPath,
                                StringRef OutputPath,
                                CheckerOptions Opts,
                                llvm::StringSet<> ProtocolReqWhitelist) {
  if (!fs::exists(LeftPath)) {
    llvm::errs() << LeftPath << " does not exist\n";
    return 1;
  }
  if (!fs::exists(RightPath)) {
    llvm::errs() << RightPath << " does not exist\n";
    return 1;
  }
  llvm::raw_ostream *OS = &llvm::errs();
  std::unique_ptr<llvm::raw_ostream> FileOS;
  if (!OutputPath.empty()) {
    std::error_code EC;
    FileOS.reset(new llvm::raw_fd_ostream(OutputPath, EC, llvm::sys::fs::F_None));
    OS = FileOS.get();
  }
  ModuleDifferDiagsConsumer PDC(true, *OS);
  SDKContext Ctx(Opts);
  Ctx.getDiags().addConsumer(PDC);

  SwiftDeclCollector LeftCollector(Ctx);
  LeftCollector.deSerialize(LeftPath);
  SwiftDeclCollector RightCollector(Ctx);
  RightCollector.deSerialize(RightPath);
  auto LeftModule = LeftCollector.getSDKRoot();
  auto RightModule = RightCollector.getSDKRoot();
  TypeAliasDiffFinder(LeftModule, RightModule,
                      Ctx.getTypeAliasUpdateMap()).search();
  PrunePass Prune(Ctx, std::move(ProtocolReqWhitelist));
  Prune.pass(LeftModule, RightModule);
  ChangeRefinementPass RefinementPass(Ctx.getNodeUpdateMap());
  RefinementPass.pass(LeftModule, RightModule);
  // Find member hoist changes to help refine diagnostics.
  findTypeMemberDiffs(LeftModule, RightModule, Ctx.getTypeMemberDiffs());

  DiagnosisEmitter::diagnosis(LeftModule, RightModule, Ctx);
  return 0;
}

static void populateAliasChanges(NodeMap &AliasMap, DiffVector &AllItems,
    const bool isRevert) {
  for (auto Pair: AliasMap) {
    auto UnderlyingType = Pair.first->getAs<SDKNodeDeclTypeAlias>()->
      getUnderlyingType()->getPrintedName();
    auto RawType = AliasMap[(SDKNode*)Pair.first]->getAs<SDKNodeDeclType>()->
      getRawValueType()->getPrintedName();
    if (isRevert) {
      auto *D = Pair.second->getAs<SDKNodeDecl>();
      AllItems.emplace_back(SDKNodeKind::DeclType,
        NodeAnnotation::RevertTypeAliasDeclToRawRepresentable, "0",
        D->getUsr(), "", RawType, UnderlyingType, D->getModuleName());
    } else {
      auto *D = Pair.first->getAs<SDKNodeDecl>();
      AllItems.emplace_back(SDKNodeKind::DeclTypeAlias,
        NodeAnnotation::TypeAliasDeclToRawRepresentable, "0",
        D->getUsr(), "", UnderlyingType, RawType, D->getModuleName());
    }
  }
}

static int compareSDKs(StringRef LeftPath, StringRef RightPath,
                       StringRef DiffPath,
                       llvm::StringSet<> &IgnoredRemoveUsrs, CheckerOptions Opts) {
  if (!fs::exists(LeftPath)) {
    llvm::errs() << LeftPath << " does not exist\n";
    return 1;
  }
  if (!fs::exists(RightPath)) {
    llvm::errs() << RightPath << " does not exist\n";
    return 1;
  }
  llvm::errs() << "Diffing: " << LeftPath << " and " << RightPath << "\n";

  ModuleDifferDiagsConsumer PDC(false);
  SDKContext Ctx(Opts);
  Ctx.getDiags().addConsumer(PDC);

  SwiftDeclCollector LeftCollector(Ctx);
  LeftCollector.deSerialize(LeftPath);
  SwiftDeclCollector RightCollector(Ctx);
  RightCollector.deSerialize(RightPath);
  llvm::errs() << "Finished deserializing" << "\n";
  auto LeftModule = LeftCollector.getSDKRoot();
  auto RightModule = RightCollector.getSDKRoot();

  // Structural diffs: not merely name changes but changes in SDK tree
  // structure.
  llvm::errs() << "Detecting type member diffs" << "\n";
  findTypeMemberDiffs(LeftModule, RightModule, Ctx.getTypeMemberDiffs());

  PrunePass Prune(Ctx);
  Prune.pass(LeftModule, RightModule);
  llvm::errs() << "Finished pruning" << "\n";
  ChangeRefinementPass RefinementPass(Ctx.getNodeUpdateMap());
  RefinementPass.pass(LeftModule, RightModule);
  DiffVector AllItems;
  DiffItemEmitter::collectDiffItems(LeftModule, AllItems);

  // Find type alias change first.
  auto &AliasMap = Ctx.getTypeAliasUpdateMap();
  TypeAliasDiffFinder(LeftModule, RightModule, AliasMap).search();
  populateAliasChanges(AliasMap, AllItems, /*IsRevert*/false);

  // Find type alias revert change.
  auto &RevertAliasMap = Ctx.getRevertTypeAliasUpdateMap();
  TypeAliasDiffFinder(RightModule, LeftModule, RevertAliasMap).search();
  populateAliasChanges(RevertAliasMap, AllItems, /*IsRevert*/true);

  AllItems.erase(std::remove_if(AllItems.begin(), AllItems.end(),
                                [&](CommonDiffItem &Item) {
    return Item.DiffKind == NodeAnnotation::RemovedDecl &&
      IgnoredRemoveUsrs.find(Item.LeftUsr) != IgnoredRemoveUsrs.end();
  }), AllItems.end());

  NoEscapeFuncParamVector AllNoEscapingFuncs;
  NoEscapingFuncEmitter::collectDiffItems(RightModule, AllNoEscapingFuncs);

  llvm::errs() << "Dumping diff to " << DiffPath << '\n';
  std::vector<OverloadedFuncInfo> Overloads;
  // OverloadMemberFunctionEmitter::collectDiffItems(RightModule, Overloads);

  auto &typeMemberDiffs = Ctx.getTypeMemberDiffs();
  std::error_code EC;
  llvm::raw_fd_ostream Fs(DiffPath, EC, llvm::sys::fs::F_None);
  removeRedundantAndSort(AllItems);
  removeRedundantAndSort(typeMemberDiffs);
  removeRedundantAndSort(AllNoEscapingFuncs);
  removeRedundantAndSort(Overloads);
  if (options::OutputInJson) {
    std::vector<APIDiffItem*> TotalItems;
    std::transform(AllItems.begin(), AllItems.end(),
                   std::back_inserter(TotalItems),
                   [](CommonDiffItem &Item) { return &Item; });
    std::transform(typeMemberDiffs.begin(), typeMemberDiffs.end(),
                   std::back_inserter(TotalItems),
                   [](TypeMemberDiffItem &Item) { return &Item; });
    std::transform(AllNoEscapingFuncs.begin(), AllNoEscapingFuncs.end(),
                   std::back_inserter(TotalItems),
                   [](NoEscapeFuncParam &Item) { return &Item; });
    std::transform(Overloads.begin(), Overloads.end(),
                   std::back_inserter(TotalItems),
                   [](OverloadedFuncInfo &Item) { return &Item; });
    APIDiffItemStore::serialize(Fs, TotalItems);
    return 0;
  }
  serializeDiffs(Fs, AllItems);
  serializeDiffs(Fs, typeMemberDiffs);
  serializeDiffs(Fs, AllNoEscapingFuncs);
  serializeDiffs(Fs, Overloads);
  return 0;
}

static int readFileLineByLine(StringRef Path, llvm::StringSet<> &Lines) {
  auto FileBufOrErr = llvm::MemoryBuffer::getFile(Path);
  if (!FileBufOrErr) {
    llvm::errs() << "error opening file '" << Path << "': "
      << FileBufOrErr.getError().message() << '\n';
    return 1;
  }

  StringRef BufferText = FileBufOrErr.get()->getBuffer();
  while (!BufferText.empty()) {
    StringRef Line;
    std::tie(Line, BufferText) = BufferText.split('\n');
    Line = Line.trim();
    if (Line.empty())
      continue;
    if (Line.startswith("// ")) // comment.
      continue;
    Lines.insert(Line);
  }
  return 0;
}

// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// getMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement getMainExecutable
// without being given the address of a function in the main executable).
void anchorForGetMainExecutable() {}

static int prepareForDump(const char *Main,
                          CompilerInvocation &InitInvok,
                          llvm::StringSet<> &Modules) {
  InitInvok.setMainExecutablePath(fs::getMainExecutable(Main,
    reinterpret_cast<void *>(&anchorForGetMainExecutable)));
  InitInvok.setModuleName("swift_ide_test");
  if (!options::SDK.empty()) {
    InitInvok.setSDKPath(options::SDK);
  } else if (const char *SDKROOT = getenv("SDKROOT")) {
    InitInvok.setSDKPath(SDKROOT);
  } else {
    llvm::errs() << "Provide '-sdk <path>' option or run with 'xcrun -sdk <..>\
    swift-api-digester'\n";
    return 1;
  }

  if (!options::Triple.empty())
    InitInvok.setTargetTriple(options::Triple);
  InitInvok.getClangImporterOptions().ModuleCachePath =
  options::ModuleCachePath;

  if (!options::SwiftVersion.empty()) {
    using version::Version;
    bool isValid = false;
    if (auto Version = Version::parseVersionString(options::SwiftVersion,
                                                   SourceLoc(), nullptr)) {
      if (auto Effective = Version.getValue().getEffectiveLanguageVersion()) {
        InitInvok.getLangOptions().EffectiveLanguageVersion = *Effective;
        isValid = true;
      }
    }
    if (!isValid) {
      llvm::errs() << "Unsupported Swift Version.\n";
      return 1;
    }
  }

  if (!options::ResourceDir.empty()) {
    InitInvok.setRuntimeResourcePath(options::ResourceDir);
  }
  std::vector<SearchPathOptions::FrameworkSearchPath> FramePaths;
  for (const auto &path : options::FrameworkPaths) {
    FramePaths.push_back({path, /*isSystem=*/false});
  }
  for (const auto &path : options::CCSystemFrameworkPaths) {
    FramePaths.push_back({path, /*isSystem=*/true});
  }
  InitInvok.setFrameworkSearchPaths(FramePaths);
  InitInvok.setImportSearchPaths(options::ModuleInputPaths);

  if (!options::ModuleList.empty()) {
    if (readFileLineByLine(options::ModuleList, Modules))
        return 1;
  }

  for (auto M : options::ModuleNames) {
    Modules.insert(M);
  }

  if (Modules.empty()) {
    llvm::errs() << "Need to specify -include-all or -module <name>\n";
    return 1;
  }
  return 0;
}

static void readIgnoredUsrs(llvm::StringSet<> &IgnoredUsrs) {
  StringRef Path = options::IgnoreRemovedDeclUSRs;
  if (Path.empty())
    return;
  if (!fs::exists(Path)) {
    llvm::errs() << Path << " does not exist.\n";
    return;
  }
  readFileLineByLine(Path, IgnoredUsrs);
}

static int deserializeDiffItems(APIDiffItemStore &Store, StringRef DiffPath,
    StringRef OutputPath) {
  Store.addStorePath(DiffPath);
  std::error_code EC;
  llvm::raw_fd_ostream FS(OutputPath, EC, llvm::sys::fs::F_None);
  APIDiffItemStore::serialize(FS, Store.getAllDiffItems());
  return 0;
}

static int deserializeNameCorrection(APIDiffItemStore &Store,
                                     StringRef OutputPath) {
  std::error_code EC;
  llvm::raw_fd_ostream FS(OutputPath, EC, llvm::sys::fs::F_None);
  std::set<NameCorrectionInfo> Result;
  for (auto *Item: Store.getAllDiffItems()) {
    if (auto *CI = dyn_cast<CommonDiffItem>(Item)) {
      if (CI->DiffKind == NodeAnnotation::Rename) {
        auto NewName = CI->getNewName();
        auto Module = CI->ModuleName;
        if (CI->rightCommentUnderscored()) {
          Result.insert(NameCorrectionInfo(NewName, NewName, Module));
        }
      }
    }
  }
  std::vector<NameCorrectionInfo> Vec;
  Vec.insert(Vec.end(), Result.begin(), Result.end());
  APIDiffItemStore::serialize(FS, Vec);
  return EC.value();
}

static CheckerOptions getCheckOpts() {
  CheckerOptions Opts;
  Opts.AvoidLocation = options::AvoidLocation;
  Opts.ABI = options::Abi;
  Opts.Verbose = options::Verbose;
  Opts.AbortOnModuleLoadFailure = options::AbortOnModuleLoadFailure;
  Opts.LocationFilter = options::LocationFilter;
  Opts.PrintModule = options::PrintModule;
  Opts.SwiftOnly = options::SwiftOnly;
  return Opts;
}

int main(int argc, char *argv[]) {
  PROGRAM_START(argc, argv);
  INITIALIZE_LLVM();

  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SDK Digester\n");
  CompilerInvocation InitInvok;

  llvm::StringSet<> Modules;
  std::vector<std::string> PrintApis;
  llvm::StringSet<> IgnoredUsrs;
  readIgnoredUsrs(IgnoredUsrs);
  CheckerOptions Opts = getCheckOpts();
  for (auto Name : options::ApisPrintUsrs)
    PrintApis.push_back(Name);
  switch (options::Action) {
  case ActionType::DumpSwiftModules:
    return (prepareForDump(argv[0], InitInvok, Modules)) ? 1 :
      dumpSwiftModules(InitInvok, Modules, options::OutputFile, PrintApis, Opts);
  case ActionType::DumpSDK:
    return (prepareForDump(argv[0], InitInvok, Modules)) ? 1 :
      dumpSDKContent(InitInvok, Modules, options::OutputFile, Opts);
  case ActionType::CompareSDKs:
  case ActionType::DiagnoseSDKs: {
    if (options::SDKJsonPaths.size() != 2) {
      llvm::errs() << "Only two SDK versions can be compared\n";
      llvm::cl::PrintHelpMessage();
      return 1;
    }
    llvm::StringSet<> protocolWhitelist;
    if (!options::ProtReqWhiteList.empty()) {
      if (readFileLineByLine(options::ProtReqWhiteList, protocolWhitelist))
          return 1;
    }
    if (options::Action == ActionType::CompareSDKs)
      return compareSDKs(options::SDKJsonPaths[0], options::SDKJsonPaths[1],
                         options::OutputFile, IgnoredUsrs, Opts);
    else
      return diagnoseModuleChange(options::SDKJsonPaths[0],
                                  options::SDKJsonPaths[1],
                                  options::OutputFile, Opts,
                                  std::move(protocolWhitelist));
  }
  case ActionType::DeserializeSDK:
  case ActionType::DeserializeDiffItems: {
    if (options::SDKJsonPaths.size() != 1) {
      llvm::cl::PrintHelpMessage();
      return 1;
    }
    if (options::Action == ActionType::DeserializeDiffItems) {
      CompilerInstance CI;
      APIDiffItemStore Store(CI.getDiags());
      return deserializeDiffItems(Store, options::SDKJsonPaths[0],
        options::OutputFile);
    } else {
      return deserializeSDKDump(options::SDKJsonPaths[0], options::OutputFile,
        Opts);
    }
  }
  case ActionType::GenerateNameCorrectionTemplate: {
    CompilerInstance CI;
    APIDiffItemStore Store(CI.getDiags());
    auto &Paths = options::SDKJsonPaths;
    for (unsigned I = 0; I < Paths.size(); I ++)
      Store.addStorePath(Paths[I]);
    return deserializeNameCorrection(Store, options::OutputFile);
  }
  case ActionType::FindUsr: {
    if (options::SDKJsonPaths.size() != 1) {
      llvm::cl::PrintHelpMessage();
      return 1;
    }
    return findDeclUsr(options::SDKJsonPaths[0], Opts);
  }
  case ActionType::None:
    llvm::errs() << "Action required\n";
    llvm::cl::PrintHelpMessage();
    return 1;
  }
}
