ASTとは
抽象構文木(AST)のこと。
http://home.a00.itscom.net/hatada/c-tips/ast/ast01.html
AST解析可能なlibrary
JavaPerser
https://github.com/javaparser/javaparser/wiki
com.sun.tools.javac.modelのlibraryを使えば、コンパイル時の中間ASTの変更も可能…??
JavaParserについてメモ
パース
ソースコードをパースするために以下のコードにてパースしCompilationUnit型へ変換する、この引数にはInputStereamやFile等指定ができる
JavaParser.parse([source]);
AST変更
CompilationUnitに一度変換すれば各ノードを表すオブジェクトを取得できるので、そこから改変が可能
CompilationUnitから直接取得できるであろうノードは以下
- ImportDeclaration
- AnnotationDeclaration
- PackageDecralation
- ClassOrInterfaceDeclaration
- EnumDeclaration
おそらくClass(またはInterface)内のノードを処理したければClassOrInterfaceDeclarationを一度取得し、改変していく。
メソッドを取得したい場合
targetclass.getMethodsByName("testMethod1")
これで名前が”testMethod1”のメソッドを表すノードMethodDeclarationのリストが取得できる。(同一の名前がある場合にはその分リストに追加される)
Modifierはprivateとかその辺の意味する。
また、引数付きのMethodを取得したい場合には、
//methodNameという名前で、Stringとintを引数に持つMethodが取得できる
ClassOrInterfaceDeclaration.getMethodsBySignature(String new methodName, new String[] {"String","int"});
ノードを消す
そのままremove()で削除可能。
名前を変える。
setName(String name)を呼ぶ。
SimpleNameオブジェクトを使って代入することもできる
初期化を変更する。
VariableDeclaratorのsetInitializerによって初期化を変更する。
引数がExpression型となっており、これはJavaParser.parseExpressionにより作成可能。
VariableDeclarator.setInitializer(JavaParser.parseExpression(content));
Classに変数を突っ込む
先ほどと同様にClassOrInterfaceDeclarationを使用する。
このオブジェクトのadd***を呼ぶと、ノードの追加と共にそのノードを表すオブジェクトを取得できる。
//private ScanSize[] aaa;を追加する
FieldDeclaration field = targetclass.addField(ScanSize[].class, "aaa", Modifier.PRIVATE);
このfieldオブジェクトのsetVariable()に、ほかで作成したVariableDeclaratorを入れれば、そのまま代入可能。
おそらくメソッドも可能。
自分のソースの変数などを別のソースに突っ込む
自分のソースを取得してパース。
Path selfSource = Paths.get("[ソースのPath]");
これで任意の宣言などが取得できるので、あとは他ソースに展開する。
参考
JavaParserについて詳しい記事
https://qiita.com/opengl-8080/items/50ddee7d635c7baee0ab#%E5%8F%82%E8%80%83
アノテーションプロセッサで AST 変換 - Lombok を参考にして変数の型をコンパイル時に変更
http://fits.hatenablog.com/entry/2015/01/17/172651