//===--- swift-refactor.cpp - Test driver for local refactoring --*- C++ -*-==//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CommandLine.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/Refactoring.h"
#include "swift/IDE/Utils.h"

#include <regex>

using namespace swift;
using namespace swift::ide;

namespace options {
static llvm::cl::opt<RefactoringKind>
Action(llvm::cl::desc("kind:"), llvm::cl::init(RefactoringKind::None),
       llvm::cl::values(
           clEnumValN(RefactoringKind::LocalRename,
                      "rename", "Perform rename refactoring"),
           clEnumValN(RefactoringKind::ExtractExpr,
                      "extract-expr", "Perform extract expression refactoring"),
           clEnumValN(RefactoringKind::ExtractRepeatedExpr,
                      "extract-repeat", "Perform extract repeated expression refactoring"),
           clEnumValN(RefactoringKind::FillProtocolStub,
                      "fill-stub", "Perform fill protocol stub refactoring"),
           clEnumValN(RefactoringKind::ExpandDefault,
                      "expand-default", "Perform expand default statement refactoring"),
           clEnumValN(RefactoringKind::ExpandSwitchCases,
                      "expand-switch-cases", "Perform switch cases expand refactoring"),
           clEnumValN(RefactoringKind::LocalizeString,
                      "localize-string", "Perform string localization refactoring"),
           clEnumValN(RefactoringKind::CollapseNestedIfExpr,
                      "collapse-nested-if", "Perform collapse nested if statements"),
           clEnumValN(RefactoringKind::ConvertToDoCatch,
                      "convert-to-do-catch", "Perform force try to do try catch refactoring"),
           clEnumValN(RefactoringKind::SimplifyNumberLiteral,
                      "simplify-long-number", "Perform simplify long number literal refactoring"),
           clEnumValN(RefactoringKind::ConvertStringsConcatenationToInterpolation,
                      "strings-concatenation-to-interpolation", "Perform strings concatenation to interpolation refactoring"),
           clEnumValN(RefactoringKind::ExtractFunction,
                      "extract-function", "Perform extract function refactoring"),
           clEnumValN(RefactoringKind::MoveMembersToExtension,
                      "move-to-extension", "Move selected members to an extension"),
           clEnumValN(RefactoringKind::GlobalRename,
                      "syntactic-rename", "Perform syntactic rename"),
           clEnumValN(RefactoringKind::FindGlobalRenameRanges,
                      "find-rename-ranges", "Find detailed ranges for syntactic rename"),
           clEnumValN(RefactoringKind::FindLocalRenameRanges,
                      "find-local-rename-ranges", "Find detailed ranges for local rename"),
           clEnumValN(RefactoringKind::TrailingClosure,
                      "trailingclosure", "Perform trailing closure refactoring")));


static llvm::cl::opt<std::string>
ModuleName("module-name", llvm::cl::desc("The module name of the given test."),
            llvm::cl::init("swift_refactor"));

static llvm::cl::opt<std::string>
SourceFilename("source-filename", llvm::cl::desc("Name of the source file"));

static llvm::cl::list<std::string>
InputFilenames(llvm::cl::Positional, llvm::cl::desc("[input files...]"),
               llvm::cl::ZeroOrMore);

static llvm::cl::opt<std::string>
LineColumnPair("pos", llvm::cl::desc("Line:Column pair or /*label*/"));

static llvm::cl::opt<std::string>
EndLineColumnPair("end-pos", llvm::cl::desc("Line:Column pair or /*label*/"));

static llvm::cl::opt<std::string>
NewName("new-name", llvm::cl::desc("A given name to rename to"),
        llvm::cl::init("new_name"));

static llvm::cl::opt<std::string>
OldName("old-name", llvm::cl::desc("The expected existing name"),
        llvm::cl::init("old_name"));

static llvm::cl::opt<bool>
IsFunctionLike("is-function-like", llvm::cl::desc("The symbol being renamed is function-like"),
               llvm::cl::ValueDisallowed);

static llvm::cl::opt<bool>
IsNonProtocolType("is-non-protocol-type",
                  llvm::cl::desc("The symbol being renamed is a type and not a protocol"));

static llvm::cl::opt<bool>
DumpInJason("dump-json",
            llvm::cl::desc("Whether to dump refactoring edits in Json"),
            llvm::cl::init(false));

static llvm::cl::opt<bool>
AvailableActions("actions",
            llvm::cl::desc("Dump the available refactoring kind for a given range"),
            llvm::cl::init(false));
}

bool doesFileExist(StringRef Path) {
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
    llvm::MemoryBuffer::getFile(Path);
  if(FileBufOrErr)
    return true;
  return false;
}

