Eclipse PDE, Navigator View, TreeSelection — Получение типа и имени файла

Я пытаюсь получить сведения о структурированном выборе пользователя 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());
   }            
}

Проблема в том, что в настоящее время он связан с API модуля компиляции JDT, который является внутренним и слишком специфичным для того, что я хочу.

В идеале я хочу иметь возможность получить базовое имя файла, тип и содержимое, не полагаясь на:

  1. Внутренний API
  2. Код модуля компиляции JDT.

Это позволит мне получить свойства универсального файла, когда пользователь щелкнет правой кнопкой мыши файл в представлении навигатора.

Может ли кто-нибудь дать мне какие-либо указания о том, как мне это сделать, пожалуйста?


person Jon    schedule 22.04.2009    source источник
comment
Возможно ли это сделать без зависимости от JDT? Есть ли обновления по состоянию на январь 2014?   -  person Paul Verest    schedule 26.01.2014


Ответы (4)


[РЕДАКТИРОВАТЬ: я добавил следующую альтернативу - исходный ответ - отец вниз]

Во-первых: если вы выберете что-то в проводнике пакетов, все выбранные элементы будут объектами модели Java — вам придется иметь дело с ними на каком-то уровне. Есть два способа справиться с этим:

  1. Используйте ICompilationUnit напрямую (см. ниже)
  2. Создайте фабрику адаптеров Eclipe для автоматизации преобразования

Заводской подход к адаптерам

Вы можете создать фабрику адаптеров (которая может находиться в вашем основном плагине или в другом), которую 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

[EDIT: я изменил ответ, но оставил следующую информацию в качестве справочной информации, потому что это стандартный способ изучения содержимого единицы компиляции, которая была выбрана в проводнике пакетов]

На самом деле это предпочтительный способ получить содержимое файла в проводнике пакетов...

Вместо использования CompilationUnit следует использовать ICompilationUnit. Большинство API-интерфейсов eclipse используют интерфейсы для общего пользования и классы для внутренних деталей.

Если вы измените свой код на

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-файл для вас. Я загляну и посмотрю, существует ли он.

person Scott Stanchfield    schedule 22.04.2009
comment
Конечно, но: Этот интерфейс не предназначен для реализации клиентами. - person Jon; 22.04.2009
comment
Вы не реализуете это; вы используете его как дескриптор реализации. Это предполагаемое использование. Посетите страницу документа (и, пожалуйста, удалите отрицательный голос!) - person Scott Stanchfield; 22.04.2009
comment
И это в любом случае мне не помогает, так как он все еще привязан к JDT, я искал свойства общего файла в соответствии с вопросом, пожалуйста, внимательно прочитайте его - все равно спасибо. - person Jon; 23.04.2009
comment
Если вы выбираете что-то в проводнике пакетов, это является ICompilationUnit. Вы не можете обойти это. Если вы хотите получить из него IFile, вы можете вызвать unit.getResource(), но зачем его конвертировать, если в этом нет необходимости. Я даю вам правильный ответ для контекста, в котором вы находитесь. Если вы делаете выбор в другом типе просмотра (не проводнике пакетов), вы можете получить что-то еще в качестве выбора. См. основное руководство JDT выше для структуры навигации. - person Scott Stanchfield; 23.04.2009
comment
И ICompilationUnit — это правильный способ доступа к нему. В документах API говорится, что клиенты не должны реализовать его, так как в общедоступном классе Foo реализует ICompilationUnit. - person Scott Stanchfield; 23.04.2009
comment
Прочитай вопрос! В идеале я хочу иметь возможность получить базовое имя файла, тип и содержимое, не полагаясь на: 1. Внутренний API 2. Код модуля компиляции JDT. - person Jon; 24.04.2009
comment
Код в вашем вопросе относится к CompilationUnit. Это говорит мне, что вы делаете выбор из проводника пакетов. Проводник пакетов представляет файлы Java как ICompilationUnits. ICompilationUnit не является внутренним — это правильный дескриптор для ссылки на java-файлы, выбранные из проводника пакетов. Вы не можете ссылаться на выбор как на что-то другое. - person Scott Stanchfield; 24.04.2009
comment
Позвольте мне спросить: чего вы пытаетесь достичь? Почему вы хотите избежать ICompilationUnit? (Вы правы, желая избежать CompilationUnit - он является внутренним) - person Scott Stanchfield; 24.04.2009
comment
Я пытаюсь избежать ICompilationUnit и CompilationUnit, потому что мне нужен ОБЩИЙ способ получения содержимого файла, имени файла и типа файла. Это может быть не файл Java или любой другой тип языка, если на то пошло, это может быть текстовый файл, это может быть файл обезьяны, это может быть файл барсука. В любом случае, мне нужны метаданные об этом файле и его содержимом. - person Jon; 29.04.2009
comment
Это зависит от того, в каком контексте вы выбираете вещи. Если вы выбираете элементы в проводнике пакетов, вам приходится иметь дело с моделью Java — от этого никуда не деться. Если вы выбираете элементы в другом представлении, это зависит от того, что показывает это представление. - person Scott Stanchfield; 29.04.2009
comment
Я обновил свой ответ, чтобы рассказать о том, как зарегистрировать адаптеры для выбора. Обратите внимание, что вам потребуется зарегистрировать адаптеры для каждого типа объекта выбора. - person Scott Stanchfield; 29.04.2009

Это (отделение Resource от 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 для доступ к IResource из выбора 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();
person VonC    schedule 26.01.2014

Чего вы пытаетесь достичь? Вы хотите получить содержимое файла? Тогда вы можете попробовать:

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

IFile file = (IFile) firstElement.getAdapter(IFile.class);
if (file != null && file.isAccessible()) {
    // Use getContents API
    ....
}
person Eugene    schedule 22.04.2009
comment
В идеале я хочу иметь возможность получить базовое имя файла, тип и содержимое. - person Jon; 23.04.2009
comment
это не будет работать, если адаптер не был зарегистрирован для преобразования выбора в IFile - см. мой ответ ниже, как это сделать - person Scott Stanchfield; 29.04.2009

Похоже, JDT уже определяет IAdapterFactory для всех элементов Java, включая модуль компиляции (org.eclipse.jdt.internal.ui.JavaElementAdapterFactory). Адаптер определен для IResource, а не IFile, поэтому вы сможете сделать:

Object firstElement = treeSelection.getFirstElement();

IResource resource = (IResource)Platform.getAdapterManager().getAdapter(firstElement, IResource.class);
person greg-449    schedule 28.01.2014