我是在Xtext中开发DSL的新手。我想添加一个突出代码块匹配开始和结束的功能。在我的语言中,每个函数必须以'begin'开头,以'end'结束,并且if条件和循环都是如此。当光标在'begin'时,我需要突出显示匹配/对应的'end'。例如下面,当光标位于第二个'begin'时,我需要突出显示相应的第一个'end':
function X
begin
if a>b
begin
a=b;
end
end
请帮忙吗?
由于
答案 0 :(得分:1)
我认为对此的支持非常好。如果您可以使用次要解决方案,您可以尝试以下
语法
Model:
greetings+=Greeting*;
Greeting:
'if' name=ID 'endif';
在UiModule中
@Override
public ICharacterPairMatcher bindICharacterPairMatcher() {
return new MyDslCharacterPairMatcher(new char[] { '(', ')', '{', '}', '[', ']' });
}
与
public class MyDslCharacterPairMatcher extends DefaultCharacterPairMatcher {
public MyDslCharacterPairMatcher(char[] chars) {
super(chars);
}
@Override
public IRegion match(IDocument document, int offset, int length) {
if (document instanceof IXtextDocument) {
IXtextDocument xtextDocument = (IXtextDocument)document;
IRegion result = xtextDocument.readOnly(new IUnitOfWork<IRegion, XtextResource>() {
@Override
public IRegion exec(XtextResource state) throws Exception {
MyDslGrammarAccess ga = state.getResourceServiceProvider().get(MyDslGrammarAccess.class);
ICompositeNode root = state.getParseResult().getRootNode();
ILeafNode matchNode = NodeModelUtils.findLeafNodeAtOffset(root, offset);
EObject object = NodeModelUtils.findActualSemanticObjectFor(matchNode);
if (object instanceof Greeting) {
Greeting g = (Greeting)object;
if (matchNode.getGrammarElement() == ga.getGreetingAccess().getIfKeyword_0()) {
ICompositeNode objectNode = NodeModelUtils.findActualNodeFor(object);
for (INode n : objectNode.getAsTreeIterable()) {
if (n.getGrammarElement() != null && n.getGrammarElement() == ga.getGreetingAccess().getEndifKeyword_2()) {
return new Region(n.getOffset(), n.getLength());
}
}
}
if (matchNode.getGrammarElement() == ga.getGreetingAccess().getEndifKeyword_2()) {
ICompositeNode objectNode = NodeModelUtils.findActualNodeFor(object);
for (INode n : objectNode.getAsTreeIterable()) {
if (n.getGrammarElement() != null && n.getGrammarElement() == ga.getGreetingAccess().getIfKeyword_0()) {
return new Region(n.getOffset(), n.getLength());
}
}
}
}
return null;
}
});
if (result != null) {
return result;
}
}
return super.match(document, offset, length);
}
}
不幸的是,JFace只突出显示一个角色。 如果你想要更多我认为你必须挂钩到IOccurrenceComputer (你必须在那时出现标记)
package org.xtext.example.mydsl1.ui;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.XtextEditor;
import org.eclipse.xtext.ui.editor.model.IXtextDocument;
import org.eclipse.xtext.ui.editor.occurrences.DefaultOccurrenceComputer;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.util.TextRegion;
import org.eclipse.xtext.util.concurrent.CancelableUnitOfWork;
import org.xtext.example.mydsl1.myDsl.Greeting;
import org.xtext.example.mydsl1.services.MyDslGrammarAccess;
public class MyDslOccurrenceComputer extends DefaultOccurrenceComputer {
@Override
public Map<Annotation, Position> createAnnotationMap(XtextEditor editor,
ITextSelection selection, SubMonitor monitor) {
final IXtextDocument document = editor.getDocument();
if (document != null) {
Map<Annotation, Position> result = document.readOnly(new CancelableUnitOfWork<Map<Annotation, Position>, XtextResource>() {
@Override
public Map<Annotation, Position> exec(XtextResource state,
final CancelIndicator cancelIndicator) throws Exception {
MyDslGrammarAccess ga = state.getResourceServiceProvider()
.get(MyDslGrammarAccess.class);
ICompositeNode root = state.getParseResult().getRootNode();
ILeafNode matchNode = NodeModelUtils.findLeafNodeAtOffset(
root, selection.getOffset());
EObject object = NodeModelUtils
.findActualSemanticObjectFor(matchNode);
if (object instanceof Greeting) {
Greeting g = (Greeting) object;
if (matchNode.getGrammarElement() == ga
.getGreetingAccess().getIfKeyword_0()) {
ICompositeNode objectNode = NodeModelUtils
.findActualNodeFor(object);
for (INode n : objectNode.getAsTreeIterable()) {
if (n.getGrammarElement() != null
&& n.getGrammarElement() == ga
.getGreetingAccess()
.getEndifKeyword_3()) {
Map<Annotation, Position> result = new HashMap<>();
addOccurrenceAnnotation(
DECLARATION_ANNOTATION_TYPE,
document,
new TextRegion(matchNode
.getOffset(), matchNode
.getLength()), result);
addOccurrenceAnnotation(
OCCURRENCE_ANNOTATION_TYPE,
document,
new TextRegion(n.getOffset(), n
.getLength()), result);
return result;
}
}
}
if (matchNode.getGrammarElement() == ga
.getGreetingAccess().getEndifKeyword_3()) {
ICompositeNode objectNode = NodeModelUtils
.findActualNodeFor(object);
for (INode n : objectNode.getAsTreeIterable()) {
if (n.getGrammarElement() != null
&& n.getGrammarElement() == ga
.getGreetingAccess()
.getIfKeyword_0()) {
Map<Annotation, Position> result = new HashMap<>();
addOccurrenceAnnotation(
DECLARATION_ANNOTATION_TYPE,
document,
new TextRegion(matchNode
.getOffset(), matchNode
.getLength()), result);
addOccurrenceAnnotation(
OCCURRENCE_ANNOTATION_TYPE,
document,
new TextRegion(n.getOffset(), n
.getLength()), result);
return result;
}
}
}
}
return null;
}
});
if (result != null) {
return result;
}
}
return super.createAnnotationMap(editor, selection, monitor);
}
}