forked from OSchip/llvm-project
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
This commit is contained in:
parent
9e0dab9352
commit
aaec9b6cfc
|
@ -35,14 +35,23 @@ namespace rename {
|
|||
class RenamingASTConsumer : public ASTConsumer {
|
||||
public:
|
||||
RenamingASTConsumer(
|
||||
const std::string &NewName, const std::string &PrevName,
|
||||
const std::vector<std::string> &USRs,
|
||||
const std::vector<std::string> &NewNames,
|
||||
const std::vector<std::string> &PrevNames,
|
||||
const std::vector<std::vector<std::string>> &USRList,
|
||||
std::map<std::string, tooling::Replacements> &FileToReplaces,
|
||||
bool PrintLocations)
|
||||
: NewName(NewName), PrevName(PrevName), USRs(USRs),
|
||||
: NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),
|
||||
FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
|
||||
|
||||
void HandleTranslationUnit(ASTContext &Context) override {
|
||||
for (unsigned I = 0; I < NewNames.size(); ++I) {
|
||||
HandleOneRename(Context, NewNames[I], PrevNames[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;
|
||||
|
@ -70,14 +79,14 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
const std::string &NewName, &PrevName;
|
||||
const std::vector<std::string> &USRs;
|
||||
const std::vector<std::string> &NewNames, &PrevNames;
|
||||
const std::vector<std::vector<std::string>> &USRList;
|
||||
std::map<std::string, tooling::Replacements> &FileToReplaces;
|
||||
bool PrintLocations;
|
||||
};
|
||||
|
||||
std::unique_ptr<ASTConsumer> RenamingAction::newASTConsumer() {
|
||||
return llvm::make_unique<RenamingASTConsumer>(NewName, PrevName, USRs,
|
||||
return llvm::make_unique<RenamingASTConsumer>(NewNames, PrevNames, USRList,
|
||||
FileToReplaces, PrintLocations);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,18 +25,19 @@ namespace rename {
|
|||
|
||||
class RenamingAction {
|
||||
public:
|
||||
RenamingAction(const std::string &NewName, const std::string &PrevName,
|
||||
const std::vector<std::string> &USRs,
|
||||
RenamingAction(const std::vector<std::string> &NewNames,
|
||||
const std::vector<std::string> &PrevNames,
|
||||
const std::vector<std::vector<std::string>> &USRList,
|
||||
std::map<std::string, tooling::Replacements> &FileToReplaces,
|
||||
bool PrintLocations = false)
|
||||
: NewName(NewName), PrevName(PrevName), USRs(USRs),
|
||||
: NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),
|
||||
FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
|
||||
|
||||
std::unique_ptr<ASTConsumer> newASTConsumer();
|
||||
|
||||
private:
|
||||
const std::string &NewName, &PrevName;
|
||||
const std::vector<std::string> &USRs;
|
||||
const std::vector<std::string> &NewNames, &PrevNames;
|
||||
const std::vector<std::vector<std::string>> &USRList;
|
||||
std::map<std::string, tooling::Replacements> &FileToReplaces;
|
||||
bool PrintLocations;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
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];
|
||||
|
||||
// Find the USRs.
|
||||
Tool.run(tooling::newFrontendActionFactory(&USRAction).get());
|
||||
const auto &USRs = USRAction.getUSRs();
|
||||
const auto &PrevName = USRAction.getUSRSpelling();
|
||||
// Get the USRs.
|
||||
rename::USRFindingAction USRAction(SymbolOffset, OldName);
|
||||
|
||||
if (PrevName.empty()) {
|
||||
// An error should have already been printed.
|
||||
exit(1);
|
||||
}
|
||||
// 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 (PrintName) {
|
||||
errs() << "clang-rename: found name: " << PrevName << '\n';
|
||||
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(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);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,14 @@ To get an offset of a symbol in a file run
|
|||
$ grep -FUbo 'foo' file.cpp
|
||||
|
||||
|
||||
You can also identify one or more symbols to be renamed by giving the fully qualified
|
||||
name:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ clang-rename rename-all -old-name=foo -new-name=bar test.cpp
|
||||
|
||||
|
||||
The tool currently supports renaming actions inside a single Translation Unit
|
||||
only. It is planned to extend the tool's functionality to support multi-TU
|
||||
renaming actions in the future.
|
||||
|
@ -55,16 +63,63 @@ text editor interface instead for better experience.
|
|||
.. code-block:: console
|
||||
|
||||
$ clang-rename -help
|
||||
Usage: clang-rename {rename-at|rename-all} [OPTION]...
|
||||
|
||||
A tool to rename symbols in C/C++ code.
|
||||
|
||||
Subcommands:
|
||||
rename-at: Perform rename off of a location in a file. (This is the default.)
|
||||
rename-all: Perform rename of all symbols matching one or more fully qualified names.
|
||||
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ clang-rename rename-at -help
|
||||
OVERVIEW: A tool to rename symbols in C/C++ code.
|
||||
clang-rename renames every occurrence of a symbol found at <offset> in
|
||||
<source0>. If -i is specified, the edited files are overwritten to disk.
|
||||
Otherwise, the results are written to stdout.
|
||||
|
||||
USAGE: clang-rename rename-at [subcommand] [options] <source0> [... <sourceN>]
|
||||
|
||||
OPTIONS:
|
||||
|
||||
Generic Options:
|
||||
|
||||
-help - Display available options (-help-hidden for more)
|
||||
-help-list - Display list of available options (-help-list-hidden for more)
|
||||
-version - Display the version of this program
|
||||
|
||||
USAGE: clang-rename [subcommand] [options] <source0> [... <sourceN>]
|
||||
clang-rename rename-at options:
|
||||
|
||||
-export-fixes=<filename> - YAML file to store suggested fixes in.
|
||||
-extra-arg=<string> - Additional argument to append to the compiler command line
|
||||
-extra-arg-before=<string> - Additional argument to prepend to the compiler command line
|
||||
-i - Overwrite edited <file>s.
|
||||
-new-name=<string> - The new name to change the symbol to.
|
||||
-offset=<uint> - Locates the symbol by offset as opposed to <line>:<column>.
|
||||
-p=<string> - Build path
|
||||
-pl - Print the locations affected by renaming to stderr.
|
||||
-pn - Print the found symbol's name prior to renaming to stderr.
|
||||
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ clang-rename rename-all -help
|
||||
OVERVIEW: A tool to rename symbols in C/C++ code.
|
||||
clang-rename renames every occurrence of a symbol named <old-name>.
|
||||
|
||||
USAGE: clang-rename rename-all [subcommand] [options] <source0> [... <sourceN>]
|
||||
|
||||
OPTIONS:
|
||||
|
||||
Clang-rename options:
|
||||
Generic Options:
|
||||
|
||||
-help - Display available options (-help-hidden for more)
|
||||
-help-list - Display list of available options (-help-list-hidden for more)
|
||||
-version - Display the version of this program
|
||||
|
||||
clang-rename rename-all options:
|
||||
|
||||
-export-fixes=<filename> - YAML file to store suggested fixes in.
|
||||
-extra-arg=<string> - Additional argument to append to the compiler command line
|
||||
|
@ -74,14 +129,6 @@ text editor interface instead for better experience.
|
|||
-offset=<uint> - Locates the symbol by offset as opposed to <line>:<column>.
|
||||
-old-name=<string> - The fully qualified name of the symbol, if -offset is not used.
|
||||
-p=<string> - Build path
|
||||
-pl - Print the locations affected by renaming to stderr.
|
||||
-pn - Print the found symbol's name prior to renaming to stderr.
|
||||
|
||||
Generic Options:
|
||||
|
||||
-help - Display available options (-help-hidden for more)
|
||||
-help-list - Display list of available options (-help-list-hidden for more)
|
||||
-version - Display the version of this program
|
||||
|
||||
|
||||
Vim Integration
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// RUN: cat %s > %t.cpp
|
||||
// RUN: clang-rename rename-all -offset=174 -new-name=Bar1 -offset=212 -new-name=Bar2 %t.cpp -i --
|
||||
// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
|
||||
class Foo1 { // CHECK: class Bar1
|
||||
};
|
||||
|
||||
class Foo2 { // CHECK: class Bar2
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
// RUN: cat %s > %t.cpp
|
||||
// RUN: clang-rename rename-all -old-name=Foo1 -new-name=Bar1 -old-name=Foo2 -new-name=Bar2 %t.cpp -i --
|
||||
// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
|
||||
class Foo1 { // CHECK: class Bar1
|
||||
};
|
||||
|
||||
class Foo2 { // CHECK: class Bar2
|
||||
};
|
|
@ -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
|
||||
|
||||
void foo() {
|
||||
|
|
|
@ -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
|
||||
// CHECK: ERROR: no new name provided.
|
||||
// CHECK: clang-rename: for the -new-name option: must be specified
|
||||
|
|
Loading…
Reference in New Issue