//===--- ClangRefactorTest.cpp - ------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements a clang-refactor-test tool that is used to test the
//  refactoring library in Clang.
//
//===----------------------------------------------------------------------===//

#include "clang-c/Refactor.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/CommandLineSourceLoc.h"
#include "clang/Tooling/Refactor/SymbolName.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;
using namespace clang;

namespace opts {

static cl::OptionCategory
    ClangRefactorTestOptions("clang-refactor-test common options");

cl::SubCommand RenameInitiateSubcommand(
    "rename-initiate", "Initiate renaming in an initial translation unit");

cl::SubCommand RenameInitiateUSRSubcommand(
    "rename-initiate-usr",
    "Initiate renaming in an translation unit on a specific declaration");

cl::SubCommand RenameIndexedFileSubcommand(
    "rename-indexed-file",
    "Initiate renaming and find occurrences in an indexed file");

cl::SubCommand ListRefactoringActionsSubcommand("list-actions",
                                                "Print the list of the "
                                                "refactoring actions that can "
                                                "be performed at the specified "
                                                "location");

cl::SubCommand InitiateActionSubcommand("initiate",
                                        "Initiate a refactoring action");

cl::SubCommand
    PerformActionSubcommand("perform",
                            "Initiate and perform a refactoring action");

const cl::desc
    AtOptionDescription("The location at which the refactoring should be "
                        "initiated (<file>:<line>:<column>)");

const cl::desc InRangeOptionDescription(
    "The location(s) at which the refactoring should be "
    "initiated (<file>:<line>:<column>-<last-column>)");

const cl::desc SelectedRangeOptionDescription(
    "The selected source range in which the refactoring should be "
    "initiated (<file>:<line>:<column>-<line>:<column>)");

static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);

namespace rename {
static cl::list<std::string> AtLocation("at", AtOptionDescription, cl::Required,
                                        cl::cat(ClangRefactorTestOptions),
                                        cl::sub(RenameInitiateSubcommand),
                                        cl::OneOrMore);

static cl::opt<std::string>
    USR("usr", cl::desc("The USR of the declaration that should be renamed"),
        cl::cat(ClangRefactorTestOptions), cl::sub(RenameInitiateUSRSubcommand),
        cl::Required);

static cl::opt<std::string>
    NewName("new-name", cl::desc("The new name to change the symbol to."),
            cl::Required, cl::cat(ClangRefactorTestOptions),
            cl::sub(RenameInitiateSubcommand),
            cl::sub(RenameInitiateUSRSubcommand));

static cl::list<std::string>
    IndexedNames("name", cl::desc("The names of the renamed symbols"),
                 cl::Required, cl::OneOrMore, cl::cat(ClangRefactorTestOptions),
                 cl::sub(RenameIndexedFileSubcommand));

static cl::list<std::string> IndexedNewNames(
    "new-name", cl::desc("The new name to change the symbol to."), cl::Required,
    cl::OneOrMore, cl::cat(ClangRefactorTestOptions),
    cl::sub(RenameIndexedFileSubcommand));

static cl::opt<std::string>
    IndexedSymbolKind("indexed-symbol-kind",
                      cl::desc("The kind of the indexed symbol."), cl::Optional,
                      cl::cat(ClangRefactorTestOptions),
                      cl::sub(RenameIndexedFileSubcommand));

static cl::opt<std::string>
    IndexedFileName("indexed-file", cl::desc("The name of the indexed file"),
                    cl::Required, cl::cat(ClangRefactorTestOptions),
                    cl::sub(RenameIndexedFileSubcommand));

static cl::list<std::string>
    IndexedLocations("indexed-at",
                     cl::desc("The location of an indexed occurrence "
                              "([<kind>|<symbol-index>:]<line>:<column>)"),
                     cl::ZeroOrMore, cl::cat(ClangRefactorTestOptions),
                     cl::sub(RenameIndexedFileSubcommand));

static cl::opt<bool> AvoidTextual(
    "no-textual-matches", cl::desc("Avoid searching for textual matches"),
    cl::cat(ClangRefactorTestOptions), cl::sub(RenameIndexedFileSubcommand));

static cl::opt<bool> DumpSymbols(
    "dump-symbols", cl::desc("Dump the information about the renamed symbols"),
    cl::cat(ClangRefactorTestOptions), cl::sub(RenameInitiateSubcommand),
    cl::sub(RenameInitiateUSRSubcommand));
}

namespace listActions {
cl::opt<std::string> AtLocation("at", AtOptionDescription, cl::Required,
                                cl::cat(ClangRefactorTestOptions),
                                cl::sub(ListRefactoringActionsSubcommand));

cl::opt<std::string> SelectedRange("selected", SelectedRangeOptionDescription,
                                   cl::cat(ClangRefactorTestOptions),
                                   cl::sub(ListRefactoringActionsSubcommand));

cl::opt<bool> DumpRawActionType(
    "dump-raw-action-type",
    cl::desc("Prints the action type integer value for each listed action"),
    cl::cat(ClangRefactorTestOptions),
    cl::sub(ListRefactoringActionsSubcommand));
}

namespace initiateAndPerform {
cl::list<std::string> InLocationRanges("in", cl::ZeroOrMore,
                                       InRangeOptionDescription,
                                       cl::cat(ClangRefactorTestOptions),
                                       cl::sub(InitiateActionSubcommand));

cl::list<std::string> AtLocations("at", cl::ZeroOrMore, AtOptionDescription,
                                  cl::cat(ClangRefactorTestOptions),
                                  cl::sub(InitiateActionSubcommand),
                                  cl::sub(PerformActionSubcommand));

cl::list<std::string> SelectedRanges("selected", cl::ZeroOrMore,
                                     SelectedRangeOptionDescription,
                                     cl::cat(ClangRefactorTestOptions),
                                     cl::sub(InitiateActionSubcommand),
                                     cl::sub(PerformActionSubcommand));

cl::opt<std::string> ActionName("action", cl::Required,
                                cl::desc("The name of the refactoring action"),
                                cl::cat(ClangRefactorTestOptions),
                                cl::sub(InitiateActionSubcommand),
                                cl::sub(PerformActionSubcommand));

cl::opt<bool> LocationAgnostic(
    "location-agnostic",
    cl::desc(
        "Ignore the location of initiation when verifying result consistency"),
    cl::cat(ClangRefactorTestOptions), cl::sub(InitiateActionSubcommand));

cl::opt<unsigned> CandidateIndex(
    "candidate",
    cl::desc(
        "The index of the refactoring candidate which should be performed"),
    cl::cat(ClangRefactorTestOptions), cl::sub(PerformActionSubcommand));

cl::opt<std::string> ContinuationFile(
    "continuation-file",
    cl::desc("The source file in which the continuation should run"),
    cl::cat(ClangRefactorTestOptions), cl::sub(PerformActionSubcommand));

cl::opt<std::string> QueryResults(
    "query-results", cl::desc("The indexer query results that should be passed "
                              "into the continuation"),
    cl::cat(ClangRefactorTestOptions), cl::sub(PerformActionSubcommand));

cl::opt<bool> EmitAssociatedInfo(
    "emit-associated", cl::desc("Dump additional associated information"),
    cl::cat(ClangRefactorTestOptions), cl::sub(PerformActionSubcommand));
}

