例によってソースコード全体についてはここ。
Sample2.java
package info.haxahaxa.astparser.sample;import info.haxahaxa.astparser.Envs;import info.haxahaxa.astparser.SourceFile;import info.haxahaxa.astparser.sample.visitor.*;import java.io.File;import org.eclipse.core.runtime.NullProgressMonitor;import org.eclipse.jdt.core.dom.AST;import org.eclipse.jdt.core.dom.ASTParser;import org.eclipse.jdt.core.dom.ASTVisitor;import org.eclipse.jdt.core.dom.CompilationUnit;import org.eclipse.jface.text.Document;import org.eclipse.text.edits.TextEdit;/*** importを削除したり,メソッドを削除したり,フィールドを削除したり,javadocコメントを削除するサンプル** @author satanabe1**/public class Sample2 {private static ASTVisitor visitor = new SampleVisitor2();public static void main(String[] arg) throws Exception {SourceFile sourceFile = new SourceFile("src" + File.separator+ "samples" + File.separator + "AntFileGen.java");CompilationUnit unit;ASTParser astParser = ASTParser.newParser(AST.JLS4);// 以下の setBindingsRecovery setStatementsRecovery はおまじない.// 完成しているソースコードを解析する時は呼ぶ必要ない.// 詳しく知りたいならば,IMBのASTParser関連のドキュメントとかを参照すべき.astParser.setBindingsRecovery(true);astParser.setStatementsRecovery(true);// 次の setResolveBindings と setEnvironment が重要!!// setResolveBindings(true) をしておかないとまともに解析はできない.// setResolveBindings をまともに機能させるために setEnvironment が必要.astParser.setResolveBindings(true);// setEnvironment の第一引数にはクラスパスの配列.第二引数にはソースコードを検索するパスの配列// 第三第四については何も考えず null, true .納得いかない時はIBMのASTPa...astParser.setEnvironment(Envs.getClassPath(), Envs.getSourcePath(),null, true);// 解析対象のソースコードの入力とかastParser.setUnitName(sourceFile.getFilePath());// なんでもいいから名前を設定しておくastParser.setSource(sourceFile.getSourceCode().toCharArray());// 解析対象コードを設定するunit = (CompilationUnit) astParser.createAST(new NullProgressMonitor());unit.recordModifications();// ASTへの操作履歴のようなものを有効に// 解析 & 変換実行unit.accept(visitor);// 変換結果を文字列で取得String code = getCode(sourceFile.getSourceCode(), unit);System.out.println(code);}/*** ASTを文字列のコードに戻すメソッド** @param code* 元のコード* @param unit* ASTVisitorで操作を行ったヤツ* @return ソースコード*/private static String getCode(String code, CompilationUnit unit) {org.eclipse.jface.text.IDocument eDoc = new Document(code);TextEdit edit = unit.rewrite(eDoc, null);try {edit.apply(eDoc);return eDoc.get();} catch (Exception ex) {ex.printStackTrace();return null;}}}
SampleVisitor2.java
package info.haxahaxa.astparser.sample.visitor;import org.eclipse.jdt.core.dom.ASTVisitor;import org.eclipse.jdt.core.dom.FieldDeclaration;import org.eclipse.jdt.core.dom.ImportDeclaration;import org.eclipse.jdt.core.dom.Javadoc;import org.eclipse.jdt.core.dom.MethodDeclaration;/*** メソッドの中身を削除したり,フィールドを削除するサンプル** @author satanabe1**/public class SampleVisitor2 extends ASTVisitor {/*** フィールド宣言をdelete!*/public boolean visit(FieldDeclaration node) {node.delete();return super.visit(node);}/*** javadocもついでにdelete!*/public boolean visit(Javadoc node) {node.delete();return super.visit(node);}/*** ダメ押しにimportもdelete!*/public boolean visit(ImportDeclaration node) {node.delete();return super.visit(node);}/*** メソッド内の処理をdelete!*/public boolean visit(MethodDeclaration node) {node.getBody().statements().clear();return super.visit(node);}}
Sample2.javaについては前回の記事にあるSample1.javaとほぼ変わらない。
変更点としては、
- 25行目のSampleVisitor2クラスのインスタンスを生成している
- 68-78行に新しいメソッドの追加
- 55-56行でのソースコードの標準出力への出力
新たに追加されたgetCodeメソッドのしている事をざっくり言ってしまえば、CompilationUnitを使っていじくり回された変更を、元のソースコードに適用して文字列に直した内容を返している。
で、
今回色々削除したり削除したり削除したりするコードがSampleVisitor2.javaとなっている。
見ての通り各visitメソッドは2行しかない。
基本はdeleteメソッドを呼ぶだけであっさり何もかも無くなっていく。
少しだけ違う処理をしているのは44行目の
node.getBody().statements().clear();なんのことはない、これはListクラスのclearメソッドを呼んでいるだけ。
このあたりで難しい事は何もないはず。
ちなみにpackage宣言なんかはCompilationUnita側からじゃないといじれない。
まとめ
delete!
delete!!
delete!!!
clear!!!!!