//===-- Move.cpp - Implement ClangMove functationalities --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Move.h"
#include "HelperDeclRefGraph.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/Core/Replacement.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"

#define DEBUG_TYPE "clang-move"

using namespace clang::ast_matchers;

namespace clang {
namespace move {
namespace {

// FIXME: Move to ASTMatchers.
AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }

AST_MATCHER(NamedDecl, notInMacro) { return !Node.getLocation().isMacroID(); }

AST_MATCHER_P(Decl, hasOutermostEnclosingClass,
              ast_matchers::internal::Matcher<Decl>, InnerMatcher) {
  const auto *Context = Node.getDeclContext();
  if (!Context)
    return false;
  while (const auto *NextContext = Context->getParent()) {
    if (isa<NamespaceDecl>(NextContext) ||
        isa<TranslationUnitDecl>(NextContext))
      break;
    Context = NextContext;
  }
  return InnerMatcher.matches(*Decl::castFromDeclContext(Context), Finder,
                              Builder);
}

AST_MATCHER_P(CXXMethodDecl, ofOutermostEnclosingClass,
              ast_matchers::internal::Matcher<CXXRecordDecl>, InnerMatcher) {
  const CXXRecordDecl *Parent = Node.getParent();
  if (!Parent)
    return false;
  while (const auto *NextParent =
             dyn_cast<CXXRecordDecl>(Parent->getParent())) {
    Parent = NextParent;
  }

  return InnerMatcher.matches(*Parent, Finder, Builder);
}

std::string CleanPath(StringRef PathRef) {
  llvm::SmallString<128> Path(PathRef);
  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
  // FIXME: figure out why this is necessary.
  llvm::sys::path::native(Path);
  return Path.str();
}

// Make the Path absolute using the CurrentDir if the Path is not an absolute
// path. An empty Path will result in an empty string.
std::string MakeAbsolutePath(StringRef CurrentDir, StringRef Path) {
  if (Path.empty())
    return "";
  llvm::SmallString<128> InitialDirectory(CurrentDir);
  llvm::SmallString<128> AbsolutePath(Path);
  llvm::sys::fs::make_absolute(InitialDirectory, AbsolutePath);
  return CleanPath(std::move(AbsolutePath));
}

// Make the Path absolute using the current working directory of the given
// SourceManager if the Path is not an absolute path.
//
// The Path can be a path relative to the build directory, or retrieved from
// the SourceManager.
std::string MakeAbsolutePath(const SourceManager &SM, StringRef Path) {
  llvm::SmallString<128> AbsolutePath(Path);
  if (std::error_code EC =
          SM.getFileManager().getVirtualFileSystem().makeAbsolute(AbsolutePath))
    llvm::errs() << "Warning: could not make absolute file: '" << EC.message()
                 << '\n';
  // Handle symbolic link path cases.
  // We are trying to get the real file path of the symlink.
  auto Dir = SM.getFileManager().getDirectory(
      llvm::sys::path::parent_path(AbsolutePath.str()));
  if (Dir) {
    StringRef DirName = SM.getFileManager().getCanonicalName(*Dir);
    // FIXME: getCanonicalName might fail to get real path on VFS.
    if (llvm::sys::path::is_absolute(DirName)) {
      SmallString<128> AbsoluteFilename;
      llvm::sys::path::append(AbsoluteFilename, DirName,
                              llvm::sys::path::filename(AbsolutePath.str()));
      return CleanPath(AbsoluteFilename);
    }
  }
  return CleanPath(AbsolutePath);
}

// Matches AST nodes that are expanded within the given AbsoluteFilePath.
AST_POLYMORPHIC_MATCHER_P(isExpansionInFile,
                          AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc),
                          std::string, AbsoluteFilePath) {
  auto &SourceManager = Finder->getASTContext().getSourceManager();
  auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getBeginLoc());
  if (ExpansionLoc.isInvalid())
    return false;
  auto *FileEntry =
      SourceManager.getFileEntryForID(SourceManager.getFileID(ExpansionLoc));
  if (!FileEntry)
    return false;
  return MakeAbsolutePath(SourceManager, FileEntry->getName()) ==
         AbsoluteFilePath;
}

class FindAllIncludes : public PPCallbacks {
public:
  explicit FindAllIncludes(SourceManager *SM, ClangMoveTool *const MoveTool)
      : SM(*SM), MoveTool(MoveTool) {}

  void InclusionDirective(SourceLocation HashLoc, const Token & /*IncludeTok*/,
                          StringRef FileName, bool IsAngled,
                          CharSourceRange FilenameRange,
                          const FileEntry * /*File*/, StringRef SearchPath,
                          StringRef /*RelativePath*/,
                          const Module * /*Imported*/,
                          SrcMgr::CharacteristicKind /*FileType*/) override {
    if (const auto *FileEntry = SM.getFileEntryForID(SM.getFileID(HashLoc)))
      MoveTool->addIncludes(FileName, IsAngled, SearchPath,
                            FileEntry->getName(), FilenameRange, SM);
  }

private:
  const SourceManager &SM;
  ClangMoveTool *const MoveTool;
};

/// Add a declatration being moved to new.h/cc. Note that the declaration will
/// also be deleted in old.h/cc.
void MoveDeclFromOldFileToNewFile(ClangMoveTool *MoveTool, const NamedDecl *D) {
  MoveTool->getMovedDecls().push_back(D);
  MoveTool->addRemovedDecl(D);
  MoveTool->getUnremovedDeclsInOldHeader().erase(D);
}

class FunctionDeclarationMatch : public MatchFinder::MatchCallback {
public:
  explicit FunctionDeclarationMatch(ClangMoveTool *MoveTool)
      : MoveTool(MoveTool) {}

  void run(const MatchFinder::MatchResult &Result) override {
    const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("function");
    assert(FD);
    const NamedDecl *D = FD;
    if (const auto *FTD = FD->getDescribedFunctionTemplate())
      D = FTD;
    MoveDeclFromOldFileToNewFile(MoveTool, D);
  }

private:
  ClangMoveTool *MoveTool;
};

class VarDeclarationMatch : public MatchFinder::MatchCallback {
public:
  explicit VarDeclarationMatch(ClangMoveTool *MoveTool)
      : MoveTool(MoveTool) {}

  void run(const MatchFinder::MatchResult &Result) override {
    const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var");
    assert(VD);
    MoveDeclFromOldFileToNewFile(MoveTool, VD);
  }

private:
  ClangMoveTool *MoveTool;
};

class TypeAliasMatch : public MatchFinder::MatchCallback {
public:
  explicit TypeAliasMatch(ClangMoveTool *MoveTool)
      : MoveTool(MoveTool) {}

  void run(const MatchFinder::MatchResult &Result) override {
    if (const auto *TD = Result.Nodes.getNodeAs<TypedefDecl>("typedef"))
      MoveDeclFromOldFileToNewFile(MoveTool, TD);
    else if (const auto *TAD =
                 Result.Nodes.getNodeAs<TypeAliasDecl>("type_alias")) {
      const NamedDecl * D = TAD;
      if (const auto * TD = TAD->getDescribedAliasTemplate())
        D = TD;
      MoveDeclFromOldFileToNewFile(MoveTool, D);
    }
  }

private:
  ClangMoveTool *MoveTool;
};

class EnumDeclarationMatch : public MatchFinder::MatchCallback {
public:
  explicit EnumDeclarationMatch(ClangMoveTool *MoveTool)
      : MoveTool(MoveTool) {}

  void run(const MatchFinder::MatchResult &Result) override {
    const auto *ED = Result.Nodes.getNodeAs<EnumDecl>("enum");
    assert(ED);
    MoveDeclFromOldFileToNewFile(MoveTool, ED);
  }

private:
  ClangMoveTool *MoveTool;
};

class ClassDeclarationMatch : public MatchFinder::MatchCallback {
public:
  explicit ClassDeclarationMatch(ClangMoveTool *MoveTool)
      : MoveTool(MoveTool) {}
  void run(const MatchFinder::MatchResult &Result) override {
    SourceManager *SM = &Result.Context->getSourceManager();
    if (const auto *CMD = Result.Nodes.getNodeAs<CXXMethodDecl>("class_method"))
      MatchClassMethod(CMD, SM);
    else if (const auto *VD =
                 Result.Nodes.getNodeAs<VarDecl>("class_static_var_decl"))
      MatchClassStaticVariable(VD, SM);
    else if (const auto *CD =
                 Result.Nodes.getNodeAs<CXXRecordDecl>("moved_class"))
      MatchClassDeclaration(CD, SM);
  }

private:
  void MatchClassMethod(const CXXMethodDecl *CMD, SourceManager *SM) {
    // Skip inline class methods. isInline() ast matcher doesn't ignore this
    // case.
    if (!CMD->isInlined()) {
      MoveTool->getMovedDecls().push_back(CMD);
      MoveTool->addRemovedDecl(CMD);
      // Get template class method from its method declaration as
      // UnremovedDecls stores template class method.
      if (const auto *FTD = CMD->getDescribedFunctionTemplate())
        MoveTool->getUnremovedDeclsInOldHeader().erase(FTD);
      else
        MoveTool->getUnremovedDeclsInOldHeader().erase(CMD);
    }
  }

  void MatchClassStaticVariable(const NamedDecl *VD, SourceManager *SM) {
    MoveDeclFromOldFileToNewFile(MoveTool, VD);
  }

  void MatchClassDeclaration(const CXXRecordDecl *CD, SourceManager *SM) {
    // Get class template from its class declaration as UnremovedDecls stores
    // class template.
    if (const auto *TC = CD->getDescribedClassTemplate())
      MoveTool->getMovedDecls().push_back(TC);
    else
      MoveTool->getMovedDecls().push_back(CD);
    MoveTool->addRemovedDecl(MoveTool->getMovedDecls().back());
    MoveTool->getUnremovedDeclsInOldHeader().erase(
        MoveTool->getMovedDecls().back());
  }

