Xtext: использование классов грамматики в ISemanticHighlightingCalculator - PullRequest
0 голосов
/ 15 февраля 2011

Слушай, у меня есть грамматика.Смотрите только конкретную часть, которую мне нужно обработать:

Par:
    id=ID | string=STRING | integer=INT;

Я хочу получить:

if it's a Par element of type ID then color the background
if it's a Par element of type STRING then set text color

А вот мой SemanticHighlightingCalculator

public class GrailSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {

    @Override
    public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor acceptor) {
        if (resource == null) return;

        Iterable<AbstractNode> allNodes = NodeUtil.getAllContents( resource.getParseResult().getRootNode() );
            for (AbstractNode node : allNodes) {
                System.out.println(node.getGrammarElement().toString());
                if (node.getGrammarElement() instanceof Par) {
                    System.out.println("Il mio par: " + ((Par)node).getId());
                    acceptor.addPosition(node.getOffset(), node.getLength(), GrailHighlightingConfiguration.ELEMENT_ID);
                }
              }
    }

}

Я делаю это, как написано здесь в документации .Я не получаю никакой ошибки во время компиляции.Вот пример вывода System.out.println(node.getGrammarElement().toString());

org.eclipse.xtext.impl.RuleCallImpl@165a43b (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@159b3 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@a866a9 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@f4c9c4 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl@a82a10 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@618b08 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@1da2b6d (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@591171 (cardinality: null) (value: ,)
org.eclipse.xtext.impl.RuleCallImpl@1882876 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@618b08 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@1da2b6d (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@591171 (cardinality: null) (value: ,)
org.eclipse.xtext.impl.RuleCallImpl@1882876 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@618b08 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@1860e4 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@ea8847 (cardinality: null) (value: ))
org.eclipse.xtext.impl.RuleCallImpl@812517 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@cbb612 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl@1990d96 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl@1e7f21 (cardinality: null)
org.eclipse.xtext.impl.ActionImpl@2c79a5 (cardinality: null) (feature: left, operator: =)
org.eclipse.xtext.impl.RuleCallImpl@aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@cbb612 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl@1990d96 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl@1e7f21 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@cbb612 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@1e668c2 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@1e7a4d0 (cardinality: null) (value: .)
org.eclipse.xtext.impl.RuleCallImpl@f55ff2 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@16e3eb3 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@d67d61 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@1860e4 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl@14afef4 (cardinality: null) (value: ))
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl@1c190a2 (cardinality: null) (value: AND)
org.eclipse.xtext.impl.RuleCallImpl@feba21 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl@16dd645 (cardinality: null) (value: NOT)
org.eclipse.xtext.impl.RuleCallImpl@e54f3 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@1e668c2 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@1e7a4d0 (cardinality: null) (value: .)
org.eclipse.xtext.impl.RuleCallImpl@f55ff2 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@16e3eb3 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@d67d61 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@eb3f66 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl@14afef4 (cardinality: null) (value: ))
org.eclipse.xtext.impl.RuleCallImpl@165a43b (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@159b3 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@a866a9 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@f4c9c4 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl@a82a10 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@618b08 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@1da2b6d (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@ea8847 (cardinality: null) (value: ))
org.eclipse.xtext.impl.RuleCallImpl@812517 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@cbb612 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl@1990d96 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl@1e7f21 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@cbb612 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@1e668c2 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@1e7a4d0 (cardinality: null) (value: .)
org.eclipse.xtext.impl.RuleCallImpl@f55ff2 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@16e3eb3 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl@d67d61 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl@1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl@1860e4 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl@14afef4 (cardinality: null) (value: ))

Ответы [ 2 ]

2 голосов
/ 29 ноября 2012

Для Xtext 2.0 этот код может использоваться в качестве шаблона:

import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;
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.syntaxcoloring.IHighlightedPositionAcceptor;
import org.eclipse.xtext.ui.editor.syntaxcoloring.ISemanticHighlightingCalculator;

public class YourDslSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {

    @Override
    public void provideHighlightingFor( XtextResource resource, IHighlightedPositionAcceptor acceptor ) {
        if( resource == null ) {
            return;
        }

        HighlightingSwitch switcher = new HighlightingSwitch( acceptor );

        Iterator<EObject> iter = EcoreUtil.getAllContents(resource, true);
        while(iter.hasNext()) {
            EObject current = iter.next();

            switcher.doSwitch( current );
        }
    }

    private class HighlightingSwitch extends YourDslSwitch<Void> {

        private final IHighlightedPositionAcceptor acceptor;

