summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-rename/tool/ClangRename.cpp
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@vmiklos.hu>2016-08-02 09:51:31 +0000
committerMiklos Vajna <vmiklos@vmiklos.hu>2016-08-02 09:51:31 +0000
commitaaec9b6cfce2e492cac2fd79687f0fab9bd8a9af (patch)
tree1a2cf444fa67050e9abb4f0ce7455722a7a4df25 /clang-tools-extra/clang-rename/tool/ClangRename.cpp
parent9e0dab935292c4e513db76781cb036c5f19ea3c7 (diff)
downloadbcm5719-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.cpp212
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);
+}
OpenPOWER on IntegriCloud