struct RefactorLoc {
  unsigned Line;
  unsigned Column;
  NameUsage Usage;
};

NameUsage convertToNameUsage(StringRef RoleString) {
  if (RoleString == "unknown")
    return NameUsage::Unknown;
  if (RoleString == "def")
    return NameUsage::Definition;
  if (RoleString == "ref")
    return NameUsage::Reference;
  if (RoleString == "call")
    return NameUsage::Call;
  llvm_unreachable("unhandled role string");
}

std::vector<RefactorLoc> getLocsByLabelOrPosition(StringRef LabelOrLineCol,
                                                         std::string &Buffer) {

  std::vector<RefactorLoc> LocResults;
  if (LabelOrLineCol.empty())
    return LocResults;

  if (LabelOrLineCol.contains(':')) {
    auto LineCol = parseLineCol(LabelOrLineCol);
    if (LineCol.hasValue()) {
      LocResults.push_back({LineCol.getValue().first,LineCol.getValue().second,
        NameUsage::Unknown});
    } else {
      llvm::errs() << "cannot parse position pair.";
    }
    return LocResults;
  }

  std::smatch Matches;
  const std::regex LabelRegex("/\\*([^ *]+)\\*/|\\n");

  std::string::const_iterator SearchStart(Buffer.cbegin());
  unsigned Line = 1;
  unsigned Column = 1;
  while (std::regex_search(SearchStart, Buffer.cend(), Matches, LabelRegex)) {
    auto EndOffset = Matches.position() + Matches.length();
    if (Matches[1].matched) {
      Column += EndOffset;
      std::string MatchedStorage(Matches[1].str());
      StringRef Matched(MatchedStorage);
      size_t ColonPos = Matched.find(':');
      if (Matched.slice(0, ColonPos) == LabelOrLineCol) {
        NameUsage Usage = NameUsage::Reference;
        if (ColonPos != StringRef::npos)
          Usage = convertToNameUsage(Matched.substr(ColonPos + 1));
        LocResults.push_back({Line, Column, Usage});
      }
    } else {
      ++Line;
      Column = 1;
    }
    SearchStart += EndOffset;
  }
  return LocResults;
}

std::vector<RenameLoc> getRenameLocs(unsigned BufferID, SourceManager &SM,
                                     ArrayRef<RefactorLoc> Locs,
                                     StringRef OldName, StringRef NewName,
                                     bool IsFunctionLike,
                                     bool IsNonProtocolType) {
  std::vector<RenameLoc> Renames;
  std::transform(Locs.begin(), Locs.end(), std::back_inserter(Renames), [&](const RefactorLoc &Loc) -> RenameLoc {
    return {Loc.Line, Loc.Column, Loc.Usage, OldName, NewName, IsFunctionLike,
      IsNonProtocolType};
  });
  return Renames;
}

RangeConfig getRange(unsigned BufferID, SourceManager &SM,
                                   RefactorLoc Start,
                                   RefactorLoc End) {
    RangeConfig Range;
    SourceLoc EndLoc = SM.getLocForLineCol(BufferID, End.Line,
                                           End.Column);
    Range.BufferId = BufferID;
    Range.Line = Start.Line;
    Range.Column = Start.Column;
    Range.Length = SM.getByteDistance(Range.getStart(SM), EndLoc);

    assert(Range.getEnd(SM) == EndLoc);
    return Range;
}

// 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() {}