cl::opt<bool> Apply(
    "apply",
    cl::desc(
        "Apply the changes and print the modified file to standard output"),
    cl::cat(ClangRefactorTestOptions), cl::sub(PerformActionSubcommand),
    cl::sub(RenameInitiateSubcommand), cl::sub(RenameIndexedFileSubcommand));

cl::opt<bool>
    Diff("diff",
         cl::desc("Display the replaced text in red when -apply is specified"),
         cl::cat(ClangRefactorTestOptions), cl::sub(PerformActionSubcommand),
         cl::sub(RenameInitiateSubcommand),
         cl::sub(RenameIndexedFileSubcommand));

cl::opt<int> Context("context", cl::desc("How many lines of context should be "
                                         "displayed when -apply is specified"),
                     cl::cat(ClangRefactorTestOptions),
                     cl::sub(PerformActionSubcommand),
                     cl::sub(RenameInitiateSubcommand),
                     cl::sub(RenameIndexedFileSubcommand));

static cl::opt<std::string> FileName(
    cl::Positional, cl::desc("<filename>"), cl::Required,
    cl::cat(ClangRefactorTestOptions), cl::sub(RenameInitiateSubcommand),
    cl::sub(RenameInitiateUSRSubcommand), cl::sub(RenameIndexedFileSubcommand),
    cl::sub(ListRefactoringActionsSubcommand),
    cl::sub(InitiateActionSubcommand), cl::sub(PerformActionSubcommand));

static cl::opt<bool> IgnoreFilenameForInitiationTU(
    "ignore-filename-for-initiation-tu", cl::Optional,
    cl::cat(ClangRefactorTestOptions), cl::sub(RenameIndexedFileSubcommand));

static cl::list<std::string> CompilerArguments(
    cl::ConsumeAfter, cl::desc("<arguments to be passed to the compiler>"),
    cl::cat(ClangRefactorTestOptions), cl::sub(RenameInitiateSubcommand),
    cl::sub(RenameInitiateUSRSubcommand), cl::sub(RenameIndexedFileSubcommand),
    cl::sub(ListRefactoringActionsSubcommand),
    cl::sub(InitiateActionSubcommand), cl::sub(PerformActionSubcommand));

static cl::opt<std::string> ImplementationTU(
    "implementation-tu", cl::desc("The name of the implementation TU"),
    cl::cat(ClangRefactorTestOptions), cl::sub(RenameInitiateSubcommand));
}

static const char *renameOccurrenceKindString(CXSymbolOccurrenceKind Kind,
                                              bool IsLocal,
                                              bool IsMacroExpansion) {
  switch (Kind) {
  case CXSymbolOccurrence_MatchingSymbol:
    return IsMacroExpansion ? "macro" : IsLocal ? "rename local" : "rename";
  case CXSymbolOccurrence_MatchingSelector:
    assert(!IsLocal && "Objective-C selector renames must be global");
    return IsMacroExpansion ? "selector in macro" : "selector";
  case CXSymbolOccurrence_MatchingImplicitProperty:
    assert(!IsLocal);
    return IsMacroExpansion ? "implicit-property in macro"
                            : "implicit-property";
  case CXSymbolOccurrence_MatchingCommentString:
    return "comment";
  case CXSymbolOccurrence_MatchingDocCommentString:
    return "documentation";
  case CXSymbolOccurrence_MatchingFilename:
    return "filename";
  case CXSymbolOccurrence_ExtractedDeclaration:
    return "extracted-decl";
  case CXSymbolOccurrence_ExtractedDeclaration_Reference:
    return "extracted-decl-ref";
  }
}

static int apply(ArrayRef<CXRefactoringReplacement> Replacements,
                 StringRef Filename) {
  // Assume that the replacements are sorted.
  auto Result = MemoryBuffer::getFile(Filename);
  if (!Result) {
    errs() << "Failed to open " << Filename << "\n";
    return 1;
  }

  raw_ostream &OS = outs();

  int Context = opts::Context;

  MemoryBuffer &Buffer = **Result;
  std::vector<std::pair<StringRef, std::vector<CXRefactoringReplacement>>>
      Lines;
  for (auto I = line_iterator(Buffer, /*SkipBlanks=*/false),
            E = line_iterator();
       I != E; ++I)
    Lines.push_back(
        std::make_pair(*I, std::vector<CXRefactoringReplacement>()));
  unsigned FlushedLine = 1;
  auto FlushUntil = [&](unsigned Line) {
    // Adjust the first flushed line if needed when printing in context mode.
    if (FlushedLine == 1 && Context)
      FlushedLine = std::max(int(Line) - Context, 1);
    for (; FlushedLine < Line; ++FlushedLine) {
      const auto &Line = Lines[FlushedLine - 1];
      if (Line.second.empty()) {
        OS << Line.first << "\n";
        continue;
      }

      unsigned I = 0;
      for (const CXRefactoringReplacement &Replacement : Line.second) {
        OS << Line.first.substr(I, Replacement.Range.Begin.Column - 1 - I);
        if (opts::Diff) {
          OS.changeColor(raw_ostream::RED, false, true);
          OS << Line.first.substr(Replacement.Range.Begin.Column - 1,
                                  Replacement.Range.End.Column - 1 -
                                      (Replacement.Range.Begin.Column - 1));
        }
        OS.changeColor(raw_ostream::GREEN);
        OS << clang_getCString(Replacement.ReplacementString);
        OS.resetColor();
        I = Replacement.Range.End.Column - 1;
      }
      OS << Line.first.substr(I);
      if (I < Line.first.size() || opts::Diff)
        OS << "\n";
    }
  };

  int EndLineMax = 0;
  for (const CXRefactoringReplacement &Replacement : Replacements) {
    EndLineMax = std::max(int(Replacement.Range.End.Line), EndLineMax);
    unsigned StartingLine = Replacement.Range.Begin.Line;
    FlushUntil(StartingLine);
    if (Replacement.Range.End.Line == StartingLine) {
      Lines[StartingLine - 1].second.push_back(Replacement);
      continue;
    }
    // Multi-line replacements have to be split
    for (unsigned I = StartingLine; I <= Replacement.Range.End.Line; ++I) {
      CXRefactoringReplacement NewReplacement;
      if (I == Replacement.Range.End.Line)
        NewReplacement.ReplacementString = Replacement.ReplacementString;
      else
        // FIXME: This is a hack to workaround the fact that the API doesn't
        // provide a way to create a null string. This should be fixed when
        // upstreaming.
        NewReplacement.ReplacementString = {0, 0};
      NewReplacement.Range.Begin.Line = I;
      NewReplacement.Range.Begin.Column =
          I == StartingLine ? Replacement.Range.Begin.Column : 1;
      NewReplacement.Range.End.Line = I;
      NewReplacement.Range.End.Column = I == Replacement.Range.End.Line
                                            ? Replacement.Range.End.Column
                                            : Lines[I - 1].first.size() + 1;
      NewReplacement.AssociatedData = nullptr;
      Lines[I - 1].second.push_back(NewReplacement);
    }
  }
  FlushUntil(Context ? std::min(int(Lines.size()), EndLineMax + Context) + 1
                     : Lines.size() + 2);
  // Print out a dividor when printing in the context mode.
  if (Context) {
    for (int I = 0; I < 80; ++I)
      OS << '-';
    OS << "\n";
  }
  return 0;
}

