Java Parserの使い方

Java Parserのインストール方法、使用方法を説明する。

Keywords

  • Java

Contents

  • 1. Java Parserとは
  • 2. 環境構築
  • 2-1. 前提
  • 2-2. build.gradleにjavaparser-symbol-solver-coreを追加して、Gradleをリフレッシュ
  • 3. 動作確認
  • 4. Javaファイル(クラス)を作成してパースする
  • 4-1. Personクラスを作成
  • 4-2. Personクラスをパース
  • 5. 抽象構文木に対して、処理を追加する。
  • 6. Java Parserのユースケース
  • 7. その他
  • 8. 参考資料

Java Parserとは

Javaの構文をパースして、抽象構文木を作成するライブラリ。抽象構文木のそれぞれのノードに対して、処理を追加できる。

MyBatis GeneratorLettuceでも使用されているライブラリ。

環境構築

前提

  • IntelliJ IDEA
  • Gradle

※IntelliJ IDEA + Gradleでプロジェクト作成方法がわからない場合は下記を参考にしてください。

IntelliJ & GradleでJavaプロジェクトを作成する

build.gradleにjavaparser-symbol-solver-coreを追加して、Gradleをリフレッシュ

javaparser-symbol-solver-coreを追加

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'com.github.javaparser', name: 'javaparser-symbol-solver-core', version: '3.13.3'
}

Gradleをリフレッシュ

動作確認

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;

public class Main {
    public static void main(String[] args){

        String code = "class A {}";
        CompilationUnit cu = StaticJavaParser.parse(code);
        System.out.println(cu);
    }
}

Javaファイル(クラス)を作成してパースする

Personクラスを作成

/**
 * This is a target class
 */
public class Person {

    private String name;
    private int age;

    public void sleep(){
        System.out.println("zzz");
    }

    public void introduce(){
        System.out.println("I am " + this.name);
    }

    public void sayHi(String whom){
        System.out.println("Hello " + whom);
    }

    // this method must not be used.
    @Deprecated
    public void xxx(){
    }
}


Personクラスをパース

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;

import java.io.File;
import java.io.FileNotFoundException;

public class Main {
    public static void main(String[] args) throws FileNotFoundException {

        File file = new File("./src/main/java/Person.java");
        CompilationUnit cu = StaticJavaParser.parse(file);

        System.out.println(cu);

    }
}

標準出力をみるだけじゃわからないが、debugでcuのchildNodesをたどるとパースされていることが確認できる。

抽象構文木に対して、処理を追加する。

CompilationUnitはacceptメソッドを持っており、VoidVisitorインターフェースかGenericVisitorインターフェースを受け取ることができる。

ここでは、VoidVisitorインターフェースを実装したVoidVisitorAdapterを継承したものをacceptに渡してみる。

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.comments.JavadocComment;
import com.github.javaparser.ast.comments.LineComment;
import com.github.javaparser.ast.expr.MarkerAnnotationExpr;
import com.github.javaparser.ast.visitor.VoidVisitor;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

import java.io.File;
import java.io.FileNotFoundException;

public class Main {
    public static void main(String[] args) throws FileNotFoundException {

        File file = new File("./src/main/java/Person.java");
        CompilationUnit cu = StaticJavaParser.parse(file);

        VoidVisitor<?> visitor = new SomeVisitor();
        cu.accept(visitor, null);

    }

    private static class SomeVisitor extends VoidVisitorAdapter<Void> {

        @Override
        public void visit(MarkerAnnotationExpr md, Void arg) {
            super.visit(md, arg);
            System.out.println("annotation: " + md.getName());
        }

        @Override
        public void visit(MethodDeclaration md, Void arg) {
            super.visit(md, arg);
            System.out.println("method: " + md.getName());
        }

        @Override
        public void visit(Modifier md, Void arg) {
            super.visit(md, arg);
            System.out.println("modifier: " + md.toString());
        }

        @Override
        public void visit(JavadocComment md, Void arg) {
            super.visit(md, arg);
            System.out.println("javadoc: " + md.toString());
        }

        @Override
        public void visit(LineComment md, Void arg) {
            super.visit(md, arg);
            System.out.println("linecomment: " + md.toString());
        }
    }
}

Java Parserのユースケース

今のところ、レビュー時によく指摘されるようなことを事前に検出できるようなプログラムの作成の時に便利かもしれない。

その他

PHPの場合はPHP-ParserでPHPファイルをパースできます。

参考資料