Compiler Tree API で Java ソースファイルをパースする2 - Groovy で実装

前回 の処理を Groovy で実装してみました。

  • Java SE 8u31
  • Groovy 2.4.0

今回使用したソースは http://github.com/fits/try_samples/tree/master/blog/20150216/

(a) com.sun.tools.javac.main.JavaCompiler 利用

前回 Java で実装した内容を Groovy で実装し直しただけです。

javacompiler_parse.groovy
import javax.tools.ToolProvider

import com.sun.tools.javac.main.JavaCompiler
import com.sun.tools.javac.util.Context

def fileManager = ToolProvider.systemJavaCompiler.getStandardFileManager(null, null, null)

def compiler = new JavaCompiler(new Context())

fileManager.getJavaFileObjects(args).each {
    def cu = compiler.parse(it)
    cu.accept(new SampleVisitor(), null)
}

groovy コマンドで実行するだけです。 当然ながら前回の Java 版と同じ結果になります。

実行結果
> groovy javacompiler_parse.groovy Sample.java

class: Sample
method: sample1
method: sample2
lambda: (n)->n * 2
class: SampleChild
method: child1
lambda: (n)->{
    System.out.println(n);
    return n > 0 && n % 2 == 0;
}
method: child2

(b) com.sun.source.util.JavacTask 利用

こちらも Groovy で実装し直しただけです。

javactask_parse.groovy
import javax.tools.ToolProvider

def compiler = ToolProvider.systemJavaCompiler
def fileManager = compiler.getStandardFileManager(null, null, null)

def task = compiler.getTask(null, fileManager, null, null, null, fileManager.getJavaFileObjects(args))

task.parse().each {
    it.accept(new SampleVisitor(), null)
}

ただし、こちらは groovy コマンドでスクリプト実行すると MissingMethodException が発生しました。

実行結果1
> groovy javactask_parse.groovy Sample.java

Caught: groovy.lang.MissingMethodException: No signature of method: com.sun.tools.javac.tree.JCTree$JCCompilationUnit.accept() is applicable for argument types: (SampleVisitor, null) values: [SampleVisitor@2cf3d63b, null]
Possible solutions: accept(com.sun.source.tree.TreeVisitor, java.lang.Object), 
accept(com.sun.tools.javac.tree.JCTree$Visitor), 
accept(com.sun.source.tree.TreeVisitor, java.lang.Object), 
accept(com.sun.tools.javac.tree.JCTree$Visitor), grep(), inspect()
・・・

JCCompilationUnit.accept(SampleVisitor, null) の箇所は javacompiler_parse.groovy でも同じだと思うのですが、こちらの方だけがエラーになる理由はよく分かりません。(Groovy の内部処理に何らかの原因があるのかもしれませんが)

ちなみに、groovyc でコンパイルして実行すると正常に実行できました。

実行結果2
> groovyc javactask_parse.groovy

> java -cp .;%JAVA_HOME%/lib/tools.jar;%GROOVY_HOME%/embeddable/groovy-all-2.4.0-indy.jar javactask_parse Sample.java

class: Sample
method: sample1
method: sample2
lambda: (n)->n * 2
class: SampleChild
method: child1
lambda: (n)->{
    System.out.println(n);
    return n > 0 && n % 2 == 0;
}
method: child2