Как по-разному выделить перекрестную ссылку Xtext для целей разных типов?

У меня есть грамматика Xtext, которая читает (частично):

grammar mm.ecxt.MMLanguage hidden(WS, COMMENT)

import "http://www.eclipse.org/emf/2002/Ecore" as ecore

...

Statement:
    ConstantStatement |
    VariableStatement |
    LabeledStatement |
    ...

LabeledStatement:
    EssentialHypothesisStatement |
    ...

ConstantStatement:
    DOLLAR_C (constants+=ConstDecl)+ DOLLAR_DOT;

VariableStatement:
    DOLLAR_V (variables+=VarDecl)+ DOLLAR_DOT;

EssentialHypothesisStatement:
    name=LABEL DOLLAR_E (symbols+=[Decl|MATHSYMBOL])+ DOLLAR_DOT;

Decl: ConstDecl | VarDecl;

ConstDecl returns ConstDecl: name=MATHSYMBOL;

VarDecl returns VarDecl: name=MATHSYMBOL;

MATHSYMBOL: PARENOPEN | PARENCLOSE | QUESTIONMARK | COMPRESSED | TLABEL | WORD;
...

(Полная грамматика - MMLanguage.xtext из текущего коммита 328a5e7 по https://github.com/marnix/metamath-eclipse-xtext/.)

Мой вопрос: как мне выделить symbols в EssentialHypothesisStatement, используя другой цвет для констант и переменных? Так что если MATHSYMBOL относится к ConstDecl, то это должно быть выделено в одну сторону, а другой - для VarDecl,

Я пытался создать ISemanticHighlightingCalculator разными способами, но я не могу определить, что такое реальный эталонный тип, ни через модель узла, ни через модель Ecore. С одной стороны, связанные с грамматикой методы только говорят мне, что ссылка идет на Decl, С другой стороны, модель Ecore EReferenceСкажите мне, является ли цель ConstDecl или VarDecl, но там я не могу найти местоположение источника MATHSYMBOL,

Обратите внимание, что я предпочитаю использовать модель узла (в отличие от модели Ecore), так как я также хочу выделить комментарии, и по соображениям производительности я не могу позволить несколько проходов по документу.

Каков хороший / канонический / эффективный / простой способ добиться этого?

1 ответ

Решение

С точки зрения EObject взгляните на org.eclipse.xtext.nodemodel.util.NodeModelUtils.findNodesForFeature(EObject, EStructuralFeature) с точки зрения модели узла, которую вы можете использовать EObjectAtOffsetHelper

образец грамматики

Model:
    defs+=Def*
    uses+=Use*
    ;

Def:
    ADef | BDef;

ADef:
    "adef" name=ID
;

BDef: 
    "bdef" name=ID
;

Use:
    "use" def=[Def]
;

И здесь Импл

public class MyDslSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {

    @Inject
    private MyDslGrammarAccess ga;

    @Inject
    private EObjectAtOffsetHelper helper;

    @Override
    public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor accoptor, CancelIndicator cancelIndicator) {
        if (resource == null)
            return;
        IParseResult parseResult = resource.getParseResult();
        if (parseResult == null || parseResult.getRootNode() == null)
            return;
        BidiTreeIterable<INode> tree = parseResult.getRootNode().getAsTreeIterable();
        for (INode node : tree) {
            if (cancelIndicator.isCanceled()) {
                return;
            }
            if (node.getGrammarElement() instanceof CrossReference) {
                if (ga.getUseAccess().getDefDefCrossReference_1_0() == node.getGrammarElement()) {
                    EObject target = helper.resolveElementAt(resource, node.getOffset());
                    if (target instanceof ADef) {
                        accoptor.addPosition(node.getOffset(), node.getLength(), HighlightingStyles.COMMENT_ID);
                    } else if (target instanceof BDef) {
                        accoptor.addPosition(node.getOffset(), node.getLength(), HighlightingStyles.STRING_ID);
                    }
                }
            }
        }


    }

}
Другие вопросы по тегам