[ASTParser 2]メソッドの中身を削除したり,フィールドを削除する | 坂道で

坂道で

ゆるめ

今回はフィールドの削除や、メソッドの中身を削除する方法について。

例によってソースコード全体についてはここ


Sample2.java
  1. package info.haxahaxa.astparser.sample;
  2. import info.haxahaxa.astparser.Envs;
  3. import info.haxahaxa.astparser.SourceFile;
  4. import info.haxahaxa.astparser.sample.visitor.*;
  5. import java.io.File;
  6. import org.eclipse.core.runtime.NullProgressMonitor;
  7. import org.eclipse.jdt.core.dom.AST;
  8. import org.eclipse.jdt.core.dom.ASTParser;
  9. import org.eclipse.jdt.core.dom.ASTVisitor;
  10. import org.eclipse.jdt.core.dom.CompilationUnit;
  11. import org.eclipse.jface.text.Document;
  12. import org.eclipse.text.edits.TextEdit;
  13. /**
  14. * importを削除したり,メソッドを削除したり,フィールドを削除したり,javadocコメントを削除するサンプル
  15. *
  16. * @author satanabe1
  17. *
  18. */
  19. public class Sample2 {
  20.     private static ASTVisitor visitor = new SampleVisitor2();
  21.     public static void main(String[] arg) throws Exception {
  22.         SourceFile sourceFile = new SourceFile("src" + File.separator
  23.                 + "samples" + File.separator + "AntFileGen.java");
  24.         CompilationUnit unit;
  25.         ASTParser astParser = ASTParser.newParser(AST.JLS4);
  26.         // 以下の setBindingsRecovery setStatementsRecovery はおまじない.
  27.         // 完成しているソースコードを解析する時は呼ぶ必要ない.
  28.         // 詳しく知りたいならば,IMBのASTParser関連のドキュメントとかを参照すべき.
  29.         astParser.setBindingsRecovery(true);
  30.         astParser.setStatementsRecovery(true);
  31.         // 次の setResolveBindings と setEnvironment が重要!!
  32.         // setResolveBindings(true) をしておかないとまともに解析はできない.
  33.         // setResolveBindings をまともに機能させるために setEnvironment が必要.
  34.         astParser.setResolveBindings(true);
  35.         // setEnvironment の第一引数にはクラスパスの配列.第二引数にはソースコードを検索するパスの配列
  36.         // 第三第四については何も考えず null, true .納得いかない時はIBMのASTPa...
  37.         astParser.setEnvironment(Envs.getClassPath(), Envs.getSourcePath(),
  38.                 null, true);
  39.         // 解析対象のソースコードの入力とか
  40.         astParser.setUnitName(sourceFile.getFilePath());// なんでもいいから名前を設定しておく
  41.         astParser.setSource(sourceFile.getSourceCode().toCharArray());// 解析対象コードを設定する
  42.         unit = (CompilationUnit) astParser.createAST(new NullProgressMonitor());
  43.         unit.recordModifications();// ASTへの操作履歴のようなものを有効に
  44.         // 解析 & 変換実行
  45.         unit.accept(visitor);
  46.         // 変換結果を文字列で取得
  47.         String code = getCode(sourceFile.getSourceCode(), unit);
  48.         System.out.println(code);
  49.     }
  50.     /**
  51.      * ASTを文字列のコードに戻すメソッド
  52.      *
  53.      * @param code
  54.      *            元のコード
  55.      * @param unit
  56.      *            ASTVisitorで操作を行ったヤツ
  57.      * @return ソースコード
  58.      */
  59.     private static String getCode(String code, CompilationUnit unit) {
  60.         org.eclipse.jface.text.IDocument eDoc = new Document(code);
  61.         TextEdit edit = unit.rewrite(eDoc, null);
  62.         try {
  63.             edit.apply(eDoc);
  64.             return eDoc.get();
  65.         } catch (Exception ex) {
  66.             ex.printStackTrace();
  67.             return null;
  68.         }
  69.     }
  70. }

SampleVisitor2.java
  1. package info.haxahaxa.astparser.sample.visitor;
  2. import org.eclipse.jdt.core.dom.ASTVisitor;
  3. import org.eclipse.jdt.core.dom.FieldDeclaration;
  4. import org.eclipse.jdt.core.dom.ImportDeclaration;
  5. import org.eclipse.jdt.core.dom.Javadoc;
  6. import org.eclipse.jdt.core.dom.MethodDeclaration;
  7. /**
  8. * メソッドの中身を削除したり,フィールドを削除するサンプル
  9. *
  10. * @author satanabe1
  11. *
  12. */
  13. public class SampleVisitor2 extends ASTVisitor {
  14.     /**
  15.      * フィールド宣言をdelete!
  16.      */
  17.     public boolean visit(FieldDeclaration node) {
  18.         node.delete();
  19.         return super.visit(node);
  20.     }
  21.     /**
  22.      * javadocもついでにdelete!
  23.      */
  24.     public boolean visit(Javadoc node) {
  25.         node.delete();
  26.         return super.visit(node);
  27.     }
  28.     /**
  29.      * ダメ押しにimportもdelete!
  30.      */
  31.     public boolean visit(ImportDeclaration node) {
  32.         node.delete();
  33.         return super.visit(node);
  34.     }
  35.     /**
  36.      * メソッド内の処理をdelete!
  37.      */
  38.     public boolean visit(MethodDeclaration node) {
  39.         node.getBody().statements().clear();
  40.         return super.visit(node);
  41.     }
  42. }

Sample2.javaについては前回の記事にあるSample1.javaとほぼ変わらない。
変更点としては、
  1. 25行目のSampleVisitor2クラスのインスタンスを生成している
  2. 68-78行に新しいメソッドの追加
  3. 55-56行でのソースコードの標準出力への出力
の3点となっている。
新たに追加されたgetCodeメソッドのしている事をざっくり言ってしまえば、CompilationUnitを使っていじくり回された変更を、元のソースコードに適用して文字列に直した内容を返している。


で、
今回色々削除したり削除したり削除したりするコードがSampleVisitor2.javaとなっている。
見ての通り各visitメソッドは2行しかない。
基本はdeleteメソッドを呼ぶだけであっさり何もかも無くなっていく。

少しだけ違う処理をしているのは44行目の
node.getBody().statements().clear();
なんのことはない、これはListクラスのclearメソッドを呼んでいるだけ。
このあたりで難しい事は何もないはず。

ちなみにpackage宣言なんかはCompilationUnita側からじゃないといじれない。

まとめ
  delete!
  delete!!
  delete!!!
  clear!!!!!