Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Willink2016-11-01 12:46:04 +0000
committerEd Willink2016-11-01 12:46:43 +0000
commitb0e854c6947b26b1d46dd5eadc6d788f47b549b7 (patch)
treeb9e0fb074cad76b8ecbe2b2d547c7330e520c6d4
parent8e48a6ce0a97c44016f1abc9b54bf73d8c4e96a6 (diff)
downloadorg.eclipse.qvtd-b0e854c6947b26b1d46dd5eadc6d788f47b549b7.tar.gz
org.eclipse.qvtd-b0e854c6947b26b1d46dd5eadc6d788f47b549b7.tar.xz
org.eclipse.qvtd-b0e854c6947b26b1d46dd5eadc6d788f47b549b7.zip
[474537] Ensure operation returns are specialized
-rw-r--r--plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java4
-rw-r--r--plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTiCompilerChain.java4
-rw-r--r--plugins/org.eclipse.qvtd.pivot.qvtcore/src/org/eclipse/qvtd/pivot/qvtcore/utilities/QVTcoreHelper.java105
3 files changed, 111 insertions, 2 deletions
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java
index 2101d4df9..736af6814 100644
--- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java
+++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtp2qvts/ExpressionAnalyzer.java
@@ -64,6 +64,7 @@ import org.eclipse.qvtd.pivot.qvtcore.OppositePropertyAssignment;
import org.eclipse.qvtd.pivot.qvtcore.PropertyAssignment;
import org.eclipse.qvtd.pivot.qvtcore.analysis.DomainUsage;
import org.eclipse.qvtd.pivot.qvtcore.util.AbstractExtendingQVTcoreVisitor;
+import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreHelper;
import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreUtil;
import com.google.common.collect.Iterables;
@@ -706,7 +707,8 @@ public class ExpressionAnalyzer extends AbstractExtendingQVTcoreVisitor<@NonNull
assert property != null;
OCLExpression value = asNavigationAssignment.getValue();
if (value != null) {
- PivotUtil.rewriteSafeNavigations(environmentFactory, value);
+ QVTcoreHelper helper = new QVTcoreHelper(environmentFactory); // FIXME Re-use a helper
+ helper.rewriteSafeNavigations(value);
}
Node targetNode = analyze(value);
NavigableEdge navigationEdge = getNavigationEdge(slotNode, property, targetNode, asNavigationAssignment);
diff --git a/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTiCompilerChain.java b/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTiCompilerChain.java
index 7efe60e8f..bd245a176 100644
--- a/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTiCompilerChain.java
+++ b/plugins/org.eclipse.qvtd.cs2as.compiler/src/org/eclipse/qvtd/cs2as/compiler/internal/OCL2QVTiCompilerChain.java
@@ -30,6 +30,7 @@ import org.eclipse.qvtd.compiler.AbstractCompilerChain;
import org.eclipse.qvtd.compiler.AbstractCompilerStep;
import org.eclipse.qvtd.compiler.CompilerChain;
import org.eclipse.qvtd.compiler.CompilerChainException;
+import org.eclipse.qvtd.pivot.qvtcore.utilities.QVTcoreHelper;
import org.eclipse.qvtd.pivot.qvtimperative.ImperativeTransformation;
import org.eclipse.qvtd.pivot.qvtimperative.utilities.QVTimperative;
@@ -142,9 +143,10 @@ public class OCL2QVTiCompilerChain extends AbstractCompilerChain {
// FIXME this workaround produces a new traversal of the resource
private void rewriteSafeNavigations(@NonNull Resource resource) {
+ QVTcoreHelper helper = new QVTcoreHelper(environmentFactory); // FIXME Re-use a helper
for (EObject rootObject : resource.getContents()) {
if (rootObject instanceof Element) {
- PivotUtil.rewriteSafeNavigations(environmentFactory, (Element) rootObject);
+ helper.rewriteSafeNavigations((Element) rootObject);
}
}
}
diff --git a/plugins/org.eclipse.qvtd.pivot.qvtcore/src/org/eclipse/qvtd/pivot/qvtcore/utilities/QVTcoreHelper.java b/plugins/org.eclipse.qvtd.pivot.qvtcore/src/org/eclipse/qvtd/pivot/qvtcore/utilities/QVTcoreHelper.java
index e6930fbe4..777cb8965 100644
--- a/plugins/org.eclipse.qvtd.pivot.qvtcore/src/org/eclipse/qvtd/pivot/qvtcore/utilities/QVTcoreHelper.java
+++ b/plugins/org.eclipse.qvtd.pivot.qvtcore/src/org/eclipse/qvtd/pivot/qvtcore/utilities/QVTcoreHelper.java
@@ -10,13 +10,28 @@
*******************************************************************************/
package org.eclipse.qvtd.pivot.qvtcore.utilities;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.ocl.pivot.CallExp;
+import org.eclipse.ocl.pivot.CollectionType;
+import org.eclipse.ocl.pivot.Element;
+import org.eclipse.ocl.pivot.LetExp;
import org.eclipse.ocl.pivot.OCLExpression;
+import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.Variable;
+import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager;
+import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
import org.eclipse.ocl.pivot.utilities.EnvironmentFactory;
+import org.eclipse.ocl.pivot.utilities.NameUtil;
import org.eclipse.qvtd.pivot.qvtbase.utilities.QVTbaseHelper;
import org.eclipse.qvtd.pivot.qvtcore.BottomPattern;
import org.eclipse.qvtd.pivot.qvtcore.GuardPattern;
@@ -78,4 +93,94 @@ public class QVTcoreHelper extends QVTbaseHelper
asVariableAssignment.setValue(asValueExpression);
return asVariableAssignment;
}
+
+ /**
+ * Rewrite asTree and all its descendants to replace all "?." and "?->" navigations by their safe counterparts.
+ * @deprecated-promote to PivotHelper for M4.
+ */
+ @Deprecated
+ public void rewriteSafeNavigations(@NonNull Element asTree) {
+ //
+ // Locate all unsafe calls first to avoid CME from concurrent locate/rewrite.
+ //
+ List<@NonNull CallExp> unsafeCallExps = null;
+ if (asTree instanceof CallExp) {
+ unsafeCallExps = rewriteUnsafeCallExp_Gather(unsafeCallExps, (CallExp)asTree);
+ }
+ for (TreeIterator<EObject> tit = asTree.eAllContents(); tit.hasNext(); ) {
+ EObject eObject = tit.next();
+ if (eObject instanceof CallExp) {
+ unsafeCallExps = rewriteUnsafeCallExp_Gather(unsafeCallExps, (CallExp)eObject);
+ }
+ }
+ //
+ // Rewrite the unsafe calls
+ //
+ if (unsafeCallExps != null) {
+ PivotMetamodelManager metamodelManager = (PivotMetamodelManager) environmentFactory.getMetamodelManager();
+ org.eclipse.ocl.pivot.Class oclAnyType = environmentFactory.getStandardLibrary().getOclAnyType();
+ Operation oclEqualsOperation = NameUtil.getNameable(oclAnyType.getOwnedOperations(), "=");
+ assert oclEqualsOperation != null;
+ org.eclipse.ocl.pivot.Class collectionType = environmentFactory.getStandardLibrary().getCollectionType();
+ Operation excludingOperation = NameUtil.getNameable(collectionType.getOwnedOperations(), "excluding");
+ assert excludingOperation != null;
+ for (CallExp unsafeCallExp : unsafeCallExps) {
+ OCLExpression source = unsafeCallExp.getOwnedSource();
+ assert source != null;
+ if (source.getType() instanceof CollectionType) {
+ rewriteUnsafeCollectionCallExp(metamodelManager, excludingOperation, unsafeCallExp);
+ }
+ else {
+ rewriteUnsafeObjectCallExp(metamodelManager, oclEqualsOperation, unsafeCallExp);
+ }
+ }
+ }
+ }
+
+ private @Nullable List<@NonNull CallExp> rewriteUnsafeCallExp_Gather(@Nullable List<@NonNull CallExp> unsafeCallExps, @NonNull CallExp callExp) {
+ OCLExpression source = callExp.getOwnedSource();
+ if ((source != null) && callExp.isIsSafe()) {
+ if (unsafeCallExps == null) {
+ unsafeCallExps = new ArrayList<@NonNull CallExp>();
+ }
+ unsafeCallExps.add(callExp);
+ }
+ return unsafeCallExps;
+ }
+
+ private void rewriteUnsafeCollectionCallExp(@NonNull PivotMetamodelManager metamodelManager, @NonNull Operation excludingOperation, @NonNull CallExp unsafeCollectionCallExp) {
+ unsafeCollectionCallExp.setIsSafe(false);
+ EObject eContainer = unsafeCollectionCallExp.eContainer();
+ EReference eContainmentFeature = unsafeCollectionCallExp.eContainmentFeature();
+ PivotUtilInternal.resetContainer(unsafeCollectionCallExp);
+ //
+ OCLExpression nullExpression = metamodelManager.createNullLiteralExp();
+ OCLExpression safeCollectionCallExp = createOperationCallExp(unsafeCollectionCallExp, excludingOperation, Collections.singletonList(nullExpression));
+ //
+ eContainer.eSet(eContainmentFeature, safeCollectionCallExp);
+ }
+
+ private void rewriteUnsafeObjectCallExp(@NonNull PivotMetamodelManager metamodelManager, @NonNull Operation oclEqualsOperation, @NonNull CallExp unsafeObjectCallExp) {
+ unsafeObjectCallExp.setIsSafe(false);
+ EObject eContainer = unsafeObjectCallExp.eContainer();
+ EReference eContainmentFeature = unsafeObjectCallExp.eContainmentFeature();
+ PivotUtilInternal.resetContainer(unsafeObjectCallExp);
+ OCLExpression oldSourceExpression = unsafeObjectCallExp.getOwnedSource();
+ assert oldSourceExpression != null;
+ //
+ Variable unsafeSourceVariable = createVariable("unsafe", oldSourceExpression);
+ OCLExpression unsafeSourceExpression1 = createVariableExp(unsafeSourceVariable);
+ unsafeObjectCallExp.setOwnedSource(unsafeSourceExpression1);
+ //
+ OCLExpression unsafeSourceExpression2 = createVariableExp(unsafeSourceVariable);
+ OCLExpression nullExpression = metamodelManager.createNullLiteralExp();
+ OCLExpression isUnsafeExpression = createOperationCallExp(unsafeSourceExpression2, oclEqualsOperation, Collections.singletonList(nullExpression));
+ //
+ OCLExpression thenExpression = metamodelManager.createNullLiteralExp();
+ OCLExpression safeObjectCallExp = metamodelManager.createIfExp(isUnsafeExpression, thenExpression, unsafeObjectCallExp);
+ //
+ LetExp safeExp = createLetExp(unsafeSourceVariable, safeObjectCallExp);
+ //
+ eContainer.eSet(eContainmentFeature, safeExp);
+ }
} \ No newline at end of file

Back to the top