如何针对不同类型的目标以不同方式突出显示 Xtext 交叉引用?
How to highlight an Xtext cross-reference differently for targets of different types?
我有一个 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 from current commit 328a5e7 of https://github.com/marnix/metamath-eclipse-xtext/。)
我的问题: 如何通过对常量和变量使用不同的颜色来突出显示 EssentialHypothesisStatement
中的 symbols
?因此,如果 MATHSYMBOL
指的是 ConstDecl
,那么它应该以一种方式突出显示,而 VarDecl
.
则应以其他方式突出显示
我已经尝试以各种方式创建 ISemanticHighlightingCalculator
,但我似乎无法检测到实际的引用类型是什么,无论是通过节点模型还是通过 Ecore 模型。一方面,与语法相关的方法只告诉我引用指向 Decl
。另一方面,Ecore 模型的 EReference
s 告诉我目标是 ConstDecl
还是 VarDecl
,但我找不到源 MATHSYMBOL
的位置].
请注意,我更喜欢使用节点模型(而不是 Ecore 模型),因为我还想突出显示评论,并且出于性能原因,我无法承受对文档进行多次传递。
什么是 good/canonical/efficient/simple 实现此目的的方法?
从 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);
}
}
}
}
}
}
我有一个 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 from current commit 328a5e7 of https://github.com/marnix/metamath-eclipse-xtext/。)
我的问题: 如何通过对常量和变量使用不同的颜色来突出显示 EssentialHypothesisStatement
中的 symbols
?因此,如果 MATHSYMBOL
指的是 ConstDecl
,那么它应该以一种方式突出显示,而 VarDecl
.
我已经尝试以各种方式创建 ISemanticHighlightingCalculator
,但我似乎无法检测到实际的引用类型是什么,无论是通过节点模型还是通过 Ecore 模型。一方面,与语法相关的方法只告诉我引用指向 Decl
。另一方面,Ecore 模型的 EReference
s 告诉我目标是 ConstDecl
还是 VarDecl
,但我找不到源 MATHSYMBOL
的位置].
请注意,我更喜欢使用节点模型(而不是 Ecore 模型),因为我还想突出显示评论,并且出于性能原因,我无法承受对文档进行多次传递。
什么是 good/canonical/efficient/simple 实现此目的的方法?
从 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);
}
}
}
}
}
}