Index: clang-rename/tool/ClangRename.cpp =================================================================== --- clang-rename/tool/ClangRename.cpp +++ clang-rename/tool/ClangRename.cpp @@ -40,44 +40,45 @@ using namespace llvm; -cl::OptionCategory ClangRenameCategory("Clang-rename options"); +cl::OptionCategory ClangRenameAtCategory("clang-rename rename-at options"); +cl::OptionCategory ClangRenameAllCategory("clang-rename rename-all options"); static cl::opt NewName( "new-name", cl::desc("The new name to change the symbol to."), - cl::cat(ClangRenameCategory)); + cl::cat(ClangRenameAtCategory), cl::cat(ClangRenameAllCategory)); static cl::opt SymbolOffset( "offset", cl::desc("Locates the symbol by offset as opposed to :."), - cl::cat(ClangRenameCategory)); + cl::cat(ClangRenameAtCategory)); static cl::opt OldName( "old-name", cl::desc("The fully qualified name of the symbol, if -offset is not used."), - cl::cat(ClangRenameCategory)); + cl::cat(ClangRenameAllCategory)); static cl::opt Inplace( "i", cl::desc("Overwrite edited s."), - cl::cat(ClangRenameCategory)); + cl::cat(ClangRenameAtCategory), cl::cat(ClangRenameAllCategory)); static cl::opt PrintName( "pn", cl::desc("Print the found symbol's name prior to renaming to stderr."), - cl::cat(ClangRenameCategory)); + cl::cat(ClangRenameAtCategory)); static cl::opt PrintLocations( "pl", cl::desc("Print the locations affected by renaming to stderr."), - cl::cat(ClangRenameCategory)); + cl::cat(ClangRenameAtCategory)); static cl::opt ExportFixes( "export-fixes", cl::desc("YAML file to store suggested fixes in."), cl::value_desc("filename"), - cl::cat(ClangRenameCategory)); + cl::cat(ClangRenameAllCategory)); #define CLANG_RENAME_VERSION "0.0.1" @@ -87,14 +88,14 @@ using namespace clang; -const char RenameUsage[] = "A tool to rename symbols in C/C++ code.\n\ +const char RenameAtUsage[] = "A tool to rename symbols in C/C++ code.\n\ clang-rename renames every occurrence of a symbol found at in\n\ . If -i is specified, the edited files are overwritten to disk.\n\ Otherwise, the results are written to stdout.\n"; -int main(int argc, const char **argv) { - cl::SetVersionPrinter(PrintVersion); - tooling::CommonOptionsParser OP(argc, argv, ClangRenameCategory, RenameUsage); +/// \brief rename-at subcommand. +int renameAtMain(int argc, const char **argv) { + tooling::CommonOptionsParser OP(argc, argv, ClangRenameAtCategory, RenameAtUsage); // Check the arguments for correctness. @@ -133,6 +134,71 @@ } else { ExitCode = Tool.run(Factory.get()); + // Write every file to stdout. Right now we just barf the files without any + // indication of which files start where, other than that we print the files + // in the same order we see them. + LangOptions DefaultLangOptions; + IntrusiveRefCntPtr DiagOpts = + new DiagnosticOptions(); + TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts); + DiagnosticsEngine Diagnostics( + IntrusiveRefCntPtr(new DiagnosticIDs()), + &*DiagOpts, &DiagnosticPrinter, false); + auto &FileMgr = Tool.getFiles(); + SourceManager Sources(Diagnostics, FileMgr); + Rewriter Rewrite(Sources, DefaultLangOptions); + + Tool.applyAllReplacements(Rewrite); + for (const auto &File : Files) { + const auto *Entry = FileMgr.getFile(File); + auto ID = Sources.translateFile(Entry); + Rewrite.getEditBuffer(ID).write(outs()); + } + } + + exit(ExitCode); +} + +const char RenameAllUsage[] = "A tool to rename symbols in C/C++ code.\n\ +clang-rename renames every occurrence of a symbol named .\n"; + +/// \brief rename-all subcommand. +int renameAllMain(int argc, const char **argv) { + tooling::CommonOptionsParser OP(argc, argv, ClangRenameAllCategory, RenameAllUsage); + + // Check the arguments for correctness. + + if (NewName.empty()) { + errs() << "clang-rename: no new name provided.\n\n"; + exit(1); + } + + // Get the USRs. + 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); + } + + // Perform the renaming. + rename::RenamingAction RenameAction(NewName, PrevName, USRs, + Tool.getReplacements(), PrintLocations); + auto Factory = tooling::newFrontendActionFactory(&RenameAction); + int ExitCode; + + if (Inplace) { + ExitCode = Tool.runAndSave(Factory.get()); + } else { + ExitCode = Tool.run(Factory.get()); + if (!ExportFixes.empty()) { std::error_code EC; llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::F_None); @@ -177,3 +243,45 @@ exit(ExitCode); } + +/// \brief Top level help. +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.\n" + << " rename-all: Perform rename of all symbols matching a fully qualified name.\n"; + return 0; +} + +/// \brief Top level version information. +static int versionMain(int argc, const char *argv[]) { + cl::PrintVersionMessage(); + return 0; +} + +int main(int argc, const char **argv) { + cl::SetVersionPrinter(PrintVersion); + + if (argc > 1) { + typedef int (*MainFunction)(int, const char *[]); + MainFunction Func = StringSwitch(argv[1]) + .Case("rename-at", renameAtMain) + .Case("rename-all", renameAllMain) + .Cases("-help", "--help", helpMain) + .Cases("-version", "--version", versionMain) + .Default(nullptr); + + if (Func) { + std::string Invocation = std::string(argv[0]) + " " + argv[1]; + argv[1] = Invocation.c_str(); + return Func(argc - 1, argv + 1); + } + } + + if (argc > 1) { + errs() << "clang-rename: unrecognized command: " << argv[1] << '\n'; + } + helpMain(argc, argv); + return 1; +} Index: test/clang-rename/ClassFindByName.cpp =================================================================== --- test/clang-rename/ClassFindByName.cpp +++ test/clang-rename/ClassFindByName.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -old-name=Foo -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-all -old-name=Foo -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo { // CHECK: class Bar Index: test/clang-rename/ClassReplacements.cpp =================================================================== --- test/clang-rename/ClassReplacements.cpp +++ test/clang-rename/ClassReplacements.cpp @@ -1,11 +1,8 @@ // RUN: rm -rf %t // RUN: mkdir -p %t/fixes // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=254 -new-name=Bar -export-fixes=%t/fixes/clang-rename.yaml %t.cpp -- +// RUN: clang-rename rename-all -old-name=Foo -new-name=Bar -export-fixes=%t/fixes/clang-rename.yaml %t.cpp -- // RUN: clang-apply-replacements %t // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo {}; // CHECK: class Bar {}; - -// Use grep -FUbo 'Foo' to get the correct offset of Cla when changing -// this file. Index: test/clang-rename/ClassSimpleRenaming.cpp =================================================================== --- test/clang-rename/ClassSimpleRenaming.cpp +++ test/clang-rename/ClassSimpleRenaming.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=136 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=146 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo {}; // CHECK: class Bar Index: test/clang-rename/ClassTest.cpp =================================================================== --- test/clang-rename/ClassTest.cpp +++ test/clang-rename/ClassTest.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=138 -new-name=Hector %t.cpp -i -- +// RUN: clang-rename rename-at -offset=148 -new-name=Hector %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Cla // CHECK: class Hector { Index: test/clang-rename/ClassTestByName.cpp =================================================================== --- test/clang-rename/ClassTestByName.cpp +++ test/clang-rename/ClassTestByName.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -old-name=Cla -new-name=Hector %t.cpp -i -- +// RUN: clang-rename rename-all -old-name=Cla -new-name=Hector %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Cla { // CHECK: class Hector }; Index: test/clang-rename/ClassTestReplacements.cpp =================================================================== --- test/clang-rename/ClassTestReplacements.cpp +++ test/clang-rename/ClassTestReplacements.cpp @@ -1,12 +1,9 @@ // RUN: rm -rf %t // RUN: mkdir -p %t/fixes // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=256 -new-name=Hector -export-fixes=%t/fixes/clang-rename.yaml %t.cpp -- +// RUN: clang-rename rename-all -old-name=Cla -new-name=Hector -export-fixes=%t/fixes/clang-rename.yaml %t.cpp -- // RUN: clang-apply-replacements %t // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Cla // CHECK: class Hector { }; - -// Use grep -FUbo 'Cla' to get the correct offset of Cla when changing -// this file. Index: test/clang-rename/ConstCastExpr.cpp =================================================================== --- test/clang-rename/ConstCastExpr.cpp +++ test/clang-rename/ConstCastExpr.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=136 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=146 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo { // CHECK: class Bar { Index: test/clang-rename/ConstructExpr.cpp =================================================================== --- test/clang-rename/ConstructExpr.cpp +++ test/clang-rename/ConstructExpr.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=136 -new-name=Boo %t.cpp -i -- +// RUN: clang-rename rename-at -offset=146 -new-name=Boo %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo {}; // CHECK: class Boo {}; Index: test/clang-rename/CtorDefTest.cpp =================================================================== --- test/clang-rename/CtorDefTest.cpp +++ test/clang-rename/CtorDefTest.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=133 -new-name=D %t.cpp -i -- +// RUN: clang-rename rename-at -offset=143 -new-name=D %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class C { Index: test/clang-rename/CtorFindByDeclaration.cpp =================================================================== --- test/clang-rename/CtorFindByDeclaration.cpp +++ test/clang-rename/CtorFindByDeclaration.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=174 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=184 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo { // CHECK: class Bar Index: test/clang-rename/CtorFindByDefinition.cpp =================================================================== --- test/clang-rename/CtorFindByDefinition.cpp +++ test/clang-rename/CtorFindByDefinition.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=212 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=222 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo { // CHECK: class Bar Index: test/clang-rename/CtorInitializer.cpp =================================================================== --- test/clang-rename/CtorInitializer.cpp +++ test/clang-rename/CtorInitializer.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=163 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=173 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Baz {}; Index: test/clang-rename/CtorInitializerTest.cpp =================================================================== --- test/clang-rename/CtorInitializerTest.cpp +++ test/clang-rename/CtorInitializerTest.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=162 -new-name=hector %t.cpp -i -- +// RUN: clang-rename rename-at -offset=172 -new-name=hector %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class A { Index: test/clang-rename/DeclRefExpr.cpp =================================================================== --- test/clang-rename/DeclRefExpr.cpp +++ test/clang-rename/DeclRefExpr.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=161 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=171 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class C { Index: test/clang-rename/DtorDeclaration.cpp =================================================================== --- test/clang-rename/DtorDeclaration.cpp +++ test/clang-rename/DtorDeclaration.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=175 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=185 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo { // CHECK: class Bar { Index: test/clang-rename/DtorDefTest.cpp =================================================================== --- test/clang-rename/DtorDefTest.cpp +++ test/clang-rename/DtorDefTest.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=135 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=145 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo { public: Index: test/clang-rename/DtorDefinition.cpp =================================================================== --- test/clang-rename/DtorDefinition.cpp +++ test/clang-rename/DtorDefinition.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=219 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=229 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo { // CHECK: class Bar { Index: test/clang-rename/DynamicCastExpr.cpp =================================================================== --- test/clang-rename/DynamicCastExpr.cpp +++ test/clang-rename/DynamicCastExpr.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=193 -new-name=X %t.cpp -i -- -frtti +// RUN: clang-rename rename-at -offset=203 -new-name=X %t.cpp -i -- -frtti // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Base { virtual int getValue() const = 0; Index: test/clang-rename/Field.cpp =================================================================== --- test/clang-rename/Field.cpp +++ test/clang-rename/Field.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=148 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=158 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Baz { Index: test/clang-rename/FieldTest.cpp =================================================================== --- test/clang-rename/FieldTest.cpp +++ test/clang-rename/FieldTest.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=150 -new-name=hector %t.cpp -i -- +// RUN: clang-rename rename-at -offset=160 -new-name=hector %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Cla { Index: test/clang-rename/FunctionMacro.cpp =================================================================== --- test/clang-rename/FunctionMacro.cpp +++ test/clang-rename/FunctionMacro.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=199 -new-name=macro_function %t.cpp -i -- +// RUN: clang-rename rename-at -offset=209 -new-name=macro_function %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s #define moo foo // CHECK: #define moo macro_function Index: test/clang-rename/MemberExprMacro.cpp =================================================================== --- test/clang-rename/MemberExprMacro.cpp +++ test/clang-rename/MemberExprMacro.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=156 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=166 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Baz { Index: test/clang-rename/Namespace.cpp =================================================================== --- test/clang-rename/Namespace.cpp +++ test/clang-rename/Namespace.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=143 -new-name=llvm %t.cpp -i -- +// RUN: clang-rename rename-at -offset=153 -new-name=llvm %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s namespace foo { // CHECK: namespace llvm { Index: test/clang-rename/NoNewName.cpp =================================================================== --- test/clang-rename/NoNewName.cpp +++ test/clang-rename/NoNewName.cpp @@ -1,4 +1,4 @@ // Check for an error while -new-name argument has not been passed to // clang-rename. -// RUN: not clang-rename -offset=133 %s 2>&1 | FileCheck %s +// RUN: not clang-rename rename-at -offset=133 %s 2>&1 | FileCheck %s // CHECK: clang-rename: no new name provided. Index: test/clang-rename/ReinterpretCastExpr.cpp =================================================================== --- test/clang-rename/ReinterpretCastExpr.cpp +++ test/clang-rename/ReinterpretCastExpr.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=133 -new-name=X %t.cpp -i -- +// RUN: clang-rename rename-at -offset=143 -new-name=X %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Cla { public: Index: test/clang-rename/StaticCastExpr.cpp =================================================================== --- test/clang-rename/StaticCastExpr.cpp +++ test/clang-rename/StaticCastExpr.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=150 -new-name=X %t.cpp -i -- +// RUN: clang-rename rename-at -offset=160 -new-name=X %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Base { }; Index: test/clang-rename/VarTest.cpp =================================================================== --- test/clang-rename/VarTest.cpp +++ test/clang-rename/VarTest.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=150 -new-name=hector %t.cpp -i -- +// RUN: clang-rename rename-at -offset=160 -new-name=hector %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s namespace A { int foo; // CHECK: int hector; } Index: test/clang-rename/Variable.cpp =================================================================== --- test/clang-rename/Variable.cpp +++ test/clang-rename/Variable.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=148 -new-name=Bar %t.cpp -i -- +// RUN: clang-rename rename-at -offset=158 -new-name=Bar %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s namespace A { Index: test/clang-rename/VariableMacro.cpp =================================================================== --- test/clang-rename/VariableMacro.cpp +++ test/clang-rename/VariableMacro.cpp @@ -1,5 +1,5 @@ // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=208 -new-name=Z %t.cpp -i -- +// RUN: clang-rename rename-at -offset=218 -new-name=Z %t.cpp -i -- // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s #define Y X // CHECK: #define Y Z