Eclipse/CDTでASTを使ってソースコードの構造を得る(最新版).
先日のTOPPERSハッカソンで青ざめ,乗り越えた顛末.
最初は,TOPPERS/JSP1.4.4 のリリースに向けた作業をしようかと思っていたのだけれど,参加者を見ていて,これはテストスイートの試作をしてみたほうが面白いのではないかと考え直した.
他の言語向け(特にLL向け)のテストスイートに比べてC言語のそれで一番面倒なのは,テストスイートの作成.Cutter では,共有ライブラリを使うことで面倒を解消しているけれども,TOPPERSのような規模で共有ライブラリは望めない.
そこで,ワタクシお得意CDTを使うべな,ということを思いついた.
CDT は,ソースコードを AST (Abstract Syntax Tree)に分解する機能を持っている.これを使えば関数名の抽出などはお手の物である.…ということは知っていた.
参考情報
グーグル先生にお伺いを立てると,情報が得られる.
日本語だと,例えば,
http://www.ibm.com/developerworks/jp/opensource/library/os-ecl-cdt3/
ここは難解だが,CDTの内部を知るためには必読
「CDTのパーサーを他の用途で使う」というエントリも見つかる.
http://munepi.cocolog-nifty.com/blog/2009/05/cdt-28c0.html
http://munepi.cocolog-nifty.com/blog/2009/05/cdt-daf0.html
なんとかなるもんねー,と思ったのだが,甘かった.
CDTの進化
結論から言うと,上記の「CDTのパーサーを他の用途で使う」は,古いCDT (おそらく3.x系)でのみ有効である.最近のCDTで使おうとすると,obsolete だったり internalパッケージだったりして使えない.
ハッカソン開始後に気づいて真っ青になった.
それへの追随
どう調べたとかいうのは端折って,結論だけ書く
ITranslationUnit tu = (ITranslationUnit) CoreModel.getDefault().create((IFile)resource); IASTTranslationUnit ast = tu.getAST(); ASTVisitor visitor = new ASTVisitor(true) { public int visit(IASTDeclarator decl) { /* do something */ return ASTVisitor.PROCESS_CONTINUE; } }; ast.accept(visitor);
以前は,IASTTranslationUnit が Java と微妙に違ったりしたのが,統一的になり割とスッキリしている.本来的には歓迎しなければならないところと思う.けれども現場技術者としては,壮大な仕様変更に,やるかたない気持ちがしなくもない.
builder の中なので,resource の型は,IResource.上の例に挙げた ASTVisitor.visit() の引数型は,IASTDeclarator なので,関数宣言があったときに呼び出される.他の要素で引っかけたいときには,ASTVisitor にある,大量の visit() を参照するとよい.
というわけで
一瞬,真っ青になったが,ハッカソン終了までには,なんとかソレっぽいものを仕上げることができた.CDT怖い.