NetBeans5.xくらいまでは、きしださんのサイトの3.4からあるようにJMIとかいうのを使ってソースにどんなクラスがあって、そこにはどんなメソッドがあって…という情報にアクセスすることができた。
結構、こういう情報をもとに何かをするのは好きだったりする。
でも、NetBeans6では、これらのAPIは軒並みというか全部?消えてなくなってしまってる。
悲しいかな。
ということで、代わりは何だろうと探してたら見つけた。
ここにあった。
http://wiki.netbeans.info/wiki/view/Java_DevelopersGuide
まだ、書いてる途中っぽいけど、ここらへんにしか情報がないっぽいのでとてもありがたい!!
ということで早速…
モジュールのプロジェクトを作って実験してみる。
モジュールのプロジェクトを、ここではShowMetaという名前で作った。
パッケージはcom.wankuma.kazuki.showmetaにしてOK。
com.wankuma.kazuki.showmetaにアクションを新規に作成する。
メニューの何処でもいいので適当な所に新規作成をする。
クラス名は、ShowActionでラベルは「見せて」にしておいた。
とりあえず選択されたファイルに定義されてるクラスの情報をゲットしてみようと思う。
とりあえず、集めたい情報を入れるためのクラスを1つこしらえる。
Clazz.java
package com.wankuma.kazuki.showmeta;
import java.util.ArrayList;
import java.util.List;
public class Clazz {
private String name;
private List<String> methods = new ArrayList<String>();
public List<String> getMethods() {
return methods;
}
public void setMethods(List<String> methods) {
this.methods = methods;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return new StringBuilder("class ").append(name).append(", methods: ").append(methods).toString();
}
}
何の変哲もないクラスなので説明は省略。
続いて、ソースのTreeをたどるためのクラスを作る。
ClassInfoScanner.java
package com.wankuma.kazuki.showmeta;
import com.sun.source.tree.ClassTree;
import com.sun.source.util.TreePathScanner;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
import org.netbeans.api.java.source.CompilationInfo;
public class ClassInfoScanner extends TreePathScanner<Clazz, Void> {
private CompilationInfo info;
public ClassInfoScanner(CompilationInfo info) {
this.info = info;
}
@Override
public Clazz visitClass(ClassTree tree, Void v) {
System.out.println("visitClass");
Element element = info.getTrees().getElement(getCurrentPath());
if (element == null) {
return null;
}
TypeElement te = (TypeElement) element;
Clazz clazz = new Clazz();
clazz.setName(te.getQualifiedName().toString());
for (ExecutableElement method : ElementFilter.methodsIn(te.getEnclosedElements())) {
clazz.getMethods().add(method.getSimpleName().toString());
}
return clazz;
}
}
なかなか、直感的に使うのは難しそうだ。
visitClassメソッドで、色々やってみている。ここらへんが感覚でわかるようになるまでガンガンコードかかないと駄目かな。
後は、ボタンを押したときに、これを読んで取得した情報を出力する。
ShowAction.java
package com.wankuma.kazuki.showmeta;
import com.sun.source.util.TreePath;
import java.io.IOException;
import org.netbeans.api.java.source.ClasspathInfo;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.Task;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObject;
import org.openide.util.Exceptions;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.IOProvider;
import org.openide.windows.InputOutput;
public final class ShowAction extends CallableSystemAction {
public void performAction() {
try {
DataObject currentDaat = Utilities.actionsGlobalContext().lookup(DataObject.class);
if (currentDaat == null) {
return;
}
FileObject currentFile = currentDaat.getPrimaryFile();
ClasspathInfo classpathInfo = ClasspathInfo.create(currentFile);
JavaSource javaSource = JavaSource.create(classpathInfo, currentFile);
javaSource.runUserActionTask(new Task<CompilationController>() {
public void run(CompilationController parameter) throws Exception {
parameter.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
Clazz clazz = new ClassInfoScanner(parameter).scan(parameter.getCompilationUnit(), null);
InputOutput io = IOProvider.getDefault().getIO("かずき", false);
io.select();
io.getOut().reset();
io.getOut().println(clazz);
}
}, true);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
public String getName() {
return NbBundle.getMessage(ShowAction.class, "CTL_ShowAction");
}
@Override
protected void initialize() {
super.initialize();
// see org.openide.util.actions.SystemAction.iconResource() Javadoc for more details
putValue("noIconInMenu", Boolean.TRUE);
}
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@Override
protected boolean asynchronous() {
return false;
}
}
これを実行すると、選択したファイルの出力ウィンドウにクラス名とメソッドが出てくる。
たとえばShowActionを選択して実行すると下のような結果になる。
class com.wankuma.kazuki.showmeta.ShowAction, methods: [performAction, getName, initialize, getHelpCtx, asynchronous]
慣れていかないといけないなぁ。