/*******************************************************************************
* Copyright (c) 2008,2010 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.eclipse.emf.mwe2.language.ui.highlighting;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.mwe2.language.mwe2.Assignment;
import org.eclipse.emf.mwe2.language.mwe2.Component;
import org.eclipse.emf.mwe2.language.services.Mwe2GrammarAccess;
import org.eclipse.xtext.common.types.JvmAnnotationReference;
import org.eclipse.xtext.common.types.JvmAnnotationTarget;
import org.eclipse.xtext.common.types.JvmMember;
import org.eclipse.xtext.common.types.JvmOperation;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration;
import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightedPositionAcceptor;
import org.eclipse.xtext.ui.editor.syntaxcoloring.ISemanticHighlightingCalculator;
import com.google.inject.Inject;
public class SemanticHighlightingCalculator implements ISemanticHighlightingCalculator {
@Inject
private Mwe2GrammarAccess grammarAccess;
public void provideHighlightingFor(final XtextResource resource, IHighlightedPositionAcceptor acceptor) {
if (resource == null)
return;
Iterator<INode> iter = resource.getParseResult().getRootNode().getAsTreeIterable().iterator();
while(iter.hasNext()) {
INode node = iter.next();
EObject grammarElement = node.getGrammarElement();
if (grammarElement == grammarAccess.getPropertyReferenceImplAccess()
.getReferableDeclaredPropertyCrossReference_0()) {
highlightNode(node, MweHighlightingConfiguration.PROPERTY_REF, acceptor);
highlightNode(node, MweHighlightingConfiguration.STRING_PROP_REF, acceptor);
for(INode sibling: node.getParent().getChildren()) {
if (sibling != node) {
if (sibling.getGrammarElement() == grammarAccess.getML_COMMENTRule() || sibling.getGrammarElement() == grammarAccess.getSL_COMMENTRule()) {
highlightNode(sibling, DefaultHighlightingConfiguration.COMMENT_ID, acceptor);
}
}
}
if (node instanceof ICompositeNode) {
for(INode child: ((ICompositeNode) node).getChildren()) {
if (child.getGrammarElement() == grammarAccess.getML_COMMENTRule() || child.getGrammarElement() == grammarAccess.getSL_COMMENTRule()) {
highlightNode(child, DefaultHighlightingConfiguration.COMMENT_ID, acceptor);
}
}
}
} else if (grammarElement == grammarAccess.getPropertyReferenceAccess().getDollarSignLeftCurlyBracketKeyword_0()
|| grammarElement == grammarAccess.getPropertyReferenceAccess().getRightCurlyBracketKeyword_2()) {
highlightNode(node, MweHighlightingConfiguration.STRING_PROP_REF, acceptor);
} else if (grammarElement == grammarAccess.getReferenceAccess()
.getReferableReferrableCrossReference_0()) {
highlightNode(node, MweHighlightingConfiguration.PROPERTY_REF, acceptor);
} else if (grammarElement == grammarAccess.getAssignmentAccess()
.getFeatureJvmIdentifiableElementCrossReference_0_0()) {
highlightNode(node, MweHighlightingConfiguration.FEATURE_REF, acceptor);
Assignment semanticObject = (Assignment) node.getSemanticElement();
if (semanticObject.getFeature() instanceof JvmOperation) {
JvmOperation operation = (JvmOperation) semanticObject.getFeature();
if (isDeprecated(operation)) {
highlightNode(node, MweHighlightingConfiguration.DEPRECATED_ELEMENT, acceptor);
}
}
} else if (grammarElement == grammarAccess.getComponentAccess().getTypeJvmTypeCrossReference_1_0_0()
|| grammarElement == grammarAccess.getRootComponentAccess().getTypeJvmTypeCrossReference_1_0_0()) {
Component component = (Component) node.getSemanticElement();
if (component.getType() instanceof JvmAnnotationTarget && isDeprecated((JvmAnnotationTarget) component.getType())) {
highlightNode(node, MweHighlightingConfiguration.DEPRECATED_ELEMENT, acceptor);
}
}
}
}
public boolean isDeprecated(JvmAnnotationTarget annotatable) {
if (annotatable == null)
return false;
List<JvmAnnotationReference> annotations = annotatable.getAnnotations();
for(JvmAnnotationReference annotation: annotations) {
if (Deprecated.class.getName().equals(annotation.getAnnotation().getIdentifier())) {
return true;
}
}
if (annotatable instanceof JvmMember) {
return isDeprecated(((JvmMember) annotatable).getDeclaringType());
}
return false;
}
private void highlightNode(INode node, String id, IHighlightedPositionAcceptor acceptor) {
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);
}
}
}
}
}