/*******************************************************************************
* Copyright (c) 2012 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.xpect.ui.highlighting;
import java.util.Map;
import java.util.regex.Pattern;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.AbstractElement;
import org.eclipse.xtext.AbstractRule;
import org.eclipse.xtext.CrossReference;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.TerminalRule;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightedPositionAcceptor;
import org.eclipse.xtext.ui.editor.syntaxcoloring.ISemanticHighlightingCalculator;
import org.xpect.XpectFile;
import org.xpect.XpectInvocation;
import org.xpect.parameter.IStatementRelatedRegion;
import org.xpect.registry.DefaultBinding;
import org.xpect.ui.util.XpectFileAccess;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
/**
* @author Moritz Eysholdt - Initial contribution and API
*/
public class XtHighlightingCalculator implements ISemanticHighlightingCalculator {
protected static Pattern ALPHANUMERIC = Pattern.compile("[a-zA-Z0-9_]+");
protected static final Map<String, String> RULE_TO_FOMRAT = Maps.newHashMap();
static {
RULE_TO_FOMRAT.put("ID", XtHighlightingConfiguration.DEFAULT_ID);
RULE_TO_FOMRAT.put("INVOCATION", XtHighlightingConfiguration.DEFAULT_ID);
RULE_TO_FOMRAT.put("ML_COMMENT", XtHighlightingConfiguration.COMMENT_ID);
RULE_TO_FOMRAT.put("SL_COMMENT", XtHighlightingConfiguration.COMMENT_ID);
RULE_TO_FOMRAT.put("INT", XtHighlightingConfiguration.NUMBER_ID);
RULE_TO_FOMRAT.put("STRING", XtHighlightingConfiguration.STRING_ID);
}
@DefaultBinding
@Inject(optional = true)
private ISemanticHighlightingCalculator original;
public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor acceptor) {
if (original != null)
original.provideHighlightingFor(resource, acceptor);
provideHighlightingForXpect(resource, acceptor);
}
protected void provideHighlightingForKeyword(ILeafNode node, Keyword kw, IHighlightedPositionAcceptor acceptor) {
if (ALPHANUMERIC.matcher(kw.getValue()).matches())
acceptor.addPosition(node.getOffset(), node.getLength(), XtHighlightingConfiguration.KEYWORD_ID);
else
acceptor.addPosition(node.getOffset(), node.getLength(), XtHighlightingConfiguration.PUNCTUATION_ID);
}
protected void provideHighlightingForRule(ILeafNode node, TerminalRule rule, IHighlightedPositionAcceptor acceptor) {
String conf = RULE_TO_FOMRAT.get(rule.getName());
if (conf != null)
acceptor.addPosition(node.getOffset(), node.getLength(), conf);
}
protected void provideHighlightingForHidden(ILeafNode node, EObject grammarEle, IHighlightedPositionAcceptor acceptor) {
if (node.getText().trim().length() == 0)
acceptor.addPosition(node.getOffset(), node.getLength(), XtHighlightingConfiguration.WHITESPACE_ID);
else
acceptor.addPosition(node.getOffset(), node.getLength(), XtHighlightingConfiguration.COMMENT_ID);
}
protected void provideHighlightingForXpect(XtextResource resource, IHighlightedPositionAcceptor acceptor) {
XtextResource xpectResource = XpectFileAccess.getXpectResource(resource);
ICompositeNode rootNode = xpectResource.getParseResult().getRootNode();
for (ILeafNode node : rootNode.getLeafNodes()) {
EObject ele = node.getGrammarElement();
if (node.isHidden())
provideHighlightingForHidden(node, ele, acceptor);
else if (ele instanceof Keyword)
provideHighlightingForKeyword(node, (Keyword) ele, acceptor);
else if (ele instanceof TerminalRule)
provideHighlightingForRule(node, (TerminalRule) ele, acceptor);
else if (ele instanceof RuleCall) {
AbstractRule rule = ((RuleCall) ele).getRule();
if (rule instanceof TerminalRule && !rule.getName().equals("ANY_OTHER"))
provideHighlightingForRule(node, (TerminalRule) rule, acceptor);
} else if (ele instanceof CrossReference) {
AbstractElement rc = ((CrossReference) ele).getTerminal();
if (rc instanceof RuleCall) {
AbstractRule rule = ((RuleCall) rc).getRule();
if (rule instanceof TerminalRule)
provideHighlightingForRule(node, (TerminalRule) rule, acceptor);
}
}
}
for (EObject obj : xpectResource.getContents())
if (obj instanceof XpectFile)
for (XpectInvocation inv : ((XpectFile) obj).getInvocations())
for (IStatementRelatedRegion region : inv.getRelatedRegions())
acceptor.addPosition(region.getOffset(), region.getLength(), XtHighlightingConfiguration.DEFAULT_ID);
}
}