forked from OSchip/llvm-project
clang-rename: add a -old-name option
This is similar to -offset with the following differences: 1) -offset can refer to local variables as well. 2) -old-name makes it easier to refer to e.g. ClassName::MemberName by spelling out the fully qualified name, instead of having to use e.g. grep to look up the exact offset. In other words, -offset is great when clang-rename is invoked by e.g. an IDE, but not really user-friendly when the tool is invoked by the user from commandline. That's the use case where -old-name is supposed to improve the situation. Reviewers: klimek Differential Revision: http://reviews.llvm.org/D21517 llvm-svn: 273304
This commit is contained in:
parent
48975881ab
commit
47bd46395a
|
@ -40,6 +40,14 @@ public:
|
|||
Point(Point) {
|
||||
}
|
||||
|
||||
// \brief Finds the NamedDecl for a name in the source.
|
||||
// \param Name the fully qualified name.
|
||||
explicit NamedDeclFindingASTVisitor(const SourceManager &SourceMgr,
|
||||
const std::string &Name)
|
||||
: Result(nullptr), SourceMgr(SourceMgr),
|
||||
Name(Name) {
|
||||
}
|
||||
|
||||
// Declaration visitors:
|
||||
|
||||
// \brief Checks if the point falls within the NameDecl. This covers every
|
||||
|
@ -93,9 +101,17 @@ private:
|
|||
// \returns false on success.
|
||||
bool setResult(const NamedDecl *Decl, SourceLocation Start,
|
||||
SourceLocation End) {
|
||||
if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
|
||||
!End.isFileID() || !isPointWithin(Start, End)) {
|
||||
return true;
|
||||
if (Name.empty()) {
|
||||
// Offset is used to find the declaration.
|
||||
if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
|
||||
!End.isFileID() || !isPointWithin(Start, End)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Fully qualified name is used to find the declaration.
|
||||
if (Name != Decl->getQualifiedNameAsString()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Result = Decl;
|
||||
return false;
|
||||
|
@ -121,6 +137,7 @@ private:
|
|||
const NamedDecl *Result;
|
||||
const SourceManager &SourceMgr;
|
||||
const SourceLocation Point; // The location to find the NamedDecl.
|
||||
const std::string Name;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -148,6 +165,22 @@ const NamedDecl *getNamedDeclAt(const ASTContext &Context,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const NamedDecl *getNamedDeclFor(const ASTContext &Context,
|
||||
const std::string &Name) {
|
||||
const auto &SourceMgr = Context.getSourceManager();
|
||||
NamedDeclFindingASTVisitor Visitor(SourceMgr, Name);
|
||||
auto Decls = Context.getTranslationUnitDecl()->decls();
|
||||
|
||||
for (auto &CurrDecl : Decls) {
|
||||
Visitor.TraverseDecl(CurrDecl);
|
||||
if (const NamedDecl *Result = Visitor.getNamedDecl()) {
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string getUSRForDecl(const Decl *Decl) {
|
||||
llvm::SmallVector<char, 128> Buff;
|
||||
|
||||
|
|
|
@ -30,6 +30,12 @@ namespace rename {
|
|||
const NamedDecl *getNamedDeclAt(const ASTContext &Context,
|
||||
const SourceLocation Point);
|
||||
|
||||
// Given an AST context and a fully qualified name, returns a NamedDecl
|
||||
// identifying the symbol with a matching name. Returns null if nothing is
|
||||
// found for the name.
|
||||
const NamedDecl *getNamedDeclFor(const ASTContext &Context,
|
||||
const std::string &Name);
|
||||
|
||||
// Converts a Decl into a USR.
|
||||
std::string getUSRForDecl(const Decl *Decl);
|
||||
|
||||
|
|
|
@ -68,7 +68,12 @@ struct NamedDeclFindingConsumer : public ASTConsumer {
|
|||
SourceMgr.getMainFileID()).getLocWithOffset(SymbolOffset);
|
||||
if (!Point.isValid())
|
||||
return;
|
||||
const NamedDecl *FoundDecl = getNamedDeclAt(Context, Point);
|
||||
const NamedDecl *FoundDecl = nullptr;
|
||||
if (OldName.empty()) {
|
||||
FoundDecl = getNamedDeclAt(Context, Point);
|
||||
} else {
|
||||
FoundDecl = getNamedDeclFor(Context, OldName);
|
||||
}
|
||||
if (FoundDecl == nullptr) {
|
||||
FullSourceLoc FullLoc(Point, SourceMgr);
|
||||
errs() << "clang-rename: could not find symbol at "
|
||||
|
@ -96,6 +101,7 @@ struct NamedDeclFindingConsumer : public ASTConsumer {
|
|||
}
|
||||
|
||||
unsigned SymbolOffset;
|
||||
std::string OldName;
|
||||
std::string *SpellingName;
|
||||
std::vector<std::string> *USRs;
|
||||
};
|
||||
|
@ -106,6 +112,7 @@ USRFindingAction::newASTConsumer() {
|
|||
new NamedDeclFindingConsumer);
|
||||
SpellingName = "";
|
||||
Consumer->SymbolOffset = SymbolOffset;
|
||||
Consumer->OldName = OldName;
|
||||
Consumer->USRs = &USRs;
|
||||
Consumer->SpellingName = &SpellingName;
|
||||
return std::move(Consumer);
|
||||
|
|
|
@ -25,7 +25,7 @@ class NamedDecl;
|
|||
namespace rename {
|
||||
|
||||
struct USRFindingAction {
|
||||
USRFindingAction(unsigned Offset) : SymbolOffset(Offset) {
|
||||
USRFindingAction(unsigned Offset, const std::string &Name) : SymbolOffset(Offset), OldName(Name) {
|
||||
}
|
||||
std::unique_ptr<ASTConsumer> newASTConsumer();
|
||||
|
||||
|
@ -40,6 +40,7 @@ struct USRFindingAction {
|
|||
|
||||
private:
|
||||
unsigned SymbolOffset;
|
||||
std::string OldName;
|
||||
std::string SpellingName;
|
||||
std::vector<std::string> USRs;
|
||||
};
|
||||
|
|
|
@ -52,6 +52,11 @@ 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",
|
||||
|
@ -96,7 +101,7 @@ int main(int argc, const char **argv) {
|
|||
// Get the USRs.
|
||||
auto Files = OP.getSourcePathList();
|
||||
tooling::RefactoringTool Tool(OP.getCompilations(), Files);
|
||||
rename::USRFindingAction USRAction(SymbolOffset);
|
||||
rename::USRFindingAction USRAction(SymbolOffset, OldName);
|
||||
|
||||
// Find the USRs.
|
||||
Tool.run(tooling::newFrontendActionFactory(&USRAction).get());
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// RUN: cat %s > %t.cpp
|
||||
// RUN: clang-rename -old-name=Cla -new-name=Hector %t.cpp -i --
|
||||
// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
|
||||
class Cla { // CHECK: class Hector
|
||||
};
|
||||
|
||||
int main() {
|
||||
Cla *Pointer = 0; // CHECK: Hector *Pointer = 0;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue