blob: 2cb0f2d26577ee1d73f16642455a99267b462393 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.qvtd.pivot.qvtcorebase.analysis;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
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.Element;
import org.eclipse.ocl.pivot.ExpressionInOCL;
import org.eclipse.ocl.pivot.IfExp;
import org.eclipse.ocl.pivot.IterateExp;
import org.eclipse.ocl.pivot.Iteration;
import org.eclipse.ocl.pivot.IteratorExp;
import org.eclipse.ocl.pivot.LanguageExpression;
import org.eclipse.ocl.pivot.LetExp;
import org.eclipse.ocl.pivot.LiteralExp;
import org.eclipse.ocl.pivot.MapLiteralExp;
import org.eclipse.ocl.pivot.MapLiteralPart;
import org.eclipse.ocl.pivot.NavigationCallExp;
import org.eclipse.ocl.pivot.NullLiteralExp;
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.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.TemplateParameter;
import org.eclipse.ocl.pivot.TemplateSignature;
import org.eclipse.ocl.pivot.TemplateableElement;
import org.eclipse.ocl.pivot.TupleLiteralExp;
import org.eclipse.ocl.pivot.TupleLiteralPart;
import org.eclipse.ocl.pivot.TupleType;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypeExp;
import org.eclipse.ocl.pivot.Variable;
import org.eclipse.ocl.pivot.VariableDeclaration;
import org.eclipse.ocl.pivot.VariableExp;
import org.eclipse.ocl.pivot.internal.manager.TemplateParameterSubstitutionVisitor;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
import org.eclipse.ocl.pivot.util.Visitable;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.qvtd.pivot.qvtbase.Domain;
import org.eclipse.qvtd.pivot.qvtbase.Function;
import org.eclipse.qvtd.pivot.qvtbase.Predicate;
import org.eclipse.qvtd.pivot.qvtbase.Rule;
import org.eclipse.qvtd.pivot.qvtbase.Transformation;
import org.eclipse.qvtd.pivot.qvtbase.TypedModel;
import org.eclipse.qvtd.pivot.qvtcorebase.AbstractMapping;
import org.eclipse.qvtd.pivot.qvtcorebase.Assignment;
import org.eclipse.qvtd.pivot.qvtcorebase.BottomPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.CoreDomain;
import org.eclipse.qvtd.pivot.qvtcorebase.GuardPattern;
import org.eclipse.qvtd.pivot.qvtcorebase.PropertyAssignment;
import org.eclipse.qvtd.pivot.qvtcorebase.RealizedVariable;
import org.eclipse.qvtd.pivot.qvtcorebase.VariableAssignment;
import org.eclipse.qvtd.pivot.qvtcorebase.util.AbstractExtendingQVTcoreBaseVisitor;
import org.eclipse.qvtd.pivot.qvtcorebase.utilities.QVTcoreBaseUtil;
/**
* AbstractDomainUsageAnalysis provides shared functionality for the overall analysis and for nested operational analyses.
*/
public abstract class AbstractDomainUsageAnalysis extends AbstractExtendingQVTcoreBaseVisitor<DomainUsage, EnvironmentFactoryInternal> implements DomainUsageAnalysis.Internal
{
private DomainUsage selfUsage = null;
protected final @NonNull Map<Element, DomainUsage> element2usage = new HashMap<Element, DomainUsage>();
protected AbstractDomainUsageAnalysis(@NonNull EnvironmentFactoryInternal environmentFactory) {
super(environmentFactory);
}
protected @NonNull DomainUsage doPropertyAssignment(Property property, @NonNull PropertyAssignment object) {
DomainUsage valueUsage = visit(object.getValue());
DomainUsage slotUsage = visit(object.getSlotExpression());
DomainUsage knownSourceUsage = getRootAnalysis().property2containingClassUsage.get(property);
if (knownSourceUsage != null) {
@SuppressWarnings("null")@NonNull DomainUsage knownTargetUsage = getRootAnalysis().property2referredTypeUsage.get(property);
intersection(knownSourceUsage, slotUsage);
return intersection(knownTargetUsage, valueUsage);
}
else {
return intersection(slotUsage, valueUsage);
}
}
protected @NonNull DomainUsage doPropertyCallExp(Property property, @NonNull NavigationCallExp object) {
DomainUsage actualSourceUsage = visit(object.getOwnedSource());
DomainUsage knownSourceUsage = getRootAnalysis().property2containingClassUsage.get(property);
if (knownSourceUsage != null) {
@SuppressWarnings("null")@NonNull DomainUsage knownTargetUsage = getRootAnalysis().property2referredTypeUsage.get(property);
return knownTargetUsage; //intersection(knownSourceUsage, actualSourceUsage);
}
else {
return actualSourceUsage;
}
}
protected @NonNull DomainUsage getDomainUsage(@Nullable EObject object) {
Domain domain = QVTcoreBaseUtil.getContainingDomain(object);
if (domain != null) {
return visit(domain.getTypedModel());
}
else {
return getRootAnalysis().getMiddleUsage();
}
}
public @NonNull Map<Element, DomainUsage> getElements2Usage() {
return element2usage;
}
public @NonNull EnvironmentFactoryInternal getEnvironmentFactory() {
return context;
}
protected abstract @NonNull RootDomainUsageAnalysis getRootAnalysis();
@Override
public @Nullable DomainUsage getUsage(@Nullable EObject element) {
return element2usage.get(element);
}
protected @NonNull DomainUsage intersection(@NonNull DomainUsage firstUsage, @NonNull DomainUsage secondUsage) {
int firstMask = ((DomainUsage.Internal)firstUsage).getMask();
int secondMask = ((DomainUsage.Internal)secondUsage).getMask();
if (firstMask == secondMask) {
if (firstUsage != secondUsage) {
if (!firstUsage.isConstant()) {
replace((DomainUsage.Internal) firstUsage, secondUsage);
return secondUsage;
}
else if (!secondUsage.isConstant()) {
replace((DomainUsage.Internal) secondUsage, firstUsage);
return firstUsage;
}
}
return firstUsage;
}
else {
int intersectionMask = firstMask & secondMask;
DomainUsage usage = getRootAnalysis().getValidUsage(intersectionMask);
if (usage != null) {
if ((usage != firstUsage) && !firstUsage.isConstant()) {
replace((DomainUsage.Internal) firstUsage, usage);
}
if ((usage != secondUsage) && !secondUsage.isConstant()) {
replace((DomainUsage.Internal) secondUsage, usage);
}
return usage;
}
else {
usage = getRootAnalysis().createVariableUsage(intersectionMask);
if (!firstUsage.isConstant()) {
replace((DomainUsage.Internal) firstUsage, usage);
}
if (!secondUsage.isConstant()) {
replace((DomainUsage.Internal) secondUsage, usage);
}
return usage;
}
}
}
protected void popSelfUsage(DomainUsage savedUsage) {
selfUsage = savedUsage;
}
protected DomainUsage pushSelfUsage(@NonNull DomainUsage usage) {
DomainUsage oldUsage = selfUsage;
int usageMask = ((DomainUsage.Internal)usage).getMask();
DomainUsage constantUsage = getRootAnalysis().getValidUsage(usageMask);
if (constantUsage == null) {
usage = getRootAnalysis().createVariableUsage(usageMask);
}
selfUsage = usage;
return oldUsage;
}
protected void replace(@NonNull DomainUsage.Internal oldUsage, @NonNull DomainUsage newUsage) {
Iterable<Element> elements = oldUsage.getElements();
if (elements != null) {
for (@SuppressWarnings("null")@NonNull Element element : elements) {
setUsage(element, newUsage);
}
}
}
protected void setBoundVariablesUsages(@NonNull Rule rule) {
DomainUsage primitiveUsage = getRootAnalysis().getPrimitiveUsage();
for (Domain domain : rule.getDomain()) {
if (domain instanceof CoreDomain) {
DomainUsage usage = visit(domain.getTypedModel());
for (Variable variable : ((CoreDomain)domain).getGuardPattern().getVariable()) {
if (variable != null) {
DomainUsage variableUsage = visit(variable.getType());
if (variableUsage != primitiveUsage) {
variableUsage = usage;
}
assert variableUsage != null;
setUsage(variable, variableUsage);
}
}
}
}
if (rule instanceof AbstractMapping) {
DomainUsage middleUsage = getRootAnalysis().getMiddleUsage();
for (Variable variable : ((AbstractMapping)rule).getGuardPattern().getVariable()) {
if (variable != null) {
DomainUsage variableUsage = visit(variable.getType());
if (variableUsage != primitiveUsage) {
variableUsage = middleUsage;
}
assert variableUsage != null;
setUsage(variable, variableUsage);
}
}
}
}
protected void setUsage(@NonNull Element element, @NonNull DomainUsage newUsage) {
element2usage.put(element, newUsage);
((DomainUsage.Internal)newUsage).addUsedBy(element);
}
@Override
public @NonNull DomainUsage visit(@Nullable Element element) {
if (element == null) {
return getRootAnalysis().getAnyUsage();
}
DomainUsage usage = element2usage.get(element);
if (usage == null) {
usage = element.accept(this);
assert usage != null : "null usage for " + element.eClass().getName() + " " + element;
setUsage(element, usage);
}
return usage;
}
@Override
public @Nullable DomainUsage visiting(@NonNull Visitable visitable) {
throw new UnsupportedOperationException("Unsupported " + visitable.eClass().getName() + " for " + getClass().getSimpleName());
}
@Override
public @Nullable DomainUsage visitBottomPattern(@NonNull BottomPattern object) {
for (Variable variable : object.getVariable()) {
visit(variable);
}
for (RealizedVariable variable : object.getRealizedVariable()) {
visit(variable);
}
for (Assignment assignment : object.getAssignment()) {
visit(assignment);
}
for (Predicate predicate : object.getPredicate()) {
visit(predicate);
}
return getDomainUsage(object);
}
@Override
public @Nullable DomainUsage visitClass(@NonNull org.eclipse.ocl.pivot.Class object) {
DomainUsage usage = getRootAnalysis().class2usage.get(object);
if (usage != null) {
return usage;
}
else {
return getRootAnalysis().getPrimitiveUsage();
}
}
@Override
public @Nullable DomainUsage visitCollectionItem(@NonNull CollectionItem object) {
return visit(object.getOwnedItem());
}
@Override
public @Nullable DomainUsage visitCollectionLiteralExp(@NonNull CollectionLiteralExp object) {
DomainUsage usage = getRootAnalysis().getAnyUsage();
for (@SuppressWarnings("null")@NonNull CollectionLiteralPart part : object.getOwnedParts()) {
usage = intersection(usage, visit(part));
}
return usage;
}
@Override
public @Nullable DomainUsage visitCollectionRange(@NonNull CollectionRange object) {
DomainUsage firstUsage = visit(object.getOwnedFirst());
DomainUsage lastUsage = visit(object.getOwnedLast());
return intersection(firstUsage, lastUsage);
}
@Override
public @Nullable DomainUsage visitCollectionType(@NonNull CollectionType object) {
return visit(object.getElementType());
}
@Override
public @Nullable DomainUsage visitCoreDomain(@NonNull CoreDomain object) {
visit(object.getGuardPattern());
visit(object.getBottomPattern());
return visit(object.getTypedModel());
}
@Override
public @Nullable DomainUsage visitExpressionInOCL(@NonNull ExpressionInOCL object) {
visit(object.getOwnedContext());
for (Variable parameter : object.getOwnedParameters()) {
visit(parameter);
}
visit(object.getOwnedResult());
return visit(object.getOwnedBody());
}
@Override
public @Nullable DomainUsage visitFunction(@NonNull Function object) {
for (@SuppressWarnings("null")@NonNull Parameter parameter : object.getOwnedParameters()) {
visit(parameter);
}
OCLExpression queryExpression = object.getQueryExpression();
if (queryExpression != null) {
return visit(queryExpression);
}
else {
return visit(object.getType());
}
}
@Override
public @Nullable DomainUsage visitIfExp(@NonNull IfExp object) {
@SuppressWarnings("unused") DomainUsage conditionUsage = visit(object.getOwnedCondition());
DomainUsage thenUsage = visit(object.getOwnedThen());
DomainUsage elseUsage = visit(object.getOwnedElse());
return intersection(thenUsage, elseUsage);
}
@Override
public @Nullable DomainUsage visitGuardPattern(@NonNull GuardPattern object) {
DomainUsage domainUsage = getDomainUsage(object);
// for (Variable variable : object.getVariable()) { // In visitTransformation
// setUsage(variable, domainUsage);
// }
for (Predicate predicate : object.getPredicate()) {
visit(predicate);
}
return domainUsage;
}
@Override
public @Nullable DomainUsage visitIterateExp(@NonNull IterateExp object) {
DomainUsage sourceUsage = visit(object.getOwnedSource());
for (Variable iterator : object.getOwnedIterators()) {
if (iterator != null) {
setUsage(iterator, sourceUsage);
}
}
visit(object.getOwnedResult());
@SuppressWarnings("unused") DomainUsage bodyUsage = visit(object.getOwnedBody());
TemplateParameterSubstitutionVisitor visitor = new TemplateParameterSubstitutionVisitor(context, object.getOwnedSource().getType(), null);
object.accept(visitor);
Iteration iteration = object.getReferredIteration();
for (EObject eObject = iteration; eObject != null; eObject = eObject.eContainer()) {
if (eObject instanceof TemplateableElement) {
TemplateSignature ownedSignature = ((TemplateableElement)eObject).getOwnedSignature();
if (ownedSignature != null) {
for (TemplateParameter templateParameter : ownedSignature.getOwnedParameters()) {
if (templateParameter != null) {
Type templateParameterType = visitor.get(templateParameter);
DomainUsage templateParameterUsage = visit(templateParameterType);
setUsage(templateParameter, templateParameterUsage);
}
}
}
}
}
return visit(iteration.getType());
}
@Override
public @Nullable DomainUsage visitIteratorExp(@NonNull IteratorExp object) {
DomainUsage sourceUsage = visit(object.getOwnedSource());
for (Variable iterator : object.getOwnedIterators()) {
if (iterator != null) {
setUsage(iterator, sourceUsage);
}
}
@SuppressWarnings("unused") DomainUsage bodyUsage = visit(object.getOwnedBody());
TemplateParameterSubstitutionVisitor visitor = new TemplateParameterSubstitutionVisitor(context, object.getOwnedSource().getType(), null);
object.accept(visitor);
Iteration iteration = object.getReferredIteration();
for (EObject eObject = iteration; eObject != null; eObject = eObject.eContainer()) {
if (eObject instanceof TemplateableElement) {
TemplateSignature ownedSignature = ((TemplateableElement)eObject).getOwnedSignature();
if (ownedSignature != null) {
for (TemplateParameter templateParameter : ownedSignature.getOwnedParameters()) {
if (templateParameter != null) {
Type templateParameterType = visitor.get(templateParameter);
DomainUsage templateParameterUsage = visit(templateParameterType);
setUsage(templateParameter, templateParameterUsage);
}
}
}
}
}
return visit(iteration.getType());
}
@Override
public @Nullable DomainUsage visitLetExp(@NonNull LetExp object) {
visit(object.getOwnedVariable());
return visit(object.getOwnedIn());
}
@Override
public @Nullable DomainUsage visitLiteralExp(@NonNull LiteralExp object) {
return getRootAnalysis().getPrimitiveUsage();
}
@Override
public @Nullable DomainUsage visitMapLiteralExp(@NonNull MapLiteralExp object) {
DomainUsage usage = getRootAnalysis().getAnyUsage();
for (@SuppressWarnings("null")@NonNull MapLiteralPart part : object.getOwnedParts()) {
usage = intersection(usage, visit(part));
}
return usage;
}
@Override
public @Nullable DomainUsage visitMapLiteralPart(@NonNull MapLiteralPart object) {
DomainUsage keyUsage = visit(object.getOwnedKey());
DomainUsage valueUsage = visit(object.getOwnedValue());
return intersection(keyUsage, valueUsage);
}
@Override
public @Nullable DomainUsage visitNullLiteralExp(@NonNull NullLiteralExp object) {
return getRootAnalysis().getAnyUsage();
}
@Override
public @Nullable DomainUsage visitOperation(@NonNull Operation object) {
DomainUsage savedUsage = pushSelfUsage(visit(object.getOwningClass()));
try {
for (@SuppressWarnings("null")@NonNull Parameter parameter : object.getOwnedParameters()) {
visit(parameter);
}
LanguageExpression bodyExpression = object.getBodyExpression();
if (bodyExpression != null) {
return visit(bodyExpression);
}
else {
return visit(object.getType());
}
}
finally {
popSelfUsage(savedUsage);
}
}
@Override
public @Nullable DomainUsage visitOperationCallExp(@NonNull OperationCallExp object) {
DomainUsage savedUsage = pushSelfUsage(visit(object.getOwnedSource()));
try {
Operation operation = ClassUtil.nonNullState(object.getReferredOperation());
DomainUsageAnalysis analysis = getRootAnalysis().getAnalysis(operation);
Map<DomainUsage, DomainUsage> referred2specialized = new HashMap<DomainUsage, DomainUsage>();
List<Parameter> ownedParameters = operation.getOwnedParameters();
int iMax = Math.min(ownedParameters.size(), object.getOwnedArguments().size());
for (int i = 0; i < iMax; i++) {
Parameter parameter = ownedParameters.get(i);
OCLExpression argument = object.getOwnedArguments().get(i);
DomainUsage referredParameterUsage = analysis.getUsage(parameter);
if (referredParameterUsage != null) {
DomainUsage specializedParameterUsage;
if (referredParameterUsage.isConstant()) {
specializedParameterUsage = referredParameterUsage;
}
else {
specializedParameterUsage = referred2specialized.get(referredParameterUsage);
if (specializedParameterUsage == null) {
// specializedParameterUsage = new DomainUsageVariable(getRootAnalysis(), ((DomainUsage.Internal)referredParameterUsage).getMask());
specializedParameterUsage = ((DomainUsage.Internal)referredParameterUsage).cloneVariable();
referred2specialized.put(referredParameterUsage, specializedParameterUsage);
}
}
DomainUsage argumentUsage = visit(argument);
intersection(argumentUsage, specializedParameterUsage);
}
}
DomainUsage operationUsage = analysis.getUsage(operation);
if ((operationUsage != null) && !operationUsage.isConstant()) {
// operationUsage = new DomainUsageVariable(getRootAnalysis(), ((DomainUsage.Internal)operationUsage).getMask());
operationUsage = ((DomainUsage.Internal)operationUsage).cloneVariable();
}
DomainUsage operationCallUsage = visit(object.getType());
return operationUsage != null ? intersection(operationUsage, operationCallUsage) : operationCallUsage;
}
finally {
popSelfUsage(savedUsage);
}
}
@Override
public @Nullable DomainUsage visitOppositePropertyCallExp(@NonNull OppositePropertyCallExp object) {
Property property = object.getReferredProperty();
Property oppositeProperty = property != null ? property.getOpposite() : null;
return doPropertyCallExp(oppositeProperty, object);
}
@Override
public @Nullable DomainUsage visitParameter(@NonNull Parameter object) {
// Operation operation = object.getOwningOperation();
// Map<Element, DomainUsage> map = analyzeOperation(operation);
// return map.get(object);
return visit(object.getType());
}
@Override
public @Nullable DomainUsage visitPredicate(@NonNull Predicate object) {
return visit(object.getConditionExpression());
}
@Override
public @Nullable DomainUsage visitPrimitiveType(@NonNull PrimitiveType object) {
return getRootAnalysis().getPrimitiveUsage();
}
@Override
public @Nullable DomainUsage visitPropertyAssignment(@NonNull PropertyAssignment object) {
Property property = object.getTargetProperty();
if ("att2col.type := prim2name".equals(object.toString())) {
property = object.getTargetProperty();
}
return doPropertyAssignment(property, object);
}
@Override
public @Nullable DomainUsage visitPropertyCallExp(@NonNull PropertyCallExp object) {
Property property = object.getReferredProperty();
return doPropertyCallExp(property, object);
}
@Override
public @Nullable DomainUsage visitRealizedVariable(@NonNull RealizedVariable object) {
return getDomainUsage(object);
}
@Override
public @Nullable DomainUsage visitRule(@NonNull Rule object) {
for (Domain domain : object.getDomain()) {
visit(domain);
}
return getRootAnalysis().getNoneUsage();
}
@Override
public @Nullable DomainUsage visitSelfType(@NonNull SelfType object) {
return selfUsage;
}
@Override
public @Nullable DomainUsage visitShadowExp(@NonNull ShadowExp object) {
DomainUsage usage = getRootAnalysis().getAnyUsage();
for (@SuppressWarnings("null")@NonNull ShadowPart part : object.getOwnedParts()) {
usage = intersection(usage, visit(part));
}
return usage;
}
@Override
public @Nullable DomainUsage visitShadowPart(@NonNull ShadowPart object) {
return visit(object.getType());
}
@Override
public @Nullable DomainUsage visitTemplateParameter(@NonNull TemplateParameter object) {
return getRootAnalysis().getAnyUsage();
}
@Override
public @Nullable DomainUsage visitTransformation(@NonNull Transformation object) {
// for (TypedModel typedModel : object.getModelParameter()) { -- done in analyzeTransformation
// visit(typedModel);
// }
Variable ownedContext = object.getOwnedContext();
DomainUsage domainUsage = getUsage(object);
if ((ownedContext != null) && (domainUsage != null)) {
setUsage(ownedContext, domainUsage);
}
//
// Ensure all operations are analyzed even if not used.
//
for (Operation operation : object.getOwnedOperations()) {
if (operation != null) {
getRootAnalysis().analyzeOperation(operation);
}
}
//
// Define all bound variables so that they back propgate to resolve domain usage variables.
//
for (Rule rule : object.getRule()) {
if (rule != null) {
setBoundVariablesUsages(rule);
}
}
//
// Analyze the rest of the tree.
//
for (Rule rule : object.getRule()) {
visit(rule);
}
return getRootAnalysis().getNoneUsage();
}
@Override
public @Nullable DomainUsage visitTupleLiteralExp(@NonNull TupleLiteralExp object) {
DomainUsage usage = getRootAnalysis().getAnyUsage();
for (@SuppressWarnings("null")@NonNull TupleLiteralPart part : object.getOwnedParts()) {
usage = intersection(usage, visit(part)); // FIXME need HYBRID
}
return usage;
}
@Override
public @Nullable DomainUsage visitTupleLiteralPart(@NonNull TupleLiteralPart object) {
return visit(object.getType());
}
@Override
public @Nullable DomainUsage visitTupleType(@NonNull TupleType object) {
DomainUsage usage = getRootAnalysis().getAnyUsage();
for (@SuppressWarnings("null")@NonNull Property part : object.getOwnedProperties()) {
usage = intersection(usage, visit(part.getType()));
}
return usage;
}
@Override
public @Nullable DomainUsage visitType(@NonNull Type object) {
return getRootAnalysis().getPrimitiveUsage();
}
@Override
public @Nullable DomainUsage visitTypeExp(@NonNull TypeExp object) {
return visit(object.getReferredType());
}
@Override
public @Nullable DomainUsage visitTypedModel(@NonNull TypedModel object) {
return element2usage.get(object);
}
@Override
public @Nullable DomainUsage visitVariable(@NonNull Variable object) {
OCLExpression ownedInit = object.getOwnedInit();
if (ownedInit != null) {
return visit(ownedInit);
}
else {
return visit(object.getType());
}
}
@Override
public @Nullable DomainUsage visitVariableAssignment(@NonNull VariableAssignment object) {
DomainUsage valueUsage = visit(object.getValue());
DomainUsage variableUsage = visit(object.getTargetVariable());
return intersection(variableUsage, valueUsage);
}
@Override
public @Nullable DomainUsage visitVariableDeclaration(@NonNull VariableDeclaration object) {
return visit(object.getType());
}
@Override
public @Nullable DomainUsage visitVariableExp(@NonNull VariableExp object) {
DomainUsage usage = element2usage.get(object.getReferredVariable());
assert usage != null : object.getReferredVariable() + " usage not defined";
return usage;
}
}