私はlibtoolingでASTを解析しようとしているClangの初心者です。 特定の関数を見つけて、元のソースファイルから新しいファイルにそのASTを移動したいと思います。Clang:元のファイルから新しいファイルに関数のASTを書き込む
私はMatchFinderで関数を見つける方法を知っていました。 新しいファイル(.cまたは.cpp)にASTを書き込む方法が不思議でした。
ありがとうございました!
私はlibtoolingでASTを解析しようとしているClangの初心者です。 特定の関数を見つけて、元のソースファイルから新しいファイルにそのASTを移動したいと思います。Clang:元のファイルから新しいファイルに関数のASTを書き込む
私はMatchFinderで関数を見つける方法を知っていました。 新しいファイル(.cまたは.cpp)にASTを書き込む方法が不思議でした。
ありがとうございました!
要約:ソーステキストを取得するには、SourceManager
で作業してください。ファンクションを元のファイルから削除するには、Replacement
を生成し、RefactoringTool
で適用します。コールバックのrunメソッドがアクセス権を取得することによって開始すると
auto matcher(std::string const & fname) {
return functionDecl(hasName(fname)).bind("f_decl");
}
:
まず、ここでは次のようになりますAST照合を想定し、関数定義のためのソースコードを取得する方法です一致ASTノード、関数宣言によって覆われたソース領域を取得し、実際のソースにSourceLocationオブジェクトに関するSouceManagerへの参照を取得:
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を使用するには1つのキャッチがあります:終了位置はコードの終了位置ではありません。それは範囲内の最後のトークンの始まりです。したがって、関数定義のためにdecl_range.getEnd()
で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);
:あなたはSourceManagerの文字バッファへのポインタを取得することができ、正確な開始と終了の位置で、
run()
で
SourceLocation
end_of_the_end(SourceLocation const & start_of_end, SourceManager & sm){
LangOptions lopt;
return Lexer::getLocForEndOfToken(start_of_end, 0, sm, lopt);
}
戻る:end_of_the_end()
は、コードの最後のビットの位置を取得するためにレクサーを使用しています
func_stringには関数のソースコードがあります。新しいファイルなどに書き込むことができます。
元のファイル内の関数のソースを削除するには、置換を生成して、RefactoringToolでそれを適用させることができます。交換を作成するために、我々はrun()
に、コードの2行を追加する必要があります。
uint32_t const decl_length =
sm.getFileOffset(decl_end_end) - sm.getFileOffset(decl_begin);
Replacement repl(sm,decl_begin,decl_length,"");
交換用のctorの交換が開始するために、どのくらいの上書きするSourceManagerを取り、何で上書きします。この置換は、元の関数定義全体を何も上書きしません。
リファクタリングツールにどのように置き換えられますか? RefactoringToolのReplacementsメンバを参照してコールバッククラスを構築することができます。 run
では、1は、結論になります。
repls_.insert(repl);
私はCoARCT, a collection of Clang refactoring examplesにアプリケーション/ FunctionMover.ccで作業サンプルアプリケーションを追加しました。
関数のAST、または基礎となるソースコードを記述しますか? –
@Those Who Call Me Tim、特定の機能を別のファイルに分割したい。 1)ASTレベル(MatchFinderによる)でこの関数を見つけ、2)別のファイルに書き出し、3)元のファイルからそれを削除することができます。 – ignorer