blob: 9bc5c1066146b0e1279b77486a3b3b368f9ae3c4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2022 Willink Transformations 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:
* E.D.Willink - initial API and implementation
* E.D.Willink (CEA LIST) - Bug 388493
* E.D.Willink (Obeo) - Bug 416287 - tuple-valued constraints
* Adolfo Sanchez-Barbudo Herrera (University of York) - Lookup Environment/Visitor
*******************************************************************************/
package org.eclipse.ocl.xtext.essentialocl.cs2as;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.BooleanLiteralExp;
import org.eclipse.ocl.pivot.CallExp;
import org.eclipse.ocl.pivot.CollectionItem;
import org.eclipse.ocl.pivot.CollectionLiteralExp;
import org.eclipse.ocl.pivot.CollectionLiteralPart;
import org.eclipse.ocl.pivot.CollectionRange;
import org.eclipse.ocl.pivot.CollectionType;
import org.eclipse.ocl.pivot.CompleteClass;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.ElementExtension;
import org.eclipse.ocl.pivot.EnumLiteralExp;
import org.eclipse.ocl.pivot.EnumerationLiteral;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.FeatureCallExp;
import org.eclipse.ocl.pivot.IfExp;
import org.eclipse.ocl.pivot.IntegerLiteralExp;
import org.eclipse.ocl.pivot.InvalidLiteralExp;
import org.eclipse.ocl.pivot.InvalidType;
import org.eclipse.ocl.pivot.IterateExp;
import org.eclipse.ocl.pivot.Iteration;
import org.eclipse.ocl.pivot.IteratorExp;
import org.eclipse.ocl.pivot.IteratorVariable;
import org.eclipse.ocl.pivot.LetExp;
import org.eclipse.ocl.pivot.LetVariable;
import org.eclipse.ocl.pivot.LoopExp;
import org.eclipse.ocl.pivot.MapLiteralExp;
import org.eclipse.ocl.pivot.MapLiteralPart;
import org.eclipse.ocl.pivot.MapType;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.NavigationCallExp;
import org.eclipse.ocl.pivot.NullLiteralExp;
import org.eclipse.ocl.pivot.NumericLiteralExp;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.OperationCallExp;
import org.eclipse.ocl.pivot.OppositePropertyCallExp;
import org.eclipse.ocl.pivot.Parameter;
import org.eclipse.ocl.pivot.PivotPackage;
import org.eclipse.ocl.pivot.PrimitiveType;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.PropertyCallExp;
import org.eclipse.ocl.pivot.SelfType;
import org.eclipse.ocl.pivot.ShadowExp;
import org.eclipse.ocl.pivot.ShadowPart;
import org.eclipse.ocl.pivot.State;
import org.eclipse.ocl.pivot.StateExp;
import org.eclipse.ocl.pivot.Stereotype;
import org.eclipse.ocl.pivot.StringLiteralExp;
import org.eclipse.ocl.pivot.TemplateParameter;
import org.eclipse.ocl.pivot.TupleLiteralExp;
import org.eclipse.ocl.pivot.TupleLiteralPart;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypeExp;
import org.eclipse.ocl.pivot.UnlimitedNaturalLiteralExp;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.ids.IdResolver;
import org.eclipse.ocl.pivot.internal.complete.StandardLibraryInternal;
import org.eclipse.ocl.pivot.internal.manager.FlowAnalysis;
import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
import org.eclipse.ocl.pivot.internal.manager.TemplateParameterSubstitutionVisitor;
import org.eclipse.ocl.pivot.internal.messages.PivotMessagesInternal;
import org.eclipse.ocl.pivot.internal.scoping.AbstractAttribution;
import org.eclipse.ocl.pivot.internal.scoping.EnvironmentView;
import org.eclipse.ocl.pivot.internal.scoping.ScopeFilter;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal.EnvironmentFactoryInternalExtension;
import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
import org.eclipse.ocl.pivot.messages.PivotMessages;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.FeatureFilter;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.PivotConstants;
import org.eclipse.ocl.pivot.utilities.PivotHelper;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.pivot.utilities.SingletonIterator;
import org.eclipse.ocl.pivot.utilities.TypeUtil;
import org.eclipse.ocl.pivot.values.TemplateParameterSubstitutions;
import org.eclipse.ocl.xtext.base.cs2as.AmbiguitiesAdapter;
import org.eclipse.ocl.xtext.base.cs2as.CS2AS;
import org.eclipse.ocl.xtext.base.cs2as.CS2ASConversion;
import org.eclipse.ocl.xtext.base.utilities.ElementUtil;
import org.eclipse.ocl.xtext.basecs.ElementCS;
import org.eclipse.ocl.xtext.basecs.ModelElementCS;
import org.eclipse.ocl.xtext.basecs.PathElementCS;
import org.eclipse.ocl.xtext.basecs.PathNameCS;
import org.eclipse.ocl.xtext.basecs.TypedRefCS;
import org.eclipse.ocl.xtext.essentialocl.attributes.AbstractOperationMatcher;
import org.eclipse.ocl.xtext.essentialocl.attributes.BinaryOperationMatcher;
import org.eclipse.ocl.xtext.essentialocl.attributes.NavigationUtil;
import org.eclipse.ocl.xtext.essentialocl.attributes.OperationMatcher;
import org.eclipse.ocl.xtext.essentialocl.attributes.UnaryOperationMatcher;
import org.eclipse.ocl.xtext.essentialoclcs.AbstractNameExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.BooleanLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.CollectionLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.CollectionLiteralPartCS;
import org.eclipse.ocl.xtext.essentialoclcs.CollectionTypeCS;
import org.eclipse.ocl.xtext.essentialoclcs.ContextCS;
import org.eclipse.ocl.xtext.essentialoclcs.CurlyBracketedClauseCS;
import org.eclipse.ocl.xtext.essentialoclcs.ExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.IfExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.IfThenExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.InfixExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.InvalidLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.LetExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.LetVariableCS;
import org.eclipse.ocl.xtext.essentialoclcs.MapLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.MapLiteralPartCS;
import org.eclipse.ocl.xtext.essentialoclcs.MapTypeCS;
import org.eclipse.ocl.xtext.essentialoclcs.NameExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.NavigatingArgCS;
import org.eclipse.ocl.xtext.essentialoclcs.NavigationRole;
import org.eclipse.ocl.xtext.essentialoclcs.NestedExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.NullLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.NumberLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.OperatorExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.PrefixExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.RoundBracketedClauseCS;
import org.eclipse.ocl.xtext.essentialoclcs.SelfExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.ShadowPartCS;
import org.eclipse.ocl.xtext.essentialoclcs.SquareBracketedClauseCS;
import org.eclipse.ocl.xtext.essentialoclcs.StringLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.TupleLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.TupleLiteralPartCS;
import org.eclipse.ocl.xtext.essentialoclcs.TypeLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.UnlimitedNaturalLiteralExpCS;
import org.eclipse.ocl.xtext.essentialoclcs.VariableCS;
import org.eclipse.ocl.xtext.essentialoclcs.util.AbstractEssentialOCLCSLeft2RightVisitor;
public class EssentialOCLCSLeft2RightVisitor extends AbstractEssentialOCLCSLeft2RightVisitor
{
/**
* Configure use of the new auto-generated lookup or the old manually coded lookup.
*/
public static boolean AUTOGENERATED_LOOKUP = false;
public static interface Invocations extends Iterable<NamedElement>
{
@Nullable NamedElement getSingleResult();
@NonNull Type getSourceType();
}
private static class PropertyScopeFilter implements ScopeFilter
{
// protected final @NonNull List<SquareBracketedClauseCS> csSquareBracketedClauses;
protected final @Nullable Property oppositeProperty;
public PropertyScopeFilter(@NonNull List<SquareBracketedClauseCS> csSquareBracketedClauses) {
// this.csSquareBracketedClauses = csSquareBracketedClauses;
Property oppositeProperty = null;
if (csSquareBracketedClauses.size() == 1) {
SquareBracketedClauseCS csSquareBracketedClause = csSquareBracketedClauses.get(0);
List<ExpCS> csTerms = csSquareBracketedClause.getOwnedTerms();
if (csTerms.size() == 1) {
ExpCS csTerm = csTerms.get(0);
NavigationCallExp navigationCallExp = PivotUtil.getPivot(NavigationCallExp.class, csTerm);
if (navigationCallExp != null) {
oppositeProperty = PivotUtil.getReferredProperty(navigationCallExp);
}
}
}
this.oppositeProperty = oppositeProperty;
}
@Override
public boolean matches(@NonNull EnvironmentView environmentView, @NonNull Object object) {
return (object instanceof Property) && (((Property)object).getOpposite() == oppositeProperty);
}
}
public static class ResolvedInvocation implements Invocations
{
protected final @NonNull Operation invocation;
public ResolvedInvocation(@NonNull Operation invocation) {
this.invocation = invocation;
}
@Override
public @NonNull NamedElement getSingleResult() {
return invocation;
}
@Override
public @NonNull Type getSourceType() {
return ClassUtil.nonNullState(invocation.getOwningClass());
}
@Override
public @NonNull Iterator<NamedElement> iterator() {
return new SingletonIterator<NamedElement>(invocation);
}
}
public static class UnresolvedInvocations implements Invocations
{
protected final @NonNull Type asType;
protected final @NonNull List<NamedElement> invocations;
public UnresolvedInvocations(@NonNull Type asType, @NonNull List<NamedElement> invocations) {
this.asType = asType;
this.invocations = invocations;
}
@Override
public @Nullable NamedElement getSingleResult() {
return invocations.size() == 1 ? invocations.get(0) : null;
}
@Override
public @NonNull Type getSourceType() {
return asType;
}
@Override
public @NonNull Iterator<NamedElement> iterator() {
return invocations.iterator();
}
}
protected final @NonNull EnvironmentFactoryInternalExtension environmentFactory;
protected final @NonNull PivotMetamodelManager metamodelManager;
protected final @NonNull StandardLibraryInternal standardLibrary;
/*protected final @NonNull PivotNameResolver nameResolver;*/
/**
* curretRoot identifies the current InfixExpCS/PrefixExpCS tree enabling the initial visit to the containment root to
* be distinguished from the subsequent visit within the logical hierarchy.
*/
private @Nullable OperatorExpCS currentRoot = null;
public EssentialOCLCSLeft2RightVisitor(@NonNull CS2ASConversion context) {
super(context);
this.environmentFactory = (EnvironmentFactoryInternalExtension) context.getEnvironmentFactory();
this.metamodelManager = environmentFactory.getMetamodelManager();
this.standardLibrary = environmentFactory.getStandardLibrary();
/*this.nameResolver = new PivotNameResolver(environmentFactory); // FIXME factory method*/
}
protected void checkForInvalidImplicitSourceType(@NonNull ExpCS csInvocationExp) {
for (ImplicitSourceTypeIterator it = new ImplicitSourceTypeIterator(csInvocationExp); it.hasNext(); ) {
Type next = it.next();
if (isInvalidType(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 ImplicitSourceVariableIterator createImplicitSourceVariableIterator(@NonNull ModelElementCS csExp) {
return new ImplicitSourceVariableIterator(csExp);
}
protected @NonNull VariableExp createImplicitVariableExp(@NonNull VariableDeclaration variable) {
VariableExp variableExp = context.refreshModelElement(VariableExp.class, PivotPackage.Literals.VARIABLE_EXP, null); // FIXME reuse
variableExp.setReferredVariable(variable);
variableExp.setName(variable.getName());
variableExp.setIsImplicit(true);
helper.setType(variableExp, variable.getType(), variable.isIsRequired(), variable.getTypeValue());
return variableExp;
}
/*
* let iterations = invocations->selectByKind(Iteration)->select(owningClass <> null) in
* let bestIteratorSize = iterations->collect(ownedIterators->size())->min() in
* let bestSizeIterations = iterations->select(ownedIterators->size() = bestIteratorSize) in
* let owningClasses = bestSizeIterations.owningClass.unspecializedClass->asSet() in
* let leafClasses = owningClasses->select(c | owningClasses->intersection(c->closure(superClasses)) = c) in
* let leafIterations = bestSizeIterations->select(leafClasses->includes(owningClass.unspecializedClass)) in
* leafIterations->any(true)
*/
protected @Nullable Iteration getBestIteration(@NonNull Invocations invocations, @Nullable RoundBracketedClauseCS csRoundBracketedClause) {
int requiredIterators = 0;
if (csRoundBracketedClause != null) {
for (NavigatingArgCS csArgument : csRoundBracketedClause.getOwnedArguments()) {
if (csArgument.getRole() == NavigationRole.ITERATOR) {
requiredIterators++;
}
}
}
if (requiredIterators == 0) {
requiredIterators = 1; // Implicit is always one iterator.
}
Iteration bestIteration = null;
org.eclipse.ocl.pivot.Class bestType = null;
for (NamedElement operation : invocations) {
if (operation instanceof Iteration) {
Iteration iteration = (Iteration) operation;
int iteratorsSize = iteration.getOwnedIterators().size();
if (iteratorsSize == requiredIterators) {
org.eclipse.ocl.pivot.Class specializedType = iteration.getOwningClass();
if (specializedType != null) {
org.eclipse.ocl.pivot.Class unspecializedType = PivotUtil.getUnspecializedTemplateableElement(specializedType);
if ((bestType == null) || !metamodelManager.isSuperClassOf(unspecializedType, bestType)) {
bestIteration = iteration;
bestType = unspecializedType;
}
}
}
}
}
return bestIteration;
}
protected @Nullable Operation getExampleOperation(@NonNull Invocations invocations, @Nullable OCLExpression sourceExp, @NonNull RoundBracketedClauseCS csRoundBracketedClause) {
NamedElement namedElement = invocations.getSingleResult();
if (namedElement != null) {
return namedElement instanceof Operation ? (Operation)namedElement : null;
}
Operation bestOperation = null;
int bestDepth = 0;
for (NamedElement invocation : invocations) {
if (invocation instanceof Operation) {
Operation operation = (Operation)invocation;
org.eclipse.ocl.pivot.Class owningClass = operation.getOwningClass();
if (owningClass != null) {
CompleteClass completeClass = metamodelManager.getCompleteClass(owningClass);
int depth = completeClass.getCompleteInheritance().getDepth();
if ((bestOperation == null) || (depth > bestDepth)) {
bestOperation = operation;
bestDepth = depth;
}
}
}
}
return bestOperation;
}
protected @Nullable VariableDeclaration getImplicitSource(@NonNull ModelElementCS csExp, @NonNull Type requiredType) {
@Nullable VariableDeclaration lastVariable = null;
for (ImplicitSourceVariableIterator it = createImplicitSourceVariableIterator(csExp); it.hasNext(); ) {
@NonNull VariableDeclaration variable = it.next();
lastVariable = variable;
Type type = variable.getType();
if ((type != null) && type.conformsTo(standardLibrary, 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
protected @Nullable Invocations getInvocations(@Nullable Type asSourceType, @Nullable Type asSourceTypeValue, @NonNull RoundBracketedClauseCS csRoundBracketedClause) {
AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
PathNameCS csPathName = csNameExp.getOwnedPathName();
if (csPathName == null) {
return null;
}
List<PathElementCS> csPathElements = csPathName.getOwnedPathElements();
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;
}
assert csLastPathElement.getElementType() != null;
Element asElement = csLastPathElement.basicGetReferredElement();
if ((asElement instanceof Operation) && !asElement.eIsProxy()) {
return new ResolvedInvocation((Operation)asElement);
}
String name = ElementUtil.getTextName(csLastPathElement);
if (name == null) {
return null;
}
int iteratorCount = 0;
int expressionCount = 0;
for (NavigatingArgCS csArg : csRoundBracketedClause.getOwnedArguments()) {
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
Type asType = context.getConverter().lookupTypeQualifier(csPathName);
if (asType == null) {
return null;
}
Invocations invocations = getInvocations(asType, asType, name, iteratorCount, expressionCount);
if ((invocations == null) && name.startsWith("_")) {
@NonNull String unescapedName = name.substring(1); // FIXME Compatibility
invocations = getInvocations(asType, asType, unescapedName, iteratorCount, expressionCount);
}
return invocations;
}
else if (asSourceType != null) { // Search for a.b() candidates in type of a
TemplateParameter asTemplateParameter = asSourceType.isTemplateParameter();
if (asTemplateParameter != null) {
org.eclipse.ocl.pivot.Class lowerBound = PivotUtil.basicGetLowerBound(asTemplateParameter);
if (lowerBound != null) { // ?? OclAny for null
asSourceType = lowerBound;
}
}
Invocations invocations = getInvocations(asSourceType, asSourceTypeValue, name, iteratorCount, expressionCount);
if ((invocations == null) && name.startsWith("_")) {
String unescapedName = name.substring(1); // FIXME Compatibility
invocations = getInvocations(asSourceType, asSourceTypeValue, unescapedName, iteratorCount, expressionCount);
}
return invocations;
}
else { // Search for a() candidates in implicit source variable types
Invocations invocations = null;
for (ImplicitSourceTypeIterator it = createImplicitSourceTypeIterator(csNameExp); (invocations == null) && it.hasNext(); ) {
Type asType = it.next();
invocations = getInvocations(asType, it.nextValue(), name, iteratorCount, expressionCount);
}
if ((invocations == null) && name.startsWith("_")) {
String unescapedName = name.substring(1); // FIXME Compatibility
for (ImplicitSourceTypeIterator it = createImplicitSourceTypeIterator(csNameExp); (invocations == null) && it.hasNext(); ) {
Type asType = it.next();
invocations = getInvocations(asType, null, unescapedName, iteratorCount, expressionCount);
}
}
return invocations;
}
}
/**
* 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. If asTypeValue is non-null a fall-back attempt to look up a static operation in asTypeValue is made.
*/
protected @Nullable Invocations getInvocations(@NonNull Type asType, @Nullable Type asTypeValue, @NonNull String name, int iteratorCount, int expressionCount) {
TemplateParameter asTemplateParameter = asType.isTemplateParameter();
if (asTemplateParameter != null) {
asType = PivotUtil.getLowerBound(asTemplateParameter, standardLibrary.getOclAnyType());
}
Iterable<@NonNull ? extends Operation> nonStaticOperations = metamodelManager.getAllOperations(asType, FeatureFilter.SELECT_NON_STATIC, name);
List<@NonNull NamedElement> invocations = getInvocationsInternal(null, nonStaticOperations, iteratorCount, expressionCount);
if (asType instanceof ElementExtension) { // FIXME review me
Type asStereotype = ((ElementExtension)asType).getStereotype();
if (asStereotype != null) {
Iterable<@NonNull ? extends Operation> stereotypeOperations = metamodelManager.getAllOperations(asStereotype, FeatureFilter.SELECT_NON_STATIC, name);
invocations = getInvocationsInternal(invocations, stereotypeOperations, iteratorCount, expressionCount);
}
}
if (asTypeValue != null) {
Iterable<@NonNull ? extends Operation> staticOperations = metamodelManager.getAllOperations(asTypeValue, FeatureFilter.SELECT_STATIC, name);
invocations = getInvocationsInternal(invocations, staticOperations, iteratorCount, expressionCount);
}
return invocations != null ? new UnresolvedInvocations(asType, invocations) : null;
}
protected @Nullable List<@NonNull NamedElement> getInvocationsInternal(@Nullable List<@NonNull NamedElement> invocations,
@NonNull Iterable<@NonNull ? extends Operation> allOperations, int iteratorCount, int expressionCount) {
for (@NonNull Operation operation : allOperations) {
Operation asOperation = null;
if (operation instanceof Iteration) {
Iteration candidateIteration = (Iteration) operation;
int iteratorsSize = candidateIteration.getOwnedIterators().size();
if ((iteratorCount == 0) || (iteratorCount == iteratorsSize)) {
asOperation = candidateIteration;
}
}
else {
Operation candidateOperation = operation;
int operationsSize = candidateOperation.getOwnedParameters().size();
if (expressionCount == operationsSize) {
asOperation = candidateOperation;
}
}
if (asOperation != null) {
if (invocations == null) {
invocations = new ArrayList<>();
}
invocations.add(asOperation);
}
}
return invocations;
}
protected @NonNull OperatorExpCS getRoot(@NonNull OperatorExpCS csOperator) {
OperatorExpCS csRoot = csOperator;
for (OperatorExpCS csParent = csRoot.getLocalParent(); csParent != null; csParent = csParent.getLocalParent()) {
csRoot = csParent;
}
return csRoot;
}
protected boolean isInvalidType(@Nullable Type type) {
return (type == null) || (type instanceof InvalidType)
|| ((type instanceof CollectionType) && (((CollectionType)type).getElementType() instanceof InvalidType));
}
/** @deprecated use ElementUtil */
@Deprecated
protected boolean isRequired(@Nullable TypedRefCS csTypeRef) {
return ElementUtil.isRequired(csTypeRef);
}
protected @NonNull OperationCallExp refreshOperationCallExp(@NonNull AbstractNameExpCS csNameExp, @Nullable OCLExpression sourceExp) {
OperationCallExp callExp = context.refreshModelElement(OperationCallExp.class, PivotPackage.Literals.OPERATION_CALL_EXP, csNameExp);
callExp.setOwnedSource(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.setOwnedSource(sourceExp);
callExp.setReferredProperty(property.getOpposite());
callExp.setName(property.getName());
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.setOwnedSource(sourceExp);
callExp.setReferredProperty(property);
callExp.setName(property.getName());
return callExp;
}
protected Element resolveAssociationClassCallExp(@NonNull NameExpCS csNameExp) {
// PathNameCS pathName = csNameExp.getPathName();
RoundBracketedClauseCS csRoundBracketedClause = csNameExp.getOwnedRoundBracketedClause();
List<SquareBracketedClauseCS> csSquareBracketedClauses = csNameExp.getOwnedSquareBracketedClauses();
if (csSquareBracketedClauses.size() > 2) {
return context.addBadExpressionError(csNameExp, "AssociationClassCallExp must have exactly only one or two square-brackets-clauses");
}
if (csRoundBracketedClause != null) {
return context.addBadExpressionError(csNameExp, "AssociationClassCallExp must have no round-brackets-clause");
}
// SquareBracketedClauseCS csSquareBracketedClause = csSquareBracketedClauses.get(0);
// CS2AS.setElementType(pathName, PivotPackage.Literals.ASSOCIATION_CLASS, csNameExp, null);
// Element element = pathName.getElement();
// return resolveShadowExp((Type)element, csNameExp);
return null;
}
protected void resolveAtPre(@Nullable AbstractNameExpCS csNameExp, @NonNull FeatureCallExp featureCallExp) {
if (csNameExp != null) {
featureCallExp.setIsPre(csNameExp.isIsPre());
}
}
/**
* Resolve an invocation such as name() or source.name(...) or source-&gt;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 RoundBracketedClauseCS csRoundBracketedClause, @NonNull Invocations invocations) {
AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
PathNameCS csPathName = csNameExp.getOwnedPathName();
if (csPathName == null) {
return null;
}
Iteration iteration = getBestIteration(invocations, csRoundBracketedClause);
if (iteration != null) {
if (sourceExp == null) {
sourceExp = createImplicitSourceVariableExp(csNameExp, iteration.getOwningClass());
}
LoopExp iterationCallExp = resolveIterationCallExp(csNameExp, sourceExp, iteration);
CS2AS.setPathElement(csPathName, iteration, null);
resolveIterationContent(csRoundBracketedClause, iterationCallExp);
return iterationCallExp;
}
Operation exampleOperation = getExampleOperation(invocations, sourceExp, csRoundBracketedClause);
if (exampleOperation != null) {
if (sourceExp == null) {
sourceExp = createImplicitSourceVariableExp(csNameExp, exampleOperation.getOwningClass());
}
OperationCallExp operationCallExp = refreshOperationCallExp(csNameExp, sourceExp);
if (invocations.getSingleResult() != null) {
context.setReferredOperation(operationCallExp, exampleOperation);
}
//
// Need to resolve types for operation arguments in order to disambiguate operation names.
//
resolveOperationArgumentTypes(exampleOperation.getOwnedParameters(), csRoundBracketedClause);
//
// Resolve the static operation/iteration by name and known operation argument types.
//
Type explicitSourceType = null;
InfixExpCS csNavigationOperator = NavigationUtil.getNavigationInfixExp(csNameExp);
if (csNavigationOperator != null) { // For a->X(); X must be resolved in the navigation source type
explicitSourceType = csNameExp.getSourceTypeValue() != null ? csNameExp.getSourceTypeValue() : csNameExp.getSourceType();
if (explicitSourceType == null) {
return null;
}
}
if (explicitSourceType == null) {
explicitSourceType = invocations.getSourceType();
}
Operation asOperation = null;
OperationMatcher matcher = new OperationMatcher(environmentFactory, explicitSourceType, csNameExp.getSourceTypeValue());
boolean isMatchable = matcher.init(csRoundBracketedClause);
if (isMatchable) {
asOperation = matcher.getBestOperation(invocations, false);
//
// Try again with argument coercion.
//
if (asOperation == null) {
asOperation = matcher.getBestOperation(invocations, true);
}
}
//
// Search for invocations with a coerced source.
//
if (asOperation == null) {
Operation asCoercion = null;
CompleteClass completeClass = metamodelManager.getCompleteClass(explicitSourceType);
for (org.eclipse.ocl.pivot.Class partialClass : completeClass.getPartialClasses()) {
if (partialClass instanceof PrimitiveType) {
for (Operation coercion : ((PrimitiveType)partialClass).getCoercions()) {
Type corcedSourceType = coercion.getType();
Invocations coercedInvocations = getInvocations(corcedSourceType, null, csRoundBracketedClause);
if (coercedInvocations != null) {
matcher = new OperationMatcher(environmentFactory, corcedSourceType, null);
isMatchable = matcher.init(csRoundBracketedClause);
if (isMatchable) {
asOperation = matcher.getBestOperation(coercedInvocations, false);
if (asOperation == null) {
asOperation = matcher.getBestOperation(coercedInvocations, true);
}
}
}
if (asOperation != null) {
asCoercion = coercion;
break;
}
}
if (asCoercion != null) {
break;
}
}
}
if (asCoercion != null) {
operationCallExp.setOwnedSource(null);
OCLExpression asCoercionCallExp = new PivotHelper(environmentFactory).createCoercionCallExp(sourceExp, asCoercion);
operationCallExp.setOwnedSource(asCoercionCallExp);
}
}
CS2AS.setPathElement(csPathName, asOperation, matcher.getAmbiguities());
if (asOperation != null) {
return resolveOperationCallExp(csRoundBracketedClause, operationCallExp, asOperation);
}
}
return null;
}
/**
* Return a non-null coercion Operation from argType to parameterType if one is available and needed.
*/
protected @Nullable Operation resolveCoercionFrom(@NonNull Type argType, @NonNull Type parameterType) {
if (!metamodelManager.conformsTo(argType, TemplateParameterSubstitutions.EMPTY, parameterType, TemplateParameterSubstitutions.EMPTY)) {
CompleteClass completeClass = metamodelManager.getCompleteClass(argType);
for (org.eclipse.ocl.pivot.Class partialClass : completeClass.getPartialClasses()) {
if (partialClass instanceof PrimitiveType) {
for (Operation coercion : ((PrimitiveType)partialClass).getCoercions()) {
Type corcedArgType = coercion.getType();
if ((corcedArgType != null) && metamodelManager.conformsTo(corcedArgType, TemplateParameterSubstitutions.EMPTY, parameterType, TemplateParameterSubstitutions.EMPTY)) {
return coercion;
}
}
}
}
}
return null;
}
protected @NonNull EnumLiteralExp resolveEnumLiteral(@NonNull ExpCS csExp, @NonNull EnumerationLiteral enumerationLiteral) {
EnumLiteralExp expression = context.refreshModelElement(EnumLiteralExp.class, PivotPackage.Literals.ENUM_LITERAL_EXP, csExp);
helper.setType(expression, enumerationLiteral.getOwningEnumeration(), true, null /* enumerationLiteral.getTypeId() */);
expression.setReferredLiteral(enumerationLiteral);
expression.setName(enumerationLiteral.getName());
return expression;
}
/**
* Resolve an invocation such as source.name or source-&gt;name
*/
protected @NonNull OCLExpression resolveExplicitSourceNavigation(@NonNull OCLExpression sourceExp, @NonNull NameExpCS csNameExp) {
PathNameCS ownedPathName = ClassUtil.nonNullState(csNameExp.getOwnedPathName());
ScopeFilter propertyScopeFilter = AbstractAttribution.NOT_STATIC_SCOPE_FILTER;
List<SquareBracketedClauseCS> csSquareBracketedClauses = csNameExp.getOwnedSquareBracketedClauses();
if (csSquareBracketedClauses.size() > 0) {
for (SquareBracketedClauseCS csSquareBracketedClause : csSquareBracketedClauses) {
for (ExpCS csExp : csSquareBracketedClause.getOwnedTerms()) {
csExp.accept(this);
}
}
propertyScopeFilter = new PropertyScopeFilter(csSquareBracketedClauses); // FIXME nonStatic
}
// FIXME Qualified navigation
Property resolvedProperty = context.lookupProperty(csNameExp, ownedPathName, propertyScopeFilter);
if ((resolvedProperty != null) && !resolvedProperty.eIsProxy()) {
if (resolvedProperty.getType() instanceof Stereotype) { // FIXME Bug 578010 - M2 properties need reification with correct types at M1
return resolvePropertyCallExp(sourceExp, csNameExp, resolvedProperty);
}
Type resolvedSourceType = PivotUtil.getType(sourceExp);
Type propertySourceType = PivotUtil.getOwningClass(resolvedProperty);
if (resolvedSourceType.conformsTo(standardLibrary, propertySourceType)) {
return resolvePropertyCallExp(sourceExp, csNameExp, resolvedProperty);
}
context.addError(csNameExp, EssentialOCLCS2ASMessages.PropertyCallExp_IncompatibleProperty, resolvedProperty);
}
Property oclInvalidProperty = standardLibrary.getOclInvalidProperty();
PropertyCallExp expression = refreshPropertyCallExp(csNameExp, sourceExp, oclInvalidProperty);
helper.setType(expression, standardLibrary.getOclInvalidType(), false, null);
ElementUtil.setLastPathElement(ownedPathName, oclInvalidProperty);
return expression;
}
protected @NonNull OCLExpression resolveImplicitAsSet(@NonNull OCLExpression sourceExp, @NonNull Type sourceType, @NonNull InfixExpCS csOperator) {
OperationCallExp expression = context.refreshModelElement(OperationCallExp.class, PivotPackage.Literals.OPERATION_CALL_EXP, null);
expression.setIsImplicit(true);
PivotUtilInternal.resetContainer(sourceExp);
expression.setOwnedSource(sourceExp);
expression.setName("oclAsSet");
resolveOperationCall(expression, csOperator);
return expression;
}
/**
* Return a non-null implicit collect() call if a sourceExp for a csElement requires an implicit collect.
* The return call has no body or return type since they cannot be synthesised until the body is synthesised.
*/
protected @Nullable IteratorExp resolveImplicitCollect(@NonNull OCLExpression sourceExp, @NonNull InfixExpCS csOperator) {
Type elementType;
Type actualSourceType = sourceExp.getType();
boolean isNullFree;
if (actualSourceType instanceof CollectionType) {
CollectionType collectionType = (CollectionType)actualSourceType;
elementType = collectionType.getElementType();
isNullFree = collectionType.isIsNullFree();
}
else if (actualSourceType instanceof MapType) {
MapType mapType = (MapType)actualSourceType;
elementType = mapType.getKeyType();
isNullFree = mapType.isKeysAreNullFree();
}
else {
return null;
}
if (elementType == null) {
return null;
}
Invocations invocations = getInvocations(actualSourceType, null, "collect", 1, 0);
if (invocations == null) {
return null;
}
Iteration asIteration = getBestIteration(invocations, null);
if (asIteration == null) {
return null;
}
boolean isSafe = PivotConstants.SAFE_OBJECT_NAVIGATION_OPERATOR.equals(csOperator.getName());
IteratorExp implicitCollectExp = context.refreshModelElement(IteratorExp.class, PivotPackage.Literals.ITERATOR_EXP, null);
implicitCollectExp.setIsImplicit(true);
PivotUtilInternal.resetContainer(sourceExp);
implicitCollectExp.setOwnedSource(sourceExp);
implicitCollectExp.setName(asIteration.getName());
implicitCollectExp.setIsSafe(isSafe);
context.setReferredIteration(implicitCollectExp, asIteration);
IteratorVariable iterator = context.refreshModelElement(IteratorVariable.class, PivotPackage.Literals.ITERATOR_VARIABLE, null); // FIXME reuse
Parameter resolvedIterator = asIteration.getOwnedIterators().get(0);
iterator.setRepresentedParameter(resolvedIterator);
helper.refreshName(iterator, "1_");
helper.setType(iterator, elementType, isSafe || isNullFree, null);
iterator.setIsImplicit(true);
implicitCollectExp.getOwnedIterators().add(iterator);
return implicitCollectExp;
}
/**
* Resolve an invocation such as name() or source.name(...) or source-&gt;name(...)
*/
protected @NonNull OCLExpression resolveInvocation(@Nullable OCLExpression sourceExp, @NonNull RoundBracketedClauseCS csRoundBracketedClause) {
AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
PathNameCS csPathName = csNameExp.getOwnedPathName();
if (csPathName != null) { // QVTr overrides to select a wider search
List<PathElementCS> csPath = csPathName.getOwnedPathElements();
int pathSize = csPath.size();
if (pathSize > 0) {
PathElementCS csLastPathElement = csPath.get(pathSize-1);
if (csLastPathElement.getElementType() == null) {
csLastPathElement.setElementType(PivotPackage.Literals.OPERATION);
}
}
}
Invocations invocations = getInvocations(sourceExp != null ? sourceExp.getType() : null,
sourceExp != null ? sourceExp.getTypeValue() : null, csRoundBracketedClause);
if (invocations != null) {
OCLExpression invocationExp = resolveBestInvocation(sourceExp, csRoundBracketedClause, invocations);
if (invocationExp != null) {
return invocationExp;
}
assert csPathName != null;
}
else {
checkForInvalidImplicitSourceType(csNameExp);
CS2AS.setPathElement(ClassUtil.nonNullState(csPathName), null, null);
}
if (sourceExp == null) {
sourceExp = createImplicitSourceVariableExp(csNameExp, standardLibrary.getOclAnyType());
}
OperationCallExp operationCallExp = refreshOperationCallExp(csNameExp, sourceExp);
Operation oclInvalidOperation = standardLibrary.getOclInvalidOperation();
context.setReferredOperation(operationCallExp, oclInvalidOperation);
if (csPathName != null) {
ElementUtil.setLastPathElement(csPathName, oclInvalidOperation);
}
context.installPivotUsage(csNameExp, operationCallExp);
helper.setType(operationCallExp, standardLibrary.getOclInvalidType(), false, null);
return operationCallExp;
}
protected boolean resolveIterationAccumulators(@NonNull RoundBracketedClauseCS csRoundBracketedClause, @NonNull LoopExp expression) {
AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
Iteration iteration = expression.getReferredIteration();
List<@NonNull Variable> pivotAccumulators = new ArrayList<>();
//
// Explicit accumulator
//
for (NavigatingArgCS csArgument : csRoundBracketedClause.getOwnedArguments()) {
if (csArgument.getRole() != NavigationRole.ACCUMULATOR) {
continue;
}
ExpCS csName = csArgument.getOwnedNameExpression();
ExpCS csInit;
if (csName instanceof InfixExpCS) {
InfixExpCS csInfixExp = (InfixExpCS)csName;
assert "=".equals(csInfixExp.getName()); // assured by EssentialOCLCSContainmentVisitor.canBeAccumulator
csInit = csInfixExp.getOwnedRight();
csName = csInfixExp.getOwnedLeft();
}
else {
csInit = csArgument.getOwnedInitExpression();
}
Variable acc = PivotUtil.getPivot(Variable.class, csName);
if (acc != null) {
context.installPivotUsage(csArgument, acc);
if (csInit != null) {
OCLExpression initExpression = context.visitLeft2Right(OCLExpression.class, csInit);
acc.setOwnedInit(initExpression);
TypedRefCS csAccType = csArgument.getOwnedType();
Type accType = null;
Boolean accIsRequired = null;
if (csAccType != null) {
accType = PivotUtil.getPivot(Type.class, csAccType);
accIsRequired = context.getConverter().isRequired(csAccType);
}
if (initExpression != null) {
if (accType == null) {
accType = initExpression.getType();
}
if (accIsRequired == null) {
accIsRequired = initExpression.isIsRequired();
}
}
helper.setType(acc, accType, accIsRequired == Boolean.TRUE, null);
}
if (pivotAccumulators.size() >= iteration.getOwnedAccumulators().size()) {
context.addError(csNameExp, EssentialOCLCS2ASMessages.IterateExp_TooManyAccumulators, ElementUtil.getTrimmedText(csNameExp.getOwnedPathName()));
return false;
}
acc.setRepresentedParameter(iteration.getOwnedAccumulators().get(pivotAccumulators.size()));
pivotAccumulators.add(acc);
}
String prefix = csArgument.getPrefix();
if ((prefix != null) && !prefix.equals(";")) {
context.addWarning(csArgument, EssentialOCLCS2ASMessages.IterateExp_BadAccumulatorSeparator, prefix);
}
if (csInit == null) {
context.addError(csArgument, EssentialOCLCS2ASMessages.IterateExp_MissingInitializer);
return false;
}
// if (csArgument.getOwnedType() != null) {
// context.addError(csArgument, "Unexpected type for parameter");
// }
}
//
// Implicit Accumulator
//
int accumulatorCount = pivotAccumulators.size();
if (expression instanceof IterateExp) {
IterateExp iterateExp = (IterateExp)expression;
if (accumulatorCount > 1) {
context.addError(csNameExp, EssentialOCLCS2ASMessages.IterateExp_TooManyAccumulators, ElementUtil.getTrimmedText(csNameExp.getOwnedPathName()));
return false;
}
else if (accumulatorCount < 1) {
context.addError(csNameExp, EssentialOCLCS2ASMessages.IterateExp_TooFewAccumulators, ElementUtil.getTrimmedText(csNameExp.getOwnedPathName()));
return false;
}
else {
iterateExp.setOwnedResult(pivotAccumulators.get(0));
}
}
else if (accumulatorCount > 0) {
context.addError(csNameExp, EssentialOCLCS2ASMessages.IteratorExp_TooManyAccumulators, ElementUtil.getTrimmedText(csNameExp.getOwnedPathName()));
}
return true;
}
protected void resolveIterationBody(@NonNull RoundBracketedClauseCS csRoundBracketedClause, @NonNull LoopExp expression) {
AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
List<@NonNull OCLExpression> pivotBodies = new ArrayList<>();
boolean hasIteratorOrAccumulator = false;
for (NavigatingArgCS csArgument : csRoundBracketedClause.getOwnedArguments()) {
if (csArgument.getRole() == NavigationRole.ITERATOR) {
hasIteratorOrAccumulator = true;
}
else if (csArgument.getRole() == NavigationRole.ACCUMULATOR) {
hasIteratorOrAccumulator = true;
}
else if (csArgument.getRole() == NavigationRole.EXPRESSION) {
if (csArgument.getOwnedInitExpression() != null) {
context.addError(csArgument, EssentialOCLCS2ASMessages.LoopExp_UnexpectedInitializer);
}
if (csArgument.getOwnedType() != null) {
context.addError(csArgument, EssentialOCLCS2ASMessages.LoopExp_UnexpectedType);
}
ExpCS name = csArgument.getOwnedNameExpression();
assert name != null;
// OCLExpression exp = context.visitLeft2Right(OCLExpression.class, name);
OCLExpression exp = !hasIteratorOrAccumulator ? PivotUtil.getPivot(OCLExpression.class, csArgument) : 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 ''{0}'' iteration body", csNameExp.getOwnedPathName()));
}
}
}
if (pivotBodies.size() != 1) {
expression.setOwnedBody(context.addBadExpressionError(csNameExp, "Iteration ''{0}'' must have exactly one body", csNameExp.getOwnedPathName()));
}
else {
expression.setOwnedBody(pivotBodies.get(0));
}
}
protected @NonNull LoopExp resolveIterationCallExp(@NonNull AbstractNameExpCS csNameExp, @NonNull OCLExpression sourceExp, @NonNull Iteration iteration) {
LoopExp expression;
if (iteration.getOwnedAccumulators().size() > 0) {
expression = context.refreshModelElement(IterateExp.class, PivotPackage.Literals.ITERATE_EXP, csNameExp);
}
else {
expression = context.refreshModelElement(IteratorExp.class, PivotPackage.Literals.ITERATOR_EXP, csNameExp);
}
expression.setOwnedSource(sourceExp);
context.setReferredIteration(expression, iteration);
return expression;
}
protected void resolveIterationContent(@NonNull RoundBracketedClauseCS csRoundBracketedClause, @NonNull LoopExp expression) {
boolean allOk = true;
OCLExpression source = ClassUtil.nonNullState(expression.getOwnedSource());
if (allOk) {
resolveIterationIterators(csRoundBracketedClause, source, expression);
}
if (allOk) {
allOk = resolveIterationAccumulators(csRoundBracketedClause, expression);
}
if (allOk) {
resolveOperationArgumentTypes(null, csRoundBracketedClause);
}
if (allOk) {
resolveIterationBody(csRoundBracketedClause, expression);
}
if (allOk && (expression instanceof IterateExp)) {
IterateExp iterateExp = (IterateExp)expression;
OCLExpression ownedBody = iterateExp.getOwnedBody();
if ((ownedBody != null) && ownedBody.isIsRequired()) {
Variable ownedResult = iterateExp.getOwnedResult();
if (ownedResult != null) {
OCLExpression ownedInit = ownedResult.getOwnedInit();
if ((ownedInit != null) && ownedInit.isIsRequired()) {
ownedResult.setIsRequired(true);
}
}
}
}
if (allOk) {
resolveOperationReturnType(expression);
}
}
protected void resolveIterationIterators(@NonNull RoundBracketedClauseCS csRoundBracketedClause, @NonNull OCLExpression source, @NonNull LoopExp expression) {
AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
OperatorExpCS csParent = csNameExp.getLocalParent();
boolean isSafe = false;
if (csParent instanceof InfixExpCS) {
String operatorName = ((InfixExpCS)csParent).getName();
isSafe = PivotConstants.SAFE_AGGREGATE_NAVIGATION_OPERATOR.equals(operatorName);
}
// boolean isSafe = PivotUtil.isSafeNavigationOperator(navigationOperatorName);
Iteration iteration = expression.getReferredIteration();
//
// Explicit iterators
//
int iterationIteratorsSize = iteration.getOwnedIterators().size();
int iteratorIndex = 0;
boolean isCollection = false;
MapType mapType = null;
List</*@Nullable*/ IteratorVariable> pivotCoIterators = null;
Type rawSourceElementType = null;
Type sourceType = csNameExp.getSourceType();
if (sourceType instanceof CollectionType) {
isCollection = true;
CollectionType sourceCollectionType = (CollectionType)sourceType;
if (sourceCollectionType.isIsNullFree()) {
isSafe = true;
}
rawSourceElementType = sourceCollectionType.getElementType();
if (sourceCollectionType.isOrdered()) {
pivotCoIterators = new ArrayList<>();
}
}
else if (sourceType instanceof MapType) {
mapType = (MapType)sourceType;
if (mapType.isKeysAreNullFree()) {
isSafe = true;
}
rawSourceElementType = mapType.getKeyType();
pivotCoIterators = new ArrayList<>();
}
if (!isCollection && (mapType == null)) {
throw new UnsupportedOperationException();
}
boolean hasCoIterator = false;
List<@NonNull Variable> pivotIterators = new ArrayList<>();
Type sourceElementType = rawSourceElementType != null ? metamodelManager.getPrimaryType(rawSourceElementType) : null;
for (int argIndex = 0; argIndex < csRoundBracketedClause.getOwnedArguments().size(); argIndex++) {
NavigatingArgCS csArgument = csRoundBracketedClause.getOwnedArguments().get(argIndex);
if (csArgument.getRole() != NavigationRole.ITERATOR) {
continue;
}
if (iterationIteratorsSize <= argIndex) {
context.addWarning(csArgument, PivotMessagesInternal.RedundantIterator_WARNING_, iteration.getName());
continue;
}
// if (csArgument.getCoIteratorName() != null) {
// )
// }
if (csArgument.getOwnedInitExpression() != null) {
context.addError(csArgument, "Unexpected initializer for iterator");
}
// if (csArgument.getOwnedType() == null) {
// context.addError(csArgument, "Missing type for iterator");
// }
ExpCS csName = csArgument.getOwnedNameExpression();
Variable iterator = PivotUtil.getPivot(Variable.class, csName);
if (iterator != null) {
context.installPivotUsage(csArgument, iterator);
Parameter formalIterator = iteration.getOwnedIterators().get(iteratorIndex);
iterator.setRepresentedParameter(formalIterator);
Type varType = null;
TypedRefCS csType = csArgument.getOwnedType();
Boolean iteratorIsRequired = null;
if (csType != null) {
iteratorIsRequired = context.isRequired(csType);
varType = PivotUtil.getPivot(Type.class, csType);
}
if (varType == null) {
varType = sourceElementType;
}
boolean isRequired = iteratorIsRequired != null ? iteratorIsRequired.booleanValue() : isSafe || formalIterator.isIsRequired();
helper.setType(iterator, varType, isRequired, null);
pivotIterators.add(iterator);
IteratorVariable coIterator = null;
VariableCS csCoIterator = csArgument.getOwnedCoIterator();
if (csCoIterator != null) {
if ((pivotCoIterators != null)) {
coIterator = PivotUtil.getPivot(IteratorVariable.class, csCoIterator);
if (coIterator != null) {
hasCoIterator = true;
Type coIteratorType = null;
TypedRefCS csCoIteratorType = csCoIterator.getOwnedType();
Boolean coIteratorIsRequired = null;
if (csCoIteratorType != null) {
coIteratorIsRequired = context.isRequired(csCoIteratorType);
coIteratorType = PivotUtil.getPivot(Type.class, csCoIteratorType);
}
if (coIteratorType == null) {
if (mapType != null) {
coIteratorType = mapType.getValueType();
coIteratorIsRequired = mapType.isValuesAreNullFree();
}
else {
coIteratorType = standardLibrary.getIntegerType();
coIteratorIsRequired = true;
}
}
boolean coIsRequired = coIteratorIsRequired != null ? coIteratorIsRequired.booleanValue() : isSafe || formalIterator.isIsRequired();
helper.setType(coIterator, coIteratorType, coIsRequired, null); // FIXME isRequired *2
}
}
else {
context.addError(csCoIterator, PivotMessages.IllegalCoIterator, sourceType);
}
}
if (pivotCoIterators != null) {
pivotCoIterators.add(coIterator);
}
iteratorIndex++;
}
}
//
// Implicit Iterators
//
while (iteratorIndex < iterationIteratorsSize) {
Parameter formalIterator = iteration.getOwnedIterators().get(iteratorIndex);
String varName = Integer.toString(iteratorIndex+1) + "_";
IteratorVariable iterator = context.refreshModelElement(IteratorVariable.class, PivotPackage.Literals.ITERATOR_VARIABLE, null);
helper.refreshName(iterator, varName);
helper.setType(iterator, sourceElementType, isSafe || formalIterator.isIsRequired(), null);
iterator.setIsImplicit(true);
iterator.setRepresentedParameter(formalIterator);
pivotIterators.add(iterator);
iteratorIndex++;
}
//
// Implicit CoIterators
//
if ((pivotCoIterators != null) && hasCoIterator) {
for (int coiteratorIndex = 0; coiteratorIndex < pivotCoIterators.size(); coiteratorIndex++) {
IteratorVariable coIterator = pivotCoIterators.get(coiteratorIndex);
if (coIterator == null) {
boolean coIteratorIsRequired ;
if (mapType != null) {
coIteratorIsRequired = isSafe || mapType.isValuesAreNullFree();
}
else {
coIteratorIsRequired = true;
}
String varName = Integer.toString(iterationIteratorsSize + coiteratorIndex+1) + "_";
coIterator = context.refreshModelElement(IteratorVariable.class, PivotPackage.Literals.ITERATOR_VARIABLE, null);
helper.refreshName(coIterator, varName);
helper.setType(coIterator, sourceElementType, coIteratorIsRequired, null);
coIterator.setIsImplicit(true);
pivotCoIterators.set(coiteratorIndex, coIterator);
}
}
}
helper.refreshList(expression.getOwnedIterators(), pivotIterators);
if (hasCoIterator) {
helper.refreshList(expression.getOwnedCoIterators(), pivotCoIterators);
}
else {
expression.getOwnedCoIterators().clear();
}
}
/**
* 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(@Nullable List<Parameter> parameters, @NonNull RoundBracketedClauseCS csRoundBracketedClause) {
int argIndex = 0;
for (NavigatingArgCS csArgument : csRoundBracketedClause.getOwnedArguments()) {
if (csArgument.getRole() == NavigationRole.ITERATOR) {
break;
}
else if (csArgument.getRole() == NavigationRole.ACCUMULATOR) {
break;
}
else if (csArgument.getRole() == NavigationRole.EXPRESSION) {
ExpCS csName = csArgument.getOwnedNameExpression();
if (csName != null) {
OCLExpression arg = null;
boolean isType = false;
if (csName instanceof NameExpCS) {
if ((parameters != null) && argIndex < parameters.size()) {
Parameter parameter = parameters.get(argIndex);
if (parameter.isIsTypeof() || (parameter.getTypeId() == standardLibrary.getOclTypeType().getTypeId())) {
isType = true;
NameExpCS csNameExp = (NameExpCS)csName;
PathNameCS csPathName = csNameExp.getOwnedPathName();
Type type = context.getConverter().lookupType(csNameExp, ClassUtil.nonNullState(csPathName));
if (type != null) {
arg = resolveTypeExp(csNameExp, type);
}
}
}
}
if (!isType) {
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 RoundBracketedClauseCS csRoundBracketedClause, @NonNull Operation operation, @NonNull OperationCallExp expression) {
@SuppressWarnings("null") @NonNull AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
List<@NonNull OCLExpression> pivotArguments = new ArrayList<>();
List<NavigatingArgCS> csArguments = csRoundBracketedClause.getOwnedArguments();
List<Parameter> ownedParameters = operation.getOwnedParameters();
int parametersCount = ownedParameters.size();
int csArgumentCount = csArguments.size();
if (csArgumentCount > 0) {
if (csArguments.get(0).getRole() != NavigationRole.EXPRESSION) {
context.addError(csNameExp, "Operation calls can only specify expressions");
}
for (int argIndex = 0; argIndex < csArgumentCount; argIndex++) {
NavigatingArgCS csArgument = csArguments.get(argIndex);
if (csArgument.getOwnedInitExpression() != null) {
context.addError(csArgument, "Unexpected initializer for expression");
}
if (csArgument.getOwnedType() != null) {
context.addError(csArgument, "Unexpected type for expression");
}
OCLExpression arg = PivotUtil.getPivot(OCLExpression.class, csArgument);
if (arg != null) {
Type argType = arg.getType();
if (argType != null) {
Type parameterType = ownedParameters.get(argIndex).getType();
if (parameterType instanceof SelfType) {
parameterType = operation.getOwningClass();
}
if (parameterType != null) {
Operation asCoercion = resolveCoercionFrom(argType, parameterType);
if (asCoercion != null) {
arg = new PivotHelper(environmentFactory).createCoercionCallExp(arg, asCoercion);
}
}
}
pivotArguments.add(arg);
}
}
}
if ((csArgumentCount != parametersCount) && (operation != standardLibrary.basicGetOclInvalidOperation())) {
context.addError(csNameExp, PivotMessagesInternal.MismatchedArgumentCount_ERROR_, csArgumentCount, parametersCount);
}
helper.refreshList(expression.getOwnedArguments(), pivotArguments);
}
protected void resolveOperationCall(@NonNull OperationCallExp expression, @NonNull OperatorExpCS csOperator) {
String name = expression.getName();
Type sourceType = PivotUtil.getType(PivotUtil.getOwnedSource(expression));
Operation asOperation = null;
Invocations invocations = null;
if (!AUTOGENERATED_LOOKUP) {
if (name != null) {
invocations = getInvocations(sourceType, null, name, 0, expression.getOwnedArguments().size());
if ((invocations == null) && name.startsWith("_")) {
String unescapedName = name.substring(1); // FIXME Compatibility
invocations = getInvocations(sourceType, null, unescapedName, 0, expression.getOwnedArguments().size());
}
}
} /*else {
// metamodelManager.getASMetamodel(); // Ensure metamodel has been loaded
SingleResultEnvironment env = nameResolver.computeReferredOperationLookup(expression);
if (env.getSize() == 1) {
asOperation = (Operation) env.getSingleResult();
context.setReferredOperation(expression, asOperation);
resolveOperationReturnType(expression);
} else if (sourceType != null && env.getSize() > 1) {
invocations = new UnresolvedInvocations(sourceType, env.getAllResults());
}
}*/
if (invocations != null) {
AbstractOperationMatcher matcher = null;
if ((csOperator instanceof InfixExpCS) && !NavigationUtil.isNavigationInfixExp(csOperator)) { // explicit: X op Y
matcher = new BinaryOperationMatcher(environmentFactory, sourceType, null, ((InfixExpCS) csOperator).getArgument());
}
else { // explicit: op X, or implicit: X.oclAsSet()->
matcher = new UnaryOperationMatcher(environmentFactory, sourceType, null);
}
asOperation = matcher.getBestOperation(invocations, false);
if (asOperation != null) {
AmbiguitiesAdapter.setAmbiguities(csOperator, matcher.getAmbiguities());
}
else {
asOperation = matcher.getBestOperation(invocations, true);
}
context.setReferredOperation(expression, asOperation);
resolveOperationReturnType(expression);
}
if (asOperation == null) {
StringBuilder s = new StringBuilder();
for (OCLExpression argument : PivotUtil.getOwnedArguments(expression)) {
Type argumentType = PivotUtilInternal.getType(argument);
if (s.length() > 0) {
s.append(",");
}
s.append(argumentType.toString());
}
if (s.length() > 0) {
context.addError(csOperator, PivotMessagesInternal.UnresolvedOperationCall_ERROR_, sourceType, csOperator.getName(), s.toString());
}
else {
context.addError(csOperator, PivotMessagesInternal.UnresolvedOperation_ERROR_, sourceType, csOperator.getName());
}
// context.addBadExpressionError(csOperator, boundMessage);
Operation oclInvalidOperation = standardLibrary.getOclInvalidOperation();
context.setReferredOperation(expression, oclInvalidOperation);
// ElementUtil.setLastPathElement(csPathName, oclInvalidOperation);
helper.setType(expression, standardLibrary.getOclInvalidType(), false, null);
}
}
protected @NonNull OperationCallExp resolveOperationCallExp(@NonNull RoundBracketedClauseCS csRoundBracketedClause, @NonNull OperationCallExp operationCallExp, @NonNull Operation operation) {
@SuppressWarnings("null")@NonNull AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
context.setReferredOperation(operationCallExp, operation);
resolveAtPre(csNameExp, operationCallExp);
context.installPivotUsage(csNameExp, operationCallExp);
resolveOperationArguments(csRoundBracketedClause, 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;
}
Type sourceType = null;
Type sourceTypeValue = null;
OCLExpression source = callExp.getOwnedSource();
if (source != null) {
sourceType = source.getType();
sourceTypeValue = source.getTypeValue();
}
TemplateParameterSubstitutions templateSubstitutions = TemplateParameterSubstitutionVisitor.createBindings(environmentFactory, sourceType, sourceTypeValue, operation);
@SuppressWarnings("unused") // Should never happen; just for debugging
boolean isConformant = true;
if (callExp instanceof OperationCallExp) {
List<@NonNull Parameter> parameters = PivotUtilInternal.getOwnedParametersList(operation);
List<@NonNull OCLExpression> arguments = PivotUtilInternal.getOwnedArgumentsList((OperationCallExp)callExp);
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 = PivotUtilInternal.getType(parameter);
Type argumentType = PivotUtilInternal.getType(argument);
if (!metamodelManager.conformsTo(argumentType, TemplateParameterSubstitutions.EMPTY, parameterType, templateSubstitutions)) {
isConformant = false;
}
}
}
else if (callExp instanceof LoopExp) {
if (callExp instanceof IterateExp) {
List<@NonNull Parameter> accumulators = PivotUtilInternal.getOwnedAccumulatorsList(((Iteration)operation));
if (accumulators.size() >= 1) {
Parameter accumulator = accumulators.get(0);
Variable result = PivotUtil.getOwnedResult((IterateExp)callExp);
Type accumulatorType = PivotUtilInternal.getType(accumulator);
Type resultType = PivotUtilInternal.getType(result);
if (!metamodelManager.conformsTo(resultType, TemplateParameterSubstitutions.EMPTY, accumulatorType, templateSubstitutions)) {
isConformant = false;
}
}
}
List<@NonNull Parameter> parameters = PivotUtilInternal.getOwnedParametersList(operation);
if (parameters.size() >= 1) {
Parameter parameter = parameters.get(0);
OCLExpression body = PivotUtil.getOwnedBody((LoopExp)callExp);
Type parameterType = PivotUtilInternal.getType(parameter);
Type bodyType = PivotUtilInternal.getType(body);
if (!metamodelManager.conformsTo(bodyType, TemplateParameterSubstitutions.EMPTY, parameterType, templateSubstitutions)) {
isConformant = false;
}
}
}
helper.setOperationReturnType(callExp, operation);
}
protected @NonNull CallExp resolvePropertyCallExp(@NonNull OCLExpression sourceExp, @NonNull NameExpCS csNameExp, @NonNull Property property) {
NavigationCallExp callExp;
if (property.isIsImplicit()) {
callExp = refreshOppositePropertyCallExp(csNameExp, sourceExp, property);
}
else {
callExp = refreshPropertyCallExp(csNameExp, sourceExp, property);
}
// if (isInvalidType(property.getType())) {
// EssentialOCLUtils.setHasError(csNameExp);
// }
resolveAtPre(csNameExp, callExp);
Type returnType = resolvePropertyReturnType(callExp, csNameExp, property);
helper.setType(callExp, returnType, property.isIsRequired() && !callExp.isIsSafe(), null);
return callExp;
}
protected @Nullable Type resolvePropertyReturnType(@NonNull NavigationCallExp callExp, @NonNull NameExpCS csNameExp, @NonNull Property property) {
Type formalType = property.getType();
if (formalType == null) {
return null;
}
OCLExpression source = callExp.getOwnedSource();
Type actualType;
Type sourceType = source != null ? source.getType() : null;
if (sourceType != null) {
actualType = metamodelManager.specializeType(formalType, callExp, sourceType, source != null ? source.getTypeValue() : null);
}
else {
actualType = formalType;
}
if (property.isIsStatic() && (actualType.isTemplateParameter() != null)) {
actualType = metamodelManager.getMetaclass(actualType);
}
return actualType;
}
protected Element resolveRoundBracketedTerm(@NonNull RoundBracketedClauseCS csRoundBracketedClause) {
AbstractNameExpCS csNameExp = csRoundBracketedClause.getOwningNameExp();
OperatorExpCS csParent = csNameExp.getLocalParent();
if (NavigationUtil.isNavigationInfixExp(csParent) && (csParent != null) && (csNameExp != ((InfixExpCS)csParent).getSource())) {
// source.name(), source->name() are resolved by the parent NavigationOperatorCS
return PivotUtil.getPivot(OCLExpression.class, csNameExp);
}
return resolveInvocation(null, csRoundBracketedClause);
}
protected @Nullable OCLExpression resolveShadowExp(@NonNull NameExpCS csNameExp) {
PathNameCS pathName = csNameExp.getOwnedPathName();
if (pathName == null) {
return null;
}
CurlyBracketedClauseCS csCurlyBracketedClause = csNameExp.getOwnedCurlyBracketedClause();
RoundBracketedClauseCS csRoundBracketedClause = csNameExp.getOwnedRoundBracketedClause();
if (csRoundBracketedClause != null) {
// FIXME (TemplateTypeArgument)
return context.addBadExpressionError(csNameExp, "ShadowExp must have no round-brackets-clause");
}
if (csNameExp.getOwnedSquareBracketedClauses().size() != 0) {
return context.addBadExpressionError(csNameExp, "ShadowExp must have no square-brackets-clause");
}
Type asType = context.lookupType(csNameExp, pathName);
@NonNull ShadowExp pivotElement = context.refreshModelElement(ShadowExp.class, PivotPackage.Literals.SHADOW_EXP, csNameExp);
pivotElement.setType(asType);
for (ShadowPartCS csPart : csCurlyBracketedClause.getOwnedParts()) {
assert csPart != null;
context.visitLeft2Right(ShadowPart.class, csPart);
}
context.refreshPivotList(ShadowPart.class, pivotElement.getOwnedParts(), csCurlyBracketedClause.getOwnedParts());
return pivotElement;
}
protected Element resolveSimpleNameExp(@NonNull NameExpCS csNameExp, @NonNull Element element) {
if (element instanceof VariableDeclaration) {
return resolveVariableExp(csNameExp, (VariableDeclaration)element);
}
else if (element instanceof Property) {
Property property = (Property) element;
OCLExpression sourceExp = createImplicitSourceVariableExp(csNameExp, property.getOwningClass());
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
}
}
protected StateExp resolveStateExp(@NonNull ExpCS csExp, @NonNull State state) {
StateExp expression = context.refreshModelElement(StateExp.class, PivotPackage.Literals.STATE_EXP, csExp);
helper.setType(expression, environmentFactory.getASClass("State"), true, null); // FIXME What should this be
expression.setReferredState(state);
expression.setName(state.getName());
return expression;
}
protected @NonNull TypeExp resolveTypeExp(@NonNull ExpCS csExp, @NonNull Type type) {
TypeExp expression = context.refreshModelElement(TypeExp.class, PivotPackage.Literals.TYPE_EXP, csExp);
IdResolver idResolver = metamodelManager.getEnvironmentFactory().getIdResolver();
Type asType = idResolver.getStaticTypeOfValue(null, type);
helper.setType(expression, asType, true, type);
expression.setReferredType(type);
expression.setName(type.getName());
return expression;
}
protected @NonNull VariableExp resolveVariableExp(@NonNull NameExpCS csNameExp, @NonNull VariableDeclaration variableDeclaration) {
VariableExp expression = context.refreshModelElement(VariableExp.class, PivotPackage.Literals.VARIABLE_EXP, csNameExp);
expression.setReferredVariable(variableDeclaration);
expression.setName(variableDeclaration.getName());
helper.setType(expression, variableDeclaration.getType(), variableDeclaration.isIsRequired(), variableDeclaration.getTypeValue());
return expression;
}
@Override
public Element visitBooleanLiteralExpCS(@NonNull BooleanLiteralExpCS csBooleanLiteralExp) {
BooleanLiteralExp expression = PivotUtil.getPivot(BooleanLiteralExp.class, csBooleanLiteralExp);
if (expression != null) {
expression.setBooleanSymbol(Boolean.valueOf(csBooleanLiteralExp.getSymbol()));
helper.setType(expression, standardLibrary.getBooleanType(), true, null);
}
return expression;
}
@Override
public Element visitCollectionLiteralExpCS(@NonNull CollectionLiteralExpCS csCollectionLiteralExp) {
Type commonType = null;
// InvalidLiteralExp invalidValue = null;
boolean isNullFree = true;
for (CollectionLiteralPartCS csPart : csCollectionLiteralExp.getOwnedParts()) {
assert csPart != null;
CollectionLiteralPart pivotPart = context.visitLeft2Right(CollectionLiteralPart.class, csPart);
Type asType = pivotPart != null ? pivotPart.getType() : null;
Type type = asType;// != null ? PivotUtil.getBehavioralType(asType) : null;
// 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, TemplateParameterSubstitutions.EMPTY, type, TemplateParameterSubstitutions.EMPTY);
}
}
if (pivotPart instanceof CollectionItem) {
if ((((CollectionItem)pivotPart).getOwnedItem() instanceof NullLiteralExp)) {
isNullFree = false;
}
}
else if (pivotPart instanceof CollectionRange) {
;
}
else {
isNullFree = false;
}
}
// 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 = standardLibrary.getOclVoidType();
}
Type type = metamodelManager.getCollectionType(collectionTypeName, commonType, isNullFree, null, null);
helper.setType(expression, type, true, null);
expression.setKind(TypeUtil.getCollectionKind((CollectionType) type));
}
return expression;
}
@Override
public Element visitCollectionLiteralPartCS(@NonNull CollectionLiteralPartCS csCollectionLiteralPart) {
ExpCS csFirst = csCollectionLiteralPart.getOwnedExpression();
if (csFirst == null) {
return null;
}
OCLExpression pivotFirst = context.visitLeft2Right(OCLExpression.class, csFirst);
OCLExpression pivotLast = null;
ExpCS csLast = csCollectionLiteralPart.getOwnedLastExpression();
if (csLast == null) {
CollectionItem expression = PivotUtil.getPivot(CollectionItem.class, csCollectionLiteralPart);
if (expression != null) {
expression.setOwnedItem(pivotFirst);
}
}
else {
CollectionRange expression = PivotUtil.getPivot(CollectionRange.class, csCollectionLiteralPart);
if (expression != null) {
expression.setOwnedFirst(pivotFirst);
pivotLast = context.visitLeft2Right(OCLExpression.class, csLast);
expression.setOwnedLast(pivotLast);
}
}
if (pivotFirst == null) {
return null;
}
Type type = pivotFirst.getType();
if (type == null) {
return null;
}
boolean isRequired = pivotFirst.isIsRequired();
if (pivotLast != null) {
Type secondType = pivotLast.getType();
if (secondType != null) {
type = metamodelManager.getCommonType(type, TemplateParameterSubstitutions.EMPTY, secondType, TemplateParameterSubstitutions.EMPTY);
}
isRequired &= pivotLast.isIsRequired();
}
CollectionLiteralPart expression = PivotUtil.getPivot(CollectionLiteralPart.class, csCollectionLiteralPart);
if (expression != null) {
helper.setType(expression, type, isRequired);
}
return expression;
}
@Override
public Element visitCollectionTypeCS(@NonNull CollectionTypeCS object) {
return null;
}
@Override
public Element visitContextCS(@NonNull ContextCS csContext) {
ExpressionInOCL pivotElement = PivotUtil.getPivot(ExpressionInOCL.class, csContext);
if (pivotElement != null) {
ExpCS csExpression = csContext.getOwnedExpression();
if (csExpression != null) {
String bodyText = ElementUtil.getRawText(csExpression);
pivotElement.setBody(bodyText);
OCLExpression expression = context.visitLeft2Right(OCLExpression.class, csExpression);
if (expression != null) {
PivotUtil.setBody(pivotElement, expression, bodyText);
helper.setType(pivotElement, expression.getType(), expression.isIsRequired());
}
}
else {
pivotElement.setBody(null);
}
}
return pivotElement;
}
@Override
public Element visitExpCS(@NonNull ExpCS object) {
return null;
}
@Override
public Element visitIfExpCS(@NonNull IfExpCS csIfExp) {
IfExp ifExpression = PivotUtil.getPivot(IfExp.class, csIfExp);
ExpCS csElse = csIfExp.getOwnedElseExpression();
if ((ifExpression != null) && (csElse != null)) {
OCLExpression elseExpression = context.visitLeft2Right(OCLExpression.class, csElse);
List<IfThenExpCS> csIfThens = csIfExp.getOwnedIfThenExpressions();
for (int i = csIfThens.size(); --i >= 0; ) {
IfThenExpCS csIfThen = csIfThens.get(i);
IfExp elseIfExpression = PivotUtil.getPivot(IfExp.class, csIfThen);
if (elseIfExpression != null) {
elseExpression = doIfThenElse(elseIfExpression, csIfThen.getOwnedCondition(), csIfThen.getOwnedThenExpression(), elseExpression);
}
}
doIfThenElse(ifExpression, csIfExp.getOwnedCondition(), csIfExp.getOwnedThenExpression(), elseExpression);
}
return ifExpression;
}
@Override
public Element visitInfixExpCS(@NonNull InfixExpCS csInfixExp) {
//
// If this is a new Operation tree start at its root.
//
OperatorExpCS csRoot = getRoot(csInfixExp);
if (csRoot != currentRoot) {
OperatorExpCS savedCurrentRoot = currentRoot;
try {
currentRoot = csRoot;
OCLExpression pivot = context.visitLeft2Right(OCLExpression.class, csRoot);
assert csRoot.getPivot() == pivot;
return pivot;
}
finally {
currentRoot = savedCurrentRoot;
}
}
OCLExpression pivot;
if (NavigationUtil.isNavigationInfixExp(csInfixExp)) {
pivot = doVisitNavigationOperatorCS(csInfixExp);
}
else {
pivot = doVisitBinaryOperatorCS(csInfixExp);
}
assert csInfixExp.getPivot() == pivot;
// if (pivot != null) {
// context.installPivotUsage(csInfixExp, pivot);
// }
return pivot;
}
protected @NonNull OCLExpression doIfThenElse(@NonNull IfExp expression, @Nullable ExpCS csCondition, @Nullable ExpCS csThen, @Nullable OCLExpression elseExpression) {
if ((csCondition != null) && (csThen != null)) {
expression.setOwnedCondition(context.visitLeft2Right(OCLExpression.class, csCondition));
OCLExpression thenExpression = context.visitLeft2Right(OCLExpression.class, csThen);
Type thenType = thenExpression != null ? thenExpression.getType() : null;
Type elseType = elseExpression != null ? elseExpression.getType() : null;
Type commonType = null;
if ((thenType != null) && (elseType != null)) {
commonType = metamodelManager.getCommonType(thenType, TemplateParameterSubstitutions.EMPTY, elseType, TemplateParameterSubstitutions.EMPTY);
if ((commonType != thenType) && (commonType != elseType)) {
PrimitiveType integerType = standardLibrary.getIntegerType();
Operation asCoercion = NameUtil.getNameable(integerType.getOwnedOperations(), "toUnlimitedNatural");
if (asCoercion != null) {
PrimitiveType unlimitedNaturalType = standardLibrary.getUnlimitedNaturalType();
if (thenType.conformsTo(standardLibrary, unlimitedNaturalType)) {
if (elseType.conformsTo(standardLibrary, integerType)) {
assert elseExpression != null;
elseExpression = new PivotHelper(environmentFactory).createCoercionCallExp(elseExpression, asCoercion);
commonType = unlimitedNaturalType;
}
}
else if (elseType.conformsTo(standardLibrary, unlimitedNaturalType)) {
if (thenType.conformsTo(standardLibrary, integerType)) {
assert thenExpression != null;
thenExpression = new PivotHelper(environmentFactory).createCoercionCallExp(thenExpression, asCoercion);
commonType = unlimitedNaturalType;
}
}
}
}
}
expression.setOwnedThen(thenExpression);
expression.setOwnedElse(elseExpression);
Type thenTypeValue = thenExpression != null ? thenExpression.getTypeValue() : null;
Type elseTypeValue = elseExpression != null ? elseExpression.getTypeValue() : null;
Type commonTypeValue = (thenTypeValue != null) && (elseTypeValue != null) ? metamodelManager.getCommonType(thenTypeValue, TemplateParameterSubstitutions.EMPTY, elseTypeValue, TemplateParameterSubstitutions.EMPTY) : null;
boolean isRequired = ((thenExpression != null) && thenExpression.isIsRequired()) && ((elseExpression != null) && elseExpression.isIsRequired());
helper.setType(expression, commonType, isRequired, commonTypeValue);
}
return expression;
}
protected @NonNull OCLExpression doVisitBinaryOperatorCS(@NonNull InfixExpCS csOperator) {
OperationCallExp expression = context.refreshModelElement(OperationCallExp.class, PivotPackage.Literals.OPERATION_CALL_EXP, csOperator);
String name = csOperator.getName();
assert name != null;
helper.refreshName(expression, name);
ExpCS csSource = csOperator.getSource();
if (csSource != null) {
OCLExpression source = context.visitLeft2Right(OCLExpression.class, csSource);
expression.setOwnedSource(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();
helper.refreshList(expression.getOwnedArguments(), newElements);
Type sourceType = source != null ? PivotUtilInternal.getType(source) : null;
Type argumentType = argument != null ? PivotUtilInternal.getType(argument) : null;
if ((sourceType != null) && (argumentType != null)) {
resolveOperationCall(expression, csOperator);
}
}
}
return expression;
}
protected OCLExpression doVisitNavigationOperatorCS(@NonNull InfixExpCS csOperator) {
OCLExpression navigatingExp = null;
ExpCS csSource = csOperator.getSource();
if (csSource != null) {
OCLExpression sourceExp = context.visitLeft2Right(OCLExpression.class, csSource);
if (sourceExp != null) {
Type asType = sourceExp.getType();
Type actualSourceType = asType;// != null ? PivotUtil.getBehavioralType(asType) : null;
if (actualSourceType != null) {
ExpCS argument = csOperator.getArgument();
if (argument instanceof NameExpCS) {
NameExpCS csNameExp = (NameExpCS) argument;
LoopExp implicitCollectExp = null;
OCLExpression collectedSourceExp = sourceExp;
//
// Condition the source for implicit set or implicit collect
//
String navigationOperatorName = csOperator.getName();
boolean isAggregate = PivotUtil.isAggregate(actualSourceType);
if (isAggregate) {
if (PivotUtil.isObjectNavigationOperator(navigationOperatorName)) {
implicitCollectExp = resolveImplicitCollect(sourceExp, csOperator);
if (implicitCollectExp != null) {
@SuppressWarnings("null")@NonNull Variable iterator = implicitCollectExp.getOwnedIterators().get(0);
collectedSourceExp = createImplicitVariableExp(iterator);
}
}
}
else {
if (PivotUtil.isAggregateNavigationOperator(navigationOperatorName)) {
collectedSourceExp = resolveImplicitAsSet(sourceExp, actualSourceType, csOperator);
}
}
Type sourceType = collectedSourceExp.getType();
csNameExp.setSourceType(sourceType);
csNameExp.setSourceTypeValue(collectedSourceExp.getTypeValue());
//
// Resolve the inner call expression
//
OCLExpression callExp;
RoundBracketedClauseCS csRoundBracketedClause = csNameExp.getOwnedRoundBracketedClause();
if (csRoundBracketedClause != null) {
callExp = resolveInvocation(collectedSourceExp, csRoundBracketedClause);
}
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) {
boolean isSafe = PivotUtil.isSafeNavigationOperator(navigationOperatorName);
// ((CallExp) callExp).setIsSafe(isSafe && (implicitCollectExp == null));
// if (isSafe) {
// callExp.setIsRequired(true); // FIXME Why?
// }
if (implicitCollectExp != null) {
implicitCollectExp.setOwnedBody(callExp);
resolveOperationReturnType(implicitCollectExp);
navigatingExp = implicitCollectExp;
}
else {
((CallExp) callExp).setIsSafe(isSafe);
if (isSafe && !isAggregate) {
callExp.setIsRequired(isAggregate);
}
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 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;
}
@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.getOwnedVariables()) {
LetVariable variable = PivotUtil.getPivot(LetVariable.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.setOwnedVariable(variable);
ExpCS csInitExpression = csLetVariable.getOwnedInitExpression();
if (csInitExpression != null) {
TypedRefCS csVariableType = csLetVariable.getOwnedType();
Boolean variableIsRequired = null;
Type variableType = null;
if (csVariableType != null) {
variableType = PivotUtil.getPivot(Type.class, csVariableType);
variableIsRequired = context.isRequired(csVariableType);
}
boolean initIsRequired = false;
OCLExpression initExpression = context.visitLeft2Right(OCLExpression.class, csInitExpression);
Type initType = null;
Type initTypeValue = null;
if (initExpression != null) {
initType = initExpression.getType();
initTypeValue = initExpression.getTypeValue();
initIsRequired = initExpression.isIsRequired();
if ((initType != null) && (variableType != null)) {
Operation asCoercion = resolveCoercionFrom(initType, variableType);
if (asCoercion != null) {
initExpression = new PivotHelper(environmentFactory).createCoercionCallExp(initExpression, asCoercion);
}
}
}
variable.setOwnedInit(initExpression);
if (variableType == null) {
variableType = initType;
}
boolean isRequired = variableIsRequired != null ? variableIsRequired.booleanValue() : initIsRequired;
helper.setType(variable, variableType, isRequired, initTypeValue);
if (lastLetExp != null) {
lastLetExp.setOwnedIn(letExp);
context.installPivotUsage(csLetExp, letExp);
}
else {
firstLetExp = letExp;
context.installPivotUsage(csLetExp, firstLetExp);
}
lastLetExp = letExp;
}
}
}
if (lastLetExp != null) {
ExpCS csIn = csLetExp.getOwnedInExpression();
if (csIn != null) {
OCLExpression in = context.visitLeft2Right(OCLExpression.class, csIn);
lastLetExp.setOwnedIn(in);
if (in != null) {
Type type = in.getType();
for (OCLExpression letExp = firstLetExp; (letExp != in) && (letExp != null); letExp = ((LetExp)letExp).getOwnedIn()) {
helper.setType(letExp, type, in.isIsRequired(), in.getTypeValue());
}
}
}
}
return firstLetExp;
}
@Override
public Element visitLetVariableCS(@NonNull LetVariableCS csLetVariable) {
return null; // Handled by parent
}
@Override
public Element visitMapLiteralExpCS(@NonNull MapLiteralExpCS csMapLiteralExp) {
Type keyType = null;
Type valueType = null;
Boolean keysAreNullFree = null;
Boolean valuesAreNullFree = null;
MapTypeCS csMapType = csMapLiteralExp.getOwnedType();
if (csMapType != null) {
TypedRefCS csKeyType = csMapType.getOwnedKeyType();
if (csKeyType != null) {
keyType = (Type) csKeyType.getPivot();
keysAreNullFree = context.isRequired(csKeyType);
}
TypedRefCS csValueType = csMapType.getOwnedValueType();
if (csValueType != null) {
valueType = (Type) csValueType.getPivot();
valuesAreNullFree = context.isRequired(csValueType);
}
}
boolean inferKeyType = keyType == null;
boolean inferValueType = valueType == null;
for (MapLiteralPartCS csPart : csMapLiteralExp.getOwnedParts()) {
assert csPart != null;
MapLiteralPart pivotPart = context.visitLeft2Right(MapLiteralPart.class, csPart);
if (pivotPart != null) {
if (inferKeyType) {
OCLExpression asKey = pivotPart.getOwnedKey();
if (asKey != null) {
if (asKey instanceof NullLiteralExp) {
keysAreNullFree = false;
}
@SuppressWarnings("deprecation")
FlowAnalysis flowAnalysis = FlowAnalysis.getFlowAnalysis(environmentFactory, asKey);
if (!flowAnalysis.isNonNull(asKey)) {
keysAreNullFree = false;
}
Type asKeyType = asKey.getType();
if (asKeyType != null) {
if (keyType == null) {
keyType = asKeyType;
}
else if (keyType != asKeyType) {
keyType = metamodelManager.getCommonType(keyType, TemplateParameterSubstitutions.EMPTY, asKeyType, TemplateParameterSubstitutions.EMPTY);
}
}
}
}
if (inferValueType) {
OCLExpression asValue = pivotPart.getOwnedValue();
if (asValue != null) {
if (asValue instanceof NullLiteralExp) {
valuesAreNullFree = false;
}
@SuppressWarnings("deprecation")
FlowAnalysis flowAnalysis = FlowAnalysis.getFlowAnalysis(environmentFactory, asValue);
if (!flowAnalysis.isNonNull(asValue)) {
valuesAreNullFree = false;
}
Type asValueType = asValue.getType();
if (asValueType != null) {
if (valueType == null) {
valueType = asValueType;
}
else if (valueType != asValueType) {
valueType = metamodelManager.getCommonType(valueType, TemplateParameterSubstitutions.EMPTY, asValueType, TemplateParameterSubstitutions.EMPTY);
}
}
}
}
}
}
MapLiteralExp expression = PivotUtil.getPivot(MapLiteralExp.class, csMapLiteralExp);
if (expression != null) {
MapTypeCS ownedMapType = csMapLiteralExp.getOwnedType();
String mapTypeName = ownedMapType.getName();
assert mapTypeName != null;
if (keyType == null) {
keyType = standardLibrary.getOclVoidType();
keysAreNullFree = true;
}
else if (inferKeyType && (keysAreNullFree == null)) {
keysAreNullFree = true;
}
if (valueType == null) {
valueType = standardLibrary.getOclVoidType();
valuesAreNullFree = true;
}
else if (inferValueType && (valuesAreNullFree == null)) {
valuesAreNullFree = true;
}
Type type = metamodelManager.getMapType(mapTypeName, keyType, keysAreNullFree != Boolean.FALSE, valueType, valuesAreNullFree != Boolean.FALSE);
helper.setType(expression, type, true, null);
}
return expression;
}
@Override
public Element visitMapLiteralPartCS(@NonNull MapLiteralPartCS csMapLiteralPart) {
ExpCS csKey = csMapLiteralPart.getOwnedKey();
ExpCS csValue = csMapLiteralPart.getOwnedValue();
if ((csKey == null) || (csValue == null)) {
return null;
}
OCLExpression asKey = context.visitLeft2Right(OCLExpression.class, csKey);
OCLExpression asValue = context.visitLeft2Right(OCLExpression.class, csValue);
MapLiteralPart expression = PivotUtil.getPivot(MapLiteralPart.class, csMapLiteralPart);
if (expression != null) {
expression.setOwnedKey(asKey);
expression.setOwnedValue(asValue);
}
return expression;
}
@Override
public Element visitMapTypeCS(@NonNull MapTypeCS object) {
return null;
}
@Override
public Element visitNameExpCS(@NonNull NameExpCS csNameExp) {
PathNameCS csPathName = csNameExp.getOwnedPathName();
if (csPathName == null) {
return context.addBadExpressionError(csNameExp, "Missing path name");
}
RoundBracketedClauseCS csRoundBracketedClause = csNameExp.getOwnedRoundBracketedClause();
if (csNameExp.getOwnedCurlyBracketedClause() != null) {
return resolveShadowExp(csNameExp);
}
else if (csNameExp.getOwnedSquareBracketedClauses().size() > 0) {
return resolveAssociationClassCallExp(csNameExp);
}
else if (csRoundBracketedClause != null) {
return resolveRoundBracketedTerm(csRoundBracketedClause);
}
checkForInvalidImplicitSourceType(csNameExp);
// csNameExp.getPathName().get
Element element = context.lookupUndecoratedName(csNameExp, csPathName);
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;
}
return resolveSimpleNameExp(csNameExp, element);
}
@Override
public Element visitNavigatingArgCS(@NonNull NavigatingArgCS csNavigatingArg) {
OCLExpression pivot = PivotUtil.getPivot(OCLExpression.class, csNavigatingArg);
if (pivot != null) {
context.installPivotUsage(csNavigatingArg, pivot);
}
return pivot;
}
@Override
public Element visitNestedExpCS(@NonNull NestedExpCS csNestedExp) {
ExpCS csSource = csNestedExp.getOwnedExpression();
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) {
helper.setType(expression, standardLibrary.getOclVoidType(), false, null);
}
return expression;
}
@Override
public Element visitNumberLiteralExpCS(@NonNull NumberLiteralExpCS csNumberLiteralExp) {
NumericLiteralExp expression = PivotUtil.getPivot(NumericLiteralExp.class, csNumberLiteralExp);
if (expression instanceof UnlimitedNaturalLiteralExp) {
helper.setType(expression, standardLibrary.getUnlimitedNaturalType(), true, null);
}
else if (expression instanceof IntegerLiteralExp) {
helper.setType(expression, standardLibrary.getIntegerType(), true, null);
}
else if (expression != null){
helper.setType(expression, standardLibrary.getRealType(), true, null);
}
return expression;
}
@Override
public Element visitPrefixExpCS(@NonNull PrefixExpCS csPrefixExp) {
//
// If this is a new Operation tree start at its root.
//
OperatorExpCS csRoot = getRoot(csPrefixExp);
if (csRoot != currentRoot) {
OperatorExpCS savedCurrentRoot = currentRoot;
try {
currentRoot = csRoot;
OCLExpression pivot = context.visitLeft2Right(OCLExpression.class, csRoot);
assert csRoot.getPivot() == pivot;
return pivot;
}
finally {
currentRoot = savedCurrentRoot;
}
}
OperationCallExp asCallExp = context.refreshModelElement(OperationCallExp.class, PivotPackage.Literals.OPERATION_CALL_EXP, csPrefixExp);
helper.refreshName(asCallExp, csPrefixExp.getName());
ExpCS csSource = csPrefixExp.getSource();
if (csSource != null) {
OCLExpression source = context.visitLeft2Right(OCLExpression.class, csSource);
if (source != null) {
asCallExp.setOwnedSource(source);
resolveOperationCall(asCallExp, csPrefixExp);
}
}
assert csPrefixExp.getPivot() == asCallExp;
return asCallExp;
}
@Override
public Element visitSelfExpCS(@NonNull SelfExpCS csSelfExp) { // FIXME Just use VariableExpCS
VariableExp expression = PivotUtil.getPivot(VariableExp.class, csSelfExp);
if (expression != null) {
ElementCS parent = csSelfExp.getParent();
if (parent != null) {
VariableDeclaration variableDeclaration = context.getConverter().lookupSelf(parent);
if (variableDeclaration == null) {
return context.addBadExpressionError(csSelfExp, PivotMessages.UnspecifiedSelfContext);
}
expression.setReferredVariable(variableDeclaration);
expression.setName(variableDeclaration.getName());
helper.setType(expression, variableDeclaration.getType(), true, variableDeclaration.getTypeValue());
}
}
return expression;
}
@Override
public Element visitShadowPartCS(@NonNull ShadowPartCS csShadowPart) {
ShadowPart pivotElement = PivotUtil.getPivot(ShadowPart.class, csShadowPart);
if (pivotElement != null) {
Property property = csShadowPart.getReferredProperty();
if (property == null) {
property = new PivotHelper(environmentFactory).getDataTypeValueProperty();
}
pivotElement.setReferredProperty(property);
helper.refreshName(pivotElement, property.getName());
helper.setType(pivotElement, property.getType(), property.isIsRequired());
ExpCS csInitExpression = csShadowPart.getOwnedInitExpression();
if (csInitExpression != null) {
OCLExpression initExpression = context.visitLeft2Right(OCLExpression.class, csInitExpression);
pivotElement.setOwnedInit(initExpression);
}
}
return pivotElement;
}
@Override
public Element visitStringLiteralExpCS(@NonNull StringLiteralExpCS csStringLiteralExp) {
StringLiteralExp pivotElement = PivotUtil.getPivot(StringLiteralExp.class, csStringLiteralExp);
if (pivotElement != null) {
helper.setType(pivotElement, standardLibrary.getStringType(), true, null);
}
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<@NonNull TupleLiteralPart> parts = ClassUtil.nullFree(expression.getOwnedParts());
assert parts != null;
Type type = standardLibrary.getCompleteModel().getTupleType(tupleTypeName, parts, null);
helper.setType(expression, type, true, null);
}
return expression;
}
@Override
public Element visitTupleLiteralPartCS(@NonNull TupleLiteralPartCS csTupleLiteralPart) {
TupleLiteralPart pivotElement = PivotUtil.getPivot(TupleLiteralPart.class, csTupleLiteralPart);
if (pivotElement != null) {
ExpCS csInitExpression = csTupleLiteralPart.getOwnedInitExpression();
if (csInitExpression != null) {
OCLExpression initExpression = context.visitLeft2Right(OCLExpression.class, csInitExpression);
pivotElement.setOwnedInit(initExpression);
TypedRefCS csType = csTupleLiteralPart.getOwnedType();
Type type = csType != null ? PivotUtil.getPivot(Type.class, csType) : initExpression != null ? initExpression.getType() : null;
helper.setType(pivotElement, type, (initExpression != null) && initExpression.isIsRequired(), null);
}
}
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 visitUnlimitedNaturalLiteralExpCS(@NonNull UnlimitedNaturalLiteralExpCS csUnlimitedNaturalLiteralExp) {
UnlimitedNaturalLiteralExp expression = PivotUtil.getPivot(UnlimitedNaturalLiteralExp.class, csUnlimitedNaturalLiteralExp);
if (expression != null) {
helper.setType(expression, standardLibrary.getUnlimitedNaturalType(), true, null);
}
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.getOwnedInitExpression());
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
}
helper.setType(variable, type, initExpression.isIsRequired(), initExpression.getTypeValue());
}
variable.setOwnedInit(initExpression);
}
return variable;
}
}