int main(int argc, char *argv[]) {
  INITIALIZE_LLVM(argc, argv);
  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift refactor\n");
  if (options::SourceFilename.empty()) {
    llvm::errs() << "cannot find source filename\n";
    return 1;
  }
  if (!doesFileExist(options::SourceFilename)) {
    llvm::errs() << "cannot open source file.\n";
    return 1;
  }

  CompilerInvocation Invocation;
  Invocation.setMainExecutablePath(
    llvm::sys::fs::getMainExecutable(argv[0],
    reinterpret_cast<void *>(&anchorForGetMainExecutable)));
  Invocation.addInputFilename(options::SourceFilename);
  Invocation.getLangOptions().AttachCommentsToDecls = true;
  Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;

  for (auto FileName : options::InputFilenames)
    Invocation.addInputFilename(FileName);
  Invocation.setModuleName(options::ModuleName);
  CompilerInstance CI;
  // Display diagnostics to stderr.
  PrintingDiagnosticConsumer PrintDiags;
  CI.addDiagnosticConsumer(&PrintDiags);
  if (CI.setup(Invocation))
    return 1;

  switch (options::Action) {
    case RefactoringKind::GlobalRename:
    case RefactoringKind::FindGlobalRenameRanges:
      CI.performParseOnly(/*EvaluateConditionals*/true);
      break;
    default:
      CI.performSema();
  }

  SourceFile *SF = nullptr;
  for (auto Unit : CI.getMainModule()->getFiles()) {
    if (auto Current = dyn_cast<SourceFile>(Unit)) {
      if (Current->getFilename() == options::SourceFilename)
        SF = Current;
    }
    if (SF)
      break;
  }
  assert(SF && "no source file?");

  SourceManager &SM = SF->getASTContext().SourceMgr;
  unsigned BufferID = SF->getBufferID().getValue();
  std::string Buffer = SM.getRangeForBuffer(BufferID).str();

  auto Start = getLocsByLabelOrPosition(options::LineColumnPair, Buffer);
  if (Start.empty()) {
    llvm::errs() << "cannot parse position pair.";
    return 1;
  }

  RefactorLoc EndLoc = Start.front();
  if (options::EndLineColumnPair.getNumOccurrences() == 1) {
    auto End = getLocsByLabelOrPosition(options::EndLineColumnPair, Buffer);
    if (End.size() > 1) {
      llvm::errs() << "only a single start and end position may be specified.";
      return 1;
    }
    EndLoc = End.front();
  }

  RefactorLoc &StartLoc = Start.front();


  if (options::Action == RefactoringKind::FindLocalRenameRanges) {
    RangeConfig Range = getRange(BufferID, SM, StartLoc, EndLoc);
    FindRenameRangesAnnotatingConsumer Consumer(SM, BufferID, llvm::outs());
    return findLocalRenameRanges(SF, Range, Consumer, PrintDiags);
  }

  if (options::Action == RefactoringKind::GlobalRename ||
      options::Action == RefactoringKind::FindGlobalRenameRanges) {
    if (!options::OldName.getNumOccurrences()) {
      llvm::errs() << "old-name must be specified.";
      return 1;
    }
    if (options::Action == RefactoringKind::GlobalRename && !options::NewName.getNumOccurrences()) {
      llvm::errs() << "new-name must be specified.";
      return 1;
    }

    std::string NewName = options::NewName;
    if (!options::NewName.getNumOccurrences()) {
      // Unlike other operations, we don't want to provide a default new_name,
      // since we don't want to validate the new name.
      NewName = "";
    }

    std::vector<RenameLoc>
    RenameLocs = getRenameLocs(BufferID, SM, Start, options::OldName, NewName,
                               options::IsFunctionLike.getNumOccurrences(),
                               options::IsNonProtocolType.getNumOccurrences());

    switch (options::Action) {
    case RefactoringKind::GlobalRename: {
      SourceEditOutputConsumer EditConsumer(SM, BufferID, llvm::outs());
      return syntacticRename(SF, RenameLocs, EditConsumer, PrintDiags);
    }
    case RefactoringKind::FindGlobalRenameRanges: {
      FindRenameRangesAnnotatingConsumer Consumer(SM, BufferID, llvm::outs());
      return findSyntacticRenameRanges(SF, RenameLocs, Consumer, PrintDiags);
    }
    default:
      llvm_unreachable("unexpected refactoring kind");
    }
  }

  RangeConfig Range = getRange(BufferID, SM, StartLoc, EndLoc);

  if (options::Action == RefactoringKind::None) {
    std::vector<RefactoringKind> Scratch;
    ArrayRef<RefactoringKind> AllKinds;
    bool RangeStartMayNeedRename = false;
    AllKinds = collectAvailableRefactorings(SF, Range,RangeStartMayNeedRename,
                                            Scratch, {&PrintDiags});
    llvm::outs() << "Action begins\n";
    for (auto Kind : AllKinds) {
      llvm::outs() << getDescriptiveRefactoringKindName(Kind) << "\n";
    }
    llvm::outs() << "Action ends\n";
    return 0;
  }

  RefactoringOptions RefactoringConfig(options::Action);
  RefactoringConfig.Range = Range;
  RefactoringConfig.PreferredName = options::NewName;
  std::string Error;
  std::unique_ptr<SourceEditConsumer> pConsumer;
  if (options::DumpInJason)
    pConsumer.reset(new SourceEditJsonConsumer(llvm::outs()));
  else
    pConsumer.reset(new SourceEditOutputConsumer(SF->getASTContext().SourceMgr,
                                                      BufferID,
                                                      llvm::outs()));

  return refactorSwiftModule(CI.getMainModule(), RefactoringConfig, *pConsumer,
                             PrintDiags);
}
