일부 소스 코드 분석을 위해 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
이 질문에 감사드립니다.이 질문은 컴파일러 트리 API에 대한 매우 간결한 예제를 실제로 두 배로 만듭니다. 레코드의 경우,'processingEnv'는'init (ProcessingEnvironment)'메소드에서 상속됩니다. 아, 그리고 JRockit 1.6.0_29는 여전히 "null"을 보여줍니다. – mgaert
대부분의 경우'AbstractProcessor.init'을 무시할 필요가 없습니다. –