Comment obtenir la méthode autour dans le fichier source Java pour un numéro de ligne donné

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

  •  20-09-2019
  •  | 
  •  

Question

J'ai un numéro de ligne d'un fichier source Java et que vous souhaitez obtenir la méthode sourounding pour ce numéro de ligne programatically.

J'ai regardé dans ANTLR qui ne m'a pas aidé beaucoup.

Janino ( http://www.janino.net ) semble prometteuse, je scanner et analyser ( et si nécessaire la compilation) du code. Ensuite, je pourrais utiliser JDI

ReferenceType.locationsOfLine(int lineNumber)

Cependant, je ne sais pas comment utiliser JDI pour ce faire et n'a pas trouvé un tutoriel qui va partout dans ce sens.

Peut-être il y a une autre façon que je suis complètement absent.

Était-ce utile?

La solution

Si vous utilisez Java 6, et si vous ne me dérange pas en utilisant les API de Sun, vous pouvez utiliser l'API javac . Vous devrez ajouter tools.jar à votre classpath.

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

Autres conseils

Vous pouvez utiliser ASM 's CodeVisitor récupérer les informations de débogage ligne d'une classe compilée. Cela vous permet d'économiser l'analyse des fichiers source Java.

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

Pour la classe 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 }

produit:

<init>
11
x
14
15
16
y
19
20

Si vous avez besoin de ces informations lors de l'exécution. Vous pouvez créer une exception et un coup d'oeil à la oligo-éléments de pile .

peut-être vous pouvez jeter une exception, l'attraper, extraire l'élément stacktrace correspondant pour obtenir le nom de la méthode.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top