Статьи

Связывание редакторов Xtext с именами файлов, а не с расширениями файлов

В настоящее время я работаю над Xtext- редактором для языка BUILD от Google, как описано в нашем блоге Google Engineering . Файлы BUILD не содержат расширения, они просто называются «BUILD». Это соглашение об именах делает работу с Xtext довольно сложной. Мне нужно было изменить поведение Xtext по умолчанию: вместо того, чтобы связывать редакторы Xtext с расширениями файлов, мне нужно было связывать их с именами файлов. В этом посте я описываю, как мне это удалось.

В этом посте я буду использовать совершенно новый проект Xtext. Для простоты я буду использовать расширение файла по умолчанию (mydsl) и грамматику. Вы можете получить исходный код этого поста из Xtext Samples , нового проекта с открытым исходным кодом, где я планирую хранить код, который я использую в постах, связанных с Xtext. Весь код выпущен в соответствии с Eclipse Public License (EPL) 1.0 .

Следующие шаги предполагают, что мы собираемся связать наш редактор Xtext с именем файла «MyDsl».

  1. Измените XtextEditor плагина, чтобы он понимал имена файлов, а не расширения файлов.
  2. Создайте ContentHandler, который описывает содержимое файлов с именем «MyDsl». В рамках этого шага нам нужно создать новый тип контента для файлов «MyDsl».
  3. Создайте IResourceServiceProvider, который предоставляет сервисы (например, валидацию, описание контента, кодировку) для файлов с именем «MyDsl».
  4. Зарегистрируйте классы, созданные на предыдущих шагах, чтобы сделать их видимыми для EMF и Xtext.

1. Измените XtextEditor плагина, чтобы он понимал имена файлов

Это самый простой из всех шагов:

  1. Откройте файл plugin.xml в проекте «ui».
  2. Выберите вкладку «plugin.xml» в нижней части редактора, чтобы напрямую редактировать код XML.
  3. В элементе редактора замените extensions = «mydsl» на filenames = «MyDsl»

2. Создайте ContentHandler, который описывает содержимое файлов с именем «MyDsl»

Вот упрощенная версия нашего ContentHandler. Вы можете найти полный файл здесь .

public class MyDslContentHandler extends ContentHandlerImpl {
  public static final String MY_DSL_FILE_CONTENT_TYPE = "com.google.eclipse.MyDsl";
 
  @Override public boolean canHandle(URI uri) {
    return isMyDslFile(uri);
  }
 
  @Override public Map<String, Object> contentDescription(URI uri, InputStream inputStream,
      Map<?, ?> options, Map context) throws IOException {
    Map<String, Object> description = super.contentDescription(uri, inputStream, options, context);
    if (canHandle(uri)) {
      description.put(VALIDITY_PROPERTY, VALID);
      description.put(CONTENT_TYPE_PROPERTY, MY_DSL_FILE_CONTENT_TYPE);
    }
    return description;
  }
}

Строка 2: мы определяем новый тип контента для файлов «MyDsl». Мы держим постоянную публику, так как мы будем использовать это позже.
Строка 4: мы указываем, что имена файлов с именем «MyDsl» могут обрабатываться ContentHandler. Мы вызываем служебный метод isMyDslFile (URI) из URI класса .
Строка 8: мы объявляем содержимое файлов «MyDsl» как допустимое и сопоставляем его тип с типом, определенным в строке 2.

3. Создайте IResourceServiceProvider, который предоставляет сервисы для файлов с именем «MyDsl»

Вот упрощенная версия нашего IResourceServiceProvider. Вы можете найти полный файл здесь .

public class MyDslResourceServiceProvider extends DefaultResourceServiceProvider {
  @Override public boolean canHandle(URI uri) {
    return isMyDslFile(uri);
  }
}

Мы вызываем служебный метод isMyDslFile (URI) из URI класса, чтобы указать, что этот IResourceServiceProvider может обрабатывать файлы с именами «MyDsl».

4. Зарегистрируйте классы, созданные на предыдущих шагах, чтобы сделать их видимыми для EMF и Xtext.

Теперь пришло время соединить все вместе. Сначала мы связываем IResourceServiceProvider с нашим MyDslResourceServiceProvider в модуле времени выполнения плагина :

 public Class<? extends IResourceServiceProvider> bindIResourceServiceProvider() {
    return MyDslResourceServiceProvider.class;
  }

Теперь мы говорим Xtext и EMF в конструкторе MyDslUiModule , чтобы они понимали файлы с именем «MyDsl».

public class MyDslUiModule extends AbstractMyDslUiModule {
 
  public MyDslUiModule(AbstractUIPlugin plugin) {
    super(plugin);
    configureXtextToWorkWithFileNames(new InjectorProvider());
  }
}

Мы передаем InjectorProvider, который получает Injector плагина только в тот момент, когда это необходимо. На данный момент мы не можем передать Инжектор напрямую, так как он не был полностью создан при вызове configureXtextToWorkWithFileNames.

Метод configureXtextToWorkWithFileNames (InjectorProvider) определен в XtextSetup :

final class XtextSetup {
 
  static void configureXtextToWorkWithFileNames(InjectorProvider injectorProvider) {
    register(new MyDslContentHandler());
    register(new ResourceFactoryDescriptor(injectorProvider));
    register(new ResourceServiceProvider(injectorProvider));
  }
 
  private static void register(ContentHandler h) {
    ContentHandler.Registry registry = ContentHandler.Registry.INSTANCE;
    registry.put(HIGH_PRIORITY, h);
  }
 
  private static void register(Resource.Factory.Descriptor d) {
    Resource.Factory.Registry registry = Resource.Factory.Registry.INSTANCE;
    registry.getContentTypeToFactoryMap().put(MY_DSL_FILE_CONTENT_TYPE, d);
  }
 
  private static void register(Provider<IResourceServiceProvider> p) {
    IResourceServiceProvider.Registry registry = IResourceServiceProvider.Registry.INSTANCE;
    registry.getContentTypeToFactoryMap().put(MY_DSL_FILE_CONTENT_TYPE, p);
  }
}

Строка 4: мы регистрируем ContentHandler, который мы создали на шаге 2.
Строка 5: мы связываем IResourceFactory в модуле Guice плагина с типом контента, определенным на шаге 2.
Строка 6: мы связываем IResourceServiceProvider, который мы создали на шаге 3 (и позже зарегистрирован в модуле Guice плагина) с типом контента, определенным на шаге 2.

Тестирование редактора

Чтобы запустить редактор, щелкните правой кнопкой мыши любой из проектов и выберите «Запуск от имени»> «Приложение Eclipse» из контекстного меню.

Вот скриншот редактора, открывающего файл с именем «MyDsl»

Резюме

В этом посте я показал, как заставить Xtext понимать имена файлов в четыре простых шага. Вы можете найти код для этого поста в проекте Xtext Samples . Вы можете оформить заказ , просмотреть его или загрузить .

Несмотря на то, что я потратил много времени на чтение кода Xtext и EMF, чтобы понять это, я не могу утверждать, что мое решение является лучшим. Пожалуйста, дайте мне знать, если вы знаете лучший способ сделать то, что я описал в этом посте ?

Обратная связь всегда приветствуется.

 

С http://alexruiz.developerblogs.com/?p=2080