我是嘗試通過libtooling分析AST的Clang的新手。 我想找到一個特定的功能,並將其AST從原始源文件移動到一個新文件。鏗鏘:從原始文件寫入函數的AST到新文件
我已經知道如何通過MatchFinder找到函數。 現在,我想知道如何將它的AST寫入一個新文件(.c或.cpp)
在此先感謝!
我是嘗試通過libtooling分析AST的Clang的新手。 我想找到一個特定的功能,並將其AST從原始源文件移動到一個新文件。鏗鏘:從原始文件寫入函數的AST到新文件
我已經知道如何通過MatchFinder找到函數。 現在,我想知道如何將它的AST寫入一個新文件(.c或.cpp)
在此先感謝!
摘要:獲取源文本,使用SourceManager
;要從原始文件中刪除該功能,請生成Replacement
並將其應用於RefactoringTool
。
首先,這裏有一個方法來獲得其中的一個函數定義的源代碼,假設AST匹配,看起來是這樣的:
auto matcher(std::string const & fname) {
return functionDecl(hasName(fname)).bind("f_decl");
}
回調的run方法將開始通過獲取的訪問匹配AST節點,得到由函數聲明所覆蓋的範圍源,並獲得到SouceManager,其涉及的SourceLocation對象的實際源的引用:
virtual void run(MatchResult_t const & result) override {
using namespace clang;
FunctionDecl * f_decl = const_cast<FunctionDecl *>(
result.Nodes.getNodeAs<FunctionDecl>("f_decl"));
if(f_decl) {
SourceManager &sm(result.Context->getSourceManager());
SourceRange decl_range(f_decl->getSourceRange());
SourceLocation decl_begin(decl_range.getBegin());
SourceLocation decl_start_end(decl_range.getEnd());
SourceLocation decl_end_end(end_of_the_end(decl_start_end,sm));
什麼與decl_start_end
和是?有一個捕獲使用SourceRange:結束位置不是代碼結束的地方;它是範圍內最後一個標記的開始。因此,如果我們使用decl_range.getEnd()
作爲函數定義進入SourceManager,我們將不會得到結束的大括號。 end_of_the_end()
使用詞法分析器來獲取代碼的最後一位的位置:
SourceLocation
end_of_the_end(SourceLocation const & start_of_end, SourceManager & sm){
LangOptions lopt;
return Lexer::getLocForEndOfToken(start_of_end, 0, sm, lopt);
}
回到run()
,準確的開始和結束位置,就可以得到指針進入SourceManager的字符緩衝區:
const char * buff_begin(sm.getCharacterData(decl_begin));
const char * buff_end(sm.getCharacterData(decl_end_end));
std::string const func_string(buff_begin,buff_end);
func_string有函數的源代碼;您可以寫入新文件等。
要消除原始文件中函數的來源,我們可以生成替換,並讓RefactoringTool將它應用於我們。要創建一個替換,我們需要的代碼兩行添加到run()
:
uint32_t const decl_length =
sm.getFileOffset(decl_end_end) - sm.getFileOffset(decl_begin);
Replacement repl(sm,decl_begin,decl_length,"");
的替代構造函數取SourceManager,從哪裏開始更換,多少覆蓋,並與覆蓋內容。這種替換無需覆蓋整個原始函數定義。
我們如何獲得RefactoringTool的Replacement?我們可以通過引用RefactoringTool的替換成員來構造回調類。在run
,一會又得出結論:
repls_.insert(repl);
我在CoARCT, a collection of Clang refactoring examples在應用/ FunctionMover.cc增加了工作的示例應用程序。
是否要爲函數或底層源代碼編寫AST? –
@那些叫我蒂姆,我想分割一個特定的功能到另一個文件。所以這個過程可能是:1)在AST級別(通過MatchFinder)找到這個函數,2)將它寫入另一個文件,3)從原始文件中移除它。 – ignorer