1

I have an Xtext grammar which reads (in part):

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;
...

(The full grammar is MMLanguage.xtext from current commit 328a5e7 of https://github.com/marnix/metamath-eclipse-xtext/.)

My question: How do I highlight the symbols in an EssentialHypothesisStatement, by using a different color for constants and variables? So if the MATHSYMBOL refers to a ConstDecl, then it should be highlighted one way, and some other way for a VarDecl.

I've tried to create an ISemanticHighlightingCalculator in all kinds of ways, but I can't seem to detect what the actual reference type is, neither through the node model nor through the Ecore model. On the one hand, the grammar-related methods only tell me that the reference goes to a Decl. On the other hand, the Ecore model's EReferences tell me whether the target is a ConstDecl or a VarDecl, but there I can't find the location of the source MATHSYMBOL.

Note that I prefer to use the node model (as opposed to the Ecore model) since I also want to highlight comments, and for performance reasons I cannot afford multiple passes over the document.

What is a good/canonical/efficient/simple way to achieve this?

4

1 回答 1

0

从 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]
;

这里是Impl

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);
                    }
                }
            }
        }


    }

}
于 2015-11-17T06:44:41.580 回答