2009-12-18 26 views
8

के लिए जावा स्रोत फ़ाइल में आस-पास की विधि कैसे प्राप्त करें मेरे पास जावा स्रोत फ़ाइल की एक पंक्ति संख्या है और प्रोग्राम संख्या के लिए उस पंक्ति संख्या के लिए sourounding विधि प्राप्त करना चाहते हैं।किसी दिए गए लाइन नंबर

मैंने ANTLR में देखा जो मुझे बहुत मदद नहीं करता था।

जानिनो (http://www.janino.net) आशाजनक प्रतीत होता है, मैं कोड स्कैन और पार्स (और यदि आवश्यक संकलन) कोड को स्कैन करता हूं। तब मैं JDI और

ReferenceType.locationsOfLine(int lineNumber) 

का उपयोग फिर भी मैं ऐसा करने के लिए JDI उपयोग करने के लिए कैसे और एक ट्यूटोरियल है कि इस दिशा में कहीं भी चला जाता है नहीं मिला पता नहीं है हो सकता है।

शायद कुछ और तरीका है कि मैं पूरी तरह से गायब हूं।

+0

क्या आप एक ही तरीके से बात कर रहे हैं- यू होगा? जैसे @@ -3452,6 +3452,59 @@ शून्य MyMethod (int a, int b) – Pod

+0

क्या आप विधि का नाम, या विधि का पाठ चाहते हैं? –

+0

विधि का नाम पर्याप्त होगा, लेकिन समस्या लंबे समय तक हल हो गई है। वैसे भी धन्यवाद :-) – roesslerj

उत्तर

11

यदि आप जावा 6 का उपयोग कर रहे हैं, और यदि आपको सूर्य के एपीआई का उपयोग करने में कोई फर्क नहीं पड़ता है, तो आप the javac API का उपयोग कर सकते हैं। आपको अपने क्लासपाथ में tools.jar जोड़ने की आवश्यकता होगी।

import java.io.IOException; 
import javax.tools.DiagnosticCollector; 
import javax.tools.JavaCompiler; 
import javax.tools.JavaFileObject; 
import javax.tools.StandardJavaFileManager; 
import javax.tools.ToolProvider; 
import javax.tools.JavaCompiler.CompilationTask; 
import com.sun.source.tree.CompilationUnitTree; 
import com.sun.source.tree.LineMap; 
import com.sun.source.tree.MethodTree; 
import com.sun.source.util.JavacTask; 
import com.sun.source.util.SourcePositions; 
import com.sun.source.util.TreeScanner; 
import com.sun.source.util.Trees; 

public class MethodFinder { 

    public static void main(String[] args) { 
     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
     DiagnosticCollector<JavaFileObject> diagnosticsCollector = new DiagnosticCollector<JavaFileObject>(); 
     StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null); 
     Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects("path/to/Source.java"); 
     CompilationTask task = compiler.getTask(null, fileManager, diagnosticsCollector, null, null, fileObjects); 

     // Here we switch to Sun-specific APIs 
     JavacTask javacTask = (JavacTask) task; 
     SourcePositions sourcePositions = Trees.instance(javacTask).getSourcePositions(); 
     Iterable<? extends CompilationUnitTree> parseResult = null; 
     try { 
      parseResult = javacTask.parse(); 
     } catch (IOException e) { 

      // Parsing failed 
      e.printStackTrace(); 
      System.exit(0); 
     } 
     for (CompilationUnitTree compilationUnitTree : parseResult) { 
      compilationUnitTree.accept(new MethodLineLogger(compilationUnitTree, sourcePositions), null); 
     } 
    } 

    private static class MethodLineLogger extends TreeScanner<Void, Void> { 
     private final CompilationUnitTree compilationUnitTree; 
     private final SourcePositions sourcePositions; 
     private final LineMap lineMap; 

     private MethodLineLogger(CompilationUnitTree compilationUnitTree, SourcePositions sourcePositions) { 
      this.compilationUnitTree = compilationUnitTree; 
      this.sourcePositions = sourcePositions; 
      this.lineMap = compilationUnitTree.getLineMap(); 
     } 

     @Override 
     public Void visitMethod(MethodTree arg0, Void arg1) { 
      long startPosition = sourcePositions.getStartPosition(compilationUnitTree, arg0); 
      long startLine = lineMap.getLineNumber(startPosition); 
      long endPosition = sourcePositions.getEndPosition(compilationUnitTree, arg0); 
      long endLine = lineMap.getLineNumber(endPosition); 

      // Voila! 
      System.out.println("Found method " + arg0.getName() + " from line " + startLine + " to line " + endLine + "."); 

      return super.visitMethod(arg0, arg1); 
     } 
    } 
} 
3

आप संकलित कक्षा से ASM के कोडविटर retrieve the debugging line information पर उपयोग कर सकते हैं। यह आपको जावा स्रोत फ़ाइलों की पार्सिंग बचाता है।

ClassReader reader = new ClassReader(A.class.getName()); 
reader.accept(new ClassVisitor() { 
    public CodeVisitor visitMethod(int access, String name, String desc, 
      String[] exceptions, Attribute attrs) { 
     System.out.println(name); 
     return new CodeVisitor() { 
      public void visitLineNumber(int line, Label start) { 
       System.out.println(line); 
      } 
     } 
    } 
}, false); 

वर्ग एक के लिए:

11 class A { 
12 
13 public void x() { 
14  int x = 1; 
15  System.out.println("Hello"); 
16 } 
17 
18 public void y() { 
19  System.out.println("World!"); 
20 } 
21 } 

यह पैदा करता है:

<init> 
11 
x 
14 
15 
16 
y 
19 
20 

आप रनटाइम पर इस जानकारी की जरूरत है। आप अपवाद बना सकते हैं और stack trace elements पर एक नज़र डालें।

+0

हैलो! इस अच्छे उत्तर के लिए धन्यवाद। यह लगभग वही है जो मैं ढूंढ रहा था। तुम्हारी मदद के लिए शुक्रिया! – roesslerj

0

शायद आप एक अपवाद फेंक सकते हैं, इसे पकड़ सकते हैं, विधि नाम प्राप्त करने के लिए संबंधित स्टैकट्रस तत्व निकालें।

+1

स्टैक ट्रेस को पार्स करने की आवश्यकता नहीं है। स्टैक ट्रेस तत्व (http://java.sun.com/javase/6/docs/api/java/lang/StackTraceElement.html) में जानकारी शामिल है। –

+0

जानकारी के लिए धन्यवाद – chburd

+0

अपर्याप्त होने के लिए खेद है। मुझे उस वर्ग की विधि प्राप्त करनी है जिसका मैं उपयोग नहीं कर रहा हूं। – roesslerj

संबंधित मुद्दे