Eclipse 插件:IDE.openEditor 抛出 IllegalArgumentException

Eclipse Plug In: IDE.openEditor throws IllegalArgumentException

我正在编写 Eclipse 插件。它 运行 是对 Java 代码的代码分析,并使用 ListViewer 报告违反特定标准的代码行。当有人在列表查看器中选择其中一行时,我想打开 Eclipse Java 文件编辑器到该文件并转到该行。分析工作的方式,每个违规都有一个字段保存违规发生的文件作为标准 java.io.File。因此,我需要将其转换为 IFile,以便我可以在 Eclipse Java 编辑器中打开它。

这是当用户单击列表查看器中的某一行时 运行 的大部分代码。违规是 class 我用来表示违反某些标准的特定行 Java 代码:

Violation selectedViolation = <I get this from the ListViewer> 
IPath path = new Path(violation.getSourceFile().getAbsolutePath());
IFile toOpen = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
IEditorPart editorPart =  PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
if (editorPart == null) {
    IWorkbenchPage curPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
    editorPart = IDE.openEditor(curPage, toOpen, true);
}

运行 这个,我在调用 IDE.openEditor 的行上得到 IllegalArgumentException(对应于 CalisthenicsView.java:75):

at org.eclipse.ui.part.FileEditorInput.getPath(FileEditorInput.java:218)
at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:3163)
at org.eclipse.ui.internal.WorkbenchPage.access(WorkbenchPage.java:3149)
at org.eclipse.ui.internal.WorkbenchPage.run(WorkbenchPage.java:3131)
at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:3126)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:3090)
at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:3080)
at org.eclipse.ui.ide.IDE.openEditor(IDE.java:541)
at org.eclipse.ui.ide.IDE.openEditor(IDE.java:500)
at com.chairbender.eclipse.object_calisthenics_analyzer.views.CalisthenicsView.selectionChanged(CalisthenicsView.java:75)

我查看了在 FileEditorInput.java:218 中抛出此问题的源代码行。显然它是这样做的(其中 "file" 与第一个代码块中的 "toOpen" 相同):

 final URI locationURI = file.getLocationURI();
 if (locationURI == null)
   throw new IllegalArgumentException();

对我来说,由于某种原因,.getFile(path) 似乎返回了一个没有 locationURI 的 IFile。不知道为什么。

有办法解决这个问题吗?有没有不同的方法可以完成此操作(将 Java 编辑器打开到特定文件的特定行)?请记住,我无权访问 IProject,因为此分析可以针对工作区中的任何项目甚至整个工作区 运行。

编辑:我不明白的另一件事是试图调用 FileEditorInput.getPaht() 的代码。查看第 3163 行的 WorkbenchPage.busyOpenEditor:

// Special handling for external editors (they have no tabs...)
    if ("org.eclipse.ui.systemExternalEditor".equals(editorId)) { //$NON-NLS-1$
        IPathEditorInput fileInput = getPathEditorInput(input);
        if (fileInput == null) {
            throw new PartInitException(WorkbenchMessages.EditorManager_systemEditorError);
        }

        String fullPath = fileInput.getPath().toOSString();
        Program.launch(fullPath);
        return null;
    }

这是调用 FileEditorInput.getPath() 的代码。显然它正在尝试打开一个名为 "external editor" 的东西,这听起来不是我想要的。我只想打开默认的 Java 源代码编辑器。这听起来像是在尝试打开其他东西。

此外,我想补充一点,toOpen(我试图打开的 IFile)的 .toString() 值是: L/Programming/runtime-New_configuration/slackbot-resistance/src/main/java/com/chairbender/slackbot/resistance/ResistanceBot.java

...所以它绝对不是空的或无效的,我假设 Eclipse 知道它是一个 Java 文件。

IPath path = new Path(violation.getSourceFile().getAbsolutePath());
IFile toOpen = ResourcesPlugin.getWorkspace().getRoot().getFile(path);

您似乎将绝对文件路径传递给 getFile 方法。 Java文档说:

This is a resource handle operation; neither the resource nor the result need exist in the workspace. The validation check on the resource name/path is not done when the resource handle is constructed; rather, it is done automatically as the resource is created.

The supplied path may be absolute or relative; in either case, it is interpreted as relative to this resource and is appended to this container's full path to form the full path of the resultant resource. A trailing separator is ignored. The path of the resulting resource must have at least two segments.

因此路径被解释为相对于当前工作区(即您的测试工作区而不是您的开发工作区)。没有进行测试以查看该文件是否实际存在。

IDE.openEditor 中的异常是因为 IFile 似乎不在工作区的有效项目中。这也是它试图打开外部编辑器的原因。

如果你想打开一个不在工作区中的文件,你需要使用 IURIEditorInput 实现 FileStoreEditorInput:

IFileStore store = EFS.getStore(file.toURI());

IEditorInput input = new FileStoreEditorInput(store);

IDE.openEditor(page, input, "editor id", true);

注意:某些编辑器不支持不在工作区中的文件,其他编辑器的功能可能有所减少。

Java 编辑器的编辑器 ID 由 JavaUI.ID_CU_EDITOR ("org.eclipse.jdt.ui.CompilationUnitEditor")

给出

如果您有一个文件在工作区中,但您只有文件的绝对路径,请使用 IWorkspaceRoot.getFileForLocation:

IFile toOpen = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path);

注意:如果找不到 IFile,这将 return null

这个问题是因为我不理解 ResourcesPlugin.getWorkspace().getRoot().getFile(path) 的文档。它说 "The supplied path may be absolute or relative; in either case, it is interpreted as relative to this resource and is appended",这让我有点困惑。如何将绝对路径解释为相对于任何事物?如果我将绝对路径传递给它,为什么它不通过检查工作空间路径是否位于传递的绝对路径的开头来使该路径相对于工作空间?我希望该方法表现得更智能。

以下对我有用。我必须使用 IPath.makeRelativeTo 方法将绝对路径从我的 java.io.File 转换为相对路径,方法是切断对应于工作区的路径部分:

IPath path = new Path(violation.getSourceFile().getAbsolutePath());
IPath workspacePath = ResourcesPlugin.getWorkspace().getRoot().getLocation();
path = path.makeRelativeTo(workspacePath);
IFile toOpen = ResourcesPlugin.getWorkspace().getRoot().getFile(path);

使用 getFileForLocation 而不是 getFile 的建议无效。无论路径是相对路径还是绝对路径,该方法总是为我返回 null。我觉得它坏了。