summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2017-03-27 10:56:34 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2017-03-27 10:56:34 +0200
commit2a6a16bd178844e4c835e4e505ede3645b18e16c (patch)
tree963aac784551f1f858cb4f2fdc005238a4255789
parent27cb24a38aa9550f5b6011464c38717eb45c1924 (diff)
clang-rename: handle C -> ns::C rename for class declarations / definitions
-rw-r--r--clang/Makefile2
-rw-r--r--clang/rename.cxx62
2 files changed, 62 insertions, 2 deletions
diff --git a/clang/Makefile b/clang/Makefile
index 7bdbec8..b50b32b 100644
--- a/clang/Makefile
+++ b/clang/Makefile
@@ -3,7 +3,7 @@
CLANGDEFS=-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -fno-rtti
CLANGWARNS=-Werror -Wall -Wno-missing-braces -Wnon-virtual-dtor -Wendif-labels -Wextra -Wundef -Wunused-macros -Wshadow -Woverloaded-virtual
CLANGFLAGS = $(CLANGDEFS) $(CLANGWARNS) -g -std=c++11
-CLANGLIBS = -lclangAST -lclangBasic -lclangFrontend -lclangRewrite -lclangTooling -lLLVMSupport
+CLANGLIBS = -lclangAST -lclangBasic -lclangFrontend -lclangRewrite -lclangTooling -lclangLex -lLLVMSupport
ifneq ($(GCOV),)
CLANGFLAGS += --coverage
endif
diff --git a/clang/rename.cxx b/clang/rename.cxx
index a4b3231..2ec5cd0 100644
--- a/clang/rename.cxx
+++ b/clang/rename.cxx
@@ -9,6 +9,36 @@
#include <clang/Rewrite/Core/Rewriter.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
+#include <clang/Lex/Lexer.h>
+
+namespace
+{
+/// From clang-tools-extra.git's clang-move/ClangMove.cpp.
+clang::SourceLocation getLocForEndOfDecl(const clang::Decl *D, const clang::LangOptions &LangOpts = clang::LangOptions()) {
+ const auto &SM = D->getASTContext().getSourceManager();
+ auto EndExpansionLoc = SM.getExpansionLoc(D->getLocEnd());
+ std::pair<clang::FileID, unsigned> LocInfo = SM.getDecomposedLoc(EndExpansionLoc);
+ // Try to load the file buffer.
+ bool InvalidTemp = false;
+ llvm::StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp);
+ if (InvalidTemp)
+ return clang::SourceLocation();
+
+ const char *TokBegin = File.data() + LocInfo.second;
+ // Lex from the start of the given location.
+ clang::Lexer Lex(SM.getLocForStartOfFile(LocInfo.first), LangOpts, File.begin(),TokBegin, File.end());
+
+ llvm::SmallVector<char, 16> Line;
+ // FIXME: this is a bit hacky to get ReadToEndOfLine work.
+ Lex.setParsingPreprocessorDirective(true);
+ Lex.ReadToEndOfLine(&Line);
+ clang::SourceLocation EndLoc = EndExpansionLoc.getLocWithOffset(Line.size());
+ // If we already reach EOF, just return the EOF SourceLocation;
+ // otherwise, move 1 offset ahead to include the trailing newline character
+ // '\n'.
+ return SM.getLocForEndOfFile(LocInfo.first) == EndLoc ? EndLoc : EndLoc.getLocWithOffset(1);
+}
+}
class RenameRewriter : public clang::Rewriter
{
@@ -70,6 +100,27 @@ class RenameVisitor : public clang::RecursiveASTVisitor<RenameVisitor>
}
}
+ /// Get the namespace part of a new name.
+ std::string GetNamespace(const std::string& rOldName)
+ {
+ auto it = mrRewriter.getNameMap().find(rOldName);
+ if (it == mrRewriter.getNameMap().end())
+ return std::string();
+
+ std::string aNewName = it->second;
+ std::string::size_type nPos = aNewName.find("::");
+ if (nPos == std::string::npos)
+ return std::string();
+
+ return aNewName.substr(0, nPos);
+ }
+
+ /// If a new name has a namespace part.
+ bool HasNamespace(const std::string& rOldName)
+ {
+ return !GetNamespace(rOldName).empty();
+ }
+
public:
explicit RenameVisitor(RenameRewriter& rRewriter)
: mrRewriter(rRewriter)
@@ -245,7 +296,16 @@ public:
bool VisitCXXRecordDecl(const clang::CXXRecordDecl* pDecl)
{
std::string aName = pDecl->getQualifiedNameAsString();
- RewriteText(pDecl->getLocation(), pDecl->getNameAsString().length(), aName);
+ if (HasNamespace(aName))
+ {
+ std::string aInsert = "namespace ";
+ aInsert += GetNamespace(aName);
+ aInsert += "\n{\n";
+ mrRewriter.ReplaceText(pDecl->getLocStart(), 0, aInsert);
+ mrRewriter.ReplaceText(getLocForEndOfDecl(pDecl), 0, "}\n");
+ }
+ else
+ RewriteText(pDecl->getLocation(), pDecl->getNameAsString().length(), aName);
return true;
}