//===-- ClangMoveMain.cpp - move defintion to new file ----------*- 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 "ClangMove.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/YAMLTraits.h"
#include <set>
#include <string>

using namespace clang;
using namespace llvm;

namespace {

std::error_code CreateNewFile(const llvm::Twine &path) {
  int fd = 0;
  if (std::error_code ec = llvm::sys::fs::openFileForWrite(
          path, fd, llvm::sys::fs::CD_CreateAlways, llvm::sys::fs::F_Text))
    return ec;

  return llvm::sys::Process::SafelyCloseFileDescriptor(fd);
}

cl::OptionCategory ClangMoveCategory("clang-move options");

cl::list<std::string> Names("names", cl::CommaSeparated,
                            cl::desc("The list of the names of classes being "
                                     "moved, e.g. \"Foo,a::Foo,b::Foo\"."),
                            cl::cat(ClangMoveCategory));

cl::opt<std::string>
    OldHeader("old_header",
              cl::desc("The relative/absolute file path of old header."),
              cl::cat(ClangMoveCategory));

cl::opt<std::string>
    OldCC("old_cc", cl::desc("The relative/absolute file path of old cc."),
          cl::cat(ClangMoveCategory));

cl::opt<std::string>
    NewHeader("new_header",
              cl::desc("The relative/absolute file path of new header."),
              cl::cat(ClangMoveCategory));

cl::opt<std::string>
    NewCC("new_cc", cl::desc("The relative/absolute file path of new cc."),
          cl::cat(ClangMoveCategory));

cl::opt<bool>
    OldDependOnNew("old_depend_on_new",
                   cl::desc("Whether old header will depend on new header. If "
                            "true, clang-move will "
                            "add #include of new header to old header."),
                   cl::init(false), cl::cat(ClangMoveCategory));

cl::opt<bool>
    NewDependOnOld("new_depend_on_old",
                   cl::desc("Whether new header will depend on old header. If "
                            "true, clang-move will "
                            "add #include of old header to new header."),
                   cl::init(false), cl::cat(ClangMoveCategory));

cl::opt<std::string>
    Style("style",
          cl::desc("The style name used for reformatting. Default is \"llvm\""),
          cl::init("llvm"), cl::cat(ClangMoveCategory));

cl::opt<bool> Dump("dump_result",
                   cl::desc("Dump results in JSON format to stdout."),
                   cl::cat(ClangMoveCategory));

cl::opt<bool> DumpDecls(
    "dump_decls",
    cl::desc("Dump all declarations in old header (JSON format) to stdout. If "
             "the option is specified, other command options will be ignored. "
             "An empty JSON will be returned if old header isn't specified."),
    cl::cat(ClangMoveCategory));

} // namespace

int main(int argc, const char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
  tooling::CommonOptionsParser OptionsParser(argc, argv, ClangMoveCategory);

  if (OldDependOnNew && NewDependOnOld) {
    llvm::errs() << "Provide either --old_depend_on_new or "
                    "--new_depend_on_old. clang-move doesn't support these two "
                    "options at same time (It will introduce include cycle).\n";
    return 1;
  }

  tooling::RefactoringTool Tool(OptionsParser.getCompilations(),
                                OptionsParser.getSourcePathList());
  // Add "-fparse-all-comments" compile option to make clang parse all comments.
  Tool.appendArgumentsAdjuster(tooling::getInsertArgumentAdjuster(
      "-fparse-all-comments", tooling::ArgumentInsertPosition::BEGIN));
  move::MoveDefinitionSpec Spec;
  Spec.Names = {Names.begin(), Names.end()};
  Spec.OldHeader = OldHeader;
  Spec.NewHeader = NewHeader;
  Spec.OldCC = OldCC;
  Spec.NewCC = NewCC;
  Spec.OldDependOnNew = OldDependOnNew;
  Spec.NewDependOnOld = NewDependOnOld;

  llvm::SmallString<128> InitialDirectory;
  if (std::error_code EC = llvm::sys::fs::current_path(InitialDirectory))
    llvm::report_fatal_error("Cannot detect current path: " +
                             Twine(EC.message()));

  move::ClangMoveContext Context{Spec, Tool.getReplacements(),
                                 InitialDirectory.str(), Style, DumpDecls};
  move::DeclarationReporter Reporter;
  move::ClangMoveActionFactory Factory(&Context, &Reporter);

  int CodeStatus = Tool.run(&Factory);
  if (CodeStatus)
    return CodeStatus;

  if (DumpDecls) {
    llvm::outs() << "[\n";
    const auto &Declarations = Reporter.getDeclarationList();
    for (auto I = Declarations.begin(), E = Declarations.end(); I != E; ++I) {
      llvm::outs() << "  {\n";
      llvm::outs() << "    \"DeclarationName\": \"" << I->QualifiedName
                   << "\",\n";
      llvm::outs() << "    \"DeclarationType\": \"" << I->Kind << "\",\n";
      llvm::outs() << "    \"Templated\": " << (I->Templated ? "true" : "false")
                   << "\n";
      llvm::outs() << "  }";
      // Don't print trailing "," at the end of last element.
      if (I != std::prev(E))
        llvm::outs() << ",\n";
    }
    llvm::outs() << "\n]\n";
    return 0;
  }

  if (!NewCC.empty()) {
    std::error_code EC = CreateNewFile(NewCC);
    if (EC) {
      llvm::errs() << "Failed to create " << NewCC << ": " << EC.message()
                   << "\n";
      return EC.value();
    }
  }
  if (!NewHeader.empty()) {
    std::error_code EC = CreateNewFile(NewHeader);
    if (EC) {
      llvm::errs() << "Failed to create " << NewHeader << ": " << EC.message()
                   << "\n";
      return EC.value();
    }
  }

  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions());
  clang::TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);
  DiagnosticsEngine Diagnostics(
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
      &DiagnosticPrinter, false);
  auto &FileMgr = Tool.getFiles();
  SourceManager SM(Diagnostics, FileMgr);
  Rewriter Rewrite(SM, LangOptions());

  if (!formatAndApplyAllReplacements(Tool.getReplacements(), Rewrite, Style)) {
    llvm::errs() << "Failed applying all replacements.\n";
    return 1;
  }

  if (Dump) {
    std::set<llvm::StringRef> Files;
    for (const auto &it : Tool.getReplacements())
      Files.insert(it.first);
    auto WriteToJson = [&](llvm::raw_ostream &OS) {
      OS << "[\n";
      for (auto I = Files.begin(), E = Files.end(); I != E; ++I) {
        OS << "  {\n";
        OS << "    \"FilePath\": \"" << *I << "\",\n";
        const auto *Entry = FileMgr.getFile(*I);
        auto ID = SM.translateFile(Entry);
        std::string Content;
        llvm::raw_string_ostream ContentStream(Content);
        Rewrite.getEditBuffer(ID).write(ContentStream);
        OS << "    \"SourceText\": \""
           << llvm::yaml::escape(ContentStream.str()) << "\"\n";
        OS << "  }";
        if (I != std::prev(E))
          OS << ",\n";
      }
      OS << "\n]\n";
    };
    WriteToJson(llvm::outs());
    return 0;
  }

  return Rewrite.overwriteChangedFiles();
}
