7

我试图在导航树视图中获取 Eclipse 用户的结构化选择的详细信息。目前我有以下基于 org.eclipse.ui.popMenus 扩展点:

public void run(IAction action) {

Shell shell = new Shell();

ISelection selection = workbenchPart.getSite().getSelectionProvider().getSelection();

if (structuredSelection instanceof org.eclipse.jface.viewers.TreeSelection) {

   org.eclipse.jface.viewers.TreeSelection treeSelection = (org.eclipse.jface.viewers.TreeSelection) structuredSelection;
   IAdaptable firstElement = (IAdaptable) treeSelection.getFirstElement();

   // Relies on an internal API, bad juju
   if (firstElement instanceof org.eclipse.jdt.internal.core.CompilationUnit) {
    org.eclipse.jdt.internal.core.CompilationUnit compilationUnit = (org.eclipse.jdt.internal.core.CompilationUnit) firstElement;                                   
    String editorSelection = new String(compilationUnit.getContents());
   }            
}

问题在于它目前与 JDT 编译单元 API 耦合,这是内部的,对于我想要的来说太具体了。

理想情况下,我希望能够获得底层文件名、类型和内容,而不必依赖:

  1. 内部 API
  2. JDT 编译单元代码。

当用户右键单击导航器视图中的文件时,这将允许我获取通用文件的属性。

有人可以为我提供有关如何执行此操作的任何指示吗?

4

4 回答 4

9

[编辑:我添加了以下替代方案-原始答案是父亲倒下]

第一:如果你在包资源管理器中选择了一些东西,被选中的项目都是Java模型对象——你必须在某种程度上处理它们。有两种方法可以处理此问题:

  1. 直接使用 ICompilationUnit(见下文)
  2. 创建一个 Eclip 适配器工厂来自动化转换

适配器工厂方法

您可以创建一个适配器工厂(它可以存在于您的主插件或其他插件中),eclipse 可以使用它来自动从 ICompilationUnit 转换为 IFile。

注意:如果您在不同的插件中创建适配器工厂,您可能需要为其设置早期启动以加载适配器工厂。否则,您需要让您的插件与选择一起使用取决于提供适配器的插件。

在http://www.eclipse.org/resources/resource.php?id=407上有一些关于适配器的详细信息,但我将在这里讨论这个问题的实现。

依赖项

将托管适配器的插件需要以下依赖项

  • org.eclispe.core.resources
  • org.eclipse.jdt.core

适配器工厂类

在新插件中定义以下类

package com.javadude.foo;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.jdt.core.ICompilationUnit;

public class CompilationUnitToFileAdapter implements IAdapterFactory {
    @Override
    public Object getAdapter(Object adaptableObject, Class adapterType) {
        if (adaptableObject instanceof ICompilationUnit)
            // note: "adapting" it here just means returning the ref'd IFile
            return (IFile) ((ICompilationUnit)adaptableObject).getResource();
        return null;
    }
    @Override
    public Class[] getAdapterList() {
        return new Class[] {IFile.class};
    }
}

扩展名

在将托管适配器工厂的插件中,将以下内容添加到您的 plugin.xml:

<extension point="org.eclipse.core.runtime.adapters">
    <factory
        adaptableType="org.eclipse.jdt.core.ICompilationUnit"
        class="com.javadude.foo.AdapterFactory1">
        <adapter type="org.eclipse.core.resources.IFile" />
    </factory>
</extension>

使用适配器

有了上述内容,您现在可以编写:

Object firstElement = ((ITreeSelection) selection).getFirstElement();
IFile file = (IFile) Platform.getAdapterManager().
                         getAdapter(firstElement, IFile.class);
if (file == null)
    // adapter not present; cannot use as IFile
else
    // adapter present - you can use it as an IFile

使用这种方法,您可以添加额外的适配器来将其他类型转换为 IFile,而您的选择代码并不关心。


直接 ICompilationUnit 方法

[编辑:我已经更改了答案,但将以下内容作为参考信息 b/c 这是探索在包资源管理器中选择的编译单元内容的标准方法]

这实际上是在包资源管理器中获取文件内容的首选方式...

您应该使用 ICompilationUnit,而不是使用 CompilationUnit。大多数 Eclipse API 使用接口用于公共消费,使用类用于内部细节。

如果您将代码更改为

if (firstElement instanceof ICompilationUnit) {
    ICompilationUnit unit = (ICompilationUnit firstElement;
    String contents = new String(unit.getContents());
}

你的身体会很好。

要查看检查/修改 Java 模型和源代码的详细信息:

(In Eclipse)
Help->
  Help Contents->
    JDT Plug-in Developer's Guide->
      Programmer's Guide->
        JDT Core

这显示了如何适当地使用 Java 模型

要隔离引用 java 模型的位置,您可以创建一个 (eclipse) 适配器,它将 Java 模型对象转换为文件。假设存在这样的适配器,然后您可以要求 AdapterManager 为您将其转换为 java 文件。我去看看有没有。

于 2009-04-22T14:09:19.207 回答
4

那(从 JDT 中解耦 Resource)是E4 (Eclipse 4)的目标之一。
REsources的插件列表不再提及 JDT(同样,仅限 Eclipse 4.x):

  • org.eclipse.core.filesystem- 一个抽象的通用文件系统 API,包括该 API 用于本地文件系统的实现。这是资源插件访问底层文件系统的 API。
  • org.eclipse.core.resources- 包含资源模型的API和实现
  • org.eclipse.core.resources.compatibility- 为在 Eclipse 3.1 或更高版本中打开旧工作区的用户提供迁移支持的插件

e4photo这样的演示项目不需要任何 JDT即可通过选择 IContainer 来访问 IResource

void setSelection(@Named(IServiceConstants.ACTIVE_SELECTION)
        IResource selection) {
...
IResource[] members = input.members();
...
IResource resource = members[i];
if (resource.getType() == IResource.FILE) {
  InputStream contents = ((IFile) resource).getContents();
于 2014-01-26T17:25:36.497 回答
3

你想达到什么目的?你想获取文件内容吗?然后你可以尝试:

IAdaptable firstElement = (IAdaptable) treeSelection.getFirstElement();

IFile file = (IFile) firstElement.getAdapter(IFile.class);
if (file != null && file.isAccessible()) {
    // Use getContents API
    ....
}
于 2009-04-22T07:30:45.997 回答
3

看起来 JDT 已经IAdapterFactory为包括编译单元 ( org.eclipse.jdt.internal.ui.JavaElementAdapterFactory) 在内的所有 Java 元素定义了一个。适配器是为IResource而不是定义的,IFile因此您应该能够:

Object firstElement = treeSelection.getFirstElement();

IResource resource = (IResource)Platform.getAdapterManager().getAdapter(firstElement, IResource.class);
于 2014-01-28T21:43:57.517 回答