  ClangMoveTool *MoveTool;
};

// Expand to get the end location of the line where the EndLoc of the given
// Decl.
SourceLocation getLocForEndOfDecl(const Decl *D,
                                  const LangOptions &LangOpts = LangOptions()) {
  const auto &SM = D->getASTContext().getSourceManager();
  // If the expansion range is a character range, this is the location of
  // the first character past the end. Otherwise it's the location of the
  // first character in the final token in the range.
  auto EndExpansionLoc = SM.getExpansionRange(D->getEndLoc()).getEnd();
  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(EndExpansionLoc);
  // Try to load the file buffer.
  bool InvalidTemp = false;
  llvm::StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp);
  if (InvalidTemp)
    return SourceLocation();

  const char *TokBegin = File.data() + LocInfo.second;
  // Lex from the start of the given location.
  Lexer Lex(SM.getLocForStartOfFile(LocInfo.first), LangOpts, File.begin(),
            TokBegin, File.end());

  llvm::SmallVector<char, 16> Line;
  // FIXME: this is a bit hacky to get ReadToEndOfLine work.
  Lex.setParsingPreprocessorDirective(true);
  Lex.ReadToEndOfLine(&Line);
  SourceLocation EndLoc = EndExpansionLoc.getLocWithOffset(Line.size());
  // If we already reach EOF, just return the EOF SourceLocation;
  // otherwise, move 1 offset ahead to include the trailing newline character
  // '\n'.
  return SM.getLocForEndOfFile(LocInfo.first) == EndLoc
             ? EndLoc
             : EndLoc.getLocWithOffset(1);
}

// Get full range of a Decl including the comments associated with it.
CharSourceRange getFullRange(const Decl *D,
                             const LangOptions &options = LangOptions()) {
  const auto &SM = D->getASTContext().getSourceManager();
  SourceRange Full(SM.getExpansionLoc(D->getBeginLoc()), getLocForEndOfDecl(D));
  // Expand to comments that are associated with the Decl.
  if (const auto *Comment = D->getASTContext().getRawCommentForDeclNoCache(D)) {
    if (SM.isBeforeInTranslationUnit(Full.getEnd(), Comment->getEndLoc()))
      Full.setEnd(Comment->getEndLoc());
    // FIXME: Don't delete a preceding comment, if there are no other entities
    // it could refer to.
    if (SM.isBeforeInTranslationUnit(Comment->getBeginLoc(), Full.getBegin()))
      Full.setBegin(Comment->getBeginLoc());
  }

  return CharSourceRange::getCharRange(Full);
}

std::string getDeclarationSourceText(const Decl *D) {
  const auto &SM = D->getASTContext().getSourceManager();
  llvm::StringRef SourceText =
      Lexer::getSourceText(getFullRange(D), SM, LangOptions());
  return SourceText.str();
}

bool isInHeaderFile(const Decl *D, llvm::StringRef OriginalRunningDirectory,
                    llvm::StringRef OldHeader) {
  const auto &SM = D->getASTContext().getSourceManager();
  if (OldHeader.empty())
    return false;
  auto ExpansionLoc = SM.getExpansionLoc(D->getBeginLoc());
  if (ExpansionLoc.isInvalid())
    return false;

  if (const auto *FE = SM.getFileEntryForID(SM.getFileID(ExpansionLoc))) {
    return MakeAbsolutePath(SM, FE->getName()) ==
           MakeAbsolutePath(OriginalRunningDirectory, OldHeader);
  }

  return false;
}

std::vector<std::string> getNamespaces(const Decl *D) {
  std::vector<std::string> Namespaces;
  for (const auto *Context = D->getDeclContext(); Context;
       Context = Context->getParent()) {
    if (llvm::isa<TranslationUnitDecl>(Context) ||
        llvm::isa<LinkageSpecDecl>(Context))
      break;

    if (const auto *ND = llvm::dyn_cast<NamespaceDecl>(Context))
      Namespaces.push_back(ND->getName().str());
  }
  std::reverse(Namespaces.begin(), Namespaces.end());
  return Namespaces;
}

