java - 从插件项目中类转换解析 Java 源代码时出现问题

标签 java parsing casting eclipse-plugin classloader

我想知道如何获取 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/

相关文章:

c - 为什么是 (int)((unsigned int)((int)v)?

c++ - 使用不同的模板参数转换模板对象,这怎么可能?

Java 10,Intellij 警告(类未导出,在同一模块中访问)

android - 如何使用按钮单击从android中的xml feed打开url

java - JFrame - 在 GridLayout 中设置行和列

regex - Perl 正则表达式语法供 ANTLR 使用

parsing - 转换为乔姆斯基范式

c++ - 将 std::string 存储到 int[] 中用于 C++ 中的大整数

java - 为什么会出现java.lang.NullPointerException?

java - 从 Kotlin 将 null 传递给不可为 null 的 Java 方法