Wie kommt man in Java-Quelldatei für eine bestimmte Zeilennummer umgebendes Verfahren

StackOverflow https://stackoverflow.com/questions/1928157

  •  20-09-2019
  •  | 
  •  

Frage

Ich habe eine Zeilenzahl einer Java-Quelldatei und will programmatisch die sourounding Methode für die Zeilennummer erhalten.

Ich sah in ANTLR was nicht half mir viel.

Janino ( http://www.janino.net ) scheint vielversprechend, würde ich scannen und Parse ( und ggf. der Kompilierung) der Code. Dann könnte ich verwenden JDI und

ReferenceType.locationsOfLine(int lineNumber)

Still Ich weiß nicht, wie JDI zu verwenden, dies zu tun und nicht gefunden, ein Tutorial, das überall in dieser Richtung geht.

Vielleicht gibt es eine andere Art und Weise, dass ich völlig fehle.

War es hilfreich?

Lösung

Wenn Sie mit Java 6, und wenn Sie nicht APIs von Sun nichts ausmacht, dann können Sie eine href verwenden <= "http://java.sun.com/javase/6/docs/technotes/guides /javac/index.html“rel = "noreferrer"> die javac API . Sie müssen tools.jar zu Classpath hinzuzufügen.

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

Andere Tipps

Sie können mit ASM 's CodeVisitor auf abrufen die Debugging-Zeileninformation aus einer kompilierten Klasse. Dies erspart Ihnen die Analyse von Java-Quelldateien.

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

Für die Klasse A:

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 }

Dies erzeugt:

<init>
11
x
14
15
16
y
19
20

Wenn Sie diese Informationen zur Laufzeit benötigen. Sie können eine Ausnahme und haben einen Blick auf die Stapel Spurenelemente .

Vielleicht können Sie eine Ausnahme werfen, fangen es, extrahieren Sie die entsprechende Stacktrace-Element den Namen der Methode zu erhalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top