tooling::Replacements
createInsertedReplacements(const std::vector<std::string> &Includes,
                           const std::vector<const NamedDecl *> &Decls,
                           llvm::StringRef FileName, bool IsHeader = false,
                           StringRef OldHeaderInclude = "") {
  std::string NewCode;
  std::string GuardName(FileName);
  if (IsHeader) {
    for (size_t i = 0; i < GuardName.size(); ++i) {
      if (!isAlphanumeric(GuardName[i]))
        GuardName[i] = '_';
    }
    GuardName = StringRef(GuardName).upper();
    NewCode += "#ifndef " + GuardName + "\n";
    NewCode += "#define " + GuardName + "\n\n";
  }

  NewCode += OldHeaderInclude;
  // Add #Includes.
  for (const auto &Include : Includes)
    NewCode += Include;

  if (!Includes.empty())
    NewCode += "\n";

  // Add moved class definition and its related declarations. All declarations
  // in same namespace are grouped together.
  //
  // Record namespaces where the current position is in.
  std::vector<std::string> CurrentNamespaces;
  for (const auto *MovedDecl : Decls) {
    // The namespaces of the declaration being moved.
    std::vector<std::string> DeclNamespaces = getNamespaces(MovedDecl);
    auto CurrentIt = CurrentNamespaces.begin();
    auto DeclIt = DeclNamespaces.begin();
    // Skip the common prefix.
    while (CurrentIt != CurrentNamespaces.end() &&
           DeclIt != DeclNamespaces.end()) {
      if (*CurrentIt != *DeclIt)
        break;
      ++CurrentIt;
      ++DeclIt;
    }
    // Calculate the new namespaces after adding MovedDecl in CurrentNamespace,
    // which is used for next iteration of this loop.
    std::vector<std::string> NextNamespaces(CurrentNamespaces.begin(),
                                            CurrentIt);
    NextNamespaces.insert(NextNamespaces.end(), DeclIt, DeclNamespaces.end());


    // End with CurrentNamespace.
    bool HasEndCurrentNamespace = false;
    auto RemainingSize = CurrentNamespaces.end() - CurrentIt;
    for (auto It = CurrentNamespaces.rbegin(); RemainingSize > 0;
         --RemainingSize, ++It) {
      assert(It < CurrentNamespaces.rend());
      NewCode += "} // namespace " + *It + "\n";
      HasEndCurrentNamespace = true;
    }
    // Add trailing '\n' after the nested namespace definition.
    if (HasEndCurrentNamespace)
      NewCode += "\n";

    // If the moved declaration is not in CurrentNamespace, add extra namespace
    // definitions.
    bool IsInNewNamespace = false;
    while (DeclIt != DeclNamespaces.end()) {
      NewCode += "namespace " + *DeclIt + " {\n";
      IsInNewNamespace = true;
      ++DeclIt;
    }
    // If the moved declaration is in same namespace CurrentNamespace, add
    // a preceeding `\n' before the moved declaration.
    // FIXME: Don't add empty lines between using declarations.
    if (!IsInNewNamespace)
      NewCode += "\n";
    NewCode += getDeclarationSourceText(MovedDecl);
    CurrentNamespaces = std::move(NextNamespaces);
  }
  std::reverse(CurrentNamespaces.begin(), CurrentNamespaces.end());
  for (const auto &NS : CurrentNamespaces)
    NewCode += "} // namespace " + NS + "\n";

  if (IsHeader)
    NewCode += "\n#endif // " + GuardName + "\n";
  return tooling::Replacements(tooling::Replacement(FileName, 0, 0, NewCode));
}

// Return a set of all decls which are used/referenced by the given Decls.
// Specically, given a class member declaration, this method will return all
// decls which are used by the whole class.
llvm::DenseSet<const Decl *>
getUsedDecls(const HelperDeclRefGraph *RG,
             const std::vector<const NamedDecl *> &Decls) {
  assert(RG);
  llvm::DenseSet<const CallGraphNode *> Nodes;
  for (const auto *D : Decls) {
    auto Result = RG->getReachableNodes(
        HelperDeclRGBuilder::getOutmostClassOrFunDecl(D));
    Nodes.insert(Result.begin(), Result.end());
  }
  llvm::DenseSet<const Decl *> Results;
  for (const auto *Node : Nodes)
    Results.insert(Node->getDecl());
  return Results;
}

} // namespace

std::unique_ptr<ASTConsumer>
ClangMoveAction::CreateASTConsumer(CompilerInstance &Compiler,
                                   StringRef /*InFile*/) {
  Compiler.getPreprocessor().addPPCallbacks(std::make_unique<FindAllIncludes>(
      &Compiler.getSourceManager(), &MoveTool));
  return MatchFinder.newASTConsumer();
}

ClangMoveTool::ClangMoveTool(ClangMoveContext *const Context,
                             DeclarationReporter *const Reporter)
    : Context(Context), Reporter(Reporter) {
  if (!Context->Spec.NewHeader.empty())
    CCIncludes.push_back("#include \"" + Context->Spec.NewHeader + "\"\n");
}

void ClangMoveTool::addRemovedDecl(const NamedDecl *Decl) {
  const auto &SM = Decl->getASTContext().getSourceManager();
  auto Loc = Decl->getLocation();
  StringRef FilePath = SM.getFilename(Loc);
  FilePathToFileID[FilePath] = SM.getFileID(Loc);
  RemovedDecls.push_back(Decl);
}

