2009-06-30 43 views
6

Tôi đang viết một số công cụ cho hệ thống xây dựng của chúng tôi để thực thi một số quy ước gọi điện nghiêm ngặt về các phương pháp thuộc các lớp chứa chú thích nhất định.Khám phá lớp của phương thức chú giải trong Bộ xử lý chú thích cho java

Tôi đang sử dụng API Compiler Tree ...

gì tôi đang tự hỏi là khi đi qua các 'cây', làm thế nào bạn có thể nói với các loại lớp/giao diện cho một MethodInvocation.

Tôi subclassing TreePathScanner với:

@Override 
public Object visitMethodInvocation(MethodInvocationTree node, Trees trees) { 

} 

Tôi hy vọng theres một cách để nói với các loại hình lớp (hoặc giao diện) mà bạn đang cố gắng để gọi các phương pháp trên. Tôi đang đi về điều này một cách sai lầm? Cảm ơn mọi ý tưởng ...

Trả lời

8

Có một vài vấn đề ở đây. Bạn có thể quan tâm đến việc biết loại Java của trình thu thập lời gọi phương thức hoặc chỉ biết rằng lớp trên phương thức được gọi. Thông tin Java có nhiều thông tin hơn vì nó cung cấp cho bạn các loại chung chung, ví dụ: List<String> trong khi Elements chỉ cung cấp cho bạn lớp học, ví dụ: List<E>.

Bắt Element

Để có được phần tử của lớp phương pháp này được gọi trên, bạn có thể làm sau:


    MethodInvocationTree node = ...; 
    Element method = 
     TreeInfo.symbol((JCTree)node.getMethodSelect()); 
    TypeElement invokedClass = (TypeElement)method.getEnclosingElement(); 

trường hợp Corner:

1. invokedClass có thể là một siêu lớp của kiểu người nhận. Vì vậy, hãy chạy đoạn mã trên new ArrayList<String>.equals(null) sẽ trả lại AbstractList thay vì ArrayList, vì equals() được triển khai trong AbstractList không ArrayList.

2. Khi xử lý yêu cầu mảng, ví dụ: new int[].clone(), bạn sẽ nhận được TypeElement của lớp Array.

Bắt loại thực

Để có được loại, không có cách nào trực tiếp để xác định nó những gì các loại nhận là. Có một số phức tạp trong việc xử lý các lời gọi phương thức trong các lớp bên trong nơi người nhận không được cung cấp rõ ràng (ví dụ: không giống như OuterClass.this.toString()). Đây là một thực hiện mẫu:


    MethodInvocationTree node = ...; 
    TypeMirror receiver; 
    if (methodSel.getKind() == Tree.Kind.MEMBER_SELECT) { 
    ExpressionTree receiver = ((MemberSelectTree)methodSel).getExpression(); 
    receiverType = ((JCTree)receiver).type; 
    } else if (methodSel.getKind() == Tree.Kind.IDENTIFIER) { 
    // need to resolve implicit this, which is described in 
    // JLS3 15.12.1 and 15.9.2 

    // A bit too much work that I don't want to work on now 
    // Look at source code of 
    // Attr.visitApply(JCMethodInvocation) 
    // resolveImplicitThis(DiagnosticPosition, Env, Type) 
    } else 
    throw new AssertionError("Unexpected type: " + methodSel.getKind()); 

Lưu ý:

Loại receiver cần phải được TypeMirror không DeclaredType không may. Khi gọi new int[5].clone(), receiver sẽ là an ArrayType trong số int[], thông tin đó nhiều thông tin hơn phương pháp trước đó.

Bắt nó chạy

Cả hai phương pháp trước đòi hỏi trình biên dịch để giải quyết các loại thông tin cho các lớp học. Trong các trường hợp thông thường, trình biên dịch chỉ giải quyết các loại khai báo phương thức chứ không giải quyết các đối tượng. Do đó, các phương pháp được mô tả trước đó sẽ trả lại null thay thế.

Để có trình biên dịch giải quyết các loại thông tin, bạn có thể làm một trong các cách sau:

1. Sử dụng AbstractTypeProcessor lớp mà chỉ đã được bổ sung vào kho trình biên dịch cho JDK 7. Kiểm tra hiện công việc trên JSR 308 và trình biên dịch của chúng. Trong khi tác phẩm chủ yếu dựa trên các loại chú thích, nó có thể hữu ích cho. Trình biên dịch cho phép bạn sử dụng lớp được cung cấp theo cách tương thích lạc hậu với Java 5.

Cách tiếp cận này cho phép bạn viết các bộ vi xử lý được gọi chỉ như bộ vi xử lý hiện tại của bạn.

2. Sử dụng JavacTask thay vào đó và gọi JavacTask.analyze(). Hãy xem phương pháp chính của this javac test để xem cách để gọi khách truy cập của bạn trên các lớp học.

Phương pháp này làm cho bộ xử lý của bạn trông giống như một công cụ phân tích hơn là trình cắm vào trình biên dịch, vì bạn cần gọi trực tiếp số thay vì phải là quy trình thông thường.

+0

Cảm ơn bạn đã phản hồi. Tuy nhiên, dòng: Phương thức phần tử = TreeInfo.symbol ((JCTree) node.getMethodSelect()); trả về giá trị null cho tôi. \t TypeMirror m = trees.getTypeMirror (đường dẫn); cũng trả về null, cũng như \t TypeElement e = (TypeElement) trees.getElement (đường dẫn); Tôi có mắc lỗi tân binh và quên khởi tạo một cái gì đó, hoặc gọi/ghi đè sai phương pháp, hoặc phân lớp sai? Một lần nữa xin cảm ơn sự giúp đỡ của bạn ... – runT1ME

+0

Tôi vừa cập nhật mục để giải thích lý do tại sao các phương thức trả về null và cách giải quyết – notnoop

+0

FYI, AbstractTypeProcessor không còn khả dụng trong bản dựng JDK 7 nữa, vì hỗ trợ cho JSR 308 đã bị loại bỏ. –

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