2010-01-23 17 views
5

मैं जेएसआर 26 9 प्रारूप में एक एनोटेशन प्रोसेसर लिखने की कोशिश कर रहा हूं जो कुछ स्रोत कोड विश्लेषण करने के लिए जावा के कंपाइलर ट्री एपीआई का उपयोग करता है। मुझे सदस्य चयन अभिव्यक्तियों में रुचि है, जैसे कि विधि कॉल।मैं javac प्लगइन से सदस्य चयनकर्ता में अभिव्यक्ति का प्रकार कैसे प्राप्त करूं?

मैं आसानी से विधि (या फ़ील्ड इत्यादि) का नाम चुन सकता हूं। लेकिन मैं जानना चाहता हूं कि सदस्य किस प्रकार से चुना जा रहा है, और मुझे ऐसा करने का सीधा तरीका नहीं दिख रहा है। Trees.getTypeMirror मैं इसे कॉल करने का प्रयास करने के लिए null देता हूं (और जावाडोक कोई संकेत नहीं देता है)।

मुझे लगता है मैं विस्तृत रूप से चयन सदस्य के बाईं ओर स्थित अभिव्यक्ति के हर तरह का विश्लेषण और पुनरावर्ती विश्लेषण द्वारा अभिव्यक्ति की स्थिर प्रकार का निर्धारण कर सकते हैं: NewClassTree, TypeCastTree, MethodInvocationTree, ArrayAccessTree, और कई अन्य। लेकिन यह बहुत सारे त्रुटि-प्रवण काम की तरह लगता है, और स्पष्ट रूप से जावैक पहले ही अभिव्यक्ति के स्थिर प्रकार को जानता है क्योंकि इसे कई उद्देश्यों के लिए इस जानकारी की आवश्यकता है। लेकिन मैं इस प्रकार की जानकारी तक कैसे पहुंच सकता हूं?

क्या मैं अब तक है:

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

उस प्रश्न के लिए धन्यवाद, जो वास्तव में कंपाइलर ट्री एपीआई के लिए एक महान संक्षिप्त उदाहरण के रूप में युगल है। रिकॉर्ड के लिए, 'प्रसंस्करण एएनवी' ऊपर 'init (प्रसंस्करण पर्यावरण)' विधि से आता है जिसे ओवरराइड किया जाना चाहिए। ओह, और जेआरॉकिट 1.6.0_2 9 अभी भी "शून्य" दिखाता है। – 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 काम करने लगता है - लेकिन केवल जेडीके 7 के तहत। मैं इसे जेडीके 6 के जावैक का उपयोग करके बिल्कुल भी काम नहीं कर सकता। –

+0

मैं एक ही मुद्दे पर फंस गया हूं, और मैं जेडीके 7 का उपयोग नहीं कर सकता। क्या आपको अंततः जेडीके 1.6 के साथ इस मुद्दे का कोई समाधान मिला ?? –

+0

क्षमा करें, इसे कभी भी जेडीके 6 पर काम नहीं मिला। –