XText как получить EObjects из другого плагина?

Я начал разработку XText DSL, который теперь имеет два подъязыка, которые ссылаются друг на друга (точнее, A относится к B). У каждого из них есть свои собственные плагины и рабочий процесс генератора.

Соответствующая часть выглядит примерно так:

Язык А:

ARoot:
    'rootOfB:' (foos+=Foo)*;

Foo:
    'foo' name=ID;

Язык Б:

import 'url-of-a' as A

BRoot:
    'rootOfA:' (bars+=Bar)*;

Bar:
    'bar' name=ID 'for' foo=[A::Foo] ;

Теперь я пытаюсь предоставить поставщика области видимости, чтобы в языке B распознавались элементы foo, но я еще не нашел способа получить доступ к проанализированным элементам A. Я провел некоторую отладку, и похоже, что ни параметр foo , ни eReference не имеет какой-либо связи с элементами языка A:

class MyScopeProvider extends AbstractDeclarativeScopeProvider {
    def IScope scope_Bar_foo(Bar bar, EReference eReference){
        // How should i reference and return all the Foo objects here?
    }
}

У элементов Foo также есть поставщик полного имени, так что это не должно быть проблемой, я протестировал его из другой области, все еще работая над плагином A:

class MyQualifiedNameProvider extends DefaultDeclarativeQualifiedNameProvider {
    override qualifiedName(Object o) {
        if (o instanceof Foo) {
            val f = o as Foo
            return QualifiedName.create(f.name)
        }
        super.qualifiedName(o);
    }
}

Итак, у меня вопрос: как мне получить проанализированные объекты EObject в другом плагине?

Пример использования:

Содержимое файла, использующего грамматику A:

rootOfA
    foo firstFoo
    foo secondFoo

Содержимое файла, использующего грамматику B:

rootOfB
    bar firstBar for [i would like reference firstFoo or secondFoo here]

person Balázs Édes    schedule 16.07.2014    source источник
comment
Я попробовал ваши образцы грамматики, и связывание работает, когда ресурсы из языка A и языка B находятся в одном проекте, это ваш случай? Кроме того, если вы нажмете Ctrl + Shift + F3, вы увидите элемент Foo? как они называются?   -  person Fabien Fleureau    schedule 16.07.2014
comment
Нет, проблема в том, что они в разных проектах (плагинах). И из проекта B я пытаюсь получить доступ к некоторым элементам модели, которые находятся в проекте A. Это должно быть возможно, но я пока не нашел способа сделать это. Когда они были в одном проекте (и грамматике), это работало.   -  person Balázs Édes    schedule 16.07.2014


Ответы (1)


Вы должны добавить зависимость к плагину A в манифесте плагина B. Вы также должны добавить зависимость в рабочий процесс mwe2.

См. http://www.eclipse.org/Xtext/documentation.html#grammarMixins для более подробной информации.

Изменить 1

Вы пытаетесь сделать ссылку на другой ресурс. В этой статье объясняются различия между локальной и глобальной областью действия: http://blogs.itemis.de/leipzig/archives/809

ScopeProvider здесь не применяется. Вы должны реализовать свою собственную ResourceDescriptionStrategy для плагина A, чтобы описать, какой EObject вы хотите экспортировать из ресурса A. В вашем ScopeProvider (плагин B) вы должны вызвать delegateGetScope(), чтобы иметь глобальную область (A + B).

Изменить 2

Если вы хотите связать два разных проекта, вы можете использовать следующий стандартный механизм Eclipse:

Щелкните правой кнопкой мыши проект B, откройте Свойства и перейдите в раздел «Справочник по проекту». Вы увидите проект А, вам просто нужно его выбрать.

Когда это будет сделано, очистите ваши два проекта, и ваша ссылка будет в порядке.

Изменить 3

Вот пример пользовательской реализации для ResourceDescriptionStrategy:

public class MyResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy {
    @Override
    public boolean createEObjectDescriptions(EObject eObject,
            IAcceptor<IEObjectDescription> acceptor) {
        if (eObject instanceof Foo) {
            QualifiedName fullyQualifiedName = getQualifiedNameProvider().getFullyQualifiedName(eObject);
            IEObjectDescription ieObjectDescription = EObjectDescription.create(fullyQualifiedName, eObject);
            acceptor.accept(ieObjectDescription);
            return true;
        }
        return super.createEObjectDescriptions(eObject, acceptor);
    }
}

Вы должны связать этот класс в плагине RuntimeModule:

public Class<? extends IDefaultResourceDescriptionStrategy> bindIDefaultResourceDescriptionStrategy() {
    return MyResourceDescriptionStrategy.class;
}

Вот пример реализации ScopeProvider с использованием «глобальной области действия»:

def IScope scope_Bar_foo(Bar bar, EReference eReference){
    return delegateGetScope(bar, eReference);
}

В этом примере он будет искать только в глобальной области. Если вы хотите добавить что-то еще в область, вы должны использовать SimpleScope, который может управлять «родительской областью».

person Fabien Fleureau    schedule 16.07.2014
comment
Я забыл упомянуть, я уже сделал оба. B зависит от A, и A присутствует в рабочем процессе B. Я почти уверен, что моя конфигурация верна и была правильной. Я ищу то, как я могу получить доступ к модели ECore A в плагине B. Какой класс предоставит проанализированную модель A (которая мне нужна в поставщике области B)? Я посмотрел на ECoreUtil и ECoreUtil2, но не уверен, насколько уместно (и возможно) получить доступ к корневой модели A. Посмотрите на MyScopeProvider в моем вопросе и прокомментированную часть, пожалуйста! - person Balázs Édes; 16.07.2014
comment
ScopeProvider используется только для локальной области (внутри того же ресурса), если вы хотите сослаться на другой ресурс, вариант использования — глобальная область. - person Fabien Fleureau; 16.07.2014
comment
Я никогда не использовал/не видел его. Не могли бы вы привести пример того, как я могу ссылаться в Bar.foo на все объекты Foo (которые, как вы можете видеть, являются частью другой грамматики, на которую ссылаются)? - person Balázs Édes; 16.07.2014
comment
Я не понимаю ваш вариант использования, можете ли вы привести пример файлов для языка A и языка B? А скажите, что именно вы пытаетесь решить? - person Fabien Fleureau; 16.07.2014
comment
Добавил пример в вопрос. Спасибо, что нашли время и попытались помочь :) - person Balázs Édes; 16.07.2014
comment
Если ресурсы находятся в разных проектах, вам нужно добавить видимость из одного проекта в другой вручную: см. мое редактирование 2. - person Fabien Fleureau; 17.07.2014
comment
Спасибо, я изучаю это. - person Balázs Édes; 17.07.2014
comment
Итак, я рассмотрел это, не могли бы вы привести пример (или ссылку на пример) того, что такое ResourceDescriptionStrategy, и как мне использовать делегированную область? Я действительно ничего не нашел (в моей версии xtext даже нет класса с именем ResourceDescriptionStrategy). Кстати, я прочитал сообщение в блоге на itemis, это было действительно полезно, чтобы понять, что происходит. - person Balázs Édes; 17.07.2014
comment
См. мой Редактировать 3. Позвольте мне сейчас, если у вас есть еще вопросы. - person Fabien Fleureau; 18.07.2014
comment
Это было очень полезно, мне еще есть над чем работать, но я думаю, что вы направили меня на правильный путь! Благодарю вас! - person Balázs Édes; 18.07.2014