2009-06-30 32 views
6

के लिए एनोटेशन प्रोसेसर में एक विधिन्वयन की कक्षा की खोज करें मैं कुछ बिल्डिंग सिस्टम वाले कुछ वर्गों से संबंधित कुछ सख्त कॉलिंग सम्मेलनों को लागू करने के लिए हमारे निर्माण प्रणाली के लिए कुछ टूल लिख रहा हूं।जावा

मैं संकलक ट्री एपीआई का उपयोग कर रहा हूँ ...

मैं क्या सोच रहा हूँ है जब 'पेड़' traversing, तुम कैसे एक MethodInvocation के लिए वर्ग/इंटरफेस के प्रकार बता सकते हैं।

मैं साथ TreePathScanner उपवर्गीकरण हूँ:

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

} 

मैं आशा करती हूं एक तरह से वर्ग (या इंटरफेस) है कि आप पर विधि को लागू करने की कोशिश कर रहे हैं के प्रकार बताने के लिए theres। क्या मैं इस बारे में गलत तरीके से जा रहा हूं? किसी भी विचार के लिए धन्यवाद ...

उत्तर

8

यहां कुछ समस्याएं हैं। आप या तो में विधि आवेषण रिसीवर के जावा प्रकार को जानना या विधि पर कक्षा को जानना जानना चाहते हैं। जावा जानकारी अधिक जानकारीपूर्ण है क्योंकि यह आपको सामान्य प्रकार भी प्रदान करती है, उदा। List<String> जबकि तत्व केवल आपको कक्षा प्रदान करेंगे, उदा। List<E>

तत्व

हो रही वर्ग पद्धति पर शुरू हो जाती है का तत्व पाने के लिए आपको कर सकते हैं निम्नलिखित:


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

कॉर्नर मामलों:

1. invoked क्लास रिसीवर प्रकार का एक सुपरक्लास हो सकता है। तो टुकड़ा चल new ArrayList<String>.equals(null) पर AbstractList बजाय ArrayList, बराबरी के बाद वापस होगा() AbstractList नहीं ArrayList में कार्यान्वित किया जाता है।

2. सरणी आमंत्रणों को संभालने पर, उदा। new int[].clone(), आप TypeElement कक्षा Array प्राप्त करेंगे।

वास्तविक प्रकार

हो रही प्रकार प्राप्त करने के लिए, वहाँ यह निर्धारित करने के लिए क्या रिसीवर प्रकार है के लिए कोई सीधा रास्ता है। अंदरूनी कक्षाओं के भीतर विधि आमंत्रण को संभालने में कुछ जटिलता है जहां रिसीवर स्पष्ट रूप से (उदा। OuterClass.this.toString() के विपरीत) नहीं दिया गया है। यहां एक नमूना दिया गया है:


    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()); 

नोट:

receiver प्रकार TypeMirror नहीं DeclaredType दुर्भाग्य की जरूरत है। new int[5].clone() पर कॉल करते समय, receiver int[] का होगा, जो पिछले विधि से अधिक जानकारीपूर्ण है।

यह

पिछले विधियों में से

दोनों को चलाने के लिए हो रही कक्षाओं के लिए प्रकार जानकारी को हल करने संकलक की आवश्यकता है। सामान्य परिस्थितियों में, कंपाइलर केवल विधि घोषणाओं के प्रकारों को हल करता है लेकिन निकायों को नहीं। इसलिए, पहले वर्णित विधियां null बदलेगी।

संकलक प्रकार की जानकारी को हल करवाने के लिए, आप में से एक निम्न तरीकों कर सकते हैं:

1. उपयोग AbstractTypeProcessor वर्ग है कि बस के लिए JDK 7. बाहर चेक काम संकलक भंडार करने के लिए जोड़ा गया JSR 308 और उनके कंपाइलर पर। जबकि काम मुख्य रूप से एनोटेटेड प्रकारों पर है, यह इसके लिए उपयोगी हो सकता है। संकलक आप जावा 5.

साथ एक पिछड़े संगत तरीके से प्रदान की कक्षा का उपयोग करने के यह दृष्टिकोण आप प्रोसेसर है कि बस अपने वर्तमान प्रोसेसर की तरह लागू करने के लिखने की अनुमति देता है।

2. इसके बजाय JavacTask का उपयोग करें और JavacTask.analyze() पर कॉल करें। this javac test की मुख्य विधि को देखने के लिए कक्षाओं पर अपने आगंतुक को आमंत्रित करने के लिए देखें।

यह दृष्टिकोण आपके प्रोसेसर को संकलक के प्लग-इन की बजाय विश्लेषण उपकरण की तरह दिखता है, क्योंकि आपको इसे नियमित प्रक्रिया होने के बजाय सीधे का आह्वान करना होगा।

+0

प्रतिक्रिया के लिए धन्यवाद। हालांकि, रेखा: तत्व विधि = TreeInfo.symbol ((JCTree) node.getMethodSelect()); मेरे लिए शून्य वापस आती है। \t TypeMirror m = tree.getTypeMirror (पथ); भी \t टाइप एलिमेंट ई = (टाइप एलिमेंट) पेड़ .getElement (पथ); क्या मैं एक रूकी गलती कर रहा हूं और कुछ शुरू करने के लिए भूल रहा हूं, या गलत विधि को कॉल/ओवरराइड कर रहा हूं, या कुछ गड़बड़ कर रहा हूं? आपकी मदद के लिए फिर से धन्यवाद ... – runT1ME

+0

मैंने अभी यह प्रविष्ट करने के लिए प्रविष्टि को अपडेट किया है कि क्यों विधियां शून्य हो जाती हैं और – notnoop

+0

एफवाईआई को कैसे संबोधित किया जाए, एबीआरटीपीप्रोसेसर अब जेडीके 7 बिल्ड में उपलब्ध नहीं है, क्योंकि जेएसआर 308 के लिए समर्थन गिरा दिया गया था। –