Xtext проблема ссылки на грамматику A из валидатора грамматики B - PullRequest
0 голосов
/ 03 сентября 2018

В Xtext, как мне следовать ссылке из грамматики B в грамматику A в рамках валидатора грамматики B (который есть в плагине ui)? Рассмотрим следующий пример.

Грамматика А это org.xtext.people.People

grammar org.xtext.people.People with org.eclipse.xtext.common.Terminals

generate people "http://www.xtext.org/people/People"

People:
    people+=Person*;

Person:
    'person' name=ID ';';

и экземпляр

person Alice {citizenship "MN"; id "12345"; }
person Bob {citizenship "CH"; id "54321";}
person Malice {citizenship "XXX"; id "66666"; }

В аэропорту записываются записи людей.

enter Alice;
enter Bob;
enter Malice; 

Записи моделируются второй грамматикой B org.xtext.entries.Entries

grammar org.xtext.entries.Entries with org.eclipse.xtext.common.Terminals

generate entries "http://www.xtext.org/entries/Entries"
import "http://www.xtext.org/people/People"

Entries:
    entries+=Entry*;

Entry:
    'enter' person=[Person] ';';

Убедившись, что у проекта Eclipse org.xtext.entries есть проект org.xtext.people на своем пути к классам, и убедившись, что плагин org.xtext.entries имеет org.xtext.people в качестве зависимости, все работает должным образом.

Существует запрет на поездки людей из страны XXX, хотя некоторые достойные люди исключены. Только ЦРУ знает, кто исключен из бана. Записи не должны быть разрешены для людей из XXX, если не исключено.

Обновленная грамматика

grammar org.xtext.entries.Entries with org.eclipse.xtext.common.Terminals

generate entries "http://www.xtext.org/entries/Entries"


import "http://www.xtext.org/people/People"

Entries:
    entries+=Entry*;

Entry:
    travelBanOverride=TravelBanOverride?
    'enter' person=[Person] ';';

TravelBanOverride: '@TravelBanOverride' '(' code=STRING ')';

с валидатором

package org.xtext.entries.validation

import org.eclipse.xtext.validation.Check
import org.xtext.entries.entries.EntriesPackage
import org.xtext.entries.entries.Entry
import org.xtext.entries.CIA

class EntriesValidator extends AbstractEntriesValidator {

    public static val BAN = 'BAN'
    public static val ILLEGAL_OVERRIDE = 'ILLEGAL_OVERRIDE'

    @Check
    def checkBan(Entry entry) {
        if (entry.person.citizenship == "XXX") {
            if (entry.travelBanOverride === null) {
                error('Violation of Travel Ban', EntriesPackage.Literals.ENTRY__PERSON, BAN)
            } 
            else {
                val overridecode = entry.travelBanOverride.code;
                val valid = CIA.valid(entry.person.name, entry.person.id, overridecode)
                if (!valid) {
                    error('Illegal override code', EntriesPackage.Literals.ENTRY__TRAVEL_BAN_OVERRIDE, ILLEGAL_OVERRIDE)
                }
            }

        }

    }

}

, где драйвер для внешнего веб-приложения CIA моделируется, например,

package org.xtext.entries;

public class CIA {


    public static boolean valid(String name, String id, String overrideCode) {
        System.out.println("UNValid["+name+","+overrideCode+"]");
        return name.equals("Malice") && id.equals("66666") && overrideCode.equals("123");
    }

}

Проверки работают как положено.

Теперь я хочу предоставить быстрое исправление для BAN, которое проверяет код переопределения от ЦРУ.

package org.xtext.entries.ui.quickfix

import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider
import org.eclipse.xtext.ui.editor.quickfix.Fix
import org.xtext.entries.validation.EntriesValidator
import org.eclipse.xtext.validation.Issue
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
import org.xtext.entries.entries.Entry
import org.xtext.entries.Helper

class EntriesQuickfixProvider extends DefaultQuickfixProvider {

    @Fix(EntriesValidator.BAN)
    def tryOverride(Issue issue, IssueResolutionAcceptor acceptor) {
        acceptor.accept(issue, 'Try override', 'Override if CIA says so.', 'override.png') 
        [element ,context |
            val entry = element as Entry
            // val person = entry.person // no such attribute
             //val person = Helper.get(entry); // The method get(Entry) from the type Helper refers to the missing type Object
        ]
    }
}

Первая закомментированная строка не компилируется: атрибута нет person. Вторая закомментированная строка - это попытка решить проблему путем получения вспомогательного класса в org.xtext.entries для получения человека, но это также не компилируется, давая "Метод get (Entry) из типа Helper, к которому относится отсутствует тип объекта " сообщение об ошибке.

Для полноты, вот этот помощник.

package org.xtext.entries

import org.xtext.people.people.Person
import org.xtext.entries.entries.Entry

class Helper {

    static def Person get(Entry entry) {
        return entry.person;
    }

}

Далее, entry.travelBanOverride компилируется нормально, а entry.person - нет. Нажатие на Entry в Eclipse приводит к переходу к ожидаемому коду, который имеет как travelBanOverride, так и person.

.

Проблема не возникает с классом Java в том же проекте и пакете.

package org.xtext.entries.ui.quickfix;

import org.xtext.entries.entries.Entry;
import org.xtext.people.people.Person;

public class Test {

    public static void main(String[] args) {
        Entry entry = null;
        Person p = entry.getPerson();
    }
}

Переписывание быстрого исправления в Java решает проблему.

package org.xtext.entries.ui.quickfix;

import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider;
import org.eclipse.xtext.ui.editor.quickfix.Fix;
import org.xtext.entries.validation.EntriesValidator;
import org.eclipse.xtext.validation.Issue;
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor;
import org.xtext.entries.entries.Entry;
import org.xtext.entries.Helper;
import org.eclipse.xtext.ui.editor.model.edit.IModificationContext;
import org.eclipse.xtext.ui.editor.model.edit.ISemanticModification;
import org.eclipse.emf.ecore.EObject;
import org.xtext.entries.entries.Entry;
import org.xtext.people.people.Person;

public class EntriesQuickfixProvider extends DefaultQuickfixProvider {



@Fix(EntriesValidator.BAN)
    public void tryOverride(final Issue issue, IssueResolutionAcceptor acceptor) {
        acceptor.accept(issue,
            "Try to override", 
            "Override",
            "override.gif", 
            new ISemanticModification() {
                public void apply(EObject element, IModificationContext context) {
                    Entry entry = (Entry) element;
                    System.out.println(entry.getPerson());
                }
            }
        );
}

}
  • Как мне следовать ссылке из грамматики B (Записи) на грамматику A (Люди) в рамках валидатора грамматики B?

1 Ответ

0 голосов
/ 07 сентября 2018

Моя ошибка в следующем.

Убедившись, что проект Eclipse org.xtext.entries имеет проект org.xtext.people на его classpath и обеспечение того, чтобы Плагин org.xtext.entries имеет org.xtext.people в качестве зависимости, все работает как положено.

Плагин org.xtext.entries.ui ui должен также иметь org.xtext.people на своем пути сборки Java (проект Eclipse). Экспортировать и сделать плагин-зависимость его недостаточно.

Обратите внимание, что этот параметр должен быть установлен заранее, до создания быстрого исправления, поскольку редактор Xtend имеет проблемы с обновлением.

...