blob: 871674255e8664566654ea137cc811d8e3eb7abf [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 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 based on MtcBroker
******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvti.analysis;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CompleteClass;
import org.eclipse.ocl.pivot.CompleteInheritance;
import org.eclipse.ocl.pivot.internal.complete.CompleteInheritanceImpl;
import org.eclipse.ocl.pivot.CompleteModel;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.InheritanceFragment;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.NavigationCallExp;
import org.eclipse.ocl.pivot.OCLExpression;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.util.Visitable;
import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.ocl.pivot.utilities.TracingOption;
import org.eclipse.ocl.pivot.utilities.TreeIterable;
import org.eclipse.qvtd.compiler.CompilerConstants;
import org.eclipse.qvtd.compiler.CompilerProblem;
import org.eclipse.qvtd.compiler.CompilerStep;
import org.eclipse.qvtd.compiler.internal.qvtb2qvts.MappingProblem;
import org.eclipse.qvtd.pivot.qvtbase.Transformation;
import org.eclipse.qvtd.pivot.qvtimperative.GuardParameter;
import org.eclipse.qvtd.pivot.qvtimperative.Mapping;
import org.eclipse.qvtd.pivot.qvtimperative.NewStatement;
import org.eclipse.qvtd.pivot.qvtimperative.ObservableStatement;
import org.eclipse.qvtd.pivot.qvtimperative.SetStatement;
import org.eclipse.qvtd.pivot.qvtimperative.Statement;
import org.eclipse.qvtd.pivot.qvtimperative.util.AbstractExtendingQVTimperativeVisitor;
import org.eclipse.qvtd.pivot.qvtimperative.utilities.QVTimperativeUtil;
import org.eclipse.qvtd.pivot.qvtschedule.utilities.DomainUsage;
public class QVTiProductionConsumption extends AbstractExtendingQVTimperativeVisitor<@Nullable Object, @Nullable Object>
{
public static final @NonNull TracingOption SUMMARY = new TracingOption(CompilerConstants.PLUGIN_ID, "qvti/check/summary");
/**
* Connection aggregates the producer/consumer analysis of a CompleteClass property slot value.
*
* This is for an exact type. The source producer analysis registers production with each
* supertype of the actual produced class.
*/
private class ConnectionAnalysis
{
private final @NonNull CompleteClass completeClass;
private final @NonNull Property property;
private final @NonNull List<@NonNull NamedElement> producers = new ArrayList<>();
private final @NonNull List<@NonNull NavigationCallExp> consumers = new ArrayList<>();
public ConnectionAnalysis(@NonNull CompleteClass completeClass, @NonNull Property property) {
this.completeClass = completeClass;
this.property = property;
}
public void addConsumer(@NonNull NavigationCallExp consumer) {
isDebugTarget(QVTimperativeUtil.getReferredProperty(consumer));
consumers.add(consumer);
}
private void isDebugTarget(@NonNull Property property) {
String name1 = property.getName();
if ("fromAttributes".equals(name1)) {
getClass();
}
Property opposite = property.getOpposite();
if (opposite != null) {
String name2 = opposite.getName();
if ("fromAttributes".equals(name2)) {
getClass();
}
}
}
public void addProducer(@NonNull NamedElement producer) {
if (producer instanceof SetStatement) {
isDebugTarget(QVTimperativeUtil.getTargetProperty((SetStatement)producer));
}
else if (producer instanceof GuardParameter) {
Property successProperty = ((GuardParameter)producer).getSuccessProperty();
if (successProperty != null) {
isDebugTarget(successProperty);
}
}
producers.add(producer);
}
public void addProducers(@NonNull ConnectionAnalysis connectionAnalysis) {
isDebugTarget(connectionAnalysis.property);
producers.addAll(connectionAnalysis.producers);
}
// public @NonNull Property getProperty() {
// return property;
// }
public @NonNull List<@NonNull CompleteClass> getAncestors() {
List<@NonNull CompleteClass> ancestors = new ArrayList<>();
CompleteClass baseCompleteClass = completeModel.getCompleteClass(QVTimperativeUtil.getOwningClass(property));
CompleteInheritance baseInheritance = baseCompleteClass.getCompleteInheritance();
CompleteInheritance derivedInheritance = completeClass.getCompleteInheritance();
int baseDepth = baseInheritance.getDepth();
int derivedDepth = derivedInheritance.getDepth();
for (int i = baseDepth; i <= derivedDepth; i++) {
Iterable<@NonNull InheritanceFragment> derivedSuperFragments = derivedInheritance.getSuperFragments(i);
for (@NonNull InheritanceFragment superFragment : derivedSuperFragments) {
Iterable<@NonNull InheritanceFragment> owningSuperFragments = superFragment.getDerivedInheritance().getSuperFragments(baseDepth);
for (@NonNull InheritanceFragment owningSuperFragment : owningSuperFragments) {
if (owningSuperFragment.getBaseInheritance() == baseInheritance) {
CompleteClass superClass = ((CompleteInheritanceImpl)superFragment.getBaseInheritance()).getCompleteClass();
ancestors.add(superClass);
}
}
}
}
return ancestors;
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
s.append(completeClass.getName());
s.append("::");
s.append(property.getName());
return s.toString();
}
public void validate(@Nullable StringBuilder s) {
if ("ClassToTable::fromAttributes".equals(toString())) {
getClass();
}
Summary summary = new Summary(this, null);
for (@NonNull NamedElement producer : producers) {
Mapping mapping = QVTimperativeUtil.getContainingMapping(producer);
summary.setProducer(mapping, completeClass, producer);
}
for (@NonNull NavigationCallExp consumer : consumers) {
Mapping mapping = QVTimperativeUtil.getContainingMapping(consumer);
summary.setConsumer(mapping, completeClass, consumer);
}
if (s != null) {
s.append("\n " + summary.appendConnectionAnalysis());
}
// for (@NonNull NamedElement producer : producers) {
summary.checkProducers();
// }
for (@NonNull NavigationCallExp consumer : consumers) {
summary.checkConsumer(s, consumer);
}
}
}
/**
* Summary aggregates the production/consumption timing on a specific Connection.
*/
private class Summary
{
private final @NonNull ConnectionAnalysis connectionAnalysis;
private final @Nullable ConnectionAnalysis forConnectionAnalysis;
private @Nullable Integer firstProducer = null;
private @Nullable Integer lastProducer = null;
private @Nullable Integer firstConsumer = null;
private @Nullable Integer lastConsumer = null;
private final @NonNull StringBuilder s = new StringBuilder();
private boolean anyObserve = false;
private @NonNull List<@NonNull NavigationCallExp> debugConsumers = new ArrayList<>();
private @NonNull List<@NonNull NamedElement> debugProducers = new ArrayList<>();
public Summary(@NonNull ConnectionAnalysis connectionAnalysis, @Nullable ConnectionAnalysis forConnectionAnalysis) {
this.connectionAnalysis = connectionAnalysis;
this.forConnectionAnalysis = forConnectionAnalysis;
s.append(connectionAnalysis.toString());
if (forConnectionAnalysis != null) {
s.append(" for ");
s.append(forConnectionAnalysis.toString());
}
}
public @NonNull String appendConnectionAnalysis() {
Integer firstProducer2 = firstProducer;
s.append("\n\tproduce " + firstProducer2);
if (firstProducer2 != null) {
if ((lastProducer != null) && (lastProducer > firstProducer2)) {
s.append(".." + lastProducer);
}
}
Integer firstConsumer2 = firstConsumer;
s.append(" consume " + firstConsumer2);
if (firstConsumer2 != null) {
if ((lastConsumer != null) && (lastConsumer > firstConsumer2)) {
s.append(".." + lastConsumer);
}
}
return s.toString();
}
public void checkConsumer(@Nullable StringBuilder s, @NonNull NavigationCallExp consumer) {
// Property referredProperty = QVTimperativeUtil.getReferredProperty(consumer);
// Map<@NonNull CompleteClass, @NonNull ConnectionAnalysis> class2connection = property2class2connection.get(referredProperty);
// assert class2connection != null;
// CompleteClass completeClass = completeModel.getCompleteClass(QVTimperativeUtil.getOwningClass(referredProperty));
// ConnectionAnalysis zbaseConnectionAnalysis = connectionAnalysis; //class2connection.get(completeClass);
// assert zbaseConnectionAnalysis != null;
CompleteClass completeClass = connectionAnalysis.completeClass;
// Map<@NonNull CompleteClass, List<@NonNull NamedElement>> class2producers = property2class2producers.get(property);
// assert class2producers != null;
// List<@NonNull NamedElement> producers = connection.producers;
// if (producers != null) {
// for (@NonNull NavigationCallExp callExp : connection.consumers) {
/// Mapping mapping = QVTimperativeUtil.getContainingMapping(callExp);
// connection.setConsumer(mapping, asClass, callExp);
// }
// }
boolean isObserve = isObserve(consumer);
Mapping mapping = QVTimperativeUtil.getContainingMapping(consumer);
int firstPass = mapping.getFirstPass();
Integer lastProducer2 = lastProducer;
if (lastProducer2 == null) {
if (isObserve) {
StringBuilder s2 = initProblem("Not-produced ", " should not be observed");
compilerStep.addProblem(new MappingProblem(CompilerProblem.Severity.ERROR, mapping, s2.toString()));
}
else {
Property referredProperty = QVTimperativeUtil.getReferredProperty(consumer);
CompleteClass baseCompleteClass = completeModel.getCompleteClass(QVTimperativeUtil.getOwningClass(referredProperty));
Map<@NonNull CompleteClass, @NonNull ConnectionAnalysis> class2connection = property2class2connection.get(referredProperty);
assert class2connection != null;
ConnectionAnalysis baseConnectionAnalysis = class2connection.get(baseCompleteClass);
assert baseConnectionAnalysis != null;
assert baseConnectionAnalysis != connectionAnalysis;
Summary summary = new Summary(baseConnectionAnalysis, connectionAnalysis);
for (@NonNull NamedElement producer2 : baseConnectionAnalysis.producers) {
Mapping mapping2 = QVTimperativeUtil.getContainingMapping(producer2);
summary.setProducer(mapping2, completeClass, producer2);
}
for (@NonNull NavigationCallExp consumer2 : connectionAnalysis.consumers) {
Mapping mapping2 = QVTimperativeUtil.getContainingMapping(consumer2);
summary.setConsumer(mapping2, completeClass, consumer2);
}
if (s != null) {
s.append(summary.appendConnectionAnalysis());
}
summary.checkConsumer(s, consumer);
// DomainUsage usage = domainUsageAnalysis.getUsage(callExp);
// if (!usage.isInput() && !usage.isPrimitive()) {
// StringBuilder s2 = initProblem(null, " should be produced");
// compilerStep.addProblem(new MappingProblem(CompilerProblem.Severity.ERROR, mapping, s2.toString()));
// }
}
}
else if (!isObserve) {
if (firstPass <= lastProducer2) {
StringBuilder s2 = initProblem(null, " should be observed");
compilerStep.addProblem(new MappingProblem(CompilerProblem.Severity.ERROR, mapping, s2.toString()));
}
}
else {
if (firstPass > lastProducer2) {
StringBuilder s2 = initProblem(null, " should not be observed");
compilerStep.addProblem(new MappingProblem(CompilerProblem.Severity.ERROR, mapping, s2.toString()));
}
}
}
public void checkProducers() {
if (anyObserve) {
Integer firstConsumer2 = firstConsumer;
Integer lastProducer2 = lastProducer;
if ((firstConsumer2 != null) && (lastProducer2 != null) && (firstConsumer2 <= lastProducer2)) {
for (@NonNull NamedElement producer : connectionAnalysis.producers) {
if (!isNotify(producer)) {
StringBuilder s = initProblem("", " should be notified");
Mapping mapping = QVTimperativeUtil.getContainingMapping(producer);
compilerStep.addProblem(new MappingProblem(CompilerProblem.Severity.ERROR, mapping, s.toString()));
}
}
}
}
}
private @NonNull StringBuilder initProblem(@Nullable String prefix, @Nullable String suffix) {
StringBuilder s = new StringBuilder();
if (prefix != null) {
s.append(prefix);
}
s.append(connectionAnalysis);
Integer firstProducer2 = firstProducer;
s.append(" produced " + firstProducer2);
if (firstProducer2 != null) {
Integer lastProducer2 = lastProducer;
if ((lastProducer2 != null) && (lastProducer2 > firstProducer2)) {
s.append(".." + lastProducer2);
}
}
Integer firstConsumer2 = firstConsumer;
s.append(" consumed " + firstConsumer2);
if (firstConsumer2 != null) {
if ((lastConsumer != null) && (lastConsumer > firstConsumer2)) {
s.append(".." + lastConsumer);
}
}
if (suffix != null) {
s.append(suffix);
}
return s;
}
private boolean isNotify(NamedElement producer) {
if (producer instanceof SetStatement) {
return ((SetStatement)producer).isIsNotify();
}
else {
return false;
}
}
private boolean isObserve(@NonNull NavigationCallExp callExp) {
Statement statement = QVTimperativeUtil.getContainingStatement(callExp);
if (statement instanceof ObservableStatement) {
List<Property> observedProperties = ((ObservableStatement)statement).basicGetObservedProperties();
if (observedProperties != null) {
return observedProperties.contains(connectionAnalysis.property);
}
}
return false;
}
public void setConsumer(@NonNull Mapping mapping, @NonNull CompleteClass completeClass, @NonNull NavigationCallExp callExp) {
debugConsumers.add(callExp);
boolean anObserve = isObserve(callExp);
if (anObserve) {
anyObserve = true;
}
int firstPass = mapping.getFirstPass();
Integer lastPassOrNull = mapping.getLastPass();
int lastPass = lastPassOrNull != null ? lastPassOrNull : firstPass;
Integer firstConsumer2 = firstConsumer;
if ((firstConsumer2 == null) || (firstPass < firstConsumer2)) {
firstConsumer = firstConsumer2 = firstPass;
}
Integer lastConsumer2 = lastConsumer;
if ((lastConsumer2 == null) || (lastPass > lastConsumer2)) {
lastConsumer = lastConsumer2 = lastPass;
}
s.append("\n\tconsume ");
s.append(connectionAnalysis);
s.append(" in ");
s.append(mapping.getName());
s.append(" at " + firstPass);
if (lastPassOrNull != null) {
s.append(".." + lastPass);
}
s.append(" " + (anObserve ? "observe" : "no-observe"));
}
public void setProducer(@NonNull Mapping mapping, @NonNull CompleteClass completeClass, @NonNull NamedElement producer) {
debugProducers.add(producer);
boolean isNotify = isNotify(producer);
int firstPass = mapping.getFirstPass();
@Nullable Integer lastPassOrNull = mapping.getLastPass();
int lastPass = lastPassOrNull != null ? lastPassOrNull : firstPass;
Integer firstProducer2 = firstProducer;
if ((firstProducer2 == null) || (firstPass < firstProducer2)) {
firstProducer = firstProducer2 = firstPass;
}
Integer lastProducer2 = lastProducer;
if ((lastProducer2 == null) || (lastPass > lastProducer2)) {
lastProducer = lastProducer2 = lastPass;
}
s.append("\n\tproduce ");
s.append(connectionAnalysis);
s.append(" in ");
s.append(mapping.getName());
s.append(" at " + firstPass);
if (lastPassOrNull != null) {
s.append(".." + lastPass);
}
s.append(" " + (isNotify ? "notify" : "no-notify"));
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
s.append(connectionAnalysis.toString());
s.append(" produce ");
s.append(firstProducer);
s.append("..");
s.append(lastProducer);
s.append(" consume ");
s.append(firstConsumer);
s.append("..");
s.append(lastConsumer);
return s.toString();
}
}
protected final @NonNull CompilerStep compilerStep;
protected final @NonNull Resource iResource;
protected final @NonNull QVTimperativeDomainUsageAnalysis domainUsageAnalysis;
// protected final @NonNull Map<org.eclipse.ocl.pivot.@NonNull Class, @NonNull List<@NonNull NamedElement>> class2producers = new HashMap<>();
protected final @NonNull Map<@NonNull Property, Map<@NonNull CompleteClass, @NonNull ConnectionAnalysis>> property2class2connection = new HashMap<>();
protected final @NonNull CompleteModel completeModel;
public QVTiProductionConsumption(@NonNull CompilerStep compilerStep, @NonNull Resource iResource) {
super(null);
this.compilerStep = compilerStep;
this.iResource = iResource;
this.domainUsageAnalysis = new QVTimperativeDomainUsageAnalysis(compilerStep.getEnvironmentFactory());
this.completeModel = compilerStep.getEnvironmentFactory().getCompleteModel();
}
public void analyze() {
//
// Traverse the model to discover the producers and consumers
//
for (@NonNull EObject eObject : new TreeIterable(iResource)) {
if (eObject instanceof Visitable) {
((Visitable)eObject).accept(this);
}
}
//
// Propagate explicit producers to their sub producers.
//
for (@NonNull Property property : property2class2connection.keySet()) {
Map<@NonNull CompleteClass, @NonNull ConnectionAnalysis> class2connection = property2class2connection.get(property);
assert class2connection != null;
for (@NonNull CompleteClass completeClass : class2connection.keySet()) {
ConnectionAnalysis connectionAnalysis = class2connection.get(completeClass);
assert connectionAnalysis != null;
for (@NonNull CompleteClass ancestorClass : connectionAnalysis.getAncestors()) {
if (ancestorClass != completeClass) {
ConnectionAnalysis ancestorConnectionAnalysis = class2connection.get(ancestorClass);
if (ancestorConnectionAnalysis != null) { // May be null if never explicitly produced/consumed
connectionAnalysis.addProducers(ancestorConnectionAnalysis);
}
}
}
}
}
//
// Propagate explicit derived producers to their super producers.
//
for (@NonNull Property property : property2class2connection.keySet()) {
Map<@NonNull CompleteClass, @NonNull ConnectionAnalysis> class2connection = property2class2connection.get(property);
assert class2connection != null;
for (@NonNull CompleteClass completeClass : class2connection.keySet()) {
ConnectionAnalysis connectionAnalysis = class2connection.get(completeClass);
assert connectionAnalysis != null;
for (@NonNull CompleteClass ancestorClass : connectionAnalysis.getAncestors()) {
if (ancestorClass != completeClass) {
ConnectionAnalysis ancestorConnectionAnalysis = class2connection.get(ancestorClass);
if (ancestorConnectionAnalysis != null) { // May be null if never explicitly produced/consumed
ancestorConnectionAnalysis.addProducers(connectionAnalysis);
}
}
}
}
}
}
protected void doProducer(@NonNull NamedElement producer, @NonNull CompleteClass targetClass, @NonNull Property setProperty) {
// CompleteClass owningClass = completeModel.getCompleteClass(QVTimperativeUtil.getOwningClass(setProperty));
// CompleteInheritance owningInheritance = owningClass.getCompleteInheritance();
// CompleteInheritance targetInheritance = targetClass.getCompleteInheritance();
// int owningDepth = owningInheritance.getDepth();
// int targetDepth = targetInheritance.getDepth();
// for (int i = owningDepth; i <= targetDepth; i++) {
// Iterable<@NonNull InheritanceFragment> superFragments = targetInheritance.getSuperFragments(i);
// for (@NonNull InheritanceFragment superFragment : superFragments) {
// Iterable<@NonNull InheritanceFragment> owningSuperFragments = superFragment.getDerivedInheritance().getSuperFragments(owningDepth);
// for (@NonNull InheritanceFragment owningSuperFragment : owningSuperFragments) {
// if (owningSuperFragment.getBaseInheritance() == owningInheritance) {
// CompleteClass superClass = ((CompleteInheritanceImpl)superFragment.getBaseInheritance()).getCompleteClass();
ConnectionAnalysis connectionAnalysis = getConnectionAnalysis(targetClass, setProperty);
connectionAnalysis.addProducer(producer);
// }
// }
// }
// }
}
protected @NonNull ConnectionAnalysis getConnectionAnalysis(@NonNull CompleteClass competeClass, @NonNull Property property) {
Map<@NonNull CompleteClass, @NonNull ConnectionAnalysis> class2connection = property2class2connection.get(property);
if (class2connection == null) {
class2connection = new HashMap<>();
property2class2connection.put(property, class2connection);
}
ConnectionAnalysis connectionAnalysis = class2connection.get(competeClass);
if (connectionAnalysis == null) {
connectionAnalysis = new ConnectionAnalysis(competeClass, property);
class2connection.put(competeClass, connectionAnalysis);
}
return connectionAnalysis;
}
public void validate() {
Set<@NonNull Property> allProperties = new HashSet<>(property2class2connection.keySet());
List<@NonNull Property> sortedProperties = new ArrayList<>(allProperties);
Collections.sort(sortedProperties, NameUtil.NAMEABLE_COMPARATOR);
StringBuilder s = SUMMARY.isActive() ? new StringBuilder() : null;
for (@NonNull Property property : sortedProperties) {
Map<@NonNull CompleteClass, @NonNull ConnectionAnalysis> class2connection = property2class2connection.get(property);
if (class2connection != null) {
List<@NonNull CompleteClass> sortedClasses = new ArrayList<>(class2connection.keySet());
Collections.sort(sortedClasses, NameUtil.NAMEABLE_COMPARATOR);
for (@NonNull CompleteClass asClass : sortedClasses) {
ConnectionAnalysis connection = class2connection.get(asClass);
assert connection != null;
connection.validate(s);
}
}
}
if (s != null) {
SUMMARY.println(s.toString());
}
}
@Override
public @Nullable Object visiting(@NonNull Visitable visitable) {
throw new UnsupportedOperationException("Unimplemented " + getClass().getName() + " for " + visitable.eClass().getName());
}
@Override
public @Nullable Object visitElement(@NonNull Element object) {
return null;
}
@Override
public @Nullable Object visitGuardParameter(@NonNull GuardParameter guardParameter) {
Property successProperty = guardParameter.getSuccessProperty();
if (successProperty != null) {
CompleteClass targetClass = completeModel.getCompleteClass(QVTimperativeUtil.getOwningClass(successProperty));
doProducer(guardParameter, targetClass, successProperty);
}
return null;
}
@Override
public @Nullable Object visitNavigationCallExp(@NonNull NavigationCallExp navigationCallExp) {
String name = navigationCallExp.getName();
if (name.equals("owningSource")) {
getClass();
}
Mapping mapping = QVTimperativeUtil.basicGetContainingMapping(navigationCallExp);
if (mapping != null) {
Property getProperty = QVTimperativeUtil.getReferredProperty(navigationCallExp);
DomainUsage usage = domainUsageAnalysis.getUsage(getProperty);
if (!usage.isInput() && !usage.isPrimitive()) { // Skip endogenously confusing input
OCLExpression ownedSource = QVTimperativeUtil.getOwnedSource(navigationCallExp);
Type sourceType = QVTimperativeUtil.getType(ownedSource);
CompleteClass sourceCompleteClass = completeModel.getCompleteClass(sourceType);
ConnectionAnalysis connectionAnalysis = getConnectionAnalysis(sourceCompleteClass, getProperty);
connectionAnalysis.addConsumer(navigationCallExp);
Property oppositeProperty = getProperty.getOpposite();
// if (oppositeProperty != null) {
// Type targetType = QVTimperativeUtil.getType(getProperty);
// CompleteClass oppositeCompleteClass = completeModel.getCompleteClass(targetType);
// Connection oppositeConnection = getConnection(oppositeCompleteClass, oppositeProperty);
// oppositeConnection.addConsumer(navigationCallExp);
// }
}
}
return null;
}
@Override
public @Nullable Object visitNewStatement(@NonNull NewStatement newStatement) {
// org.eclipse.ocl.pivot.Class newClass = (Class) QVTimperativeUtil.getType(newStatement);
// List<@NonNull NamedElement> producers = class2producers.get(newClass);
// if (producers == null) {
// producers = new ArrayList<>();
// class2producers.put(newClass, producers);
// }
// producers.add(newStatement);
return null;
}
@Override
public @Nullable Object visitSetStatement(@NonNull SetStatement setStatement) {
Property setProperty = QVTimperativeUtil.getTargetProperty(setStatement);
String name = setProperty.getName();
if (name.equals("fromAttributes")) {
getClass();
}
else if (name.equals("owner")) {
getClass();
}
CompleteClass targetClass = completeModel.getCompleteClass(QVTimperativeUtil.getType(QVTimperativeUtil.getTargetVariable(setStatement)));
doProducer(setStatement, targetClass, setProperty);
Property oppositeProperty = setProperty.getOpposite();
if (oppositeProperty != null) {
targetClass = completeModel.getCompleteClass(QVTimperativeUtil.getOwningClass(oppositeProperty));
doProducer(setStatement, targetClass, oppositeProperty);
}
return null;
}
@Override
public @Nullable Object visitTransformation(@NonNull Transformation transformation) {
domainUsageAnalysis.analyzeTransformation(transformation);
return null;
}
}