2010-01-23 4 views
5

일부 소스 코드 분석을 위해 javac의 컴파일러 트리 API를 사용하는 JSR 269 형식의 주석 프로세서를 작성하려고합니다. 메소드 호출과 같은 멤버 선택 식에 관심이 있습니다.javac 플러그인에서 MemberSelectTree의 표현식 유형을 얻으려면 어떻게해야합니까?

나는 쉽게 메서드 (또는 필드 등)를 선택할 수 있습니다. 그러나 어떤 유형의 멤버가 선택되었는지 알고 싶습니다.이 작업을 수행하는 간단한 방법을 찾을 수 없습니다. Trees.getTypeMirror은 내가 호출하려고 시도한 모든 것에 대해 null을 반환합니다 (그리고 Javadoc은 힌트를 제공하지 않습니다).

은 내가 철저 구성원 선택의 왼쪽에 표현의 모든 종류를 분석하고 재귀 적 분석에 의해 표현의 정적 유형을 결정할 수도있을 것 같군요 : NewClassTree, TypeCastTree, MethodInvocationTree, ArrayAccessTree, 그리고 많은 다른 사람. 하지만 이것은 많은 오류가 발생하기 쉬운 작업처럼 보입니다. javac은 많은 정보를 필요로하기 때문에 정적 유형의 표현식을 이미 알고 있습니다. 그러나이 유형 정보에 어떻게 접근 할 수 있습니까?

내가 지금까지 가지고 :

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; 
    } 
} 

무엇을 몇 가지 간단한 코드를 만드는 방법을 실행할 때 출력은 호출

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

이 질문에 감사드립니다.이 질문은 컴파일러 트리 API에 대한 매우 간결한 예제를 실제로 두 배로 만듭니다. 레코드의 경우,'processingEnv'는'init (ProcessingEnvironment)'메소드에서 상속됩니다. 아, 그리고 JRockit 1.6.0_29는 여전히 "null"을 보여줍니다. – mgaert

+0

대부분의 경우'AbstractProcessor.init'을 무시할 필요가 없습니다. –

답변

1

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

은 매우 유사한를 해결하는 것 같다 질문, 그래서 거기에 주어진 조언을 사용하려고합니다. 안타깝게도 똑바로 보이지 않으며 com.sun.tools.javac 패키지를 사용해야합니다.

+0

http://bitbucket.org/jglick/qualifiedpublic/src/f2d33fd97c83/src/qualifiedpublic/PublicProcessor.java는 작동하는 것처럼 보이지만 JDK 7에서만 사용할 수 있습니다. JDK 6의 javac를 사용하여 전혀 작동하지 않습니다. –

+0

동일한 문제에 봉착했으며 Jdk7을 사용할 수 없습니다. 마침내 Jdk1.6에서이 문제에 대한 해결책을 찾았습니까 ?? –

+0

죄송합니다. JDK 6에서는 작동하지 않습니다. –

관련 문제