2010-01-23 10 views
5

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 
+0

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

+0

Çoğu durumda 'AbstractProcessor.init' özelliğini geçersiz kılmaya gerek yoktur. –

cevap

1

Discover the class of a methodinvocation in the Annotation Processor for java

çok benzer bir adresleme gibi görünüyor soru, bu yüzden orada verilen tavsiyeyi kullanmaya çalışacağım. Ne yazık ki basit görünmüyor ve com.sun.tools.javac paketinin kullanılması gerekiyor.

+0

http://bitbucket.org/jglick/qualifiedpublic/src/f2d33fd97c83/src/qualifiedpublic/PublicProcessor.java işe yarayacak gibi görünüyor - sadece JDK 7 altında. JDK 6'nın javacını kullanarak hiç çalışamıyorum. –

+0

Aynı konuda takıldım ve Jdk7'yi kullanamıyorum. Sonunda Jdk1.6 ile bu soruna bir çözüm buldunuz mu? –

+0

Üzgünüm, asla JDK 6 üzerinde çalışmam. –