blob: ea052dadf5bca55a54a533db97ba091efde751c8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010,2013 E.D.Willink 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
*
* Contributors:
* E.D.Willink - initial API and implementation
* E.D.Willink (CEA LIST) - Bug 388493
* E.D.Willink (Obeo) - Bug 416287 - tuple-valued constraints
*******************************************************************************/
package org.eclipse.ocl.examples.xtext.essentialocl.cs2as;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.examples.domain.elements.DomainOperation;
import org.eclipse.ocl.examples.domain.elements.FeatureFilter;
import org.eclipse.ocl.examples.domain.utilities.DomainUtil;
import org.eclipse.ocl.examples.library.collection.CollectionFlattenOperation;
import org.eclipse.ocl.examples.pivot.BooleanLiteralExp;
import org.eclipse.ocl.examples.pivot.CallExp;
import org.eclipse.ocl.examples.pivot.CollectionItem;
import org.eclipse.ocl.examples.pivot.CollectionLiteralExp;
import org.eclipse.ocl.examples.pivot.CollectionLiteralPart;
import org.eclipse.ocl.examples.pivot.CollectionRange;
import org.eclipse.ocl.examples.pivot.CollectionType;
import org.eclipse.ocl.examples.pivot.ConstructorExp;
import org.eclipse.ocl.examples.pivot.ConstructorPart;
import org.eclipse.ocl.examples.pivot.Element;
import org.eclipse.ocl.examples.pivot.ElementExtension;
import org.eclipse.ocl.examples.pivot.EnumLiteralExp;
import org.eclipse.ocl.examples.pivot.EnumerationLiteral;
import org.eclipse.ocl.examples.pivot.Environment;
import org.eclipse.ocl.examples.pivot.ExpressionInOCL;
import org.eclipse.ocl.examples.pivot.FeatureCallExp;
import org.eclipse.ocl.examples.pivot.IfExp;
import org.eclipse.ocl.examples.pivot.IntegerLiteralExp;
import org.eclipse.ocl.examples.pivot.InvalidLiteralExp;
import org.eclipse.ocl.examples.pivot.InvalidType;
import org.eclipse.ocl.examples.pivot.IterateExp;
import org.eclipse.ocl.examples.pivot.Iteration;
import org.eclipse.ocl.examples.pivot.IteratorExp;
import org.eclipse.ocl.examples.pivot.LetExp;
import org.eclipse.ocl.examples.pivot.LoopExp;
import org.eclipse.ocl.examples.pivot.Metaclass;
import org.eclipse.ocl.examples.pivot.NamedElement;
import org.eclipse.ocl.examples.pivot.NavigationCallExp;
import org.eclipse.ocl.examples.pivot.NullLiteralExp;
import org.eclipse.ocl.examples.pivot.NumericLiteralExp;
import org.eclipse.ocl.examples.pivot.OCLExpression;
import org.eclipse.ocl.examples.pivot.Operation;
import org.eclipse.ocl.examples.pivot.OperationCallExp;
import org.eclipse.ocl.examples.pivot.OppositePropertyCallExp;
import org.eclipse.ocl.examples.pivot.Parameter;
import org.eclipse.ocl.examples.pivot.ParameterableElement;
import org.eclipse.ocl.examples.pivot.PivotConstants;
import org.eclipse.ocl.examples.pivot.PivotPackage;
import org.eclipse.ocl.examples.pivot.Property;
import org.eclipse.ocl.examples.pivot.PropertyCallExp;
import org.eclipse.ocl.examples.pivot.State;
import org.eclipse.ocl.examples.pivot.StateExp;
import org.eclipse.ocl.examples.pivot.StringLiteralExp;
import org.eclipse.ocl.examples.pivot.TemplateParameter;
import org.eclipse.ocl.examples.pivot.TemplateSignature;
import org.eclipse.ocl.examples.pivot.TupleLiteralExp;
import org.eclipse.ocl.examples.pivot.TupleLiteralPart;
import org.eclipse.ocl.examples.pivot.Type;
import org.eclipse.ocl.examples.pivot.TypeExp;
import org.eclipse.ocl.examples.pivot.TypedElement;
import org.eclipse.ocl.examples.pivot.UnlimitedNaturalLiteralExp;
import org.eclipse.ocl.examples.pivot.Variable;
import org.eclipse.ocl.examples.pivot.VariableDeclaration;
import org.eclipse.ocl.examples.pivot.VariableExp;
import org.eclipse.ocl.examples.pivot.lookup.ISingleResultEnvironment;
import org.eclipse.ocl.examples.pivot.lookup.NewPivotNameResolver;
import org.eclipse.ocl.examples.pivot.manager.MetaModelManager;
import org.eclipse.ocl.examples.pivot.messages.OCLMessages;
import org.eclipse.ocl.examples.pivot.scoping.EnvironmentView;
import org.eclipse.ocl.examples.pivot.scoping.ScopeFilter;
import org.eclipse.ocl.examples.pivot.scoping.ScopeView;
import org.eclipse.ocl.examples.pivot.utilities.PivotUtil;
import org.eclipse.ocl.examples.xtext.base.basecs.ElementCS;
import org.eclipse.ocl.examples.xtext.base.basecs.ModelElementCS;
import org.eclipse.ocl.examples.xtext.base.basecs.PathElementCS;
import org.eclipse.ocl.examples.xtext.base.basecs.PathNameCS;
import org.eclipse.ocl.examples.xtext.base.basecs.TypedRefCS;
import org.eclipse.ocl.examples.xtext.base.cs2as.CS2Pivot;
import org.eclipse.ocl.examples.xtext.base.cs2as.CS2PivotConversion;
import org.eclipse.ocl.examples.xtext.base.scoping.BaseScopeView;
import org.eclipse.ocl.examples.xtext.base.utilities.ElementUtil;
import org.eclipse.ocl.examples.xtext.essentialocl.attributes.BinaryOperationFilter;
import org.eclipse.ocl.examples.xtext.essentialocl.attributes.ImplicitCollectFilter;
import org.eclipse.ocl.examples.xtext.essentialocl.attributes.ImplicitCollectionFilter;
import org.eclipse.ocl.examples.xtext.essentialocl.attributes.UnaryOperationFilter;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.AbstractNameExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.BinaryOperatorCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.BooleanLiteralExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.CollectionLiteralExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.CollectionLiteralPartCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.CollectionTypeCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.ConstructorExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.ConstructorPartCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.ContextCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.ExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.IfExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.IndexExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.InfixExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.InvalidLiteralExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.InvocationExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.LetExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.LetVariableCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.NameExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.NavigatingArgCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.NavigationOperatorCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.NavigationRole;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.NestedExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.NullLiteralExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.NumberLiteralExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.OperatorCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.PrefixExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.SelfExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.StringLiteralExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.TupleLiteralExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.TupleLiteralPartCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.TypeLiteralExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.UnaryOperatorCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.UnlimitedNaturalLiteralExpCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.VariableCS;
import org.eclipse.ocl.examples.xtext.essentialocl.essentialoclcs.util.AbstractEssentialOCLCSLeft2RightVisitor;
public class EssentialOCLCSLeft2RightVisitor extends AbstractEssentialOCLCSLeft2RightVisitor
{
/**
* Configure use of the new auto-generated lookup or the old manually coded lookup.
* @since 3.5
*/
public static boolean AUTOGENERATED_LOOKUP = true;
private static final class TypeArgumentFilter implements ScopeFilter
{
public static TypeArgumentFilter INSTANCE = new TypeArgumentFilter();
public int compareMatches(@NonNull MetaModelManager metaModelManager, @NonNull Object match1, @Nullable Map<TemplateParameter, ParameterableElement> bindings1,
@NonNull Object match2, @Nullable Map<TemplateParameter, ParameterableElement> bindings2) {
return 0;
}
public boolean matches(@NonNull EnvironmentView environmentView, @NonNull Object object) {
if (object instanceof Type) {
return true;
}
if (object instanceof TypedElement) {
return ((TypedElement)object).getType() instanceof Metaclass<?>;
}
return false;
}
}
// private static final Logger logger = Logger.getLogger(EssentialOCLLeft2RightVisitor.class);
protected final @NonNull MetaModelManager metaModelManager;
/**
* @since 3.5
*/
protected final @NonNull NewPivotNameResolver lResolver;
public EssentialOCLCSLeft2RightVisitor(@NonNull CS2PivotConversion context) {
super(context);
this.metaModelManager = context.getMetaModelManager();
this.lResolver = new NewPivotNameResolver(metaModelManager); // FIXME factory method
}
/* protected OCLExpression zzcheckImplementation(NamedExpCS csNavigatingExp,
Feature feature, CallExp callExp, OCLExpression expression) {
LibraryFeature implementation;
try {
implementation = metaModelManager.getImplementation(feature);
} catch (Exception e) {
return context.addBadExpressionError(csNavigatingExp, "Failed to load '" + feature.getImplementationClass() + "': " + e);
}
if (implementation != null) {
LibraryValidator validator = implementation.getValidator(metaModelManager);
if (validator != null) {
Diagnostic diagnostic = validator.validate(metaModelManager, callExp);
if (diagnostic != null) {
context.addDiagnostic(csNavigatingExp, diagnostic);
}
}
}
return expression;
} */
protected void checkForInvalidImplicitSourceType(@NonNull ExpCS csInvocationExp) {
for (ImplicitSourceTypeIterator it = new ImplicitSourceTypeIterator(csInvocationExp); it.hasNext(); ) {
if (isInvalidType(it.next())) {
csInvocationExp.setHasError(true);
break;
}
}
}
protected ImplicitSourceTypeIterator createImplicitSourceTypeIterator(@NonNull ElementCS csElement) {
return new ImplicitSourceTypeIterator(csElement);
}
protected @NonNull OCLExpression createImplicitSourceVariableExp(@NonNull AbstractNameExpCS csNameExp, Type owningType) {
VariableDeclaration sourceVariable = owningType != null ? getImplicitSource(csNameExp, owningType) : null;
if (sourceVariable == null) {
@SuppressWarnings("unused") VariableDeclaration sourceVariable2 = owningType != null ? getImplicitSource(csNameExp, owningType) : null;
return context.addBadExpressionError(csNameExp, "No implicit source");
}
else {
return createImplicitVariableExp(sourceVariable);
}
}
protected @NonNull VariableExp createImplicitVariableExp(@NonNull VariableDeclaration variable) {
VariableExp variableExp = context.refreshModelElement(VariableExp.class, PivotPackage.Literals.VARIABLE_EXP, null); // FIXME reuse
variableExp.setReferredVariable(variable);
variableExp.setImplicit(true);
context.setType(variableExp, variable.getType(), variable.isRequired());
return variableExp;
}
/* private TemplateParameterSubstitution findFormalParameter(TemplateParameter formalTemplateParameter, Type actualType) {
for (TemplateBinding actualTemplateBinding : actualType.getTemplateBinding()) {
for (TemplateParameterSubstitution actualTemplateParameterSubstitution : actualTemplateBinding.getParameterSubstitution()) {
TemplateParameter actualFormal = actualTemplateParameterSubstitution.getFormal();
if (actualFormal == formalTemplateParameter) {
return actualTemplateParameterSubstitution;
}
}
}
if (actualType instanceof org.eclipse.ocl.examples.pivot.Class) {
for (org.eclipse.ocl.examples.pivot.Class superClass : ((org.eclipse.ocl.examples.pivot.Class)actualType).getSuperClass()) {
TemplateParameterSubstitution actualTemplateParameterSubstitution = findFormalParameter(formalTemplateParameter, superClass);
if (actualTemplateParameterSubstitution != null) {
return actualTemplateParameterSubstitution;
}
}
}
return null;
} */
protected @Nullable Iteration getBestIteration(@NonNull List<NamedElement> invocations) {
Iteration bestIteration = null;
Type bestType = null;
int bestIteratorsSize = Integer.MAX_VALUE;
for (NamedElement operation : invocations) {
if (operation instanceof Iteration) {
Iteration iteration = (Iteration) operation;
int iteratorsSize = iteration.getOwnedIterator().size();
if ((bestIteration == null) || (iteratorsSize <= bestIteratorsSize)) {
Type specializedType = iteration.getOwningType();
if (specializedType != null) {
Type unspecializedType = PivotUtil.getUnspecializedTemplateableElement(specializedType);
if ((bestType == null) || !metaModelManager.isSuperClassOf(unspecializedType, bestType)) {
bestIteration = iteration;
bestType = unspecializedType;
bestIteratorsSize = iteratorsSize;
}
}
}
}
}
return bestIteration;
}
protected @Nullable Operation getExampleOperation(@NonNull List<NamedElement> invocations) {
if (invocations.size() <= 1) {
NamedElement namedElement = invocations.get(0);
return namedElement instanceof Operation ? (Operation)namedElement : null;
}
@SuppressWarnings("null")@NonNull EReference aReferredOperation = PivotPackage.Literals.OPERATION_CALL_EXP__REFERRED_OPERATION;
EnvironmentView environmentView = new EnvironmentView(metaModelManager, aReferredOperation, null);
environmentView.addElements(invocations);
environmentView.resolveDuplicates();
Object content = environmentView.getEntries().iterator().next().getValue();
if (content instanceof List<?>) {
content = ((List<?>)content).get(0);
}
return (Operation) content;
}
/* private TemplateParameter getFormal(List<TemplateBinding> templateBindings, TemplateParameter templateParameter) {
for (TemplateBinding templateBinding : templateBindings) {
for (TemplateParameterSubstitution templateParameterSubstitution : templateBinding.getParameterSubstitution()) {
if (templateParameter == templateParameterSubstitution.getFormal()) {
return templateParameterSubstitution.getActual().getOwningTemplateParameter();
}
}
}
return null;
} */
protected @Nullable List<NamedElement> getInvocations(@Nullable OCLExpression sourceExp, @NonNull InvocationExpCS csInvocationExp) {
NameExpCS csNameExp = csInvocationExp.getNameExp();
if (csNameExp == null) {
return null;
}
PathNameCS csPathName = csNameExp.getPathName();
if (csPathName == null) {
return null;
}
List<PathElementCS> csPathElements = csPathName.getPath();
if (csPathElements == null) {
return null;
}
int pathSize = csPathElements.size();
if (pathSize <= 0) {
return null;
}
PathElementCS csLastPathElement = csPathElements.get(pathSize-1);
if (csLastPathElement == null) {
return null;
}
Element asElement = csLastPathElement.basicGetElement();
if ((asElement instanceof Operation) && !asElement.eIsProxy()) {
return Collections.singletonList((NamedElement)asElement);
}
String name = ElementUtil.getTextName(csLastPathElement);
if (name == null) {
return null;
}
int iteratorCount = 0;
int expressionCount = 0;
for (NavigatingArgCS csArg : csInvocationExp.getArgument()) {
if (csArg.getRole() == NavigationRole.ITERATOR) {
iteratorCount++;
}
else if (csArg.getRole() == NavigationRole.EXPRESSION) {
expressionCount++;
}
}
if (pathSize > 1) { // Search for B::b() or a.B::b() candidates in B
Element asScope = csPathElements.get(pathSize - 2).getElement();
if (!(asScope instanceof Type)) {
return null;
}
Type asType = (Type)asScope;
List<NamedElement> invocations = getInvocations(asType, name, iteratorCount, expressionCount);
if ((invocations == null) && name.startsWith("_")) {
@SuppressWarnings("null")@NonNull String unescapedName = name.substring(1); // FIXME Compatibility
invocations = getInvocations(asType, unescapedName, iteratorCount, expressionCount);
}
return invocations;
}
else if (sourceExp != null) { // Search for a.b() candidates in type of a
Type asType = sourceExp.getType();
if (asType == null) {
return null;
}
if (asType.getOwningTemplateParameter() != null) {
asType = metaModelManager.getOclAnyType();
}
List<NamedElement> invocations = getInvocations(asType, name, iteratorCount, expressionCount);
if ((invocations == null) && name.startsWith("_")) {
@SuppressWarnings("null")@NonNull String unescapedName = name.substring(1); // FIXME Compatibility
invocations = getInvocations(asType, unescapedName, iteratorCount, expressionCount);
}
return invocations;
}
else { // Search for a() candidates in implicit source variable types
List<NamedElement> invocations = null;
for (ImplicitSourceTypeIterator it = createImplicitSourceTypeIterator(csInvocationExp); (invocations == null) && it.hasNext(); ) {
Type asType = it.next();
invocations = getInvocations(asType, name, iteratorCount, expressionCount);
}
if ((invocations == null) && name.startsWith("_")) {
@SuppressWarnings("null")@NonNull String unescapedName = name.substring(1); // FIXME Compatibility
for (ImplicitSourceTypeIterator it = createImplicitSourceTypeIterator(csInvocationExp); (invocations == null) && it.hasNext(); ) {
Type asType = it.next();
invocations = getInvocations(asType, unescapedName, iteratorCount, expressionCount);
}
}
return invocations;
}
}
protected @Nullable VariableDeclaration getImplicitSource(@NonNull ModelElementCS csExp, @NonNull Type requiredType) {
@Nullable VariableDeclaration lastVariable = null;
for (ImplicitSourceVariableIterator it = new ImplicitSourceVariableIterator(csExp); it.hasNext(); ) {
@NonNull Variable variable = it.next();
lastVariable = variable;
Type type = variable.getType();
if ((type != null) && type.conformsTo(metaModelManager, requiredType)) {
return variable;
}
}
return lastVariable; // If no good variable found, the outermost variable is the least bad.
} // FIXME report all possible variables as bad to user
/**
* Return all operations/iterations in asType and its superclasses whose name is name. For iterations the number of iteration iterators must
* match iteratorCount unless iteratorCount is zero. For operations the number of parameters must be expressionCount. Returns null if
* nothing is found.
*/
protected @Nullable List<NamedElement> getInvocations(@NonNull Type asType, @NonNull String name, int iteratorCount, int expressionCount) {
Iterable<? extends DomainOperation> instanceOperations = metaModelManager.getAllOperations(asType, FeatureFilter.SELECT_NON_STATIC, name);
List<NamedElement> invocations = getInvocationsInternal(null, instanceOperations, iteratorCount, expressionCount);
if (asType instanceof ElementExtension) {
Type asStereotype = ((ElementExtension)asType).getStereotype();
if (asStereotype != null) {
Iterable<? extends DomainOperation> stereotypeOperations = metaModelManager.getAllOperations(asStereotype, FeatureFilter.SELECT_NON_STATIC, name);
invocations = getInvocationsInternal(invocations, stereotypeOperations, iteratorCount, expressionCount);
}
}
if (asType instanceof Metaclass<?>) {
Type instanceType = ((Metaclass<?>)asType).getInstanceType();
if (instanceType != null) {
Iterable<? extends DomainOperation> classOperations = metaModelManager.getAllOperations(instanceType, FeatureFilter.SELECT_STATIC, name);
invocations = getInvocationsInternal(invocations, classOperations, iteratorCount, expressionCount);
}
}
return invocations;
}
protected @Nullable List<NamedElement> getInvocationsInternal(@Nullable List<NamedElement> invocations,
@NonNull Iterable<? extends DomainOperation> allOperations, int iteratorCount, int expressionCount) {
for (DomainOperation operation : allOperations) {
Operation asOperation = null;
if (operation instanceof Iteration) {
Iteration candidateIteration = (Iteration) operation;
int iteratorsSize = candidateIteration.getOwnedIterator().size();
if ((iteratorCount == 0) || (iteratorCount == iteratorsSize)) {
asOperation = candidateIteration;
}
}
else if (operation instanceof Operation){
Operation candidateOperation = (Operation) operation;
int operationsSize = candidateOperation.getOwnedParameter().size();
if (expressionCount == operationsSize) {
asOperation = candidateOperation;
}
}
if (asOperation != null) {
if (invocations == null) {
invocations = new ArrayList<NamedElement>();
}
invocations.add(asOperation);
}
}
return invocations;
}
protected boolean isInvalidType(@Nullable Type type) {
return (type == null) || (type instanceof InvalidType)
|| ((type instanceof CollectionType) && (((CollectionType)type).getElementType() instanceof InvalidType));
}
protected @NonNull OperationCallExp refreshOperationCallExp(@NonNull InvocationExpCS csInvocationExp, @NonNull OCLExpression sourceExp) {
OperationCallExp callExp = context.refreshModelElement(OperationCallExp.class, PivotPackage.Literals.OPERATION_CALL_EXP, csInvocationExp);
callExp.setSource(sourceExp);
return callExp;
}
protected @NonNull OppositePropertyCallExp refreshOppositePropertyCallExp(@NonNull NameExpCS csNameExp, @NonNull OCLExpression sourceExp, @NonNull Property property) {
OppositePropertyCallExp callExp = context.refreshModelElement(OppositePropertyCallExp.class, PivotPackage.Literals.OPPOSITE_PROPERTY_CALL_EXP, csNameExp);
callExp.setSource(sourceExp);
callExp.setReferredProperty(property.getOpposite());
return callExp;
}
protected @NonNull PropertyCallExp refreshPropertyCallExp(@NonNull NameExpCS csNameExp, @NonNull OCLExpression sourceExp, @NonNull Property property) {
PropertyCallExp callExp = context.refreshModelElement(PropertyCallExp.class, PivotPackage.Literals.PROPERTY_CALL_EXP, csNameExp);
callExp.setSource(sourceExp);
callExp.setReferredProperty(property);
return callExp;
}
protected void resolveAtPre(@Nullable NameExpCS csNameExp, @NonNull FeatureCallExp featureCallExp) {
if (csNameExp != null) {
featureCallExp.setIsPre(csNameExp.isAtPre());
}
}
/**
* Resolve an invocation such as name() or source.name(...) or source->name(...) to the best candidate from invocations.
* <p>
* sourceExp is null for an implicit source invocation.
* <p>
* csInvocationExp.getNamedElement() must be invoked once, after the left-hand context has been established to enable the lokup to
* proceed in a simple (perhaps rivial) fashion.
*/
protected @Nullable OCLExpression resolveBestInvocation(@Nullable OCLExpression sourceExp, @NonNull InvocationExpCS csInvocationExp, @NonNull List<NamedElement> invocations) {
Iteration iteration = getBestIteration(invocations);
if (iteration != null) {
if (sourceExp == null) {
sourceExp = createImplicitSourceVariableExp(csInvocationExp, iteration.getOwningType());
}
LoopExp iterationCallExp = resolveIterationCallExp(csInvocationExp, sourceExp, iteration);
@SuppressWarnings("unused")NamedElement namedElement = csInvocationExp.getNamedElement(); // Now let Xtext find the iteration
resolveIterationContent(csInvocationExp, iterationCallExp);
return iterationCallExp;
}
else {
Operation exampleOperation = getExampleOperation(invocations);
if (exampleOperation != null) {
if (sourceExp == null) {
sourceExp = createImplicitSourceVariableExp(csInvocationExp, exampleOperation.getOwningType());
}
OperationCallExp operationCallExp = refreshOperationCallExp(csInvocationExp, sourceExp);
if (invocations.size() == 1) {
context.setReferredOperation(operationCallExp, exampleOperation);
}
//
// Need to resolve types for operation arguments in order to disambiguate operation names.
//
resolveOperationArgumentTypes(csInvocationExp);
//
// Resolve the static operation/iteration by name and known operation argument types.
//
NamedElement namedElement = csInvocationExp.getNamedElement(); // Now let Xtext resolve the operation
if (namedElement instanceof Operation) {
return resolveOperationCallExp(csInvocationExp, operationCallExp, (Operation)namedElement);
}
}
}
return null;
}
protected @NonNull EnumLiteralExp resolveEnumLiteral(@NonNull ExpCS csExp, @NonNull EnumerationLiteral enumerationLiteral) {
EnumLiteralExp expression = context.refreshModelElement(EnumLiteralExp.class, PivotPackage.Literals.ENUM_LITERAL_EXP, csExp);
context.setType(expression, enumerationLiteral.getEnumeration(), true);
expression.setReferredEnumLiteral(enumerationLiteral);
return expression;
}
/**
* Resolve an invocation such as source.name or source->name
*/
protected @NonNull OCLExpression resolveExplicitSourceNavigation(@NonNull OCLExpression sourceExp, @NonNull NameExpCS csNamedExp) {
NamedElement namedElement = csNamedExp.getNamedElement();
if ((namedElement instanceof Property) && !namedElement.eIsProxy()) {
CallExp callExp = resolvePropertyCallExp(sourceExp, csNamedExp, (Property)namedElement);
return callExp;
}
PropertyCallExp expression = refreshPropertyCallExp(csNamedExp, sourceExp, metaModelManager.getOclInvalidProperty());
context.setType(expression, metaModelManager.getOclInvalidType(), false);
return expression;
}
protected @NonNull OCLExpression resolveImplicitAsSet(@NonNull OCLExpression sourceExp, @NonNull Type sourceType, @NonNull NavigationOperatorCS csOperator) {
OperationCallExp expression = context.refreshModelElement(OperationCallExp.class, PivotPackage.Literals.OPERATION_CALL_EXP, null);
expression.setImplicit(true);
PivotUtil.resetContainer(sourceExp);
expression.setSource(sourceExp);
expression.setName("oclAsSet");
resolveOperationCall(expression, csOperator, new ImplicitCollectionFilter(sourceType));
return expression;
}
/**
* Return a non-null implicit collect() call if a sourceExp for a csElement requires an implicit collect.
* The return call has noo bosdy or return type since they cannot be synmthesized until the body is synthesized.
*/
protected @Nullable IteratorExp resolveImplicitCollectExp(@NonNull OCLExpression sourceExp, @NonNull AbstractNameExpCS csElement) {
OperatorCS parent = csElement.getParent();
if (!(parent instanceof NavigationOperatorCS)) {
return null;
}
if (parent.getSource() == csElement) {
return null;
}
NavigationOperatorCS navigationOperatorCS = (NavigationOperatorCS)parent;
if (!PivotConstants.OBJECT_NAVIGATION_OPERATOR.equals(navigationOperatorCS.getName())) {
return null;
}
Type actualSourceType = sourceExp.getType();
if (!(actualSourceType instanceof CollectionType)) {
return null;
}
Type elementType = ((CollectionType)actualSourceType).getElementType();
if (elementType == null) {
return null;
}
IteratorExp implicitCollectExp = context.refreshModelElement(IteratorExp.class, PivotPackage.Literals.ITERATOR_EXP, null);
implicitCollectExp.setSource(sourceExp);
implicitCollectExp.setImplicit(true);
@SuppressWarnings("null") @NonNull EReference eReference = PivotPackage.Literals.LOOP_EXP__REFERRED_ITERATION;
EnvironmentView environmentView = new EnvironmentView(metaModelManager, eReference, "collect");
environmentView.addFilter(new ImplicitCollectFilter((CollectionType) actualSourceType, elementType));
Type lowerBoundType = (Type) PivotUtil.getLowerBound(actualSourceType);
environmentView.computeLookups(lowerBoundType, null);
Iteration resolvedIteration = (Iteration)environmentView.getContent();
if (resolvedIteration == null) {
return null;
}
context.setReferredIteration(implicitCollectExp, resolvedIteration);
Variable iterator = context.refreshModelElement(Variable.class, PivotPackage.Literals.VARIABLE, null); // FIXME reuse
Parameter resolvedIterator = resolvedIteration.getOwnedIterator().get(0);
iterator.setRepresentedParameter(resolvedIterator);
context.refreshName(iterator, "1_");
context.setType(iterator, elementType, false);
iterator.setImplicit(true);
implicitCollectExp.getIterator().add(iterator);
return implicitCollectExp;
}
/**
* Resolve an invocation such as name() or source.name(...) or source->name(...)
*/
protected @NonNull OCLExpression resolveInvocation(@Nullable OCLExpression sourceExp, @NonNull InvocationExpCS csInvocationExp) {
List<NamedElement> invocations = getInvocations(sourceExp, csInvocationExp);
if (invocations != null) {
OCLExpression invocationExp = resolveBestInvocation(sourceExp, csInvocationExp, invocations);
if (invocationExp != null) {
return invocationExp;
}
}
else {
checkForInvalidImplicitSourceType(csInvocationExp);
csInvocationExp.getNamedElement(); // Now let Xtext register the unresolved operation
}
if (sourceExp == null) {
sourceExp = createImplicitSourceVariableExp(csInvocationExp, metaModelManager.getOclAnyType());
}
OperationCallExp operationCallExp = refreshOperationCallExp(csInvocationExp, sourceExp);
context.setReferredOperation(operationCallExp, metaModelManager.getOclInvalidOperation());
context.installPivotUsage(csInvocationExp, operationCallExp);
context.setType(operationCallExp, metaModelManager.getOclInvalidType(), false);
return operationCallExp;
}
protected void resolveIterationAccumulators(@NonNull InvocationExpCS csInvocationExp, @NonNull LoopExp expression) {
Iteration iteration = expression.getReferredIteration();
List<Variable> pivotAccumulators = new ArrayList<Variable>();
//
// Explicit accumulator
//
for (NavigatingArgCS csArgument : csInvocationExp.getArgument()) {
if (csArgument.getRole() != NavigationRole.ACCUMULATOR) {
continue;
}
ExpCS csName = csArgument.getName();
Variable acc = PivotUtil.getPivot(Variable.class, csName);
if (acc != null) {
context.installPivotUsage(csArgument, acc);
ExpCS csInit = csArgument.getInit();
if (csInit != null) {
OCLExpression initExpression = context.visitLeft2Right(OCLExpression.class, csInit);
acc.setInitExpression(initExpression);
TypedRefCS csAccType = csArgument.getOwnedType();
Type initType = initExpression.getType();
Type accType;
if (csAccType != null) {
accType = PivotUtil.getPivot(Type.class, csAccType);
}
else {
accType = initType;
}
if (metaModelManager.isUnderspecified(initType)) {
initExpression.setType(accType);
}
context.setType(acc, accType, false);
}
acc.setRepresentedParameter(iteration.getOwnedAccumulator().get(pivotAccumulators.size()));
pivotAccumulators.add(acc);
}
if (csArgument.getInit() == null) {
context.addDiagnostic(csArgument, "Missing initializer for accumulator");
}
// if (csArgument.getOwnedType() != null) {
// context.addError(csArgument, "Unexpected type for parameter");
// }
}
//
// Implicit Accumulator
//
if (expression instanceof IterateExp) {
IterateExp iterateExp = (IterateExp)expression;
if (pivotAccumulators.size() > 1) {
context.addDiagnostic(csInvocationExp, "Iterate '" + csInvocationExp.getPathName() + "' cannot have more than one accumulator");
}
else {
iterateExp.setResult(pivotAccumulators.get(0));
}
}
else if (pivotAccumulators.size() > 0) {
context.addDiagnostic(csInvocationExp, "Iteration '" + csInvocationExp.getPathName() + "' cannot have an accumulator");
}
}
protected void resolveIterationBody(@NonNull InvocationExpCS csInvocationExp, @NonNull LoopExp expression) {
List<OCLExpression> pivotBodies = new ArrayList<OCLExpression>();
for (NavigatingArgCS csArgument : csInvocationExp.getArgument()) {
if (csArgument.getRole() == NavigationRole.EXPRESSION) {
if (csArgument.getInit() != null) {
context.addDiagnostic(csArgument, "Unexpected initializer for expression");
}
if (csArgument.getOwnedType() != null) {
context.addDiagnostic(csArgument, "Unexpected type for expression");
}
ExpCS name = csArgument.getName();
assert name != null;
OCLExpression exp = context.visitLeft2Right(OCLExpression.class, name);
// context.installPivotElement(csArgument, exp);
if (exp != null) {
context.installPivotUsage(csArgument, exp);
pivotBodies.add(exp);
}
else {
pivotBodies.add(context.addBadExpressionError(csArgument, "Invalid '" + csInvocationExp.getPathName() + "' iteration body"));
}
}
}
if (pivotBodies.size() != 1) {
expression.setBody(context.addBadExpressionError(csInvocationExp, "Iteration '" + csInvocationExp.getPathName() + "' must have exactly one body"));
}
else {
expression.setBody(pivotBodies.get(0));
}
}
protected @NonNull LoopExp resolveIterationCallExp(@NonNull InvocationExpCS csInvocationExp, @NonNull OCLExpression sourceExp, @NonNull Iteration iteration) {
LoopExp expression;
if (iteration.getOwnedAccumulator().size() > 0) {
expression = context.refreshModelElement(IterateExp.class, PivotPackage.Literals.ITERATE_EXP, csInvocationExp);
}
else {
expression = context.refreshModelElement(IteratorExp.class, PivotPackage.Literals.ITERATOR_EXP, csInvocationExp);
}
expression.setSource(sourceExp);
context.setReferredIteration(expression, iteration);
return expression;
}
protected void resolveIterationContent(@NonNull InvocationExpCS csInvocationExp, @NonNull LoopExp expression) {
OCLExpression source = DomainUtil.nonNullState(expression.getSource());
resolveIterationIterators(csInvocationExp, source, expression);
resolveIterationAccumulators(csInvocationExp, expression);
resolveOperationArgumentTypes(csInvocationExp);
resolveIterationBody(csInvocationExp, expression);
resolveOperationReturnType(expression);
}
protected void resolveIterationIterators(@NonNull InvocationExpCS csInvocationExp, @NonNull OCLExpression source, @NonNull LoopExp expression) {
Iteration iteration = expression.getReferredIteration();
List<Variable> pivotIterators = new ArrayList<Variable>();
//
// Explicit iterators
//
int iterationIteratorsSize = iteration.getOwnedIterator().size();
Type sourceType = ((CollectionType)csInvocationExp.getSourceType()).getElementType();
Type sourceElementType = sourceType != null ? metaModelManager.getPrimaryType(sourceType) : null;
for (int argIndex = 0; argIndex < csInvocationExp.getArgument().size(); argIndex++) {
NavigatingArgCS csArgument = csInvocationExp.getArgument().get(argIndex);
if (csArgument.getRole() != NavigationRole.ITERATOR) {
continue;
}
if (iterationIteratorsSize <= argIndex) {
context.addWarning(csArgument, OCLMessages.RedundantIterator_WARNING_, iteration.getName());
continue;
}
if (csArgument.getInit() != null) {
context.addDiagnostic(csArgument, "Unexpected initializer for iterator");
}
// if (csArgument.getOwnedType() == null) {
// context.addError(csArgument, "Missing type for iterator");
// }
ExpCS csName = csArgument.getName();
Variable iterator = PivotUtil.getPivot(Variable.class, csName);
if (iterator != null) {
context.installPivotUsage(csArgument, iterator);
iterator.setRepresentedParameter(iteration.getOwnedIterator().get(pivotIterators.size()));
TypedRefCS csType = csArgument.getOwnedType();
Type varType = csType != null ? PivotUtil.getPivot(Type.class, csType) : sourceElementType;
if (varType == null) {
varType = sourceElementType;
}
context.setType(iterator, varType, false);
pivotIterators.add(iterator);
}
}
//
// Implicit Iterators
//
while (pivotIterators.size() < iterationIteratorsSize) {
String varName = Integer.toString(pivotIterators.size()+1) + "_";
Variable iterator = context.refreshModelElement(Variable.class, PivotPackage.Literals.VARIABLE, null);
context.refreshName(iterator, varName);
context.setType(iterator, sourceElementType, false);
iterator.setImplicit(true);
iterator.setRepresentedParameter(iteration.getOwnedIterator().get(pivotIterators.size()));
pivotIterators.add(iterator);
}
context.refreshList(expression.getIterator(), pivotIterators);
}
/**
* Determine the type of each operation argument so that the appropriate operation overload can be selected.
* Arguments aligned with type (MetaClass) parameters are set to be parsed as types avoiding ambiguities from
* implicit opposite properties. Iterator bodies are left unresolved.
*/
protected void resolveOperationArgumentTypes(@NonNull InvocationExpCS csInvocationExp) {
int argIndex = 0;
for (NavigatingArgCS csArgument : csInvocationExp.getArgument()) {
if (csArgument.getRole() == NavigationRole.ITERATOR) {
break;
}
else if (csArgument.getRole() == NavigationRole.ACCUMULATOR) {
break;
}
else if (csArgument.getRole() == NavigationRole.EXPRESSION) {
ExpCS csName = csArgument.getName();
if (csName != null) {
if (csName instanceof NameExpCS) {
PathNameCS csPathName = ((NameExpCS)csName).getPathName();
if (csPathName != null) {
Element callExp = csInvocationExp.getPivot();
if (callExp instanceof OperationCallExp) {
Operation operation = ((OperationCallExp)callExp).getReferredOperation();
if (operation != null) {
List<Parameter> parameters = operation.getOwnedParameter();
if (argIndex < parameters.size()) {
Type type = parameters.get(argIndex).getType();
if (type instanceof Metaclass<?>) {
CS2Pivot.setElementType(csPathName, PivotPackage.Literals.NAMED_ELEMENT, csName, TypeArgumentFilter.INSTANCE);
}
}
}
}
}
}
OCLExpression arg = context.visitLeft2Right(OCLExpression.class, csName);
if (arg != null) {
context.installPivotUsage(csArgument, arg);
}
}
argIndex++;
}
}
}
/**
* Complete the installation of each operation argument in its operation call.
*/
protected void resolveOperationArguments(@NonNull InvocationExpCS csInvocationExp, @NonNull Operation operation, @NonNull OperationCallExp expression) {
List<OCLExpression> pivotArguments = new ArrayList<OCLExpression>();
List<NavigatingArgCS> csArguments = csInvocationExp.getArgument();
List<Parameter> ownedParameters = operation.getOwnedParameter();
int parametersCount = ownedParameters.size();
int csArgumentCount = csArguments.size();
if (csArgumentCount > 0) {
if (csArguments.get(0).getRole() != NavigationRole.EXPRESSION) {
context.addDiagnostic(csInvocationExp, "Operation calls can only specify expressions");
}
for (int argIndex = 0; argIndex < csArgumentCount; argIndex++) {
NavigatingArgCS csArgument = csArguments.get(argIndex);
if (csArgument.getInit() != null) {
context.addDiagnostic(csArgument, "Unexpected initializer for expression");
}
if (csArgument.getOwnedType() != null) {
context.addDiagnostic(csArgument, "Unexpected type for expression");
}
OCLExpression arg = PivotUtil.getPivot(OCLExpression.class, csArgument);
if (arg != null) {
pivotArguments.add(arg);
}
}
}
if ((csArgumentCount != parametersCount) && (operation != metaModelManager.basicGetOclInvalidOperation())) {
String boundMessage = DomainUtil.bind(OCLMessages.MismatchedArgumentCount_ERROR_, csArgumentCount, parametersCount);
context.addDiagnostic(csInvocationExp, boundMessage);
}
context.refreshList(expression.getArgument(), pivotArguments);
}
protected void resolveOperationCall(@NonNull OperationCallExp expression, @NonNull OperatorCS csOperator, @NonNull ScopeFilter filter) {
Type sourceType = PivotUtil.getType(expression.getSource());
Operation operation = null;
if (!AUTOGENERATED_LOOKUP) {
@SuppressWarnings("null") @NonNull EReference eReference = PivotPackage.Literals.OPERATION_CALL_EXP__REFERRED_OPERATION;
EnvironmentView environmentView = new EnvironmentView(metaModelManager, eReference, expression.getName());
environmentView.addFilter(filter);
int size = 0;
if (sourceType != null) {
Type lowerBoundType = (Type) PivotUtil.getLowerBound(sourceType);
size = environmentView.computeLookups(lowerBoundType, null);
}
if (size == 1) {
operation = (Operation)environmentView.getContent();
}
}
else {
ISingleResultEnvironment env = lResolver.computeReferredOperationLookup(expression, filter);
if (env.getSize() == 1) {
operation = (Operation) env.getSingleResult();
}
}
if (operation != null) {
context.setReferredOperation(expression, operation);
resolveOperationReturnType(expression);
}
else {
StringBuilder s = new StringBuilder();
for (OCLExpression argument : expression.getArgument()) {
Type argumentType = PivotUtil.getType(argument);
if (s.length() > 0) {
s.append(",");
}
if (argumentType != null) {
s.append(argumentType.toString());
}
}
String boundMessage;
if (s.length() > 0) {
boundMessage = DomainUtil.bind(OCLMessages.UnresolvedOperationCall_ERROR_, csOperator, sourceType, s.toString());
}
else {
boundMessage = DomainUtil.bind(OCLMessages.UnresolvedOperation_ERROR_, csOperator, sourceType);
}
// context.addBadExpressionError(csOperator, boundMessage);
context.addDiagnostic(csOperator, boundMessage);
context.setReferredOperation(expression, metaModelManager.getOclInvalidOperation());
context.setType(expression, metaModelManager.getOclInvalidType(), false);
}
}
protected @NonNull OperationCallExp resolveOperationCallExp(@NonNull InvocationExpCS csInvocationExp, @NonNull OperationCallExp operationCallExp, @NonNull Operation operation) {
context.setReferredOperation(operationCallExp, operation);
resolveAtPre(csInvocationExp.getNameExp(), operationCallExp);
context.installPivotUsage(csInvocationExp, operationCallExp);
resolveOperationArguments(csInvocationExp, operation, operationCallExp);
resolveOperationReturnType(operationCallExp);
return operationCallExp;
}
protected void resolveOperationReturnType(@NonNull CallExp callExp) {
Operation operation = null;
if (callExp instanceof OperationCallExp) {
operation = ((OperationCallExp)callExp).getReferredOperation();
}
else if (callExp instanceof LoopExp) {
operation = ((LoopExp)callExp).getReferredIteration();
}
if (operation == null) {
return;
}
Map<TemplateParameter, ParameterableElement> templateBindings = new HashMap<TemplateParameter, ParameterableElement>();
Type sourceType = null;
OCLExpression source = callExp.getSource();
if (source != null) {
sourceType = source.getType();
}
if (sourceType != null) {
if (operation.isStatic() && (sourceType instanceof Metaclass<?>)) {
sourceType = ((Metaclass<?>)sourceType).getInstanceType();
}
templateBindings.put(null, sourceType); // Use the null key to pass OclSelf without creating an object
}
PivotUtil.getAllTemplateParameterSubstitutions(templateBindings, sourceType);
// PivotUtil.getAllTemplateParameterSubstitutions(templateBindings, operation);
TemplateSignature templateSignature = operation.getOwnedTemplateSignature();
if (templateSignature != null) {
for (TemplateParameter templateParameter : templateSignature.getOwnedParameter()) {
templateBindings.put(templateParameter, null);
}
}
String implementationClass = operation.getImplementationClass();
if ((implementationClass != null) && implementationClass.equals(CollectionFlattenOperation.class.getName())) { // FIXME Use Tree(T) to make this modellable
Type elementType = sourceType;
while (elementType instanceof CollectionType) {
elementType = ((CollectionType)elementType).getElementType();
}
if (elementType != null) {
templateBindings.put(operation.getOwnedTemplateSignature().getOwnedParameter().get(0), elementType);
}
}
@SuppressWarnings("unused") // Should never happen; just for debugging
boolean isConformant = true;
if (callExp instanceof OperationCallExp) {
List<Parameter> parameters = operation.getOwnedParameter();
List<OCLExpression> arguments = ((OperationCallExp)callExp).getArgument();
int iMax = Math.min(parameters.size(), arguments.size());
for (int i = 0; i < iMax; i++) {
Parameter parameter = parameters.get(i);
OCLExpression argument = arguments.get(i);
Type parameterType = PivotUtil.getType(parameter);
Type argumentType = PivotUtil.getType(argument);
if ((parameterType != null) && (argumentType != null)) {
if (!metaModelManager.conformsTo(argumentType, parameterType, templateBindings)) {
isConformant = false;
}
}
}
}
else if (callExp instanceof LoopExp) {
if (callExp instanceof IterateExp) {
List<Parameter> accumulators = ((Iteration)operation).getOwnedAccumulator();
if (accumulators.size() >= 1) {
Parameter accumulator = accumulators.get(0);
Variable result = ((IterateExp)callExp).getResult();
Type accumulatorType = PivotUtil.getType(accumulator);
Type resultType = PivotUtil.getType(result);
if ((accumulatorType != null) && (resultType != null)) {
if (!metaModelManager.conformsTo(resultType, accumulatorType, templateBindings)) {
isConformant = false;
}
}
}
}
List<Parameter> parameters = ((Iteration)operation).getOwnedParameter();
if (parameters.size() >= 1) {
Parameter parameter = parameters.get(0);
OCLExpression body = ((LoopExp)callExp).getBody();
Type parameterType = PivotUtil.getType(parameter);
Type bodyType = PivotUtil.getType(body);
if ((bodyType != null) && (parameterType != null)) {
if (!metaModelManager.conformsTo(bodyType, parameterType, templateBindings)) {
isConformant = false;
}
}
}
}
Type behavioralType = PivotUtil.getType(operation);
Type returnType = behavioralType != null ? metaModelManager.getSpecializedType(behavioralType, templateBindings) : null;
if (operation instanceof Iteration) {
List<Parameter> formalIterators = ((Iteration)operation).getOwnedIterator();
List<Variable> actualIterators = ((LoopExp)callExp).getIterator();
int iMax = Math.min(formalIterators.size(), actualIterators.size());
for (int i = 0; i < iMax; i++) {
Parameter iterator = formalIterators.get(i);
Variable actualVariable = actualIterators.get(i);
Type behavioralIteratorType = PivotUtil.getType(iterator);
Type iteratorType = behavioralIteratorType != null ? metaModelManager.getSpecializedType(behavioralIteratorType, templateBindings) : null;
actualVariable.setType(iteratorType);
}
}
//
// The flattening of collect() and consequently implicit-collect is not modelled accurately so we need to code it.
//
if ((operation instanceof Iteration) && "collect".equals(operation.getName()) && (callExp instanceof LoopExp) && (returnType instanceof CollectionType)) {
OCLExpression body = ((LoopExp)callExp).getBody();
Type bodyType = PivotUtil.getType(body);
if (bodyType != null) {
if (bodyType instanceof CollectionType) {
@NonNull Type elementType = bodyType;
while (elementType instanceof CollectionType) {
Type elementType2 = ((CollectionType)elementType).getElementType();
if (elementType2 != null) {
elementType = elementType2;
}
}
boolean isOrdered = ((CollectionType)returnType).isOrdered();
returnType = metaModelManager.getCollectionType(isOrdered, false, elementType, null, null); // FIXME null, null
}
}
}
if (operation.isStatic() && (behavioralType != null) && (behavioralType.getOwningTemplateParameter() != null) && (returnType != null)) {
returnType = metaModelManager.getMetaclass(returnType);
}
context.setType(callExp, returnType, operation.isRequired());
}
protected @NonNull CallExp resolvePropertyCallExp(@NonNull OCLExpression sourceExp, @NonNull NameExpCS csNameExp, @NonNull Property property) {
NavigationCallExp callExp;
if (property.isImplicit()) {
callExp = refreshOppositePropertyCallExp(csNameExp, sourceExp, property);
}
else {
callExp = refreshPropertyCallExp(csNameExp, sourceExp, property);
}
// if (isInvalidType(property.getType())) {
// EssentialOCLUtils.setHasError(csNameExp);
// }
resolveAtPre(csNameExp, callExp);
Type returnType = resolvePropertyReturnType(sourceExp, csNameExp, property);
context.setType(callExp, returnType, property.isRequired());
return callExp;
}
protected Type resolvePropertyReturnType(@NonNull OCLExpression sourceExp, @NonNull NameExpCS csNameExp, @NonNull Property property) {
Map<TemplateParameter, ParameterableElement> templateBindings = new HashMap<TemplateParameter, ParameterableElement>();
Type sourceType = sourceExp.getType();
if (sourceType != null) {
if (property.isStatic() && (sourceType instanceof Metaclass<?>)) {
sourceType = ((Metaclass<?>)sourceType).getInstanceType();
}
templateBindings.put(null, sourceType); // Use the null key to pass OclSelf without creating an object
Type owningType = property.getOwningType();
if (owningType instanceof Metaclass) {
owningType = PivotUtil.getUnspecializedTemplateableElement(owningType);
templateBindings.put(owningType.getOwnedTemplateSignature().getOwnedParameter().get(0), sourceType); // Use the null key to pass OclSelf without creating an object
}
}
PivotUtil.getAllTemplateParameterSubstitutions(templateBindings, sourceType);
Type returnType = null;
Type behavioralType = PivotUtil.getType(property);
if (behavioralType != null) {
returnType = metaModelManager.getSpecializedType(behavioralType, templateBindings);
if (property.isStatic() && (behavioralType.getOwningTemplateParameter() != null)) {
returnType = metaModelManager.getMetaclass(returnType);
}
}
return returnType;
}
protected StateExp resolveStateExp(@NonNull ExpCS csExp, @NonNull State state) {
StateExp expression = context.refreshModelElement(StateExp.class, PivotPackage.Literals.STATE_EXP, csExp);
context.setType(expression, metaModelManager.getPivotType("State"), true); // FIXME What should this be
expression.setReferredState(state);
return expression;
}
protected @NonNull TypeExp resolveTypeExp(@NonNull ExpCS csExp, @NonNull Type type) {
TypeExp expression = context.refreshModelElement(TypeExp.class, PivotPackage.Literals.TYPE_EXP, csExp);
context.setType(expression, metaModelManager.getMetaclass(type), true);
expression.setReferredType(type);
return expression;
}
protected @NonNull VariableExp resolveVariableExp(@NonNull AbstractNameExpCS csNameExp, @NonNull VariableDeclaration variableDeclaration) {
VariableExp expression = context.refreshModelElement(VariableExp.class, PivotPackage.Literals.VARIABLE_EXP, csNameExp);
expression.setReferredVariable(variableDeclaration);
context.setType(expression, variableDeclaration.getType(), variableDeclaration.isRequired());
return expression;
}
@Override
public @NonNull Element visitBinaryOperatorCS(@NonNull BinaryOperatorCS csOperator) {
OperationCallExp expression = context.refreshModelElement(OperationCallExp.class, PivotPackage.Literals.OPERATION_CALL_EXP, csOperator);
String name = csOperator.getName();
assert name != null;
context.refreshName(expression, name);
ExpCS csSource = csOperator.getSource();
if (csSource != null) {
OCLExpression source = context.visitLeft2Right(OCLExpression.class, csSource);
expression.setSource(source);
ExpCS csArgument = csOperator.getArgument();
if (csArgument != null) {
OCLExpression argument = context.visitLeft2Right(OCLExpression.class, csArgument);
List<? extends OCLExpression> newElements = argument != null ? Collections.singletonList(argument) : Collections.<OCLExpression>emptyList();
context.refreshList(expression.getArgument(), newElements);
Type sourceType = PivotUtil.getType(source);
Type argumentType = PivotUtil.getType(argument);
if ((sourceType != null) && (argumentType != null)) {
resolveOperationCall(expression, csOperator, new BinaryOperationFilter(sourceType, argumentType));
}
}
}
return expression;
}
@Override
public Element visitBooleanLiteralExpCS(@NonNull BooleanLiteralExpCS csBooleanLiteralExp) {
BooleanLiteralExp expression = PivotUtil.getPivot(BooleanLiteralExp.class, csBooleanLiteralExp);
if (expression != null) {
expression.setBooleanSymbol(Boolean.valueOf(csBooleanLiteralExp.getName()));
context.setType(expression, metaModelManager.getBooleanType(), true);
}
return expression;
}
@Override
public Element visitCollectionLiteralExpCS(@NonNull CollectionLiteralExpCS csCollectionLiteralExp) {
Type commonType = null;
// InvalidLiteralExp invalidValue = null;
for (CollectionLiteralPartCS csPart : csCollectionLiteralExp.getOwnedParts()) {
assert csPart != null;
CollectionLiteralPart pivotPart = context.visitLeft2Right(CollectionLiteralPart.class, csPart);
Type type = pivotPart.getType();
// if (type instanceof InvalidType) { // FIXME Use propagated reason via InvalidType
// if (invalidValue == null) {
// invalidValue = metaModelManager.createInvalidValue(csPart, null, "Invalid Collection content", null);
// }
// }
// else
if (type != null) {
if (commonType == null) {
commonType = type;
}
else if (commonType != type) {
commonType = metaModelManager.getCommonType(commonType, type, null);
}
}
}
// if (invalidValue != null) {
// context.installPivotElement(csCollectionLiteralExp, invalidValue);
// return invalidValue;
// }
CollectionLiteralExp expression = PivotUtil.getPivot(CollectionLiteralExp.class, csCollectionLiteralExp);
if (expression != null) {
CollectionTypeCS ownedCollectionType = csCollectionLiteralExp.getOwnedType();
String collectionTypeName = ownedCollectionType.getName();
assert collectionTypeName != null;
TypedRefCS ownedElementType = ownedCollectionType.getOwnedType();
if (ownedElementType != null) {
commonType = (Type) ownedElementType.getPivot();
}
if (commonType == null) {
commonType = metaModelManager.createUnspecifiedType();
}
Type type = metaModelManager.getCollectionType(collectionTypeName, commonType, null, null);
context.setType(expression, type, true);
expression.setKind(PivotUtil.getCollectionKind((CollectionType) type));
}
return expression;
}
@Override
public Element visitCollectionLiteralPartCS(@NonNull CollectionLiteralPartCS csCollectionLiteralPart) {
ExpCS csFirst = csCollectionLiteralPart.getExpressionCS();
if (csFirst == null) {
return null;
}
OCLExpression pivotFirst = context.visitLeft2Right(OCLExpression.class, csFirst);
ExpCS csLast = csCollectionLiteralPart.getLastExpressionCS();
if (csLast == null) {
CollectionItem expression = PivotUtil.getPivot(CollectionItem.class, csCollectionLiteralPart);
if (expression != null) {
expression.setItem(pivotFirst);
}
}
else {
CollectionRange expression = PivotUtil.getPivot(CollectionRange.class, csCollectionLiteralPart);
if (expression != null) {
expression.setFirst(pivotFirst);
OCLExpression pivotLast = context.visitLeft2Right(OCLExpression.class, csLast);
expression.setLast(pivotLast);
}
}
Type type = pivotFirst.getType();
if (type == null) {
return null;
}
boolean isRequired = pivotFirst.isRequired();
if (csLast != null) {
OCLExpression pivotLast = PivotUtil.getPivot(OCLExpression.class, csLast);
if (pivotLast != null) {
Type secondType = pivotLast.getType();
if (secondType != null) {
type = metaModelManager.getCommonType(type, secondType, null);
}
isRequired &= pivotLast.isRequired();
}
}
CollectionLiteralPart expression = PivotUtil.getPivot(CollectionLiteralPart.class, csCollectionLiteralPart);
if (expression != null) {
context.setType(expression, type, isRequired);
}
return expression;
}
@Override
public Element visitCollectionTypeCS(@NonNull CollectionTypeCS object) {
return null;
}
@Override
public Element visitConstructorExpCS(@NonNull ConstructorExpCS csConstructorExp) {
ConstructorExp expression = PivotUtil.getPivot(ConstructorExp.class, csConstructorExp);
if (expression != null) {
expression.setType((Type) csConstructorExp.getNamedElement());
for (ConstructorPartCS csPart : csConstructorExp.getOwnedParts()) {
assert csPart != null;
context.visitLeft2Right(ConstructorPart.class, csPart);
}
}
return expression;
}
@Override
public Element visitConstructorPartCS(@NonNull ConstructorPartCS csConstructorPart) {
ConstructorPart pivotElement = PivotUtil.getPivot(ConstructorPart.class, csConstructorPart);
if (pivotElement != null) {
Property property = csConstructorPart.getProperty();
pivotElement.setReferredProperty(property);
context.refreshName(pivotElement, property.getName());
context.setType(pivotElement, property.getType(), property.isRequired());
ExpCS csInitExpression = csConstructorPart.getInitExpression();
if (csInitExpression != null) {
OCLExpression initExpression = context.visitLeft2Right(OCLExpression.class, csInitExpression);
pivotElement.setInitExpression(initExpression);
}
}
return pivotElement;
}
@Override
public Element visitContextCS(@NonNull ContextCS csContext) {
ExpressionInOCL pivotElement = PivotUtil.getPivot(ExpressionInOCL.class, csContext);
if (pivotElement != null) {
pivotElement.getLanguage().clear();
pivotElement.getBody().clear();
ExpCS csExpression = csContext.getOwnedExpression();
if (csExpression != null) {
pivotElement.getLanguage().add("OCL");
pivotElement.getBody().add(csExpression.toString());
OCLExpression expression = context.visitLeft2Right(OCLExpression.class, csExpression);
if (expression != null) {
PivotUtil.setBody(pivotElement, expression, ElementUtil.getExpressionText(csExpression));
context.setType(pivotElement, expression.getType(), expression.isRequired());
}
}
}
return pivotElement;
}
@Override
public Element visitExpCS(@NonNull ExpCS object) {
return null;
}
@Override
public Element visitIfExpCS(@NonNull IfExpCS csIfExp) {
IfExp expression = PivotUtil.getPivot(IfExp.class, csIfExp);
if (expression != null) {
ExpCS csIf = csIfExp.getCondition();
ExpCS csThen = csIfExp.getThenExpression();
ExpCS csElse = csIfExp.getElseExpression();
if ((csIf != null) && (csThen != null) && (csElse != null)) {
expression.setCondition(context.visitLeft2Right(OCLExpression.class, csIf));
OCLExpression thenExpression = context.visitLeft2Right(OCLExpression.class, csThen);
expression.setThenExpression(thenExpression);
OCLExpression elseExpression = context.visitLeft2Right(OCLExpression.class, csElse);
expression.setElseExpression(elseExpression);
Type thenType = thenExpression != null ? thenExpression.getType() : null;
Type elseType = elseExpression != null ? elseExpression.getType() : null;
Type commonType = (thenType != null) && (elseType != null) ? metaModelManager.getCommonType(thenType, elseType, null) : null;
boolean isRequired = ((thenExpression != null) && thenExpression.isRequired()) && ((elseExpression != null) && elseExpression.isRequired());
context.setType(expression, commonType, isRequired);
}
}
return expression;
}
@Override
public Element visitIndexExpCS(@NonNull IndexExpCS csIndexExp) {
// Navigating completions are orchestrated by the SimpleNamedExpCS.
return null;
}
@Override
public Element visitInfixExpCS(@NonNull InfixExpCS csInfixExp) {
//
// Find the root.
//
OperatorCS csRoot = csInfixExp.getOwnedOperator().get(0);
for (OperatorCS csParent = csRoot.getParent(); csParent != null; csParent = csParent.getParent()) {
csRoot = csParent;
}
//
// Build the corresponding AST and reuse as the Infix node.
//
OCLExpression pivot = context.visitLeft2Right(OCLExpression.class, csRoot);
if (pivot != null) {
context.installPivotUsage(csInfixExp, pivot);
}
return pivot;
}
@Override
public Element visitInvalidLiteralExpCS(@NonNull InvalidLiteralExpCS csInvalidLiteralExp) {
InvalidLiteralExp expression = PivotUtil.getPivot(InvalidLiteralExp.class, csInvalidLiteralExp);
if (expression == null) {
expression = metaModelManager.createInvalidExpression();
}
// expression.setType(metaModelManager.getOclInvalidType());
context.installPivotUsage(csInvalidLiteralExp, expression);
return expression;
}
/**
* Resolve an invocation such as name()
*/
@Override
public Element visitInvocationExpCS(@NonNull InvocationExpCS csInvocationExp) {
OperatorCS csParent = csInvocationExp.getParent();
if ((csParent instanceof NavigationOperatorCS) && (csInvocationExp != csParent.getSource())) {
// source.name(), source->name() are resolved by the parent NavigationOperatorCS
return PivotUtil.getPivot(OCLExpression.class, csInvocationExp);
}
return resolveInvocation(null, csInvocationExp);
}
@Override
public Element visitLetExpCS(@NonNull LetExpCS csLetExp) {
// Each CS Let Variable becomes a Pivot LetExpression and Variable
// The CS Let therefore just re-uses the Pivot of the first CS Let Variable
LetExp firstLetExp = null;
LetExp lastLetExp = null;
for (LetVariableCS csLetVariable : csLetExp.getVariable()) {
Variable variable = PivotUtil.getPivot(Variable.class, csLetVariable);
if (variable != null) {
LetExp letExp;
EObject variableContainer = variable.eContainer();
if (variableContainer instanceof LetExp) {
letExp = (LetExp)variableContainer;
}
else {
letExp = context.refreshModelElement(LetExp.class, PivotPackage.Literals.LET_EXP, null); // FIXME reuse
}
letExp.setVariable(variable);
ExpCS csInitExpression = csLetVariable.getInitExpression();
if (csInitExpression != null) {
OCLExpression initExpression = context.visitLeft2Right(OCLExpression.class, csInitExpression);
variable.setInitExpression(initExpression);
Type initType = initExpression != null ? initExpression.getType() : null;
boolean isRequired = variable.isRequired() && (initExpression != null) && initExpression.isRequired();
TypedRefCS csVariableType = csLetVariable.getOwnedType();
Type variableType = csVariableType != null ? PivotUtil.getPivot(Type.class, csVariableType) : null;
if (variableType == null) {
variableType = initType;
}
else if ((initExpression != null) && metaModelManager.isUnderspecified(initType)) {
initExpression.setType(variableType);
}
context.setType(variable, variableType, isRequired);
if (lastLetExp != null) {
lastLetExp.setIn(letExp);
context.installPivotUsage(csLetExp, letExp);
}
else {
firstLetExp = letExp;
context.installPivotUsage(csLetExp, firstLetExp);
}
lastLetExp = letExp;
}
}
}
if (lastLetExp != null) {
ExpCS csIn = csLetExp.getIn();
if (csIn != null) {
OCLExpression in = context.visitLeft2Right(OCLExpression.class, csIn);
lastLetExp.setIn(in);
if (in != null) {
Type type = in.getType();
for (OCLExpression letExp = firstLetExp; (letExp != in) && (letExp != null); letExp = ((LetExp)letExp).getIn()) {
context.setType(letExp, type, in.isRequired());
}
}
}
}
return firstLetExp;
}
@Override
public Element visitLetVariableCS(@NonNull LetVariableCS csLetVariable) {
return null; // Handled by parent
}
@Override
public Element visitNameExpCS(@NonNull NameExpCS csNameExp) {
checkForInvalidImplicitSourceType(csNameExp);
Element element = csNameExp.getNamedElement();
if ((element == null) || element.eIsProxy()) {
Element pivot = csNameExp.getPivot();
if (pivot instanceof InvalidLiteralExp) {
return pivot;
}
InvalidLiteralExp invalidLiteralExp = metaModelManager.createInvalidExpression();
context.installPivotUsage(csNameExp, invalidLiteralExp);
return invalidLiteralExp;
}
else if (element instanceof VariableDeclaration) {
return resolveVariableExp(csNameExp, (VariableDeclaration)element);
}
else if (element instanceof Property) {
Property property = (Property) element;
OCLExpression sourceExp = createImplicitSourceVariableExp(csNameExp, property.getOwningType());
return resolvePropertyCallExp(sourceExp, csNameExp, property);
}
else if (element instanceof Operation) {
return context.addBadExpressionError(csNameExp, "No parameters for operation " + ((Operation)element).getName());
}
else if (element instanceof Type) {
return resolveTypeExp(csNameExp, (Type) element);
}
else if (element instanceof EnumerationLiteral) {
return resolveEnumLiteral(csNameExp, (EnumerationLiteral) element);
}
else if (element instanceof State) {
return resolveStateExp(csNameExp, (State) element);
}
else {
return context.addBadExpressionError(csNameExp, "Unsupported NameExpCS " + element.eClass().getName()); // FIXME
}
}
@Override
public Element visitNavigatingArgCS(@NonNull NavigatingArgCS csNavigatingArg) {
OCLExpression pivot = PivotUtil.getPivot(OCLExpression.class, csNavigatingArg.getName());
if (pivot != null) {
context.installPivotUsage(csNavigatingArg, pivot);
}
return pivot;
}
@Override
public OCLExpression visitNavigationOperatorCS(@NonNull NavigationOperatorCS csOperator) {
OCLExpression navigatingExp = null;
ExpCS csSource = csOperator.getSource();
if (csSource != null) {
OCLExpression sourceExp = context.visitLeft2Right(OCLExpression.class, csSource);
if (sourceExp != null) {
Type actualSourceType = PivotUtil.getType(sourceExp);
if (actualSourceType != null) {
ExpCS argument = csOperator.getArgument();
if (argument instanceof AbstractNameExpCS) {
AbstractNameExpCS csNameExp = (AbstractNameExpCS) argument;
LoopExp implicitCollectExp = null;
OCLExpression collectedSourceExp = sourceExp;
//
// Condition the source for implicit set or implicit collect
//
String navigationOperatorName = csOperator.getName();
if (actualSourceType instanceof CollectionType) {
if (PivotConstants.OBJECT_NAVIGATION_OPERATOR.equals(navigationOperatorName)) {
implicitCollectExp = resolveImplicitCollectExp(sourceExp, csNameExp);
if (implicitCollectExp != null) {
@SuppressWarnings("null")@NonNull Variable iterator = implicitCollectExp.getIterator().get(0);
collectedSourceExp = createImplicitVariableExp(iterator);
}
}
}
else {
if (PivotConstants.COLLECTION_NAVIGATION_OPERATOR.equals(navigationOperatorName)) {
collectedSourceExp = resolveImplicitAsSet(sourceExp, actualSourceType, csOperator);
}
}
csNameExp.setSourceType(collectedSourceExp.getType());
//
// Resolve the inner call expression
//
OCLExpression callExp;
if (csNameExp instanceof InvocationExpCS) {
callExp = resolveInvocation(collectedSourceExp, (InvocationExpCS) csNameExp);
}
else if (argument instanceof NameExpCS) {
callExp = resolveExplicitSourceNavigation(collectedSourceExp, (NameExpCS) argument);
}
else {
callExp = context.addBadExpressionError(argument, "bad navigation argument");
}
//
// Complete the wrapping of the inner call expression in an outer implicit collect expression
//
if (callExp instanceof CallExp) {
if (implicitCollectExp != null) {
implicitCollectExp.setBody(callExp);
resolveOperationReturnType(implicitCollectExp);
navigatingExp = implicitCollectExp;
}
else {
navigatingExp = callExp;
}
}
else {
navigatingExp = callExp; // Place holder for an error
}
}
else if (argument != null) {
navigatingExp = context.addBadExpressionError(argument, "bad navigation argument");
}
}
}
if (navigatingExp != null) {
context.installPivotUsage(csOperator, navigatingExp);
}
}
return navigatingExp;
}
@Override
public Element visitNestedExpCS(@NonNull NestedExpCS csNestedExp) {
ExpCS csSource = csNestedExp.getSource();
if (csSource == null) {
return null;
}
OCLExpression pivot = context.visitLeft2Right(OCLExpression.class, csSource);
if (pivot != null) {
context.installPivotUsage(csNestedExp, pivot);
}
return pivot;
}
@Override
public Element visitNullLiteralExpCS(@NonNull NullLiteralExpCS csNullLiteralExp) {
NullLiteralExp expression = PivotUtil.getPivot(NullLiteralExp.class, csNullLiteralExp);
if (expression != null) {
context.setType(expression, metaModelManager.getOclVoidType(), false);
}
return expression;
}
@Override
public Element visitNumberLiteralExpCS(@NonNull NumberLiteralExpCS csNumberLiteralExp) {
NumericLiteralExp expression = PivotUtil.getPivot(NumericLiteralExp.class, csNumberLiteralExp);
if (expression instanceof UnlimitedNaturalLiteralExp) {
context.setType(expression, metaModelManager.getUnlimitedNaturalType(), true);
}
else if (expression instanceof IntegerLiteralExp) {
context.setType(expression, metaModelManager.getIntegerType(), true);
}
else if (expression != null){
context.setType(expression, metaModelManager.getRealType(), true);
}
return expression;
}
@Override
public Element visitOperatorCS(@NonNull OperatorCS object) {
return null;
}
@Override
public Element visitPrefixExpCS(@NonNull PrefixExpCS csPrefixExp) {
UnaryOperatorCS csRoot = csPrefixExp.getOwnedOperator().get(0);
if (csRoot == null) {
return null;
}
if (csPrefixExp.eContainer() instanceof InfixExpCS) {
// PrefixExpCS embedded in InfixExpCS is resolved as part of the Infix tree;
}
else {
// initializePrefixOperators(csPrefixExp, null);
context.visitLeft2Right(OCLExpression.class, csRoot);
}
OCLExpression pivotElement = PivotUtil.getPivot(OCLExpression.class, csRoot);
if (pivotElement != null) {
context.installPivotUsage(csPrefixExp, pivotElement);
}
return pivotElement;
}
@Override
public Element visitSelfExpCS(@NonNull SelfExpCS csSelfExp) { // FIXME Just use VariableExpCS
VariableExp expression = PivotUtil.getPivot(VariableExp.class, csSelfExp);
if (expression != null) {
ElementCS parent = csSelfExp.getLogicalParent();
if (parent != null) {
@SuppressWarnings("null") @NonNull EReference eReference = PivotPackage.Literals.EXPRESSION_IN_OCL__CONTEXT_VARIABLE;
EnvironmentView environmentView = new EnvironmentView(metaModelManager, eReference, Environment.SELF_VARIABLE_NAME);
ScopeView baseScopeView = BaseScopeView.getScopeView(metaModelManager, parent, eReference);
environmentView.computeLookups(baseScopeView);
VariableDeclaration variableDeclaration = (VariableDeclaration) environmentView.getContent();
if (variableDeclaration == null) {
return context.addBadExpressionError(csSelfExp, "The context of 'self' is unspecified");
}
expression.setReferredVariable(variableDeclaration);
context.setType(expression, variableDeclaration.getType(), true);
}
}
return expression;
}
@Override
public Element visitStringLiteralExpCS(@NonNull StringLiteralExpCS csStringLiteralExp) {
StringLiteralExp pivotElement = PivotUtil.getPivot(StringLiteralExp.class, csStringLiteralExp);
if (pivotElement != null) {
context.setType(pivotElement, metaModelManager.getStringType(), true);
}
return pivotElement;
}
@Override
public Element visitTupleLiteralExpCS(@NonNull TupleLiteralExpCS csTupleLiteralExp) {
TupleLiteralExp expression = PivotUtil.getPivot(TupleLiteralExp.class, csTupleLiteralExp);
if (expression != null) {
for (TupleLiteralPartCS csPart : csTupleLiteralExp.getOwnedParts()) {
assert csPart != null;
context.visitLeft2Right(TupleLiteralPart.class, csPart);
}
String tupleTypeName = "Tuple"; //ownedCollectionType.getName();
List<TupleLiteralPart> parts = expression.getPart();
assert parts != null;
Type type = metaModelManager.getTupleType(tupleTypeName, parts, null);
context.setType(expression, type, true);
}
return expression;
}
@Override
public Element visitTupleLiteralPartCS(@NonNull TupleLiteralPartCS csTupleLiteralPart) {
TupleLiteralPart pivotElement = PivotUtil.getPivot(TupleLiteralPart.class, csTupleLiteralPart);
if (pivotElement != null) {
ExpCS csInitExpression = csTupleLiteralPart.getInitExpression();
if (csInitExpression != null) {
OCLExpression initExpression = context.visitLeft2Right(OCLExpression.class, csInitExpression);
pivotElement.setInitExpression(initExpression);
TypedRefCS csType = csTupleLiteralPart.getOwnedType();
Type type = csType != null ? PivotUtil.getPivot(Type.class, csType) : initExpression.getType();
context.setType(pivotElement, type, initExpression.isRequired());
}
}
return pivotElement;
}
@Override
public Element visitTypeLiteralExpCS(@NonNull TypeLiteralExpCS csTypeLiteralExp) {
TypedRefCS csType = csTypeLiteralExp.getOwnedType();
// context.visitInOrder(csType, null);
Type type = PivotUtil.getPivot(Type.class, csType);
return type != null ? resolveTypeExp(csTypeLiteralExp, type) : null;
}
@Override
public Element visitUnaryOperatorCS(@NonNull UnaryOperatorCS csOperator) {
OperationCallExp expression = context.refreshModelElement(OperationCallExp.class, PivotPackage.Literals.OPERATION_CALL_EXP, csOperator);
String name = csOperator.getName();
assert name != null;
context.refreshName(expression, name);
ExpCS csSource = csOperator.getSource();
if (csSource != null) {
OCLExpression source = context.visitLeft2Right(OCLExpression.class, csSource);
if (source != null) {
expression.setSource(source);
Type sourceType = PivotUtil.getType(source);
if (sourceType != null) {
resolveOperationCall(expression, csOperator, new UnaryOperationFilter(sourceType));
}
}
}
return expression;
}
@Override
public Element visitUnlimitedNaturalLiteralExpCS(@NonNull UnlimitedNaturalLiteralExpCS csUnlimitedNaturalLiteralExp) {
UnlimitedNaturalLiteralExp expression = PivotUtil.getPivot(UnlimitedNaturalLiteralExp.class, csUnlimitedNaturalLiteralExp);
if (expression != null) {
context.setType(expression, metaModelManager.getUnlimitedNaturalType(), true);
}
return expression;
}
@Override
public Element visitVariableCS(@NonNull VariableCS csVariable) {
Variable variable = PivotUtil.getPivot(Variable.class, csVariable);
if (variable != null) {
OCLExpression initExpression = PivotUtil.getPivot(OCLExpression.class, csVariable.getInitExpression());
if (initExpression != null) {
Type initType = initExpression.getType();
TypedRefCS csType = csVariable.getOwnedType();
Type type;
if (csType != null) {
type = PivotUtil.getPivot(Type.class, csType);
}
else {
type = initType;
// FIXME deduction is more complex than this
}
if (metaModelManager.isUnderspecified(initType)) {
initExpression.setType(type);
}
context.setType(variable, type, initExpression.isRequired());
}
variable.setInitExpression(initExpression);
}
return variable;
}
}