/// Converts the given renamed \p Occurrence into a string value that represents
/// this occurrence.
static std::string
occurrenceToString(const CXSymbolOccurrence &Occurrence, bool IsLocal,
                   const tooling::SymbolName &NewName,
                   const tooling::SymbolName &ExpectedReplacementStrings,
                   StringRef Filename) {
  std::string Str;
  llvm::raw_string_ostream OS(Str);
  OS << renameOccurrenceKindString(Occurrence.Kind, IsLocal,
                                   Occurrence.IsMacroExpansion)
     << ' ';
  if (!Filename.empty())
    OS << '"' << Filename << "\" ";

  bool FirstRange = true;
  assert(NewName.size() >= Occurrence.NumNamePieces &&
         "new name doesn't match the number of pieces");
  for (unsigned J = 0; J != Occurrence.NumNamePieces; ++J) {
    if (!FirstRange) // TODO
      OS << ", ";

    // Print the replacement string if it doesn't match the expected string.
    if (NewName[J] != ExpectedReplacementStrings[J])
      OS << '"' << NewName[J] << "\" ";

    CXFileRange Range = Occurrence.NamePieces[J];
    OS << Range.Begin.Line << ":" << Range.Begin.Column << " -> "
       << Range.End.Line << ":" << Range.End.Column;
    FirstRange = false;
  }
  return OS.str();
}

static CXCursorKind
renameIndexedOccurrenceKindStringToKind(StringRef Str, CXCursorKind Default) {
  return llvm::StringSwitch<CXCursorKind>(Str)
      .Case("objc-im", CXCursor_ObjCInstanceMethodDecl)
      .Case("objc-cm", CXCursor_ObjCClassMethodDecl)
      .Case("objc-message", CXCursor_ObjCMessageExpr)
      .Case("include", CXCursor_InclusionDirective)
      .Default(Default);
}

/// Parses the string passed as the -indexed-at argument.
std::pair<CXRenamedIndexedSymbolLocation, unsigned>
parseIndexedOccurrence(StringRef IndexedOccurrence,
                       CXCursorKind DefaultCursorKind) {
  StringRef LineColumnLoc = IndexedOccurrence;
  CXCursorKind Kind = DefaultCursorKind;
  unsigned SymbolIndex = 0;
  if (LineColumnLoc.count(':') > 1) {
    std::pair<StringRef, StringRef> Split = LineColumnLoc.split(':');
    // The first value is either the kind or the symbol index.
    if (Split.first.getAsInteger(10, SymbolIndex)) {
      if (Split.second.count(':') > 1) {
        std::pair<StringRef, StringRef> SecondSplit = Split.second.split(':');
        if (SecondSplit.first.getAsInteger(10, SymbolIndex))
          assert(false && "expected symbol index");
        Split.second = SecondSplit.second;
      }
      Kind = renameIndexedOccurrenceKindStringToKind(Split.first, Kind);
    }
    LineColumnLoc = Split.second;
  }
  auto Loc = std::string("-:") + LineColumnLoc.str();
  auto Location = ParsedSourceLocation::FromString(Loc);
  return std::make_pair(
      CXRenamedIndexedSymbolLocation{{Location.Line, Location.Column}, Kind},
      SymbolIndex);
}

/// Compare the produced occurrences to the expected occurrences that were
/// gathered at the first location. Return true if the occurrences are
/// different.
static bool compareOccurrences(ArrayRef<std::string> ExpectedReplacements,
                               CXSymbolOccurrencesResult Occurrences,
                               bool IsLocal,
                               const tooling::SymbolName &NewSymbolName,
                               bool PrintFilenames) {
  unsigned NumFiles = clang_SymbolOccurrences_getNumFiles(Occurrences);
  size_t ExpectedReplacementIndex = 0;
  for (unsigned FileIndex = 0; FileIndex < NumFiles; ++FileIndex) {
    CXSymbolOccurrencesInFile FileResult;
    clang_SymbolOccurrences_getOccurrencesForFile(Occurrences, FileIndex,
                                                  &FileResult);
    StringRef Filename =
        PrintFilenames ? clang_getCString(FileResult.Filename) : "";

    for (unsigned I = 0; I != FileResult.NumOccurrences; ++I) {
      std::string Replacement =
          occurrenceToString(FileResult.Occurrences[I], IsLocal, NewSymbolName,
                             NewSymbolName, Filename);
      if (ExpectedReplacementIndex >= ExpectedReplacements.size() ||
          Replacement != ExpectedReplacements[ExpectedReplacementIndex])
        return true;
      ++ExpectedReplacementIndex;
    }
  }
  // Verify that all of the expected replacements were checked.
  return ExpectedReplacementIndex != ExpectedReplacements.size();
}

struct ImplementationTUWrapper {
  CXTranslationUnit TU = nullptr;

  ImplementationTUWrapper() {}
  ~ImplementationTUWrapper() { clang_disposeTranslationUnit(TU); }

  ImplementationTUWrapper(const ImplementationTUWrapper &) = delete;
  ImplementationTUWrapper &operator=(const ImplementationTUWrapper &) = delete;

  bool load(CXRefactoringAction Action, CXIndex CIdx,
            ArrayRef<const char *> Args);
};

bool ImplementationTUWrapper::load(CXRefactoringAction Action, CXIndex CIdx,
                                   ArrayRef<const char *> Args) {
  if (!clang_RefactoringAction_requiresImplementationTU(Action))
    return false;
  CXString USR =
      clang_RefactoringAction_getUSRThatRequiresImplementationTU(Action);
  outs() << "Implementation TU USR: '" << clang_getCString(USR) << "'\n";
  clang_disposeString(USR);
  if (!TU) {
    CXErrorCode Err = clang_parseTranslationUnit2(
        CIdx, opts::ImplementationTU.c_str(), Args.data(), Args.size(), 0, 0,
        CXTranslationUnit_KeepGoing, &TU);
    if (Err != CXError_Success) {
      errs() << "error: failed to load implementation TU '"
             << opts::ImplementationTU << "'\n";
      return true;
    }
  }
  CXErrorCode Err = clang_RefactoringAction_addImplementationTU(Action, TU);
  if (Err != CXError_Success) {
    errs() << "error: failed to add implementation TU '"
           << opts::ImplementationTU << "'\n";
    return true;
  }
  return false;
}

static bool reportNewNameError(CXErrorCode Err) {
  std::string NewName = opts::RenameIndexedFileSubcommand
                            ? opts::rename::IndexedNewNames[0]
                            : opts::rename::NewName;
  if (Err == CXError_RefactoringNameSizeMismatch)
    errs() << "error: the number of strings in the new name '" << NewName
           << "' doesn't match the the number of strings in the old name\n";
  else if (Err == CXError_RefactoringNameInvalid)
    errs() << "error: invalid new name '" << NewName << "'\n";
  else
    return true;
  return false;
}

