Bazı kaynak kodu analizi yapmak için javac'ın Compiler Tree API'sini kullanan JSR 269 biçiminde bir ek not işlemci yazmayı deniyorum. Metot çağrıları gibi üye seçim ifadeleriyle ilgileniyorum.Bir javac eklentisinden bir MemberSelectTree ifadesinin türünü nasıl alabilirim?
Seçilmiş olan yöntemin (veya alanın, vb.) Ismini kolayca alabilirim. Ama üye hangi türden seçildiğini bilmek istiyorum ve bunu yapmak için basit bir yol bulamıyorum. Trees.getTypeMirror
, çağırmayı denediğim her şey için null
değerini döndürür (ve Javadoc hiçbir ipucu vermez).
ben etraflıca seçmek üyesinin sol tarafındaki ifadenin her türlü analiz ve özyinelemeli analiziyle ifade statik türünü belirlemek herhalde: NewClassTree
, TypeCastTree
, MethodInvocationTree
, ArrayAccessTree
, ve diğerleri. Ancak bu hataya yatkın bir iş gibi görünüyor ve açıkça javac, bu bilgiyi birçok amaç için gerektirdiğinden, ifadenin statik tipini zaten biliyor. Ancak bu tür bilgilere nasıl erişebilirim?
Ne var bugüne kadar:
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreePathScanner;
import com.sun.source.util.Trees;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class PublicProcessor extends AbstractProcessor {
public @Override boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element e : roundEnv.getRootElements()) {
final Trees trees = Trees.instance(processingEnv);
final TreePath root = trees.getPath(e);
new TreePathScanner<Void,Void>() {
public @Override Void visitMethodInvocation(MethodInvocationTree node, Void p) {
System.err.println("visiting method invocation: " + node + " of kind: " + node.getMethodSelect().getKind());
TreePath expr = TreePath.getPath(root, node);
System.err.println(" of type: " + trees.getTypeMirror(expr));
return super.visitMethodInvocation(node, p);
}
public @Override Void visitMemberSelect(MemberSelectTree node, Void p) {
System.err.println("accessing member: " + node.getIdentifier());
System.err.println(" from: " + getCurrentPath().getCompilationUnit().getSourceFile().toUri());
TreePath expr = TreePath.getPath(root, node.getExpression());
System.err.println(" in expr: " + expr.getLeaf());
System.err.println(" of type: " + trees.getTypeMirror(expr));
return super.visitMemberSelect(node, p);
}
}.scan(root, null);
}
return true;
}
}
ve ne bazı basit kod yapma yöntemine çalıştırdığınızda yazdırır çağırır:
visiting method invocation: new Class().method() of kind: MEMBER_SELECT
of type: null
accessing member: method
from: .../Whatever.java
in expr: new Class()
of type: null
Bu soru için, Compiler Tree API'sı için harika bir özlü örnek olarak ikiye katlanan bu soru için teşekkür ederiz. Kayıt için yukarıdaki "processingEnv", aynı zamanda geçersiz kılınması gereken bir "init (ProcessingEnvironment)" yönteminden gelir. Oh ve JRockit 1.6.0_29 hala "null" değerini gösteriyor. – mgaert
Çoğu durumda 'AbstractProcessor.init' özelliğini geçersiz kılmaya gerek yoktur. –