例によってソースコード全体についてはここ。
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!!!!!