void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
  auto InOldHeader =
      isExpansionInFile(makeAbsolutePath(Context->Spec.OldHeader));
  auto InOldCC = isExpansionInFile(makeAbsolutePath(Context->Spec.OldCC));
  auto InOldFiles = anyOf(InOldHeader, InOldCC);
  auto classTemplateForwardDecls =
      classTemplateDecl(unless(has(cxxRecordDecl(isDefinition()))));
  auto ForwardClassDecls = namedDecl(
      anyOf(cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition()))),
            classTemplateForwardDecls));
  auto TopLevelDecl =
      hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()));

  //============================================================================
  // Matchers for old header
  //============================================================================
  // Match all top-level named declarations (e.g. function, variable, enum) in
  // old header, exclude forward class declarations and namespace declarations.
  //
  // We consider declarations inside a class belongs to the class. So these
  // declarations will be ignored.
  auto AllDeclsInHeader = namedDecl(
      unless(ForwardClassDecls), unless(namespaceDecl()),
      unless(usingDirectiveDecl()), // using namespace decl.
      notInMacro(),
      InOldHeader,
      hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
      hasDeclContext(decl(anyOf(namespaceDecl(), translationUnitDecl()))));
  Finder->addMatcher(AllDeclsInHeader.bind("decls_in_header"), this);

  // Don't register other matchers when dumping all declarations in header.
  if (Context->DumpDeclarations)
    return;

  // Match forward declarations in old header.
  Finder->addMatcher(namedDecl(ForwardClassDecls, InOldHeader).bind("fwd_decl"),
                     this);

  //============================================================================
  // Matchers for old cc
  //============================================================================
  auto IsOldCCTopLevelDecl = allOf(
      hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))), InOldCC);
  // Matching using decls/type alias decls which are in named/anonymous/global
  // namespace, these decls are always copied to new.h/cc. Those in classes,
  // functions are covered in other matchers.
  Finder->addMatcher(namedDecl(anyOf(usingDecl(IsOldCCTopLevelDecl),
                                     usingDirectiveDecl(unless(isImplicit()),
                                                        IsOldCCTopLevelDecl),
                                     typeAliasDecl(IsOldCCTopLevelDecl)),
                               notInMacro())
                         .bind("using_decl"),
                     this);

  // Match static functions/variable definitions which are defined in named
  // namespaces.
  Optional<ast_matchers::internal::Matcher<NamedDecl>> HasAnySymbolNames;
  for (StringRef SymbolName : Context->Spec.Names) {
    llvm::StringRef GlobalSymbolName = SymbolName.trim().ltrim(':');
    const auto HasName = hasName(("::" + GlobalSymbolName).str());
    HasAnySymbolNames =
        HasAnySymbolNames ? anyOf(*HasAnySymbolNames, HasName) : HasName;
  }

  if (!HasAnySymbolNames) {
    llvm::errs() << "No symbols being moved.\n";
    return;
  }
  auto InMovedClass =
      hasOutermostEnclosingClass(cxxRecordDecl(*HasAnySymbolNames));

  // Matchers for helper declarations in old.cc.
  auto InAnonymousNS = hasParent(namespaceDecl(isAnonymous()));
  auto NotInMovedClass= allOf(unless(InMovedClass), InOldCC);
  auto IsOldCCHelper =
      allOf(NotInMovedClass, anyOf(isStaticStorageClass(), InAnonymousNS));
  // Match helper classes separately with helper functions/variables since we
  // want to reuse these matchers in finding helpers usage below.
  //
  // There could be forward declarations usage for helpers, especially for
  // classes and functions. We need include these forward declarations.
  //
  // Forward declarations for variable helpers will be excluded as these
  // declarations (with "extern") are not supposed in cpp file.
   auto HelperFuncOrVar =
      namedDecl(notInMacro(), anyOf(functionDecl(IsOldCCHelper),
                                    varDecl(isDefinition(), IsOldCCHelper)));
  auto HelperClasses =
      cxxRecordDecl(notInMacro(), NotInMovedClass, InAnonymousNS);
  // Save all helper declarations in old.cc.
  Finder->addMatcher(
      namedDecl(anyOf(HelperFuncOrVar, HelperClasses)).bind("helper_decls"),
      this);

  // Construct an AST-based call graph of helper declarations in old.cc.
  // In the following matcheres, "dc" is a caller while "helper_decls" and
  // "used_class" is a callee, so a new edge starting from caller to callee will
  // be add in the graph.
  //
  // Find helper function/variable usages.
  Finder->addMatcher(
      declRefExpr(to(HelperFuncOrVar), hasAncestor(decl().bind("dc")))
          .bind("func_ref"),
      &RGBuilder);
  // Find helper class usages.
  Finder->addMatcher(
      typeLoc(loc(recordType(hasDeclaration(HelperClasses.bind("used_class")))),
              hasAncestor(decl().bind("dc"))),
      &RGBuilder);

  //============================================================================
  // Matchers for old files, including old.h/old.cc
  //============================================================================
  // Create a MatchCallback for class declarations.
  MatchCallbacks.push_back(std::make_unique<ClassDeclarationMatch>(this));
  // Match moved class declarations.
  auto MovedClass = cxxRecordDecl(InOldFiles, *HasAnySymbolNames,
                                  isDefinition(), TopLevelDecl)
                        .bind("moved_class");
  Finder->addMatcher(MovedClass, MatchCallbacks.back().get());
  // Match moved class methods (static methods included) which are defined
  // outside moved class declaration.
  Finder->addMatcher(
      cxxMethodDecl(InOldFiles, ofOutermostEnclosingClass(*HasAnySymbolNames),
                    isDefinition())
          .bind("class_method"),
      MatchCallbacks.back().get());
  // Match static member variable definition of the moved class.
  Finder->addMatcher(
      varDecl(InMovedClass, InOldFiles, isDefinition(), isStaticDataMember())
          .bind("class_static_var_decl"),
      MatchCallbacks.back().get());

  MatchCallbacks.push_back(std::make_unique<FunctionDeclarationMatch>(this));
  Finder->addMatcher(functionDecl(InOldFiles, *HasAnySymbolNames, TopLevelDecl)
                         .bind("function"),
                     MatchCallbacks.back().get());

  MatchCallbacks.push_back(std::make_unique<VarDeclarationMatch>(this));
  Finder->addMatcher(
      varDecl(InOldFiles, *HasAnySymbolNames, TopLevelDecl).bind("var"),
      MatchCallbacks.back().get());

  // Match enum definition in old.h. Enum helpers (which are defined in old.cc)
  // will not be moved for now no matter whether they are used or not.
  MatchCallbacks.push_back(std::make_unique<EnumDeclarationMatch>(this));
  Finder->addMatcher(
      enumDecl(InOldHeader, *HasAnySymbolNames, isDefinition(), TopLevelDecl)
          .bind("enum"),
      MatchCallbacks.back().get());

  // Match type alias in old.h, this includes "typedef" and "using" type alias
  // declarations. Type alias helpers (which are defined in old.cc) will not be
  // moved for now no matter whether they are used or not.
  MatchCallbacks.push_back(std::make_unique<TypeAliasMatch>(this));
  Finder->addMatcher(namedDecl(anyOf(typedefDecl().bind("typedef"),
                                     typeAliasDecl().bind("type_alias")),
                               InOldHeader, *HasAnySymbolNames, TopLevelDecl),
                     MatchCallbacks.back().get());
}

