Простая инструкция импорта в XText
Я хочу добавить некоторые объекты из другого файла в XText в область видимости. Чтобы проиллюстрировать то, что мне нужно, у меня есть такая игрушечная грамматика:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
(imports += Import)*
(classes += ClassDef )*;
Import:
'import' filename += STRING;
ClassDef:
'class' name=ID ('extends' extends=[ClassDef])?;
Предположим, я хочу иметь возможность расширять только те классы, которые определены до данного класса, и только те, которые начинаются с той же первой буквы, что и определяемый класс.
Рекомендуемый способ сделать это-черезопределение области . Вот поставщик области, который делает это в пределах одного файла:
package org.xtext.example.mydsl.scoping
import ....
class MyDslScopeProvider extends AbstractMyDslScopeProvider {
override getScope(EObject context, EReference reference){
if(reference == MyDslPackage.Literals.CLASS_DEF__EXTENDS){
if(! (context instanceof ClassDef) ) {return IScope.NULLSCOPE }
val root = (context as ClassDef).getRootContainer
val classes = root.getAllContentsOfType(ClassDef)
val before = classes.subList(0, classes.indexOf(context))
val fstLetter = (context as ClassDef).name.charAt(0)
val haveSame1stLetter = before.filter[name.charAt(0) == fstLetter]
return Scopes::scopeFor(haveSame1stLetter)
}
}
}
Я хочу получить доступ к объявлениям классов из импортированных файлов можно следующим образом:
// --- c ---
class Xlib
class Xextend extends Xlib
// --- main.mydsl ---
import "lib.mydsl"
class A
class Xmain extends Xlib
Я нашел несколько противоречивых предложений об использовании importURI вещи, но это, кажется, не работает для меня и кажется устаревшим способом делать вещи сейчас.
В документации упоминается, что для перекрестных ссылок на ресурсы мне, вероятно, нужно:
- создайте экземпляр
IGlobalScopeProvider, - экспорт элементов в составе
IResourceDescription
- преобразование между
QualifiedNameи его строкой представление - реализовать и связать мои собственные
IDefaultResourceDescriptionStrategy
- получить
IContainerизIContainer.Manager - получить
IResourceDescriptions(обратите внимание на форму множественного числа) изIContainer
... и еще много других вещей. К сожалению, они не складываются в целостную картину того, что я должен сделать для достижения желаемого поведения.
Edit: следуя предложению Свена, я придумал решение. Если кто-то заинтересован-я разместил код в этой gist.
2 ответов:
Существуют приличные реализации по умолчанию для всех упомянутых вами сервисов, поэтому вам не нужно их реализовывать, если вы не хотите изменить способ их работы.
Действительно не рекомендуется использовать механизм importUri, но вместо этого вы должны использовать ссылку на основе имени, которая является более надежной.
Xtext автоматически поддерживает для вас индекс, содержащий глобально видимые полные имена. Есть две стороны индекса:
1. Вклад в развитие Индекс
Во время индексирования ResourceDescriptionManager запрашивает именованные элементы. Реализация по умолчанию будет включать любые элементы, имеющие имя свойства. Если вы хотите изменить это поведение, вы можете подклассировать
DefaultResourceDescriptionStrategyи переопределитьcreateEObjectDesciptions. Например, вы можете экспортировать корневой элемент вашей модели, используя простое имя ресурса, чтобы разрешитьImport : 'import' referencedModel+=[Model|STRING] ;Это позволит только импортировать файлы, если вы хотите поддерживать импорт файлов из разных папок, я бы рекомендуем использовать пространства имен.
namespace foo; type Bar {}Другой файл
import foo.Bar type Foo extends Bar2. Использование индекса
Поставщик области автоматически делегирует функции GlobalScopeProvider, который будет предоставлять описания из индекса. Поэтому, если вы убедитесь, что элементы индексируются правильно (см.) они автоматически попадут в область действия провайдера.
Привет, я действительно не могу вас понять. Либо вы просто используете Import Uri, хотя это не рекомендуется https://www.eclipse.org/forums/index.php?t=msg&th=1078818&goto=1736351msg_1736351 или вы используете область на основе пространства имен (не знаю, хотите ли вы поддерживать относительный импорт или причудливые схемы Uri), адаптируя поставщик имен (дайте элементу имя.elementname) и importednamespaceawarelocalscopeprovider (превратить Import xxx в Import xxx.*)
Не могли бы вы дать больше подсказок на ваши требования
Comments