vmiklos created this revision. vmiklos added a reviewer: klimek. vmiklos added a subscriber: cfe-commits.
This way parsing the source input multiple times for multiple renames can be avoided. http://reviews.llvm.org/D21814 Files: clang-rename/RenamingAction.cpp clang-rename/RenamingAction.h clang-rename/tool/ClangRename.cpp test/clang-rename/ClassTestMulti.cpp test/clang-rename/ClassTestMultiByName.cpp
Index: test/clang-rename/ClassTestMultiByName.cpp =================================================================== --- /dev/null +++ test/clang-rename/ClassTestMultiByName.cpp @@ -0,0 +1,8 @@ +// RUN: cat %s > %t.cpp +// RUN: clang-rename -old-name=Cla1,Cla2 -new-name=Kla1,Kla2 %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s +class Cla1 { // CHECK: class Kla1 +}; + +class Cla2 { // CHECK: class Kla2 +}; Index: test/clang-rename/ClassTestMulti.cpp =================================================================== --- /dev/null +++ test/clang-rename/ClassTestMulti.cpp @@ -0,0 +1,8 @@ +// RUN: cat %s > %t.cpp +// RUN: clang-rename -offset=145,183 -new-name=Kla1,Kla2 %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s +class Cla1 { // CHECK: class Kla1 +}; + +class Cla2 { // CHECK: class Kla2 +}; Index: clang-rename/tool/ClangRename.cpp =================================================================== --- clang-rename/tool/ClangRename.cpp +++ clang-rename/tool/ClangRename.cpp @@ -38,23 +38,24 @@ #include "llvm/Support/Host.h" #include <cstdlib> #include <string> +#include <sstream> using namespace llvm; cl::OptionCategory ClangRenameCategory("Clang-rename options"); static cl::opt<std::string> -NewName( +NewNames( "new-name", cl::desc("The new name to change the symbol to."), cl::cat(ClangRenameCategory)); -static cl::opt<unsigned> -SymbolOffset( +static cl::opt<std::string> +SymbolOffsets( "offset", cl::desc("Locates the symbol by offset as opposed to <line>:<column>."), cl::cat(ClangRenameCategory)); static cl::opt<std::string> -OldName( +OldNames( "old-name", cl::desc("The fully qualified name of the symbol, if -offset is not used."), cl::cat(ClangRenameCategory)); @@ -91,39 +92,100 @@ const char RenameUsage[] = "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"; +Otherwise, the results are written to stdout.\n\ +-offset, -old-name and -new-name accept a comma-separated list to perform\n\ +multiple renames with one invocation.\n"; int main(int argc, const char **argv) { cl::SetVersionPrinter(PrintVersion); tooling::CommonOptionsParser OP(argc, argv, ClangRenameCategory, RenameUsage); // Check the arguments for correctness. - if (NewName.empty()) { + if (NewNames.empty()) { errs() << "clang-rename: no new name provided.\n\n"; cl::PrintHelpMessage(); exit(1); } - // Get the USRs. - auto Files = OP.getSourcePathList(); - tooling::RefactoringTool Tool(OP.getCompilations(), Files); - rename::USRFindingAction USRAction(SymbolOffset, OldName); + // Tokenize the new names. + std::stringstream NewNameStream(NewNames); + std::vector<std::string> NewNameList; + while (NewNameStream.good()) { + std::string Token; + std::getline(NewNameStream, Token, ','); + NewNameList.push_back(Token); + } + + // Tokenize the offsets. + std::stringstream SymbolOffsetStream(SymbolOffsets); + std::vector<unsigned> SymbolOffsetList; + while (SymbolOffsetStream.good()) { + std::string Token; + std::getline(SymbolOffsetStream, Token, ','); + if (Token.empty()) { + break; + } + SymbolOffsetList.push_back(std::stoi(Token)); + } + + if (!SymbolOffsetList.empty() && SymbolOffsetList.size() != NewNameList.size()) { + errs() << "clang-rename: number of offsets (" << SymbolOffsetList.size() << + ") do not equal to number of new names (" << NewNameList.size() << + ").\n\n"; + cl::PrintHelpMessage(); + exit(1); + } - // Find the USRs. - Tool.run(tooling::newFrontendActionFactory(&USRAction).get()); - const auto &USRs = USRAction.getUSRs(); - const auto &PrevName = USRAction.getUSRSpelling(); + // Tokenize the old names. + std::stringstream OldNameStream(OldNames); + std::vector<std::string> OldNameList; + while (OldNameStream.good()) { + std::string Token; + std::getline(OldNameStream, Token, ','); + if (Token.empty()) { + break; + } + OldNameList.push_back(Token); + } - if (PrevName.empty()) - // An error should have already been printed. + if (!OldNameList.empty() && OldNameList.size() != NewNameList.size()) { + errs() << "clang-rename: number of old names (" << OldNameList.size() << + ") do not equal to number of new names (" << NewNameList.size() << + ").\n\n"; + cl::PrintHelpMessage(); exit(1); + } - if (PrintName) - errs() << "clang-rename: found name: " << PrevName << "\n"; + std::vector<std::vector<std::string>> USRList; + std::vector<std::string> PrevNameList; + auto Files = OP.getSourcePathList(); + tooling::RefactoringTool Tool(OP.getCompilations(), Files); + unsigned Count = OldNameList.size() ? OldNameList.size() : SymbolOffsetList.size(); + for (unsigned I = 0; I < Count; ++I) { + unsigned SymbolOffset = SymbolOffsetList.empty() ? 0 : SymbolOffsetList[I]; + const std::string& OldName = OldNameList.empty() ? std::string() : OldNameList[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(); + PrevNameList.push_back(PrevName); + + if (PrevName.empty()) + // An error should have already been printed. + exit(1); + + if (PrintName) + errs() << "clang-rename: found name: " << PrevName << "\n"; + } // Perform the renaming. - rename::RenamingAction RenameAction(NewName, PrevName, USRs, + rename::RenamingAction RenameAction(NewNameList, PrevNameList, USRList, Tool.getReplacements(), PrintLocations); auto Factory = tooling::newFrontendActionFactory(&RenameAction); int res; Index: clang-rename/RenamingAction.h =================================================================== --- clang-rename/RenamingAction.h +++ clang-rename/RenamingAction.h @@ -25,18 +25,18 @@ class RenamingAction { public: - RenamingAction(const std::string &NewName, const std::string &PrevName, - const std::vector<std::string> &USRs, + RenamingAction(const std::vector<std::string> &NewNameList, const std::vector<std::string> &PrevNameList, + const std::vector<std::vector<std::string>> &USRList, tooling::Replacements &Replaces, bool PrintLocations = false) - : NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces), + : NewNameList(NewNameList), PrevNameList(PrevNameList), USRList(USRList), Replaces(Replaces), PrintLocations(PrintLocations) { } std::unique_ptr<ASTConsumer> newASTConsumer(); private: - const std::string &NewName, &PrevName; - const std::vector<std::string> &USRs; + const std::vector<std::string> &NewNameList, &PrevNameList; + const std::vector<std::vector<std::string>> &USRList; tooling::Replacements &Replaces; bool PrintLocations; }; Index: clang-rename/RenamingAction.cpp =================================================================== --- clang-rename/RenamingAction.cpp +++ clang-rename/RenamingAction.cpp @@ -34,16 +34,24 @@ class RenamingASTConsumer : public ASTConsumer { public: - RenamingASTConsumer(const std::string &NewName, - const std::string &PrevName, - const std::vector<std::string> &USRs, + RenamingASTConsumer(const std::vector<std::string> &NewNameList, + const std::vector<std::string> &PrevNameList, + const std::vector<std::vector<std::string>> &USRList, tooling::Replacements &Replaces, bool PrintLocations) - : NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces), + : NewNameList(NewNameList), PrevNameList(PrevNameList), USRList(USRList), Replaces(Replaces), PrintLocations(PrintLocations) { } void HandleTranslationUnit(ASTContext &Context) override { + for (unsigned I = 0; I < NewNameList.size(); ++I) { + HandleOneRename(Context, NewNameList[I], PrevNameList[I], USRList[I]); + } + } + + void HandleOneRename(ASTContext &Context, const std::string &NewName, + const std::string &PrevName, + const std::vector<std::string> &USRs) { const auto &SourceMgr = Context.getSourceManager(); std::vector<SourceLocation> RenamingCandidates; std::vector<SourceLocation> NewCandidates; @@ -72,14 +80,14 @@ } private: - const std::string &NewName, &PrevName; - const std::vector<std::string> &USRs; + const std::vector<std::string> &NewNameList, &PrevNameList; + const std::vector<std::vector<std::string>> &USRList; tooling::Replacements &Replaces; bool PrintLocations; }; std::unique_ptr<ASTConsumer> RenamingAction::newASTConsumer() { - return llvm::make_unique<RenamingASTConsumer>(NewName, PrevName, USRs, + return llvm::make_unique<RenamingASTConsumer>(NewNameList, PrevNameList, USRList, Replaces, PrintLocations); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits