diff options
| author | Miklos Vajna <vmiklos@vmiklos.hu> | 2016-08-02 09:51:31 +0000 |
|---|---|---|
| committer | Miklos Vajna <vmiklos@vmiklos.hu> | 2016-08-02 09:51:31 +0000 |
| commit | aaec9b6cfce2e492cac2fd79687f0fab9bd8a9af (patch) | |
| tree | 1a2cf444fa67050e9abb4f0ce7455722a7a4df25 /clang-tools-extra/clang-rename/tool/ClangRename.cpp | |
| parent | 9e0dab935292c4e513db76781cb036c5f19ea3c7 (diff) | |
| download | bcm5719-llvm-aaec9b6cfce2e492cac2fd79687f0fab9bd8a9af.tar.gz bcm5719-llvm-aaec9b6cfce2e492cac2fd79687f0fab9bd8a9af.zip | |
clang-rename: split existing options into two new subcommands
- rename-at is meant to be integrated with editors and works mainly off
of a location in a file, and this is the default
- rename-all is optimized for one or more oldname->newname renames, and
works with clang-apply-replacements
Reviewers: bkramer, klimek
Subscribers: omtcyfz
Differential Revision: https://reviews.llvm.org/D21814
llvm-svn: 277438
Diffstat (limited to 'clang-tools-extra/clang-rename/tool/ClangRename.cpp')
| -rw-r--r-- | clang-tools-extra/clang-rename/tool/ClangRename.cpp | 212 |
1 files changed, 142 insertions, 70 deletions
diff --git a/clang-tools-extra/clang-rename/tool/ClangRename.cpp b/clang-tools-extra/clang-rename/tool/ClangRename.cpp index f1e8ba5ad5b..3a468c4a9b6 100644 --- a/clang-tools-extra/clang-rename/tool/ClangRename.cpp +++ b/clang-tools-extra/clang-rename/tool/ClangRename.cpp @@ -39,94 +39,146 @@ using namespace llvm; -cl::OptionCategory ClangRenameCategory("Clang-rename options"); - -static cl::opt<std::string> -NewName( - "new-name", - cl::desc("The new name to change the symbol to."), - cl::cat(ClangRenameCategory)); -static cl::opt<unsigned> -SymbolOffset( - "offset", - cl::desc("Locates the symbol by offset as opposed to <line>:<column>."), - cl::cat(ClangRenameCategory)); -static cl::opt<std::string> -OldName( - "old-name", - cl::desc("The fully qualified name of the symbol, if -offset is not used."), - cl::cat(ClangRenameCategory)); -static cl::opt<bool> -Inplace( - "i", - cl::desc("Overwrite edited <file>s."), - cl::cat(ClangRenameCategory)); -static cl::opt<bool> -PrintName( - "pn", - cl::desc("Print the found symbol's name prior to renaming to stderr."), - cl::cat(ClangRenameCategory)); -static cl::opt<bool> -PrintLocations( - "pl", - cl::desc("Print the locations affected by renaming to stderr."), - cl::cat(ClangRenameCategory)); -static cl::opt<std::string> -ExportFixes( - "export-fixes", - cl::desc("YAML file to store suggested fixes in."), - cl::value_desc("filename"), - cl::cat(ClangRenameCategory)); - using namespace clang; -const char RenameUsage[] = "A tool to rename symbols in C/C++ code.\n\ +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 renames every occurrence of a symbol named <old-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[]); + int main(int argc, const char **argv) { - tooling::CommonOptionsParser OP(argc, argv, ClangRenameCategory, RenameUsage); + 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); + + 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::OneOrMore : 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)); + + tooling::CommonOptionsParser OP(argc, argv, *Category, Usage); // Check the arguments for correctness. - if (NewName.empty()) { - errs() << "ERROR: no new name provided.\n\n"; + // Check if NewNames is a valid identifier in C++17. + 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"; + exit(1); + } + } + + 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); } - // Check if NewName is a valid identifier in C++17. - 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"; + 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() + << ").\n\n"; + cl::PrintHelpMessage(); exit(1); } - // Get the USRs. + std::vector<std::vector<std::string>> USRList; + std::vector<std::string> PrevNames; auto Files = OP.getSourcePathList(); tooling::RefactoringTool Tool(OP.getCompilations(), Files); - rename::USRFindingAction USRAction(SymbolOffset, OldName); - - // Find the USRs. - Tool.run(tooling::newFrontendActionFactory(&USRAction).get()); - const auto &USRs = USRAction.getUSRs(); - const auto &PrevName = USRAction.getUSRSpelling(); - - if (PrevName.empty()) { - // An error should have already been printed. - exit(1); - } + 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); + } - if (PrintName) { - errs() << "clang-rename: found name: " << PrevName << '\n'; + if (PrintName) { + errs() << "clang-rename: found name: " << PrevName << '\n'; + } } // Perform the renaming. - rename::RenamingAction RenameAction(NewName, PrevName, USRs, + rename::RenamingAction RenameAction(NewNames, PrevNames, USRList, Tool.getReplacements(), PrintLocations); auto Factory = tooling::newFrontendActionFactory(&RenameAction); int ExitCode; @@ -161,12 +213,11 @@ int main(int argc, const char **argv) { // indication of which files start where, other than that we print the files // in the same order we see them. LangOptions DefaultLangOptions; - IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = - new DiagnosticOptions(); + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), - &*DiagOpts, &DiagnosticPrinter, false); + IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, + &DiagnosticPrinter, false); auto &FileMgr = Tool.getFiles(); SourceManager Sources(Diagnostics, FileMgr); Rewriter Rewrite(Sources, DefaultLangOptions); @@ -181,3 +232,24 @@ int main(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); +} |