void ClangMoveTool::run(const ast_matchers::MatchFinder::MatchResult &Result) {
  if (const auto *D = Result.Nodes.getNodeAs<NamedDecl>("decls_in_header")) {
    UnremovedDeclsInOldHeader.insert(D);
  } else if (const auto *FWD =
                 Result.Nodes.getNodeAs<CXXRecordDecl>("fwd_decl")) {
    // Skip all forward declarations which appear after moved class declaration.
    if (RemovedDecls.empty()) {
      if (const auto *DCT = FWD->getDescribedClassTemplate())
        MovedDecls.push_back(DCT);
      else
        MovedDecls.push_back(FWD);
    }
  } else if (const auto *ND =
                 Result.Nodes.getNodeAs<NamedDecl>("helper_decls")) {
    MovedDecls.push_back(ND);
    HelperDeclarations.push_back(ND);
    LLVM_DEBUG(llvm::dbgs() << "Add helper : " << ND->getNameAsString() << " ("
                            << ND << ")\n");
  } else if (const auto *UD = Result.Nodes.getNodeAs<NamedDecl>("using_decl")) {
    MovedDecls.push_back(UD);
  }
}

std::string ClangMoveTool::makeAbsolutePath(StringRef Path) {
  return MakeAbsolutePath(Context->OriginalRunningDirectory, Path);
}

void ClangMoveTool::addIncludes(llvm::StringRef IncludeHeader, bool IsAngled,
                                llvm::StringRef SearchPath,
                                llvm::StringRef FileName,
                                CharSourceRange IncludeFilenameRange,
                                const SourceManager &SM) {
  SmallVector<char, 128> HeaderWithSearchPath;
  llvm::sys::path::append(HeaderWithSearchPath, SearchPath, IncludeHeader);
  std::string AbsoluteIncludeHeader =
      MakeAbsolutePath(SM, llvm::StringRef(HeaderWithSearchPath.data(),
                                           HeaderWithSearchPath.size()));
  std::string IncludeLine =
      IsAngled ? ("#include <" + IncludeHeader + ">\n").str()
               : ("#include \"" + IncludeHeader + "\"\n").str();

  std::string AbsoluteOldHeader = makeAbsolutePath(Context->Spec.OldHeader);
  std::string AbsoluteCurrentFile = MakeAbsolutePath(SM, FileName);
  if (AbsoluteOldHeader == AbsoluteCurrentFile) {
    // Find old.h includes "old.h".
    if (AbsoluteOldHeader == AbsoluteIncludeHeader) {
      OldHeaderIncludeRangeInHeader = IncludeFilenameRange;
      return;
    }
    HeaderIncludes.push_back(IncludeLine);
  } else if (makeAbsolutePath(Context->Spec.OldCC) == AbsoluteCurrentFile) {
    // Find old.cc includes "old.h".
    if (AbsoluteOldHeader == AbsoluteIncludeHeader) {
      OldHeaderIncludeRangeInCC = IncludeFilenameRange;
      return;
    }
    CCIncludes.push_back(IncludeLine);
  }
}