int rename(CXTranslationUnit TU, CXIndex CIdx, ArrayRef<const char *> Args) {
  assert(!opts::RenameIndexedFileSubcommand);
  // Contains the renamed source replacements for the first location. It is
  // compared to replacements from follow-up renames to ensure that all renames
  // give the same result.
  std::vector<std::string> ExpectedReplacements;
  // Should we print out the filenames. False by default, but true when multiple
  // files are modified.
  bool PrintFilenames = false;
  ImplementationTUWrapper ImplementationTU;

  auto RenameAt = [&](const ParsedSourceLocation &Location,
                      const std::string &USR) -> int {
    CXRefactoringAction RenamingAction;
    CXErrorCode Err;
    CXDiagnosticSet Diags = nullptr;
    if (USR.empty()) {
      CXSourceLocation Loc =
          clang_getLocation(TU, clang_getFile(TU, Location.FileName.c_str()),
                            Location.Line, Location.Column);
      Err = clang_Refactoring_initiateAction(
          TU, Loc, clang_getNullRange(), CXRefactor_Rename,
          /*Options=*/nullptr, &RenamingAction, &Diags);
    } else {
      Err = clang_Refactoring_initiateActionOnDecl(
          TU, USR.c_str(), CXRefactor_Rename, /*Options=*/nullptr,
          &RenamingAction, nullptr);
    }
    if (Err != CXError_Success) {
      errs() << "error: could not rename symbol "
             << (USR.empty() ? "at the given location\n"
                             : "with the given USR\n");
      if (USR.empty()) {
        unsigned NumDiags = clang_getNumDiagnosticsInSet(Diags);
        for (unsigned DiagID = 0; DiagID < NumDiags; ++DiagID) {
          CXDiagnostic Diag = clang_getDiagnosticInSet(Diags, DiagID);
          CXString Spelling = clang_getDiagnosticSpelling(Diag);
          errs() << clang_getCString(Spelling) << "\n";
          clang_disposeString(Spelling);
        }
      }
      clang_disposeDiagnosticSet(Diags);
      return 1;
    }
    clang_disposeDiagnosticSet(Diags);

    if (ImplementationTU.load(RenamingAction, CIdx, Args))
      return 1;

    Err = clang_Refactoring_initiateRenamingOperation(RenamingAction);
    if (Err != CXError_Success) {
      errs() << "error: failed to initiate the renaming operation!\n";
      return 1;
    }

    bool IsLocal = clang_RefactoringAction_getInitiatedActionType(
                       RenamingAction) == CXRefactor_Rename_Local;

    unsigned NumSymbols = clang_RenamingOperation_getNumSymbols(RenamingAction);
    if (opts::rename::DumpSymbols) {
      outs() << "Renaming " << NumSymbols << " symbols\n";
      for (unsigned I = 0; I < NumSymbols; ++I) {
        CXString USR =
            clang_RenamingOperation_getUSRForSymbol(RenamingAction, I);
        outs() << "'" << clang_getCString(USR) << "'\n";
        clang_disposeString(USR);
      }
    }

    CXSymbolOccurrencesResult Occurrences;
    Occurrences = clang_Refactoring_findSymbolOccurrencesInInitiationTU(
        RenamingAction, Args.data(), Args.size(), 0, 0);

    clang_RefactoringAction_dispose(RenamingAction);

    // FIXME: This is a hack
    LangOptions LangOpts;
    LangOpts.ObjC1 = true;
    tooling::SymbolName NewSymbolName(opts::rename::NewName, LangOpts);

    if (ExpectedReplacements.empty()) {
      if (opts::Apply) {
        // FIXME: support --apply.
      }

      unsigned NumFiles = clang_SymbolOccurrences_getNumFiles(Occurrences);
      if (NumFiles > 1)
        PrintFilenames = true;
      // Convert the occurrences to strings
      for (unsigned FileIndex = 0; FileIndex < NumFiles; ++FileIndex) {
        CXSymbolOccurrencesInFile FileResult;
        clang_SymbolOccurrences_getOccurrencesForFile(Occurrences, FileIndex,
                                                      &FileResult);
        StringRef Filename =
            PrintFilenames ? clang_getCString(FileResult.Filename) : "";
        for (unsigned I = 0; I != FileResult.NumOccurrences; ++I)
          ExpectedReplacements.push_back(
              occurrenceToString(FileResult.Occurrences[I], IsLocal,
                                 NewSymbolName, NewSymbolName, Filename));
      }
      clang_SymbolOccurrences_dispose(Occurrences);
      return 0;
    }
    // Compare the produced occurrences to the expected occurrences that were
    // gathered at the first location.
    bool AreOccurrencesDifferent =
        compareOccurrences(ExpectedReplacements, Occurrences, IsLocal,
                           NewSymbolName, PrintFilenames);
    clang_SymbolOccurrences_dispose(Occurrences);
    if (!AreOccurrencesDifferent)
      return 0;
    errs() << "error: occurrences for a rename at " << Location.FileName << ":"
           << Location.Line << ":" << Location.Column
           << " differ to occurrences from the rename at the first location!\n";
    return 1;
  };

  std::vector<ParsedSourceLocation> ParsedLocations;
  for (const auto &I : enumerate(opts::rename::AtLocation)) {
    auto Location = ParsedSourceLocation::FromString(I.value());
    if (Location.FileName.empty()) {
      errs()
          << "error: The -at option must use the <file:line:column> format\n";
      return 1;
    }
    ParsedLocations.push_back(Location);
  }

  if (opts::RenameInitiateUSRSubcommand) {
    if (RenameAt(ParsedSourceLocation(), opts::rename::USR))
      return 1;
  } else {
    assert(!ParsedLocations.empty() && "No -at locations");

    for (const auto &Location : ParsedLocations) {
      if (RenameAt(Location, ""))
        return 1;
    }
  }

  // Print the produced renamed replacements
  if (opts::Apply)
    return 0;
  for (const auto &Replacement : ExpectedReplacements)
    outs() << Replacement << "\n";
  if (ExpectedReplacements.empty())
    outs() << "no replacements found\n";
  return 0;
}

