diff options
Diffstat (limited to 'clang-tools-extra/clang-rename/tool/ClangRename.cpp')
-rw-r--r-- | clang-tools-extra/clang-rename/tool/ClangRename.cpp | 211 |
1 files changed, 66 insertions, 145 deletions
diff --git a/clang-tools-extra/clang-rename/tool/ClangRename.cpp b/clang-tools-extra/clang-rename/tool/ClangRename.cpp index 8e59994b582..9cc29ff963f 100644 --- a/clang-tools-extra/clang-rename/tool/ClangRename.cpp +++ b/clang-tools-extra/clang-rename/tool/ClangRename.cpp @@ -38,28 +38,12 @@ #include <system_error> using namespace llvm; - using namespace clang; -cl::OptionCategory ClangRenameAtCategory("clang-rename rename-at options"); -cl::OptionCategory ClangRenameAllCategory("clang-rename rename-all options"); - -const char RenameAtUsage[] = "A tool to rename symbols in C/C++ code.\n\ -clang-rename renames every occurrence of a symbol found at <offset> in\n\ -<source0>. If -i is specified, the edited files are overwritten to disk.\n\ -Otherwise, the results are written to stdout.\n"; - -const char RenameAllUsage[] = "A tool to rename symbols in C/C++ code.\n\ -clang-rename performs renaming given pairs {offset | old-name} -> new-name.\n"; - -static int renameAtMain(int argc, const char *argv[]); -static int renameAllMain(int argc, const char *argv[]); -static int helpMain(int argc, const char *argv[]); - /// \brief An oldname -> newname rename. struct RenameAllInfo { - std::string OldName; unsigned Offset = 0; + std::string QualifiedName; std::string NewName; }; @@ -72,8 +56,8 @@ namespace yaml { /// (de)serialized. template <> struct MappingTraits<RenameAllInfo> { static void mapping(IO &IO, RenameAllInfo &Info) { - IO.mapOptional("OldName", Info.OldName); IO.mapOptional("Offset", Info.Offset); + IO.mapOptional("QualifiedName", Info.QualifiedName); IO.mapRequired("NewName", Info.NewName); } }; @@ -81,72 +65,42 @@ template <> struct MappingTraits<RenameAllInfo> { } // end namespace yaml } // end namespace llvm -int main(int argc, const char **argv) { - if (argc > 1) { - using MainFunction = std::function<int(int, const char *[])>; - MainFunction Func = StringSwitch<MainFunction>(argv[1]) - .Case("rename-at", renameAtMain) - .Case("rename-all", renameAllMain) - .Cases("-help", "--help", helpMain) - .Default(nullptr); +static cl::OptionCategory ClangRenameOptions("clang-rename common options"); + +static cl::list<unsigned> SymbolOffsets( + "offset", + cl::desc("Locates the symbol by offset as opposed to <line>:<column>."), + cl::ZeroOrMore, cl::cat(ClangRenameOptions)); +static cl::opt<bool> Inplace("i", cl::desc("Overwrite edited <file>s."), + cl::cat(ClangRenameOptions)); +static cl::list<std::string> + QualifiedNames("qualified-name", + cl::desc("The fully qualified name of the symbol."), + cl::ZeroOrMore, cl::cat(ClangRenameOptions)); + +static cl::list<std::string> + NewNames("new-name", cl::desc("The new name to change the symbol to."), + cl::ZeroOrMore, cl::cat(ClangRenameOptions)); +static cl::opt<bool> PrintName( + "pn", + cl::desc("Print the found symbol's name prior to renaming to stderr."), + cl::cat(ClangRenameOptions)); +static cl::opt<bool> PrintLocations( + "pl", cl::desc("Print the locations affected by renaming to stderr."), + cl::cat(ClangRenameOptions)); +static cl::opt<std::string> + ExportFixes("export-fixes", + cl::desc("YAML file to store suggested fixes in."), + cl::value_desc("filename"), cl::cat(ClangRenameOptions)); +static cl::opt<std::string> + Input("input", cl::desc("YAML file to load oldname-newname pairs from."), + cl::Optional, cl::cat(ClangRenameOptions)); - if (Func) { - std::string Invocation = std::string(argv[0]) + " " + argv[1]; - argv[1] = Invocation.c_str(); - return Func(argc - 1, argv + 1); - } else { - return renameAtMain(argc, argv); - } - } - - helpMain(argc, argv); - return 1; -} - -int subcommandMain(bool isRenameAll, int argc, const char **argv) { - cl::OptionCategory *Category = nullptr; - const char *Usage = nullptr; - if (isRenameAll) { - Category = &ClangRenameAllCategory; - Usage = RenameAllUsage; - } else { - Category = &ClangRenameAtCategory; - Usage = RenameAtUsage; - } - - cl::list<std::string> NewNames( - "new-name", cl::desc("The new name to change the symbol to."), - (isRenameAll ? cl::ZeroOrMore : cl::Required), cl::cat(*Category)); - cl::list<unsigned> SymbolOffsets( - "offset", - cl::desc("Locates the symbol by offset as opposed to <line>:<column>."), - (isRenameAll ? cl::ZeroOrMore : cl::Required), cl::cat(*Category)); - cl::list<std::string> OldNames( - "old-name", - cl::desc( - "The fully qualified name of the symbol, if -offset is not used."), - (isRenameAll ? cl::ZeroOrMore : cl::Optional), - cl::cat(ClangRenameAllCategory)); - cl::opt<bool> Inplace("i", cl::desc("Overwrite edited <file>s."), - cl::cat(*Category)); - cl::opt<bool> PrintName( - "pn", - cl::desc("Print the found symbol's name prior to renaming to stderr."), - cl::cat(ClangRenameAtCategory)); - cl::opt<bool> PrintLocations( - "pl", cl::desc("Print the locations affected by renaming to stderr."), - cl::cat(ClangRenameAtCategory)); - cl::opt<std::string> ExportFixes( - "export-fixes", cl::desc("YAML file to store suggested fixes in."), - cl::value_desc("filename"), cl::cat(*Category)); - cl::opt<std::string> Input( - "input", cl::desc("YAML file to load oldname-newname pairs from."), - cl::Optional, cl::cat(ClangRenameAllCategory)); - - tooling::CommonOptionsParser OP(argc, argv, *Category, Usage); +int main(int argc, const char **argv) { + tooling::CommonOptionsParser OP(argc, argv, ClangRenameOptions); if (!Input.empty()) { - // Populate OldNames and NewNames from a YAML file. + // Populate QualifiedNames and NewNames from a YAML file. ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = llvm::MemoryBuffer::getFile(Input); if (!Buffer) { @@ -159,8 +113,8 @@ int subcommandMain(bool isRenameAll, int argc, const char **argv) { llvm::yaml::Input YAML(Buffer.get()->getBuffer()); YAML >> Infos; for (const auto &Info : Infos) { - if (!Info.OldName.empty()) - OldNames.push_back(Info.OldName); + if (!Info.QualifiedName.empty()) + QualifiedNames.push_back(Info.QualifiedName); else SymbolOffsets.push_back(Info.Offset); NewNames.push_back(Info.NewName); @@ -168,18 +122,23 @@ int subcommandMain(bool isRenameAll, int argc, const char **argv) { } // Check the arguments for correctness. - if (NewNames.empty()) { - errs() << "clang-rename: either -new-name or -input is required.\n\n"; + errs() << "clang-rename: -new-name must be specified.\n\n"; + exit(1); + } + + if (SymbolOffsets.empty() == QualifiedNames.empty()) { + errs() << "clang-rename: -offset and -qualified-name can't be present at " + "the same time.\n"; exit(1); } // Check if NewNames is a valid identifier in C++17. + LangOptions Options; + Options.CPlusPlus = true; + Options.CPlusPlus1z = true; + IdentifierTable Table(Options); for (const auto &NewName : NewNames) { - LangOptions Options; - Options.CPlusPlus = true; - Options.CPlusPlus1z = true; - IdentifierTable Table(Options); auto NewNameTokKind = Table.get(NewName).getTokenID(); if (!tok::isAnyIdentifier(NewNameTokKind)) { errs() << "ERROR: new name is not a valid identifier in C++17.\n\n"; @@ -187,55 +146,38 @@ int subcommandMain(bool isRenameAll, int argc, const char **argv) { } } - if (!OldNames.empty() && OldNames.size() != NewNames.size()) { - errs() << "clang-rename: number of old names (" << OldNames.size() - << ") do not equal to number of new names (" << NewNames.size() - << ").\n\n"; - cl::PrintHelpMessage(); - exit(1); - } - - if (!SymbolOffsets.empty() && SymbolOffsets.size() != NewNames.size()) { - errs() << "clang-rename: number of symbol offsets (" << SymbolOffsets.size() - << ") do not equal to number of new names (" << NewNames.size() + if (SymbolOffsets.size() + QualifiedNames.size() != NewNames.size()) { + errs() << "clang-rename: number of symbol offsets(" << SymbolOffsets.size() + << ") + number of qualified names (" << QualifiedNames.size() + << ") must be equal to number of new names(" << NewNames.size() << ").\n\n"; cl::PrintHelpMessage(); exit(1); } - std::vector<std::vector<std::string>> USRList; - std::vector<std::string> PrevNames; auto Files = OP.getSourcePathList(); tooling::RefactoringTool Tool(OP.getCompilations(), Files); - unsigned Count = OldNames.size() ? OldNames.size() : SymbolOffsets.size(); - for (unsigned I = 0; I < Count; ++I) { - unsigned SymbolOffset = SymbolOffsets.empty() ? 0 : SymbolOffsets[I]; - const std::string &OldName = OldNames.empty() ? std::string() : OldNames[I]; - - // Get the USRs. - rename::USRFindingAction USRAction(SymbolOffset, OldName); - - // Find the USRs. - Tool.run(tooling::newFrontendActionFactory(&USRAction).get()); - const auto &USRs = USRAction.getUSRs(); - USRList.push_back(USRs); - const auto &PrevName = USRAction.getUSRSpelling(); - PrevNames.push_back(PrevName); - - if (PrevName.empty()) { - // An error should have already been printed. - exit(1); + rename::USRFindingAction FindingAction(SymbolOffsets, QualifiedNames); + Tool.run(tooling::newFrontendActionFactory(&FindingAction).get()); + const std::vector<std::vector<std::string>> &USRList = + FindingAction.getUSRList(); + const std::vector<std::string> &PrevNames = FindingAction.getUSRSpellings(); + if (PrintName) { + for (const auto &PrevName : PrevNames) { + outs() << "clang-rename found name: " << PrevName << '\n'; } + } - if (PrintName) { - errs() << "clang-rename: found name: " << PrevName << '\n'; - } + if (FindingAction.errorOccurred()) { + // Diagnostics are already issued at this point. + exit(1); } // Perform the renaming. rename::RenamingAction RenameAction(NewNames, PrevNames, USRList, Tool.getReplacements(), PrintLocations); - auto Factory = tooling::newFrontendActionFactory(&RenameAction); + std::unique_ptr<tooling::FrontendActionFactory> Factory = + tooling::newFrontendActionFactory(&RenameAction); int ExitCode; if (Inplace) { @@ -287,24 +229,3 @@ int subcommandMain(bool isRenameAll, int argc, const char **argv) { exit(ExitCode); } - -/// \brief Top level help. -/// FIXME It would be better if this could be auto-generated. -static int helpMain(int argc, const char *argv[]) { - errs() << "Usage: clang-rename {rename-at|rename-all} [OPTION]...\n\n" - "A tool to rename symbols in C/C++ code.\n\n" - "Subcommands:\n" - " rename-at: Perform rename off of a location in a file. (This " - "is the default.)\n" - " rename-all: Perform rename of all symbols matching one or more " - "fully qualified names.\n"; - return 0; -} - -static int renameAtMain(int argc, const char *argv[]) { - return subcommandMain(false, argc, argv); -} - -static int renameAllMain(int argc, const char *argv[]) { - return subcommandMain(true, argc, argv); -} |