void ClangMoveTool::removeDeclsInOldFiles() {
  if (RemovedDecls.empty()) return;

  // If old_header is not specified (only move declarations from old.cc), remain
  // all the helper function declarations in old.cc as UnremovedDeclsInOldHeader
  // is empty in this case, there is no way to verify unused/used helpers.
  if (!Context->Spec.OldHeader.empty()) {
    std::vector<const NamedDecl *> UnremovedDecls;
    for (const auto *D : UnremovedDeclsInOldHeader)
      UnremovedDecls.push_back(D);

    auto UsedDecls = getUsedDecls(RGBuilder.getGraph(), UnremovedDecls);

    // We remove the helper declarations which are not used in the old.cc after
    // moving the given declarations.
    for (const auto *D : HelperDeclarations) {
      LLVM_DEBUG(llvm::dbgs() << "Check helper is used: "
                              << D->getNameAsString() << " (" << D << ")\n");
      if (!UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(
              D->getCanonicalDecl()))) {
        LLVM_DEBUG(llvm::dbgs() << "Helper removed in old.cc: "
                                << D->getNameAsString() << " (" << D << ")\n");
        RemovedDecls.push_back(D);
      }
    }
  }

  for (const auto *RemovedDecl : RemovedDecls) {
    const auto &SM = RemovedDecl->getASTContext().getSourceManager();
    auto Range = getFullRange(RemovedDecl);
    tooling::Replacement RemoveReplacement(
        SM, CharSourceRange::getCharRange(Range.getBegin(), Range.getEnd()),
        "");
    std::string FilePath = RemoveReplacement.getFilePath().str();
    auto Err = Context->FileToReplacements[FilePath].add(RemoveReplacement);
    if (Err)
      llvm::errs() << llvm::toString(std::move(Err)) << "\n";
  }
  const auto &SM = RemovedDecls[0]->getASTContext().getSourceManager();

  // Post process of cleanup around all the replacements.
  for (auto &FileAndReplacements : Context->FileToReplacements) {
    StringRef FilePath = FileAndReplacements.first;
    // Add #include of new header to old header.
    if (Context->Spec.OldDependOnNew &&
        MakeAbsolutePath(SM, FilePath) ==
            makeAbsolutePath(Context->Spec.OldHeader)) {
      // FIXME: Minimize the include path like clang-include-fixer.
      std::string IncludeNewH =
          "#include \"" + Context->Spec.NewHeader + "\"\n";
      // This replacment for inserting header will be cleaned up at the end.
      auto Err = FileAndReplacements.second.add(
          tooling::Replacement(FilePath, UINT_MAX, 0, IncludeNewH));
      if (Err)
        llvm::errs() << llvm::toString(std::move(Err)) << "\n";
    }

    auto SI = FilePathToFileID.find(FilePath);
    // Ignore replacements for new.h/cc.
    if (SI == FilePathToFileID.end()) continue;
    llvm::StringRef Code = SM.getBufferData(SI->second);
    auto Style = format::getStyle(format::DefaultFormatStyle, FilePath,
                                  Context->FallbackStyle);
    if (!Style) {
      llvm::errs() << llvm::toString(Style.takeError()) << "\n";
      continue;
    }
    auto CleanReplacements = format::cleanupAroundReplacements(
        Code, Context->FileToReplacements[FilePath], *Style);

    if (!CleanReplacements) {
      llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
      continue;
    }
    Context->FileToReplacements[FilePath] = *CleanReplacements;
  }
}

void ClangMoveTool::moveDeclsToNewFiles() {
  std::vector<const NamedDecl *> NewHeaderDecls;
  std::vector<const NamedDecl *> NewCCDecls;
  for (const auto *MovedDecl : MovedDecls) {
    if (isInHeaderFile(MovedDecl, Context->OriginalRunningDirectory,
                       Context->Spec.OldHeader))
      NewHeaderDecls.push_back(MovedDecl);
    else
      NewCCDecls.push_back(MovedDecl);
  }

  auto UsedDecls = getUsedDecls(RGBuilder.getGraph(), RemovedDecls);
  std::vector<const NamedDecl *> ActualNewCCDecls;

  // Filter out all unused helpers in NewCCDecls.
  // We only move the used helpers (including transively used helpers) and the
  // given symbols being moved.
  for (const auto *D : NewCCDecls) {
    if (llvm::is_contained(HelperDeclarations, D) &&
        !UsedDecls.count(HelperDeclRGBuilder::getOutmostClassOrFunDecl(
            D->getCanonicalDecl())))
      continue;

    LLVM_DEBUG(llvm::dbgs() << "Helper used in new.cc: " << D->getNameAsString()
                            << " " << D << "\n");
    ActualNewCCDecls.push_back(D);
  }

  if (!Context->Spec.NewHeader.empty()) {
    std::string OldHeaderInclude =
        Context->Spec.NewDependOnOld
            ? "#include \"" + Context->Spec.OldHeader + "\"\n"
            : "";
    Context->FileToReplacements[Context->Spec.NewHeader] =
        createInsertedReplacements(HeaderIncludes, NewHeaderDecls,
                                   Context->Spec.NewHeader, /*IsHeader=*/true,
                                   OldHeaderInclude);
  }
  if (!Context->Spec.NewCC.empty())
    Context->FileToReplacements[Context->Spec.NewCC] =
        createInsertedReplacements(CCIncludes, ActualNewCCDecls,
                                   Context->Spec.NewCC);
}

