Я имею номер строки исходного файла Java и хочу получить sourounding метод для того номера строки программно.
Я изучил ANTLR, который не помог мне очень.
Янино (http://www.janino.net) кажется обещанием, я просканировал бы и проанализировал бы (и если необходимая компиляция) код. Затем я мог использовать JDI и
ReferenceType.locationsOfLine(int lineNumber)
Тем не менее я не знаю, как использовать JDI для того, чтобы сделать это и не нашел учебное руководство, которое идет куда угодно в этом направлении.
Возможно, существует некоторый другой способ, которым я являюсь абсолютно пропавшим.
Если вы используете Java 6 и не возражаете против использования API-интерфейсов Sun, вы можете использовать API-интерфейс javac . Вам нужно будет добавить 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);
}
}
}
Вы можете использовать CodeVisitor ASM , чтобы получить информацию о строке отладки из скомпилированного класса. Это избавит вас от необходимости синтаксического анализа исходных файлов 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);
Для класса 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 }
Это дает:
<init>
11
x
14
15
16
y
19
20
Если вам нужна эта информация во время выполнения. Вы можете создать исключение и просмотреть элементы трассировки стека .
возможно, вы можете создать исключение, перехватить его, извлечь соответствующий элемент stacktrace, чтобы получить имя метода.