        public HighlightingSwitch( IHighlightedPositionAcceptor acceptor ) {
            this.acceptor = acceptor;
        }

        @Override
        public Void caseOption( Option object ) {
            INode node = getFirstFeatureNode( object, YourDslPackage.eINSTANCE.getOption_Name() );
            highlightNode( node, YourDslHighlightingConfiguration.OPTION );
            return null;
        }

        private void highlightNode( INode node, String id ) {
            if( node == null )
                return;
            if( node instanceof ILeafNode ) {
                acceptor.addPosition( node.getOffset(), node.getLength(), id );
            } else {
                for( ILeafNode leaf : node.getLeafNodes() ) {
                    if( !leaf.isHidden() ) {
                        acceptor.addPosition( leaf.getOffset(), leaf.getLength(), id );
                    }
                }
            }
        }
    }

    public INode getFirstFeatureNode( EObject semantic, EStructuralFeature feature ) {
        if( feature == null )
            return NodeModelUtils.findActualNodeFor( semantic );
        List<INode> nodes = NodeModelUtils.findNodesForFeature( semantic, feature );
        if( !nodes.isEmpty() )
            return nodes.get( 0 );
        return null;
    }    

}

Это повторяет все узлы в вашей модели и вызывает регистр в HighlightingSwitch.

ВВ случае с делом вам нужно найти INode, относящийся к этой функции, или экземпляр EObject, который вас интересует, и затем вы можете выделить его.

Обратите внимание, что getFirstFeatureNode() не выполняет поиск в целомAST для узла;Реализация на самом деле довольно быстрая.

Конфигурация стиля выглядит следующим образом:

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration;
import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightingConfigurationAcceptor;
import org.eclipse.xtext.ui.editor.utils.TextStyle;

public class YourDslHighlightingConfiguration extends DefaultHighlightingConfiguration {

    public static final String OPTION = "yourDsl.option";

    public void configure(IHighlightingConfigurationAcceptor acceptor) {

        acceptor.acceptDefaultHighlighting( OPTION, "Option", option() );

        super.configure( acceptor );
    }

    public TextStyle option() {
        TextStyle textStyle = defaultTextStyle().copy();
        textStyle.setColor( new RGB( 0, 26, 171 ) );
        textStyle.setStyle( SWT.ITALIC );
        return textStyle;
    }
}

Не забудьте связать два новых класса в вашем модуле пользовательского интерфейса!

2 голосов
/ 27 апреля 2011

Я только начинаю с XText, но могу помочь.Мне удалось получить подсветку синтаксиса, работающую для небольшого проекта с кодом, похожим на ваш, но с некоторыми отличиями.Я нашел полезную публикацию форума на форумах Eclipse здесь .

На основе вывода консоли похоже, что он никогда не распознает ни один из абстрактных узлов как экземпляр Par.

Различия между форумом Eclipse и вашим кодом, по-видимому, следующие:

  • Он использует Iterator<EObject> iter = EcoreUtil.getAllContents(resource, true); и цикл while для перебора результатов.
  • Он проверяетНапечатайте (в вашем случае для Par) против объекта EObject напрямую, вместо использования getGrammarElement.

Это может быть так же просто, как изменить его, как указано выше, на что-то вроде:

public class GrailSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {

@Override
public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor acceptor) {
    if (resource == null) return;

    Iterator<EObject> iter = EcoreUtil.getAllContents(resource, true);
    while (iter.hasNext()) {
        EObject current = iter.next();
        if (current instanceof Par) {
            Par parNode = (Par) current;
            if (parNode.getId() != null) {
                acceptor.addPosition(node.getOffset(), node.getLength(), GrailHighlightingConfiguration.ELEMENT_ID);
            } else if (parNode.getString() != null) {
                acceptor.addPosition(node.getOffset(), node.getLength(), GrailHighlightingConfiguration.ELEMENT_STRING);
            } else if (parNode.getInt() != null) {
                acceptor.addPosition(node.getOffset(), node.getLength(), GrailHighlightingConfiguration.ELEMENT_INT);
            }
        }
    }
}

Я включил некоторый код для обработки других опций подсветки, поэтому вам нужно добавить обработчики ELEMENT_STRING и ELEMENT_INT к вашему configure() методу в любой вызываемый класс IHighlightingConfiguration, чтобы вернуть TextStyle, применимый ких.

Также обратите внимание, что я не проверял ничего из вышеперечисленного, так что на самом деле это может быть совершенно неправильно и вводить в заблуждение!Надеюсь, что нет.:)

...