Eclipse PDE、导航器视图、TreeSelection - 获取文件类型和名称

发布于 2024-07-17 20:07:47 字数 1150 浏览 5 评论 0原文

我正在尝试获取 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 耦合,该 API 是内部的,对于我想要的内容来说过于具体。

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

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

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

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

I'm trying to obtain details of an Eclipse user's structured selection in the Navigator Tree view. At present I have the following which is based on the org.eclipse.ui.popMenus extension point:

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());
   }            
}

The problem with this is that it's currently coupled to the JDT compilation unit API, which is internal and too specific for what I want.

Ideally I want to be able to get the underlying file name, type and contents without having to rely on:

  1. An internal API
  2. The JDT Compilation Unit Code.

This would then allow me to obtain the properties of a generic file when the user right clicks on a file in the navigator view.

Can somebody provide me with any pointers on how I go about doing this please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

萌辣 2024-07-24 20:07:47

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

首先:如果您在 Package Explorer 中选择某些内容,则所选项目都是 Java 模型对象 - 您必须在某种程度上处理它们。 有两种方法可以处理这个问题:

  1. 直接使用 ICompilationUnit(请参阅下文)
  2. 创建一个 Eclipe 适配器工厂来自动执行转换

适配器工厂方法

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

注意:如果您在不同的插件中创建适配器工厂,您可能需要为其设置早期启动才能加载适配器工厂。 否则,您需要让您的插件能够根据提供适配器的插件进行选择。

有关适配器的一些详细信息,请访问 http://www.eclipse.org/resources/ resources.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 文件。 我去看看有没有。

[EDIT: I added the following alternative - the original answer is father down]

First: if you select something in the Package Explorer, the selected items are all Java Model objects - you have to deal with them at some level. There are two ways you can handle this:

  1. Use the ICompilationUnit directly (see farther down)
  2. Create an Eclipe adapter factory to automate the conversion

Adapter Factory Approach

You can create an adapter factory (which can live in your main plugin or a different one) that eclipse can use to automatically convert from an ICompilationUnit to an IFile.

Note: if you create the adapter factory in a different plugin, you'll probably need to set up an early-startup for it to get the adapter factory loaded. Otherwise, you'll need to have your plugin that will work with the selection depend on the plugin that provides the adapter.

There's some great details on adapters at http://www.eclipse.org/resources/resource.php?id=407, but I'll go over an implementation for this problem here.

Dependencies

The plugin that will host the adapter needs the following dependencies

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

The adapter factory class

Define the following class in your new plugin

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};
    }
}

The extension

In the plugin that will host the adapter factory, add the following to your 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>

Using the Adapter

With the above in place, you can now write:

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

Using this approach, you can add additional adapters to convert other types to IFile and your selection code doesn't care.


Direct ICompilationUnit Approach

[EDIT: I've changing the answer, but leaving the following as reference information b/c it's the standard way to explore the content of a compilation unit that was selected in the package explorer]

This is actually the preferred way to get the contents of a file in the package explorer...

Rather than use CompilationUnit, you should use ICompilationUnit. Most of the eclipse APIs use interfaces for public consumption, and classes for internal details.

If you change your code to

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

You'll be in good shape.

To see details of examining/modifying the Java Model and source code:

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

That shows how to work with the Java Model appropriately

To isolate where you reference the java model, you can create an (eclipse) adapter that will convert Java Model objects into files. Assuming such an adapter exists, you can then ask the AdapterManager to convert it to a java file for you. I'll take a peek and see if one exists.

玉环 2024-07-24 20:07:47

这(将资源与 JDT 解耦)是 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

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();

That (decoupling Resource from JDT) was one of the goals of E4 (Eclipse 4).
The plugin list for REsources doesn't mention JDT anymore (again, Eclipse 4.x only):

  • org.eclipse.core.filesystem - An abstract, generic file system API, including an implementation of this API for the local file system. This is the API through which the resources plugin accesses an underlying file system.
  • org.eclipse.core.resources - Contains the API and implementation of the resource model
  • org.eclipse.core.resources.compatibility - A plug-in providing migration support for users opening old workspaces in Eclipse 3.1 or greater

A Demo project like e4photo don't require any JDT for accessing IResource from the selection of an IContainer.

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();
a√萤火虫的光℡ 2024-07-24 20:07:47

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

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

IFile file = (IFile) firstElement.getAdapter(IFile.class);
if (file != null && file.isAccessible()) {
    // Use getContents API
    ....
}

What are you trying to achieve? Do you want to get file contents? Then you can try:

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

IFile file = (IFile) firstElement.getAdapter(IFile.class);
if (file != null && file.isAccessible()) {
    // Use getContents API
    ....
}
找个人就嫁了吧 2024-07-24 20:07:47

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

Object firstElement = treeSelection.getFirstElement();

IResource resource = (IResource)Platform.getAdapterManager().getAdapter(firstElement, IResource.class);

It looks like the JDT is already defining an IAdapterFactory for all Java elements including compilation unit (org.eclipse.jdt.internal.ui.JavaElementAdapterFactory). The adapter is defined for IResource rather than IFile so you should be able to do:

Object firstElement = treeSelection.getFirstElement();

IResource resource = (IResource)Platform.getAdapterManager().getAdapter(firstElement, IResource.class);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文