int renameIndexedFile(CXIndex CIdx, ArrayRef<const char *> Args) {
  assert(opts::RenameIndexedFileSubcommand);

  // Compute the number of symbols.
  unsigned NumSymbols = opts::rename::IndexedNames.size();

  // Get the occurrences of a symbol.
  CXCursorKind DefaultCursorKind = renameIndexedOccurrenceKindStringToKind(
      opts::rename::IndexedSymbolKind, CXCursor_NotImplemented);
  std::vector<std::vector<CXIndexedSymbolLocation>> IndexedOccurrences(
      NumSymbols, std::vector<CXIndexedSymbolLocation>());
  for (const auto &IndexedOccurrence : opts::rename::IndexedLocations) {
    auto Occurrence =
        parseIndexedOccurrence(IndexedOccurrence, DefaultCursorKind);
    unsigned SymbolIndex = Occurrence.second;
    assert(SymbolIndex < IndexedOccurrences.size() && "Invalid symbol index");
    IndexedOccurrences[SymbolIndex].push_back(CXIndexedSymbolLocation{
        Occurrence.first.Location, Occurrence.first.CursorKind});
  }

  // Create the indexed symbols.
  std::vector<CXIndexedSymbol> IndexedSymbols;
  for (const auto &I : llvm::enumerate(IndexedOccurrences)) {
    const auto &Occurrences = I.value();
    const char *Name =
        opts::rename::IndexedNames[opts::rename::IndexedNames.size() < 2
                                       ? 0
                                       : I.index()]
            .c_str();
    IndexedSymbols.push_back({Occurrences.data(), (unsigned)Occurrences.size(),
                              DefaultCursorKind, Name});
  }

  CXRefactoringOptionSet Options = nullptr;
  if (opts::rename::AvoidTextual) {
    Options = clang_RefactoringOptionSet_create();
    clang_RefactoringOptionSet_add(Options,
                                   CXRefactorOption_AvoidTextualMatches);
  }

  CXSymbolOccurrencesResult Occurrences;
  CXErrorCode Err = clang_Refactoring_findSymbolOccurrencesInIndexedFile(
      IndexedSymbols.data(), IndexedSymbols.size(), CIdx,
      opts::rename::IndexedFileName.c_str(), Args.data(), Args.size(), 0, 0,
      Options, &Occurrences);
  if (Err != CXError_Success) {
    if (reportNewNameError(Err))
      errs() << "error: failed to perform indexed file rename\n";
    return 1;
  }

  if (Options)
    clang_RefactoringOptionSet_dispose(Options);

  // Should we print out the filenames. False by default, but true when multiple
  // files are modified.
  bool PrintFilenames = false;
  unsigned NumFiles = clang_SymbolOccurrences_getNumFiles(Occurrences);
  if (NumFiles > 1)
    PrintFilenames = true;

  LangOptions LangOpts;
  LangOpts.ObjC1 = true;
  tooling::SymbolName ExpectedReplacementStrings(
      opts::rename::IndexedNewNames[0], LangOpts);

  // Print the occurrences.
  bool HasReplacements = false;
  for (unsigned FileIndex = 0; FileIndex < NumFiles; ++FileIndex) {
    CXSymbolOccurrencesInFile FileResult;
    clang_SymbolOccurrences_getOccurrencesForFile(Occurrences, FileIndex,
                                                  &FileResult);
    StringRef Filename =
        PrintFilenames ? clang_getCString(FileResult.Filename) : "";
    HasReplacements = FileResult.NumOccurrences;
    for (unsigned I = 0; I != FileResult.NumOccurrences; ++I) {
      unsigned SymbolIndex = FileResult.Occurrences[I].SymbolIndex;
      const char *NewName =
          opts::rename::IndexedNewNames[opts::rename::IndexedNewNames.size() < 2
                                            ? 0
                                            : SymbolIndex]
              .c_str();
      LangOptions LangOpts;
      LangOpts.ObjC1 = true;
      tooling::SymbolName NewSymbolName(NewName, LangOpts);

      outs() << occurrenceToString(FileResult.Occurrences[I], /*IsLocal*/ false,
                                   NewSymbolName, ExpectedReplacementStrings,
                                   Filename)
             << "\n";
    }
  }
  if (!HasReplacements)
    outs() << "no replacements found\n";
  clang_SymbolOccurrences_dispose(Occurrences);
  return 0;
}

/// Returns the last column number of a line in a file.
static unsigned lastColumnForFile(StringRef Filename, unsigned LineNo) {
  auto Buf = llvm::MemoryBuffer::getFile(Filename);
  if (!Buf)
    return 0;
  unsigned LineCount = 1;
  for (llvm::line_iterator Lines(**Buf, /*SkipBlanks=*/false);
       !Lines.is_at_end(); ++Lines, ++LineCount) {
    if (LineNo == LineCount)
      return Lines->size() + 1;
  }
  return 0;
}

struct ParsedSourceLineRange : ParsedSourceLocation {
  unsigned MaxColumn;

  ParsedSourceLineRange() {}
  ParsedSourceLineRange(const ParsedSourceLocation &Loc)
      : ParsedSourceLocation(Loc), MaxColumn(Loc.Column) {}

  static Optional<ParsedSourceLineRange> FromString(StringRef Str) {
    std::pair<StringRef, StringRef> RangeSplit = Str.rsplit('-');
    auto PSL = ParsedSourceLocation::FromString(RangeSplit.first);
    ParsedSourceLineRange Result;
    Result.FileName = std::move(PSL.FileName);
    Result.Line = PSL.Line;
    Result.Column = PSL.Column;
    if (Result.FileName.empty())
      return None;
    if (RangeSplit.second == "end")
      Result.MaxColumn = lastColumnForFile(Result.FileName, Result.Line);
    else if (RangeSplit.second.getAsInteger(10, Result.MaxColumn))
      return None;
    if (Result.MaxColumn < Result.Column)
      return None;
    return Result;
  }
};

struct ParsedSourceRange {
  ParsedSourceLocation Begin, End;

  ParsedSourceRange(const ParsedSourceLocation &Begin,
                    const ParsedSourceLocation &End)
      : Begin(Begin), End(End) {}

  static Optional<ParsedSourceRange> FromString(StringRef Str) {
    std::pair<StringRef, StringRef> RangeSplit = Str.rsplit('-');
    auto Begin = ParsedSourceLocation::FromString(RangeSplit.first);
    if (Begin.FileName.empty())
      return None;
    std::string EndString = Begin.FileName + ":" + RangeSplit.second.str();
    auto End = ParsedSourceLocation::FromString(EndString);
    if (End.FileName.empty())
      return None;
    return ParsedSourceRange(Begin, End);
  }
};

int listRefactoringActions(CXTranslationUnit TU) {
  auto Location =
      ParsedSourceLocation::FromString(opts::listActions::AtLocation);
  if (Location.FileName.empty()) {
    errs() << "error: The -at option must use the <file:line:column> format\n";
    return 1;
  }
  CXSourceRange Range;
  if (!opts::listActions::SelectedRange.empty()) {
    auto SelectionRange =
        ParsedSourceRange::FromString(opts::listActions::SelectedRange);
    if (!SelectionRange) {
      errs() << "error: The -selected option must use the "
                "<file:line:column-line:column> format\n";
      return 1;
    }
    auto Begin = SelectionRange.getValue().Begin;
    auto End = SelectionRange.getValue().End;
    CXFile File = clang_getFile(TU, Begin.FileName.c_str());
    Range =
        clang_getRange(clang_getLocation(TU, File, Begin.Line, Begin.Column),
                       clang_getLocation(TU, File, End.Line, End.Column));
  } else
    Range = clang_getNullRange();
  CXSourceLocation Loc =
      clang_getLocation(TU, clang_getFile(TU, Location.FileName.c_str()),
                        Location.Line, Location.Column);
  CXRefactoringActionSet ActionSet;
  CXRefactoringActionSetWithDiagnostics FailedActionSet;
  CXErrorCode Err =
      clang_Refactoring_findActionsWithInitiationFailureDiagnosicsAt(
          TU, Loc, Range, /*Options=*/nullptr, &ActionSet, &FailedActionSet);
  if (FailedActionSet.NumActions) {
    errs() << "Failed to initiate " << FailedActionSet.NumActions
           << " actions because:\n";
    for (unsigned I = 0; I < FailedActionSet.NumActions; ++I) {
      errs() << clang_getCString(clang_RefactoringActionType_getName(
                    FailedActionSet.Actions[I].Action))
             << ":";
      CXDiagnosticSet Diags = FailedActionSet.Actions[I].Diagnostics;
      unsigned NumDiags = clang_getNumDiagnosticsInSet(Diags);
      for (unsigned DiagID = 0; DiagID < NumDiags; ++DiagID) {
        CXDiagnostic Diag = clang_getDiagnosticInSet(Diags, DiagID);
        CXString Spelling = clang_getDiagnosticSpelling(Diag);
        errs() << ' ' << clang_getCString(Spelling);
        clang_disposeString(Spelling);
      }
      errs() << "\n";
    }
  }
  if (Err == CXError_RefactoringActionUnavailable)
    errs() << "No refactoring actions are available at the given location\n";
  if (Err != CXError_Success)
    return 1;
  // Print the list of refactoring actions.
  outs() << "Found " << ActionSet.NumActions << " actions:\n";
  for (unsigned I = 0; I < ActionSet.NumActions; ++I) {
    outs() << clang_getCString(
        clang_RefactoringActionType_getName(ActionSet.Actions[I]));
    if (opts::listActions::DumpRawActionType)
      outs() << "(" << ActionSet.Actions[I] << ")";
    outs() << "\n";
  }
  clang_RefactoringActionSet_dispose(&ActionSet);
  clang_RefactoringActionSetWithDiagnostics_dispose(&FailedActionSet);
  return 0;
}