// Move all contents from OldFile to NewFile.
void ClangMoveTool::moveAll(SourceManager &SM, StringRef OldFile,
                            StringRef NewFile) {
  auto FE = SM.getFileManager().getFile(makeAbsolutePath(OldFile));
  if (!FE) {
    llvm::errs() << "Failed to get file: " << OldFile << "\n";
    return;
  }
  FileID ID = SM.getOrCreateFileID(*FE, SrcMgr::C_User);
  auto Begin = SM.getLocForStartOfFile(ID);
  auto End = SM.getLocForEndOfFile(ID);
  tooling::Replacement RemoveAll(SM, CharSourceRange::getCharRange(Begin, End),
                                 "");
  std::string FilePath = RemoveAll.getFilePath().str();
  Context->FileToReplacements[FilePath] = tooling::Replacements(RemoveAll);

  StringRef Code = SM.getBufferData(ID);
  if (!NewFile.empty()) {
    auto AllCode =
        tooling::Replacements(tooling::Replacement(NewFile, 0, 0, Code));
    auto ReplaceOldInclude = [&](CharSourceRange OldHeaderIncludeRange) {
      AllCode = AllCode.merge(tooling::Replacements(tooling::Replacement(
          SM, OldHeaderIncludeRange, '"' + Context->Spec.NewHeader + '"')));
    };
    // Fix the case where old.h/old.cc includes "old.h", we replace the
    // `#include "old.h"` with `#include "new.h"`.
    if (Context->Spec.NewCC == NewFile && OldHeaderIncludeRangeInCC.isValid())
      ReplaceOldInclude(OldHeaderIncludeRangeInCC);
    else if (Context->Spec.NewHeader == NewFile &&
             OldHeaderIncludeRangeInHeader.isValid())
      ReplaceOldInclude(OldHeaderIncludeRangeInHeader);
    Context->FileToReplacements[NewFile] = std::move(AllCode);
  }
}

void ClangMoveTool::onEndOfTranslationUnit() {
  if (Context->DumpDeclarations) {
    assert(Reporter);
    for (const auto *Decl : UnremovedDeclsInOldHeader) {
      auto Kind = Decl->getKind();
      bool Templated = Decl->isTemplated();
      const std::string QualifiedName = Decl->getQualifiedNameAsString();
      if (Kind == Decl::Kind::Var)
        Reporter->reportDeclaration(QualifiedName, "Variable", Templated);
      else if (Kind == Decl::Kind::Function ||
               Kind == Decl::Kind::FunctionTemplate)
        Reporter->reportDeclaration(QualifiedName, "Function", Templated);
      else if (Kind == Decl::Kind::ClassTemplate ||
               Kind == Decl::Kind::CXXRecord)
        Reporter->reportDeclaration(QualifiedName, "Class", Templated);
      else if (Kind == Decl::Kind::Enum)
        Reporter->reportDeclaration(QualifiedName, "Enum", Templated);
      else if (Kind == Decl::Kind::Typedef || Kind == Decl::Kind::TypeAlias ||
               Kind == Decl::Kind::TypeAliasTemplate)
        Reporter->reportDeclaration(QualifiedName, "TypeAlias", Templated);
    }
    return;
  }

  if (RemovedDecls.empty())
    return;
  // Ignore symbols that are not supported when checking if there is unremoved
  // symbol in old header. This makes sure that we always move old files to new
  // files when all symbols produced from dump_decls are moved.
  auto IsSupportedKind = [](const NamedDecl *Decl) {
    switch (Decl->getKind()) {
    case Decl::Kind::Function:
    case Decl::Kind::FunctionTemplate:
    case Decl::Kind::ClassTemplate:
    case Decl::Kind::CXXRecord:
    case Decl::Kind::Enum:
    case Decl::Kind::Typedef:
    case Decl::Kind::TypeAlias:
    case Decl::Kind::TypeAliasTemplate:
    case Decl::Kind::Var:
      return true;
    default:
      return false;
    }
  };
  if (std::none_of(UnremovedDeclsInOldHeader.begin(),
                   UnremovedDeclsInOldHeader.end(), IsSupportedKind) &&
      !Context->Spec.OldHeader.empty()) {
    auto &SM = RemovedDecls[0]->getASTContext().getSourceManager();
    moveAll(SM, Context->Spec.OldHeader, Context->Spec.NewHeader);
    moveAll(SM, Context->Spec.OldCC, Context->Spec.NewCC);
    return;
  }
  LLVM_DEBUG(RGBuilder.getGraph()->dump());
  moveDeclsToNewFiles();
  removeDeclsInOldFiles();
}

} // namespace move
} // namespace clang
