找到匹配的'开始' - '结束'并突出他们

时间:2014-11-19 09:46:05

标签: eclipse-rcp xtext

我是在Xtext中开发DSL的新手。我想添加一个突出代码块匹配开始和结束的功能。在我的语言中,每个函数必须以'begin'开头,以'end'结束,并且if条件和循环都是如此。当光标在'begin'时,我需要突出显示匹配/对应的'end'。例如下面,当光标位于第二个'begin'时,我需要突出显示相应的第一个'end':

function X 
  begin
     if a>b
       begin
         a=b;
       end
   end

请帮忙吗?

由于

1 个答案:

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

}