static std::string locationToString(CXSourceLocation Loc) {
  unsigned Line, Column;
  clang_getFileLocation(Loc, nullptr, &Line, &Column, nullptr);
  std::string S;
  llvm::raw_string_ostream OS(S);
  OS << Line << ':' << Column;
  return OS.str();
}

static std::string rangeToString(CXSourceRange Range) {
  return locationToString(clang_getRangeStart(Range)) + " -> " +
         locationToString(clang_getRangeEnd(Range));
}

static std::string
refactoringCandidatesToString(CXRefactoringCandidateSet Candidates) {
  std::string Results = "with multiple candidates:";
  for (unsigned I = 0; I < Candidates.NumCandidates; ++I) {
    Results += "\n";
    Results += clang_getCString(Candidates.Candidates[I].Description);
  }
  return Results;
}

static void printEscaped(StringRef Str, raw_ostream &OS) {
  size_t Pos = Str.find('\n');
  OS << Str.substr(0, Pos);
  if (Pos == StringRef::npos)
    return;
  OS << "\\n";
  printEscaped(Str.substr(Pos + 1), OS);
}

bool printRefactoringReplacements(
    CXRefactoringResult Result, CXRefactoringContinuation Continuation,
    CXRefactoringContinuation CurrentContinuation) {
  CXRefactoringReplacements Replacements =
      clang_RefactoringResult_getSourceReplacements(Result);
  if (Replacements.NumFileReplacementSets == 0) {
    if (CurrentContinuation)
      return false;
    errs() << "error: no replacements produced!\n";
    return true;
  }
  // Print out the produced results.
  for (unsigned FileIndex = 0; FileIndex < Replacements.NumFileReplacementSets;
       ++FileIndex) {
    const CXRefactoringFileReplacementSet &FileSet =
        Replacements.FileReplacementSets[FileIndex];
    if (opts::Apply) {
      apply(llvm::makeArrayRef(FileSet.Replacements, FileSet.NumReplacements),
            clang_getCString(FileSet.Filename));
      continue;
    }
    for (unsigned I = 0; I < FileSet.NumReplacements; ++I) {
      const CXRefactoringReplacement &Replacement = FileSet.Replacements[I];

      if (Continuation) {
        // Always print the filenames in with continuations.
        outs() << '"' << clang_getCString(FileSet.Filename) << "\" ";
      }
      outs() << '"';
      printEscaped(clang_getCString(Replacement.ReplacementString), outs());
      outs() << "\" ";
      CXFileRange Range = Replacement.Range;
      outs() << Range.Begin.Line << ":" << Range.Begin.Column << " -> "
             << Range.End.Line << ":" << Range.End.Column;
      if (opts::initiateAndPerform::EmitAssociatedInfo) {
        CXRefactoringReplacementAssociatedSymbolOccurrences Info =
            clang_RefactoringReplacement_getAssociatedSymbolOccurrences(
                Replacement);
        for (const CXSymbolOccurrence &SymbolOccurrence :
             llvm::makeArrayRef(Info.AssociatedSymbolOccurrences,
                                Info.NumAssociatedSymbolOccurrences)) {
          outs() << " [Symbol " << renameOccurrenceKindString(
                                       SymbolOccurrence.Kind, /*IsLocal*/ false,
                                       SymbolOccurrence.IsMacroExpansion)
                 << ' ' << SymbolOccurrence.SymbolIndex;
          for (const auto &Piece :
               llvm::makeArrayRef(SymbolOccurrence.NamePieces,
                                  SymbolOccurrence.NumNamePieces)) {
            outs() << ' ' << Piece.Begin.Line << ":" << Piece.Begin.Column
                   << " -> " << Piece.End.Line << ":" << Piece.End.Column;
          }
          outs() << ']';
        }
      }
      outs() << "\n";
    }
  }
  return false;
}

/// Returns the last column number of a line in a file.
static std::string queryResultsForFile(StringRef Filename, StringRef Name,
                                       StringRef FileSubstitution) {
  auto Buf = llvm::MemoryBuffer::getFile(Filename);
  if (!Buf)
    return "<invalid>";
  StringRef Buffer = (*Buf)->getBuffer();
  std::string Label = Name.str() + ":";
  size_t I = Buffer.find(Label);
  if (I == StringRef::npos)
    return "<invalid>";
  I = I + Label.size();
  auto Result = Buffer.substr(I, Buffer.find('\n', I) - I);
  std::string Sub1 = llvm::Regex("%s").sub(FileSubstitution, Result);
  return llvm::Regex("%S").sub(llvm::sys::path::parent_path(FileSubstitution),
                               Sub1);
}

static Optional<std::pair<unsigned, unsigned>>
findSelectionLocInSource(StringRef Buffer, StringRef Label) {
  size_t I = Buffer.find(Label);
  if (I == StringRef::npos)
    return None;
  I = I + Label.size();
  auto LocParts =
      Buffer.substr(I, Buffer.find_first_of("\n/", I) - I).trim().split(":");
  unsigned CurrentLine = Buffer.take_front(I).count('\n') + 1;
  if (LocParts.second.empty())
    return None;
  StringRef LineString = LocParts.first;
  unsigned Line, Column;
  enum ExprKind { Literal, Add, Sub };
  ExprKind Expr = LineString.startswith("+")
                      ? Add
                      : LineString.startswith("-") ? Sub : Literal;
  if (LineString.drop_front(Expr != Literal ? 1 : 0).getAsInteger(10, Line))
    return None;
  if (Expr == Add)
    Line += CurrentLine;
  else if (Expr == Sub)
    Line = CurrentLine - Line;
  if (LocParts.second.getAsInteger(10, Column))
    return None;
  return std::make_pair(Line, Column);
}

