Я пытаюсь получить сведения о структурированном выборе пользователя 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, который является внутренним и слишком специфичным для того, что я хочу.
В идеале я хочу иметь возможность получить базовое имя файла, тип и содержимое, не полагаясь на:
- Внутренний API
- Код модуля компиляции JDT.
Это позволит мне получить свойства универсального файла, когда пользователь щелкнет правой кнопкой мыши файл в представлении навигатора.
Может ли кто-нибудь дать мне какие-либо указания о том, как мне это сделать, пожалуйста?
Ответ 1 · рейтинг 9 · Scott Stanchfield
[РЕДАКТИРОВАТЬ: я добавил следующую альтернативу - исходный ответ - отец вниз]
Во-первых: если вы выберете что-то в проводнике пакетов, все выбранные элементы будут объектами модели Java - вам придется иметь дело с ними на каком-то уровне. Есть два способа справиться с этим:
- Используйте ICompilationUnit напрямую (см. ниже)
- Создайте фабрику адаптеров 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-файл для вас. Я загляну и посмотрю, существует ли он.