Как выделить перекрестную ссылку 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. С другой стороны, EReferences модели Ecore говорят мне, является ли цель ConstDecl или VarDecl, но там я не могу найти местоположение источника MATHSYMBOL.

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

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


person MarnixKlooster ReinstateMonica    schedule 26.10.2015    source источник


Ответы (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);
                    }
                }
            }
        }


    }

}
person Christian Dietrich    schedule 17.11.2015