static Optional<ParsedSourceLocation> selectionLocForFile(StringRef Filename,
                                                          StringRef Name) {
  auto Buf = llvm::MemoryBuffer::getFile(Filename);
  if (!Buf)
    return None;

  StringRef Buffer = (*Buf)->getBuffer();
  std::string Label = Name.str() + ":";
  auto Start = findSelectionLocInSource(Buffer, Label);
  if (!Start)
    return None;
  // Create the resulting source location.
  // FIXME: Parse can be avoided.
  std::string Str;
  llvm::raw_string_ostream OS(Str);
  OS << Filename << ":" << Start->first << ":" << Start->second;
  return ParsedSourceLocation::FromString(OS.str());
}

static Optional<ParsedSourceRange> selectionRangeForFile(StringRef Filename,
                                                         StringRef Name) {
  auto Buf = llvm::MemoryBuffer::getFile(Filename);
  if (!Buf)
    return None;

  StringRef Buffer = (*Buf)->getBuffer();
  std::string BeginLabel = Name.str() + "-begin:";
  std::string EndLabel = Name.str() + "-end:";
  auto Start = findSelectionLocInSource(Buffer, BeginLabel);
  auto End = findSelectionLocInSource(Buffer, EndLabel);
  if (!Start || !End)
    return None;
  // Create the resulting source range.
  // FIXME: Parse can be avoided.
  std::string Str;
  llvm::raw_string_ostream OS(Str);
  OS << Filename << ":" << Start->first << ":" << Start->second << "-"
     << End->first << ":" << End->second;
  return ParsedSourceRange::FromString(OS.str());
}

bool performOperation(CXRefactoringAction Action, ArrayRef<const char *> Args,
                      CXIndex CIdx) {
  if (opts::initiateAndPerform::CandidateIndex.getNumOccurrences()) {
    if (clang_RefactoringAction_selectRefactoringCandidate(
            Action, opts::initiateAndPerform::CandidateIndex)) {
      errs() << "error: failed to select the refactoring candidate!\n";
      return true;
    }
  }
  CXRefactoringOptionSet Options = nullptr;
  CXString FailureReason;
  CXRefactoringResult Result = clang_Refactoring_performOperation(
      Action, Args.data(), Args.size(), nullptr, 0, Options, &FailureReason);
  if (!Result) {
    errs() << "error: failed to perform the refactoring operation";
    if (const char *Reason = clang_getCString(FailureReason))
      errs() << " (" << Reason << ')';
    errs() << "!\n";
    clang_disposeString(FailureReason);
    return true;
  }
  CXRefactoringContinuation Continuation =
      clang_RefactoringResult_getContinuation(Result);
  bool AreReplacementsInvalid =
      printRefactoringReplacements(Result, Continuation, Continuation);
  clang_RefactoringResult_dispose(Result);
  if (AreReplacementsInvalid) {
    clang_RefactoringContinuation_dispose(Continuation);
    return true;
  }
  if (!Continuation)
    return false;
  assert(clang_RefactoringContinuation_getNumIndexerQueries(Continuation) !=
             0 &&
         "Missing indexer queries?");
  std::string QueryResults = queryResultsForFile(
      opts::FileName, opts::initiateAndPerform::QueryResults,
      /*FileSubstitution=*/opts::initiateAndPerform::ContinuationFile);
  clang_RefactoringContinuation_loadSerializedIndexerQueryResults(
      Continuation, /*Source=*/QueryResults.c_str());
  CXDiagnosticSet Diags =
      clang_RefactoringContinuation_verifyBeforeFinalizing(Continuation);
  if (Diags) {
    llvm::errs() << "error: continuation failed: ";
    for (unsigned I = 0, E = clang_getNumDiagnosticsInSet(Diags); I != E; ++I) {
      CXDiagnostic Diag = clang_getDiagnosticInSet(Diags, I);
      CXString Spelling = clang_getDiagnosticSpelling(Diag);
      errs() << clang_getCString(Spelling) << "\n";
      clang_disposeString(Spelling);
      clang_disposeDiagnostic(Diag);
    }
    clang_RefactoringContinuation_dispose(Continuation);
    clang_disposeDiagnosticSet(Diags);
    return true;
  }
  clang_RefactoringContinuation_finalizeEvaluationInInitationTU(Continuation);
  // Load the continuation TU.
  CXTranslationUnit ContinuationTU;
  CXErrorCode Err = clang_parseTranslationUnit2(
      CIdx, opts::initiateAndPerform::ContinuationFile.c_str(), Args.data(),
      Args.size(), 0, 0, CXTranslationUnit_KeepGoing, &ContinuationTU);
  if (Err != CXError_Success) {
    errs() << "error: failed to load '"
           << opts::initiateAndPerform::ContinuationFile.c_str() << "'\n";
    clang_RefactoringContinuation_dispose(Continuation);
    return true;
  }
  Result = clang_RefactoringContinuation_continueOperationInTU(
      Continuation, ContinuationTU, &FailureReason);
  if (!Result) {
    errs() << "error: failed to perform the refactoring continuation";
    if (const char *Reason = clang_getCString(FailureReason))
      errs() << " (" << Reason << ')';
    errs() << "!\n";
    clang_disposeString(FailureReason);
    clang_disposeTranslationUnit(ContinuationTU);
    clang_RefactoringContinuation_dispose(Continuation);
    return true;
  }
  // FIXME: Continuations can be chained in the future.
  AreReplacementsInvalid =
      printRefactoringReplacements(Result, Continuation, nullptr);
  clang_RefactoringResult_dispose(Result);
  clang_disposeTranslationUnit(ContinuationTU);
  clang_RefactoringContinuation_dispose(Continuation);
  return AreReplacementsInvalid;
}

