2010-01-23 20 views
5

Tôi đang cố viết một bộ xử lý chú thích ở định dạng JSR 269 sử dụng API của trình biên dịch cây javac để thực hiện một số phân tích mã nguồn. Tôi quan tâm đến các biểu thức chọn thành viên, chẳng hạn như các cuộc gọi phương thức.Làm cách nào để nhận loại biểu thức trong MemberSelectTree từ plugin javac?

Tôi có thể dễ dàng nhận tên của phương thức (hoặc trường, v.v.) đang được chọn. Nhưng tôi muốn biết loại thành viên nào đang được chọn, và tôi dường như không thể tìm ra cách đơn giản để làm điều này. Trees.getTypeMirror trả về null cho tất cả mọi thứ tôi thử gọi nó trên (và Javadoc không đưa ra gợi ý).

Tôi cho rằng tôi thấu đáo có thể phân tích tất cả các loại biểu hiện ở phía bên trái của thành viên lựa chọn và xác định loại tĩnh của biểu thức bằng cách phân tích đệ quy: NewClassTree, TypeCastTree, MethodInvocationTree, ArrayAccessTree, và nhiều người khác. Nhưng điều này có vẻ như rất nhiều công việc dễ bị lỗi, và rõ ràng javac đã biết loại tĩnh của biểu thức vì nó cần thông tin này cho nhiều mục đích. Nhưng làm cách nào để tôi có quyền truy cập vào thông tin loại này?

Những gì tôi có cho đến nay:

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

và những gì nó in khi chạy trên một số phương pháp làm cho mã đơn giản gọi:

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

Cảm ơn câu hỏi đó, điều này thực sự là một ví dụ ngắn gọn cho API biên dịch cây. Đối với bản ghi, trên 'processingEnv' xuất phát từ phương thức' init (ProcessingEnvironment) 'cũng nên được ghi đè. Oh, và JRockit 1.6.0_29 vẫn hiển thị "null". – mgaert

+0

Không cần ghi đè 'AbstractProcessor.init' trong hầu hết các trường hợp. –

Trả lời

1

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

dường như được giải quyết một rất giống nhau câu hỏi, vì vậy tôi sẽ cố gắng sử dụng lời khuyên đưa ra ở đó. Thật không may nó không nhìn đơn giản, và sử dụng các gói com.sun.tools.javac dường như được yêu cầu.

+0

http://bitbucket.org/jglick/qualifiedpublic/src/f2d33fd97c83/src/qualifiedpublic/PublicProcessor.java dường như hoạt động - nhưng chỉ theo JDK 7. Tôi không thể làm cho nó hoạt động được bằng cách sử dụng javac của JDK 6. –

+0

Tôi đang mắc kẹt trên cùng một vấn đề, và tôi không thể sử dụng Jdk7. Bạn cuối cùng đã tìm thấy bất kỳ giải pháp cho vấn đề này với Jdk1.6 ?? –

+0

Xin lỗi, không bao giờ làm việc với JDK 6. –

Các vấn đề liên quan