blob: 8b6e6d516cc7226f50b002a51d49bbdfa64e41c3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 Borland Software Corporation and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Borland Software Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.editor.ui.colorer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lpg.runtime.IToken;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalModuleEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.IntermediateClassFactory;
import org.eclipse.m2m.internal.qvt.oml.compiler.CompiledUnit;
import org.eclipse.m2m.internal.qvt.oml.cst.AssertExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ClassifierDefCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ClassifierPropertyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ContextualPropertyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ImperativeIterateExpCS;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingDeclarationCS;
import org.eclipse.m2m.internal.qvt.oml.cst.ModulePropertyCS;
import org.eclipse.m2m.internal.qvt.oml.cst.UnitCS;
import org.eclipse.m2m.internal.qvt.oml.editor.ui.colorer.QVTColorManager.ColorDescriptor;
import org.eclipse.m2m.internal.qvt.oml.expressions.ContextualProperty;
import org.eclipse.m2m.internal.qvt.oml.expressions.EntryOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.ExpressionsPackage;
import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.Library;
import org.eclipse.m2m.internal.qvt.oml.expressions.MappingOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.ModelParameter;
import org.eclipse.m2m.internal.qvt.oml.expressions.Module;
import org.eclipse.m2m.internal.qvt.oml.expressions.VarParameter;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.ImperativeIterateExp;
import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.Typedef;
import org.eclipse.ocl.cst.CSTNode;
import org.eclipse.ocl.cst.FeatureCallExpCS;
import org.eclipse.ocl.cst.IntegerLiteralExpCS;
import org.eclipse.ocl.cst.IteratorExpCS;
import org.eclipse.ocl.cst.PathNameCS;
import org.eclipse.ocl.cst.RealLiteralExpCS;
import org.eclipse.ocl.cst.SimpleNameCS;
import org.eclipse.ocl.cst.VariableExpCS;
import org.eclipse.ocl.ecore.CollectionType;
import org.eclipse.ocl.ecore.IteratorExp;
import org.eclipse.ocl.ecore.PrimitiveType;
import org.eclipse.ocl.util.OCLStandardLibraryUtil;
import org.eclipse.ocl.utilities.PredefinedType;
class QVTSemanticHighlighter {
private final int INDEX_NUMBERS;
private final int INDEX_INTERM_DATA;
private final int INDEX_MODULE_ELEMENT;
private final int INDEX_USER_MODEL_ELEMENT;
private final int INDEX_MODEL_PARAMETER;
private final int INDEX_SELF_VARIABLE;
private final int INDEX_RESULT_VARIABLE;
private final int INDEX_FATAL_ASSERT;
private final int INDEX_STDLIB_ELEMENT;
//private final int INDEX_OPERATION_PARAMETER;
private SemanticHighlightingReconciler.PositionCollector fCollector;
private EPackage fOCLStdlibPckg;
private Library fQVTStdlib;
QVTSemanticHighlighter(ColorDescriptor[] semanticHighlightings) {
Map<String, Integer> map = new HashMap<String, Integer>();
int i = 0;
for (ColorDescriptor colorDescriptor : semanticHighlightings) {
map.put(colorDescriptor.key(), i++);
}
INDEX_NUMBERS = getColorIndex(QVTColorManager.NUMBER, map);
INDEX_INTERM_DATA = getColorIndex(QVTColorManager.INTERMEDIATE_DATA, map);
INDEX_MODULE_ELEMENT = getColorIndex(QVTColorManager.MODULE_ELEMENT, map);
INDEX_MODEL_PARAMETER = getColorIndex(QVTColorManager.MODEL_PARAMETER, map);
INDEX_USER_MODEL_ELEMENT = getColorIndex(QVTColorManager.USER_MODEL_ELEMENT, map);
INDEX_STDLIB_ELEMENT = getColorIndex(QVTColorManager.STDLIB_ELEMENT, map);
INDEX_RESULT_VARIABLE = getColorIndex(QVTColorManager.RESULT_VARIABLE, map);
INDEX_SELF_VARIABLE = getColorIndex(QVTColorManager.SELF_VARIABLE, map);
INDEX_FATAL_ASSERT = getColorIndex(QVTColorManager.FATAL_ASSERT, map);
//INDEX_OPERATION_PARAMETER = getColorIndex(QVTColorManager.OPERATION_PARAMETER, map);
}
void setCollector(SemanticHighlightingReconciler.PositionCollector positionCollector) {
fCollector = positionCollector;
}
protected boolean visit(CompiledUnit unit) {
UnitCS unitCST = unit.getUnitCST();
if(unitCST == null) {
return false;
}
try {
boolean modelOK = setModel(unit);
if(!modelOK) {
return false;
}
TreeIterator<EObject> allContents = unitCST.eAllContents();
while (allContents.hasNext()) {
CSTNode object = (CSTNode) allContents.next();
if(object instanceof PathNameCS) {
PathNameCS pathNameCS = (PathNameCS) object;
visit(pathNameCS);
} else if(object instanceof SimpleNameCS) {
visit((SimpleNameCS) object);
} else if(object instanceof IntegerLiteralExpCS) {
visit((IntegerLiteralExpCS) object);
} else if(object instanceof RealLiteralExpCS) {
visit((RealLiteralExpCS) object);
} else if(object instanceof FeatureCallExpCS) {
visit((FeatureCallExpCS) object);
} else if(object instanceof ClassifierDefCS) {
visit((ClassifierDefCS) object);
} else if(object instanceof VariableExpCS) {
visit((VariableExpCS)object);
} else if(object instanceof MappingDeclarationCS) {
visit((MappingDeclarationCS) object);
} else if(object instanceof AssertExpCS) {
visit((AssertExpCS) object);
} else if(object instanceof ModulePropertyCS) {
visit((ModulePropertyCS) object);
} else if(object instanceof IteratorExpCS) {
visit((IteratorExpCS) object);
} else if(object instanceof ImperativeIterateExpCS) {
visit((ImperativeIterateExpCS) object);
}
}
} finally {
setModel(null);
}
return false;
}
protected boolean visit(MappingDeclarationCS n) {
SimpleNameCS simpleNameCS = n.getSimpleNameCS();
if(n.getAst() instanceof EntryOperation) {
return false;
}
return fCollector.visitToken(simpleNameCS, INDEX_MODULE_ELEMENT);
}
protected boolean visit(SimpleNameCS n) {
Object ast = n.getAst();
if(ast instanceof EClassifier) {
EClassifier type = (EClassifier) ast;
if(type.eClass() == org.eclipse.ocl.ecore.EcorePackage.eINSTANCE.getVoidType()) {
// may be unresolved type
return false;
}
if(isStdlibElement(type)) {
if(type instanceof CollectionType == false) {
return fCollector.visitToken(n, INDEX_STDLIB_ELEMENT);
}
} else if(type instanceof Module &&
n.eContainingFeature() != org.eclipse.ocl.cst.CSTPackage.eINSTANCE.getPathNameCS_SimpleNames()) {
return fCollector.visitToken(n, INDEX_MODULE_ELEMENT);
} else if(type.eClass().getEPackage() != ExpressionsPackage.eINSTANCE) {
return fCollector.visitToken(n, INDEX_USER_MODEL_ELEMENT);
}
} else if(ast instanceof EEnumLiteral) {
return fCollector.visitToken(n, INDEX_USER_MODEL_ELEMENT);
} else if(ast instanceof EPackage) {
if(isStdlibElement((EPackage)ast)) {
return fCollector.visitToken(n, INDEX_STDLIB_ELEMENT);
} else {
return fCollector.visitToken(n, INDEX_USER_MODEL_ELEMENT);
}
}
if(ast instanceof ModelParameter) {
return fCollector.visitToken(n, INDEX_MODEL_PARAMETER);
}
return false;
}
protected boolean visit(PathNameCS n) {
EClassifier type = null;
Object ast = n.getAst();
type = toType(type, ast);
if(type != null) {
if(type instanceof PrimitiveType) {
return fCollector.visitToken(n, INDEX_STDLIB_ELEMENT);
} else {
if (type instanceof EClass
&& IntermediateClassFactory.isIntermediateClass(type)) {
return fCollector.visitToken(n, INDEX_INTERM_DATA);
}
}
}
return false;
}
protected boolean visit(FeatureCallExpCS callCS) {
SimpleNameCS nameCS = callCS.getSimpleNameCS();
if(nameCS == null) {
return false;
}
Object ast = nameCS.getAst();
if(ast instanceof EOperation) {
EOperation operation = (EOperation) ast;
if(operation instanceof MappingOperation) {
return fCollector.visitToken(callCS.getSimpleNameCS(), INDEX_MODULE_ELEMENT);
} else if(operation instanceof ImperativeOperation) {
return fCollector.visitToken(callCS.getSimpleNameCS(), INDEX_MODULE_ELEMENT);
}
if(isStdlibElement(operation)) {
int operCode = OCLStandardLibraryUtil.getOperationCode(operation.getName());
switch(operCode) {
case PredefinedType.NOT:
case PredefinedType.OR:
case PredefinedType.AND:
case PredefinedType.XOR:
case PredefinedType.DIVIDE:
case PredefinedType.EQUAL:
case PredefinedType.NOT_EQUAL:
case PredefinedType.GREATER_THAN:
case PredefinedType.GREATER_THAN_EQUAL:
case PredefinedType.LESS_THAN:
case PredefinedType.LESS_THAN_EQUAL:
case PredefinedType.MINUS:
case PredefinedType.PLUS:
case PredefinedType.TIMES:
return false;
}
return fCollector.visitToken(callCS.getSimpleNameCS(), INDEX_STDLIB_ELEMENT);
}
} else if(ast instanceof EStructuralFeature) {
EStructuralFeature feature = (EStructuralFeature) ast;
if(IntermediateClassFactory.isIntermediateClass(feature.getEContainingClass())) {
return fCollector.visitToken(callCS.getSimpleNameCS(), INDEX_INTERM_DATA);
} else if(ast instanceof ContextualProperty) {
return fCollector.visitToken(callCS.getSimpleNameCS(), INDEX_INTERM_DATA);
}
if(feature.getEContainingClass().eClass() == EcorePackage.eINSTANCE.getEClass()) {
return fCollector.visitToken(callCS.getSimpleNameCS(), INDEX_USER_MODEL_ELEMENT);
}
return fCollector.visitToken(callCS.getSimpleNameCS(), INDEX_MODULE_ELEMENT);
}
return true;
}
protected boolean visit(ClassifierDefCS classifierDefCS) {
for(ClassifierPropertyCS next : classifierDefCS.getProperties()) {
fCollector.visitToken(next.getSimpleNameCS(), INDEX_INTERM_DATA);
}
return fCollector.visitToken(classifierDefCS.getSimpleNameCS(), INDEX_INTERM_DATA);
}
protected boolean visit(ImperativeIterateExpCS iteratorExpCS) {
IToken endToken = iteratorExpCS.getEndToken();
if(endToken != null && "]".equals(endToken.toString())) { //$NON-NLS-1$
return false;
}
Object ast = iteratorExpCS.getAst();
if(ast instanceof ImperativeIterateExp) {
return fCollector.visitToken(iteratorExpCS.getSimpleNameCS(), INDEX_STDLIB_ELEMENT);
}
return false;
}
protected boolean visit(IteratorExpCS iteratorExpCS) {
Object ast = iteratorExpCS.getAst();
if(ast instanceof IteratorExp) {
return fCollector.visitToken(iteratorExpCS.getSimpleNameCS(), INDEX_STDLIB_ELEMENT);
}
return false;
}
protected boolean visit(ModulePropertyCS propertyCS) {
SimpleNameCS simpleNameCS = propertyCS.getSimpleNameCS();
if(simpleNameCS != null) {
if (propertyCS instanceof ContextualPropertyCS
|| propertyCS instanceof ClassifierPropertyCS) {
return fCollector.visitToken(simpleNameCS, INDEX_INTERM_DATA);
}
return fCollector.visitToken(simpleNameCS, INDEX_MODULE_ELEMENT);
}
return false;
}
protected boolean visit(VariableExpCS variableExpCS) {
SimpleNameCS simpleNameCS = variableExpCS.getSimpleNameCS();
Object ast = simpleNameCS.getAst();
if(ast instanceof ModelParameter) {
fCollector.visitToken(simpleNameCS, INDEX_MODEL_PARAMETER);
} else if(ast instanceof VarParameter) {
final String varName = simpleNameCS.getValue();
if("self".equals(varName)) { //$NON-NLS-1$
fCollector.visitToken(simpleNameCS, INDEX_SELF_VARIABLE);
} else if("result".equals(varName)) { //$NON-NLS-1$
fCollector.visitToken(simpleNameCS, INDEX_RESULT_VARIABLE);
}
} else if(ast instanceof EStructuralFeature) {
EStructuralFeature feature = (EStructuralFeature) ast;
EClass ownerClass = feature.getEContainingClass();
if(feature instanceof ContextualProperty ||
IntermediateClassFactory.isIntermediateClass(ownerClass)) {
return fCollector.visitToken(simpleNameCS, INDEX_INTERM_DATA);
} else if(ownerClass.eClass() == EcorePackage.eINSTANCE.getEClass()) {
return fCollector.visitToken(simpleNameCS, INDEX_USER_MODEL_ELEMENT);
}
return fCollector.visitToken(simpleNameCS, INDEX_MODULE_ELEMENT);
}
return false;
}
protected boolean visit(AssertExpCS assertExpCS) {
SimpleNameCS severity = assertExpCS.getSeverity();
if(severity != null && "fatal".equals(severity.getValue())) { //$NON-NLS-1$
return fCollector.visitToken(severity, INDEX_FATAL_ASSERT);
}
return false;
}
protected boolean visit(IntegerLiteralExpCS n) {
return fCollector.visitToken(n, INDEX_NUMBERS);
}
protected boolean visit(RealLiteralExpCS n) {
return fCollector.visitToken(n, INDEX_NUMBERS);
}
private int getColorIndex(String colorKey, Map<String, Integer> map) {
Integer index = map.get(colorKey);
return index != null ? index.intValue() : -1;
}
private boolean isStdlibElement(EClassifier type) {
EPackage ePackage = type.getEPackage();
return ePackage != null && isStdlibElement(ePackage) || type instanceof PredefinedType<?>;
}
private boolean isStdlibElement(EPackage ePackage) {
EObject root = EcoreUtil.getRootContainer(ePackage);
return root == fQVTStdlib || root == fOCLStdlibPckg;
}
private boolean isStdlibElement(EOperation operation) {
EClass eClass = operation.getEContainingClass();
return eClass != null && isStdlibElement(eClass);
}
private boolean setModel(CompiledUnit model) {
if(model != null) {
List<QvtOperationalModuleEnv> envList = model.getModuleEnvironments();
// get standard library instances from any of the available environments
if(envList != null && !envList.isEmpty()) {
QvtOperationalModuleEnv env = envList.get(0);
fQVTStdlib = env.getQVTStandardLibrary().getStdLibModule();
fOCLStdlibPckg = env.getOCLStandardLibrary().getBoolean().getEPackage();
} else {
// NO stdlib available
return false;
}
} else {
fQVTStdlib = null;
fOCLStdlibPckg = null;
}
return true;
}
private EClassifier toType(EClassifier type, Object ast) {
if(ast instanceof Typedef) {
type = ((Typedef) ast).getBase();
} else if(ast instanceof EClassifier) {
type = (EClassifier) ast;
}
return type;
}
}