int initiateAndPerformAction(CXTranslationUnit TU, ArrayRef<const char *> Args,
                             CXIndex CIdx) {
  std::vector<ParsedSourceLineRange> Ranges;
  std::vector<ParsedSourceRange> SelectionRanges;
  for (const auto &Range : opts::initiateAndPerform::InLocationRanges) {
    auto ParsedLineRange = ParsedSourceLineRange::FromString(Range);
    if (!ParsedLineRange) {
      errs()
          << "error: The -in option must use the <file:line:column[-column]> "
             "format\n";
      return 1;
    }
    Ranges.push_back(ParsedLineRange.getValue());
  }
  for (const auto &Range : opts::initiateAndPerform::AtLocations) {
    if (!StringRef(Range).contains(':')) {
      auto ParsedLocation = selectionLocForFile(opts::FileName, Range);
      if (!ParsedLocation) {
        errs() << "error: The -at option must use the <file:line:column> "
                  "format\n";
        return 1;
      }
      Ranges.push_back(*ParsedLocation);
      continue;
    }
    // TODO: Remove old location in arguments in favour of new testing
    // locations.
    auto ParsedLocation = ParsedSourceLocation::FromString(Range);
    if (ParsedLocation.FileName.empty()) {
      errs() << "error: The -at option must use the <file:line:column> "
                "format\n";
      return 1;
    }
    Ranges.push_back(ParsedLocation);
  }
  for (const auto &Range : opts::initiateAndPerform::SelectedRanges) {
    auto ParsedRange = StringRef(Range).contains(':')
                           ? ParsedSourceRange::FromString(Range)
                           : selectionRangeForFile(opts::FileName, Range);
    if (!ParsedRange) {
      errs() << "error: The -selected option must use the "
                "<file:line:column-line:column> format or refer to the name of "
                "the selection specifier in the source\n";
      return 1;
    }
    SelectionRanges.push_back(ParsedRange.getValue());
  }
  if (Ranges.empty() && SelectionRanges.empty()) {
    errs() << "error: -in or -at options must be specified at least once!";
    return 1;
  }
  if (!Ranges.empty() && !SelectionRanges.empty()) {
    errs() << "error: -in or -at options can't be used with -selected!";
    return 1;
  }

  auto ActionTypeOrNone = StringSwitch<Optional<CXRefactoringActionType>>(
                              opts::initiateAndPerform::ActionName)
#define REFACTORING_OPERATION_ACTION(Name, Spelling, Command)                  \
  .Case(Command, CXRefactor_##Name)
#define REFACTORING_OPERATION_SUB_ACTION(Name, Parent, Spelling, Command)      \
  .Case(Command, CXRefactor_##Parent##_##Name)
#include "clang/Tooling/Refactor/RefactoringActions.def"
                              .Default(None);
  if (!ActionTypeOrNone) {
    errs() << "error: invalid action '" << opts::initiateAndPerform::ActionName
           << "'\n";
    return 1;
  }
  CXRefactoringActionType ActionType = *ActionTypeOrNone;

  Optional<bool> Initiated;
  Optional<std::string> InitiationFailureReason;
  Optional<std::string> LocationCandidateInformation;
  auto InitiateAndPerform =
      [&](const ParsedSourceLocation &Location, unsigned Column,
          Optional<ParsedSourceRange> SelectionRange = None) -> bool {
    CXSourceLocation Loc =
        clang_getLocation(TU, clang_getFile(TU, Location.FileName.c_str()),
                          Location.Line, Column);
    CXSourceRange Range;
    if (SelectionRange) {
      auto Begin = SelectionRange.getValue().Begin;
      auto End = SelectionRange.getValue().End;
      CXFile File = clang_getFile(TU, Begin.FileName.c_str());
      Range =
          clang_getRange(clang_getLocation(TU, File, Begin.Line, Begin.Column),
                         clang_getLocation(TU, File, End.Line, End.Column));
    } else
      Range = clang_getNullRange();
    CXRefactoringAction Action;
    CXString FailureReason;
    CXErrorCode Err = clang_Refactoring_initiateActionAt(
        TU, Loc, Range, ActionType, /*Options=*/nullptr, &Action,
        &FailureReason);
    std::string ReasonString;
    if (const char *Reason = clang_getCString(FailureReason))
      ReasonString = Reason;
    clang_disposeString(FailureReason);
    if (InitiationFailureReason.hasValue() &&
        InitiationFailureReason.getValue() != ReasonString) {
      errs() << "error: inconsistent results in a single action range!\n";
      return true;
    }
    InitiationFailureReason = std::move(ReasonString);
    if (Err == CXError_RefactoringActionUnavailable) {
      if (Initiated.hasValue() && Initiated.getValue()) {
        errs() << "error: inconsistent results in a single action range!\n";
        return true;
      }
      Initiated = false;
    } else if (Err != CXError_Success)
      return true;
    else if (Initiated.hasValue() && !Initiated.getValue()) {
      errs() << "error: inconsistent results in a single action range!\n";
      return true;
    } else
      Initiated = true;

    CXRefactoringCandidateSet Candidates;
    if (clang_RefactoringAction_getRefactoringCandidates(Action, &Candidates) ==
            CXError_Success &&
        Candidates.NumCandidates > 1) {
      std::string CandidateString = refactoringCandidatesToString(Candidates);
      if (LocationCandidateInformation) {
        if (*LocationCandidateInformation != CandidateString) {
          errs() << "error: inconsistent results in a single action range!\n";
          return true;
        }
      } else
        LocationCandidateInformation = CandidateString;
    } else if (opts::InitiateActionSubcommand &&
               !opts::initiateAndPerform::LocationAgnostic) {
      CXSourceRange Range =
          clang_RefactoringAction_getSourceRangeOfInterest(Action);
      std::string LocationString =
          std::string("at ") +
          (!clang_Range_isNull(Range)
               ? SelectionRange ? rangeToString(Range)
                                : locationToString(clang_getRangeStart(Range))
               : "<unknown>");
      if (!LocationCandidateInformation.hasValue())
        LocationCandidateInformation = LocationString;
      else if (LocationCandidateInformation.getValue() != LocationString) {
        errs() << "error: inconsistent results in a single action range!\n";
        return true;
      }
    }

    if (!*Initiated)
      return false;

    bool Failed = opts::PerformActionSubcommand
                      ? performOperation(Action, Args, CIdx)
                      : false;
    clang_RefactoringAction_dispose(Action);
    return Failed;
  };

  // Iterate over all of the possible locations and perform the initiation
  // at each range.
  for (const ParsedSourceLineRange &LineRange : Ranges) {
    for (unsigned Column = LineRange.Column; Column <= LineRange.MaxColumn;
         ++Column) {
      if (InitiateAndPerform(LineRange, Column))
        return 1;
    }
  }

  for (const ParsedSourceRange &SelectionRange : SelectionRanges) {
    if (InitiateAndPerform(SelectionRange.Begin, SelectionRange.Begin.Column,
                           SelectionRange))
      return 1;
  }

  if (!Initiated.getValue()) {
    errs() << "Failed to initiate the refactoring action";
    if (InitiationFailureReason.hasValue() &&
        !InitiationFailureReason.getValue().empty())
      errs() << " (" << InitiationFailureReason.getValue() << ')';
    errs() << "!\n";
    return 1;
  }
  if (opts::InitiateActionSubcommand) {
    outs() << "Initiated the '" << opts::initiateAndPerform::ActionName
           << "' action";
    if (!opts::initiateAndPerform::LocationAgnostic)
      outs() << ' ' << LocationCandidateInformation.getValue();
    outs() << "\n";
  }
  return 0;
}

int main(int argc, const char **argv) {
  cl::HideUnrelatedOptions(opts::ClangRefactorTestOptions);

  cl::ParseCommandLineOptions(argc, argv, "Clang refactoring test tool\n");
  cl::PrintOptionValues();

  CXIndex CIdx = clang_createIndex(0, 0);

  std::vector<const char *> Args;
  for (const auto &Arg : opts::CompilerArguments) {
    Args.push_back(Arg.c_str());
  }
  CXTranslationUnit TU;
  CXErrorCode Err = clang_parseTranslationUnit2(
      CIdx,
      opts::IgnoreFilenameForInitiationTU ? nullptr : opts::FileName.c_str(),
      Args.data(), Args.size(), 0, 0, CXTranslationUnit_KeepGoing, &TU);
  if (Err != CXError_Success) {
    errs() << "error: failed to load '" << opts::FileName << "'\n";
    return 1;
  }

  if (opts::RenameInitiateSubcommand || opts::RenameInitiateUSRSubcommand)
    return rename(TU, CIdx, Args);
  else if (opts::RenameIndexedFileSubcommand)
    return renameIndexedFile(CIdx, Args);
  else if (opts::ListRefactoringActionsSubcommand)
    return listRefactoringActions(TU);
  else if (opts::InitiateActionSubcommand || opts::PerformActionSubcommand)
    return initiateAndPerformAction(TU, Args, CIdx);

  clang_disposeTranslationUnit(TU);
  clang_disposeIndex(CIdx);

  return 0;
}
