叮当声:将函数的AST从原始文件写入新文件 [英] Clang: write a function's AST from original file to a new file
问题描述
我是Clang的新手,他正尝试通过libtooling分析AST.我想找到一个特定的函数,并将其AST从原始源文件移动到新文件.
I'm a novice for Clang who is trying to analyze AST via libtooling. I want to find a particular function, and move its AST from original source file to a new file.
我知道如何通过MatchFinder查找功能.现在,我想知道如何将其AST写入新文件(.c或.cpp)
I've known how to find the function by MatchFinder. Now, I was wondering how to write its AST to a new file(.c or .cpp)
提前谢谢!
推荐答案
摘要:要获取源文本,请使用 SourceManager
;要从原始文件中删除该功能,请生成一个 Replacement
,然后将其与 RefactoringTool
一起应用.
Summary: to get the source text, work with the SourceManager
; to remove the function from the original file, generate a Replacement
and apply it with a RefactoringTool
.
首先,这是一种获取函数定义源代码的方法,假设AST匹配器如下所示:
First, here's a way to get at the source code for a function definition, assuming an AST matcher that looks something like this:
auto matcher(std::string const & fname) {
return functionDecl(hasName(fname)).bind("f_decl");
}
Callback的run方法将首先获得对匹配的AST节点的访问权,获得函数声明所涵盖的源范围,并获得对SouceManager的引用,该引用将SourceLocation对象与实际源相关联:>
The run method of the Callback would begin by getting access to the matched AST node, getting the source range covered by the function declaration, and getting a reference to the SouceManager, which relates the SourceLocation objects to the actual source:
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
和 decl_end_end
是什么?使用SourceRange有一个陷阱:结束位置不是代码结束的位置;它是范围中最后一个标记的开始.因此,如果使用带有 decl_range.getEnd()
的SourceManager进行函数定义,则不会得到右大括号. end_of_the_end()
使用一个词法分析器来获取代码最后一位的位置:
What's with decl_start_end
and decl_end_end
? There is one catch to using a SourceRange: the ending location is not where the code ends; it is the beginning of the last token in the range. So if we go to the SourceManager with decl_range.getEnd()
for a function definition, we won't get the closing curly bracket. end_of_the_end()
uses a lexer to get the location of the last bit of the code:
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的字符缓冲区:
Back in run()
, with accurate beginning and ending locations, you can get pointers into the SourceManager's character buffer:
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具有函数的源代码;您可以写入新文件等.
func_string has the function's source code; you can write to new file etc.
要消除原始文件中函数的源代码,我们可以生成一个Replacement,然后让RefactoringTool为我们应用它.要创建替换项,我们需要在 run()
中再添加两行代码:
To eliminate the function's source in the original file, we can generate a Replacement, and let the RefactoringTool apply that for us. To create a Replacement, we need to add two more lines of code to run()
:
uint32_t const decl_length =
sm.getFileOffset(decl_end_end) - sm.getFileOffset(decl_begin);
Replacement repl(sm,decl_begin,decl_length,"");
Replacement ctor使用SourceManager,在何处开始替换,覆盖多少以及覆盖内容.此替换内容将完全覆盖整个原始函数定义.
The Replacement ctor takes the SourceManager, where to begin replacing, how much to overwrite, and what to overwrite with. This Replacement overwrites the entire original function definition with nothing.
我们如何将替代品带到RefactoringTool?我们可以使用对RefactoringTool的Replacements成员的引用来构造回调类.然后在 run
中得出结论:
How do we get that Replacement to the RefactoringTool? We could construct the callback class with a reference to the RefactoringTool's Replacements member. In run
, one would then conclude:
repls_.insert(repl);
我在apps/FunctionMover.cc的 CoARCT(一个Clang重构示例集合)中添加了一个有效的示例应用程序.
I've added a working example application in apps/FunctionMover.cc in CoARCT, a collection of Clang refactoring examples.
这篇关于叮当声:将函数的AST从原始文件写入新文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!