我想知道如何获取 Java 源文件中给定行号的周围方法。我在 stackoverflow 中找到了一个解决方案,链接如下:
How to get surrounding method in Java source file for a given line number
这个解决方案的问题是我正在开发一个插件项目。当我尝试使用此解决方案时,出现以下错误异常:
java.lang.ClassCastException: com.sun.tools.javac.api.JavacTaskImpl cannot be cast to com.sun.source.util.JavacTask
at xxx.xxx.xxx.xxx.views.versionsCompare.VersionsCompareView.widgetSelected(VersionsCompareView.java:330)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:234)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2640)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2438)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:671)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:664)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:620)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
at org.eclipse.equinox.launcher.Main.run(Main.java:1408)
at org.eclipse.equinox.launcher.Main.main(Main.java:1384)
我的代码是:
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
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 Principal {
public static void main(String[] args) {
try {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnosticsCollector = new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null);
Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects("C:\\Users\\Alejandro\\Desktop\\comparar\\pkg\\clase.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 = javacTask.parse();
for (CompilationUnitTree compilationUnitTree : parseResult) {
compilationUnitTree.accept(new MethodLineLogger(compilationUnitTree, sourcePositions), null);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/* Class for visit methods */
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);
System.out.println("Found method " + arg0.getName() + " from line " + startLine + " to line " + endLine + ".");
return super.visitMethod(arg0, arg1);
}
}
}
浏览互联网,我认为该问题是由于插件项目中存在多个类加载器而无法强制转换这一事实引起的:
JavacTask javacTask = (JavacTask) 任务;
我已经尝试了一切,但没有更多的想法,有人可以给我任何帮助吗?
提前谢谢您。
最佳答案
我面临着完全相同的问题,但不是作为插件,而是作为 ant 任务。你是对的——这是一个类加载器问题。 对我有用的是使用 ant 中的“fork”属性。所以你的解决方案是类似的 - 打开一个外部流程。恶心!
关于java - 从插件项目中类转换解析 Java 源代码时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9997804/