简体   繁体   English

Eclipse PDE,Navigator View,TreeSelection - 获取文件类型和名称

[英]Eclipse PDE, Navigator View, TreeSelection - Obtaining the file type and name

I'm trying to obtain details of an Eclipse user's structured selection in the Navigator Tree view. 我正在尝试在“导航器树”视图中获取Eclipse用户的结构化选择的详细信息。 At present I have the following which is based on the org.eclipse.ui.popMenus extension point: 目前我有以下基于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());
   }            
}

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. 这个问题是它目前已经加入了JDT编译单元API,它是内部的,并且对我想要的东西太具体了。

Ideally I want to be able to get the underlying file name, type and contents without having to rely on: 理想情况下,我希望能够获得基础文件名,类型和内容,而不必依赖:

  1. An internal API 内部API
  2. The JDT Compilation Unit Code. JDT编译单元代码。

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? 有人可以向我提供有关我如何做到这一点的任何指示吗?

[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. 首先:如果您在Package Explorer中选择了某些内容,则所选项目都是Java Model对象 - 您必须在某个级别处理它们。 There are two ways you can handle this: 有两种方法可以解决这个问题:

  1. Use the ICompilationUnit directly (see farther down) 直接使用ICompilationUnit(参见更远的地方)
  2. Create an Eclipe adapter factory to automate the conversion 创建一个Eclipe适配器工厂以自动执行转换

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. 你可以创建一个适配器工厂(它可以存在于你的主插件或不同的插件中),eclipse可以使用它来自动从ICompilationUnit转换为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. 关于适配器的一些很好的细节在http://www.eclipse.org/resources/resource.php?id=407 ,但我将在这里讨论这个问题的实现。

Dependencies 依赖

The plugin that will host the adapter needs the following dependencies 将托管适配器的插件需要以下依赖项

  • org.eclispe.core.resources org.eclispe.core.resources
  • org.eclipse.jdt.core 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: 在将托管适配器工厂的插件中,将以下内容添加到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. 使用此方法,您可以添加其他适配器以将其他类型转换为IFile,并且您的选择代码无关紧要。


Direct ICompilationUnit Approach 直接ICompilationUnit方法

[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] [编辑:我已经改变了答案,但是将以下内容作为参考信息b / c,这是探索在包浏览器中选择的编译单元内容的标准方法]

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. 您应该使用ICompilationUnit,而不是使用CompilationUnit。 Most of the eclipse APIs use interfaces for public consumption, and classes for internal details. 大多数eclipse API使用接口进行公共消费,使用类来获取内部细节。

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: 要查看检查/修改Java模型和源代码的详细信息:

(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 这显示了如何适当地使用Java模型

To isolate where you reference the java model, you can create an (eclipse) adapter that will convert Java Model objects into files. 要隔离引用java模型的位置,可以创建一个(eclipse)适配器,它将Java Model对象转换为文件。 Assuming such an adapter exists, you can then ask the AdapterManager to convert it to a java file for you. 假设存在这样的适配器,您可以请求AdapterManager将其转换为java文件。 I'll take a peek and see if one exists. 我会先看看是否存在。

That (decoupling Resource from JDT) was one of the goals of E4 (Eclipse 4) . 那(将资源与JDT分离)是E4(Eclipse 4)的目标之一。
The plugin list for REsources doesn't mention JDT anymore (again, Eclipse 4.x only): REsources插件列表不再提及JDT(同样,仅限Eclipse 4.x):

  • org.eclipse.core.filesystem - An abstract, generic file system API, including an implementation of this API for the local file system. org.eclipse.core.filesystem - 一个抽象的通用文件系统API,包括本地文件系统的此API实现。 This is the API through which the resources plugin accesses an underlying file system. 这是资源插件通过其访问底层文件系统的API。
  • org.eclipse.core.resources - Contains the API and implementation of the resource model org.eclipse.core.resources - 包含API和资源模型的实现
  • org.eclipse.core.resources.compatibility - A plug-in providing migration support for users opening old workspaces in Eclipse 3.1 or greater org.eclipse.core.resources.compatibility - 为在Eclipse 3.1或更高版本中打开旧工作区的用户提供迁移支持的插件

A Demo project like e4photo don't require any JDT for accessing IResource from the selection of an IContainer . 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();

It looks like the JDT is already defining an IAdapterFactory for all Java elements including compilation unit ( org.eclipse.jdt.internal.ui.JavaElementAdapterFactory ). 看起来JDT已经为所有Java元素定义了一个IAdapterFactory ,包括编译单元( org.eclipse.jdt.internal.ui.JavaElementAdapterFactory )。 The adapter is defined for IResource rather than IFile so you should be able to do: 适配器是为IResource而不是IFile定义的,所以你应该能够做到:

Object firstElement = treeSelection.getFirstElement();

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM