diff options
author | Ed Willink | 2020-02-23 10:03:57 +0000 |
---|---|---|
committer | Ed Willink | 2020-02-25 12:35:13 +0000 |
commit | 34098865e729dd0ed0ea6526de9ff2cf2c866d97 (patch) | |
tree | 7aa00a6082301523bd3648b22f17c92c49eb31e3 | |
parent | 7bcb9c8424ef3ebddda9140dba5ad9aa67566751 (diff) | |
download | org.eclipse.qvtd-34098865e729dd0ed0ea6526de9ff2cf2c866d97.tar.gz org.eclipse.qvtd-34098865e729dd0ed0ea6526de9ff2cf2c866d97.tar.xz org.eclipse.qvtd-34098865e729dd0ed0ea6526de9ff2cf2c866d97.zip |
[560427] detect incompatible root/head usage
7 files changed, 63 insertions, 29 deletions
diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/HeadAnalysis.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/HeadAnalysis.java index 222b40ae4..83c32ba91 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/HeadAnalysis.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/HeadAnalysis.java @@ -176,6 +176,8 @@ public abstract class HeadAnalysis this.mappingRegion = mappingRegion;; } + protected abstract boolean canBeSameGroup(@NonNull Edge source2targetEdge); + protected @NonNull List<@NonNull HeadNodeGroup> computeHeadNodeGroups(@NonNull Map<@NonNull Node, @NonNull Set<@NonNull Node>> targetFromSourcesClosure, @NonNull Map<@NonNull Node, @NonNull Set<@NonNull Node>> sourceToTargetsClosure, @Nullable List<@NonNull Node> preferredHeadNodes) { diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/HeadNodeGroup.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/HeadNodeGroup.java index 654af8d21..1785367fd 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/HeadNodeGroup.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/HeadNodeGroup.java @@ -40,6 +40,8 @@ import com.google.common.collect.Iterables; */ public abstract class HeadNodeGroup implements Nameable { + protected final @NonNull HeadAnalysis headAnalysis; + /** * The mutually to-one navigable nodes that define the head group. */ @@ -50,8 +52,9 @@ public abstract class HeadNodeGroup implements Nameable */ private Set<@NonNull Node> uniqueNodes = null; - public HeadNodeGroup(@NonNull List<@NonNull Node> headGroupNodes) { + public HeadNodeGroup(@NonNull HeadAnalysis headAnalysis, @NonNull List<@NonNull Node> headGroupNodes) { assert !headGroupNodes.isEmpty(); + this.headAnalysis = headAnalysis; this.headGroupNodes = headGroupNodes; } @@ -61,7 +64,7 @@ public abstract class HeadNodeGroup implements Nameable boolean gotOne = false; for (@NonNull Edge source2targetEdge : QVTscheduleUtil.getOutgoingEdges(sourceNode)) { Node targetNode = QVTscheduleUtil.getTargetNode(source2targetEdge); - if (targetNode.isUnconditional() && canBeSameGroup(sourceNode, source2targetEdge) && !uniqueNodes.contains(targetNode)) { + if (targetNode.isUnconditional() && headAnalysis.canBeSameGroup(source2targetEdge) && !uniqueNodes.contains(targetNode)) { if (source2targetEdge.isCast()) { // Can happen when analyzing traced heads uniqueNodes.add(targetNode); workList.add(targetNode); @@ -154,8 +157,6 @@ public abstract class HeadNodeGroup implements Nameable } } - protected abstract boolean canBeSameGroup(@NonNull Node sourceNode, @NonNull Edge source2targetEdge); - public @NonNull Iterable<@NonNull Node> getHeadNodes() { return headGroupNodes; } @@ -181,6 +182,10 @@ public abstract class HeadNodeGroup implements Nameable return toOneSet2; } + public @Nullable Iterable<@NonNull Node> getUniqueNodes() { + return uniqueNodes != null ? uniqueNodes : getToOneSet(); + } + /** * Return true if all of the headNodes of this HeadNodeGroup are reachable as to-one nodess of thatHeadNodeGroup. */ diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/RuleHeadAnalysis.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/RuleHeadAnalysis.java index cf22f60a6..f9901c128 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/RuleHeadAnalysis.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/RuleHeadAnalysis.java @@ -30,20 +30,14 @@ import org.eclipse.qvtd.pivot.qvtschedule.utilities.QVTscheduleUtil; import com.google.common.collect.Sets; /** - * RuleHeadAnalysis is a helper class to compute the head nodes of a region. + * RuleHeadAnalysis is a helper class to compute the head nodes of a region after synthesisfor a chosen direction. */ public class RuleHeadAnalysis extends HeadAnalysis { protected static final class RuleHeadNodeGroup extends HeadNodeGroup { - protected RuleHeadNodeGroup(@NonNull List<@NonNull Node> headGroupNodes) { - super(headGroupNodes); - } - - @Override - protected boolean canBeSameGroup(@NonNull Node sourceNode, @NonNull Edge source2targetEdge) { - boolean isOldSource = sourceNode.isOld(); - return isOldSource ? source2targetEdge.isOld() : true; //source2targetEdge.isNew(); // nonTopWhen my be REALIZED sourceNode and PREDICATED source2targetEdge + protected RuleHeadNodeGroup(@NonNull RuleHeadAnalysis ruleHeadAnalysis, @NonNull List<@NonNull Node> headGroupNodes) { + super(ruleHeadAnalysis, headGroupNodes); } @Override @@ -85,6 +79,13 @@ public class RuleHeadAnalysis extends HeadAnalysis } } + @Override + protected boolean canBeSameGroup(@NonNull Edge source2targetEdge) { + Node sourceNode = QVTscheduleUtil.getSourceNode(source2targetEdge); + boolean isOldSource = sourceNode.isOld(); + return isOldSource ? source2targetEdge.isOld() : true; //source2targetEdge.isNew(); // nonTopWhen my be REALIZED sourceNode and PREDICATED source2targetEdge + } + private void checkHeadNodeConsistency(@NonNull Iterable<@NonNull Node> headNodes) { Set<@NonNull Node> debugHeadNodes = new HashSet<>(); for (@NonNull Node node : QVTscheduleUtil.getOwnedNodes(mappingRegion)) { @@ -175,7 +176,7 @@ public class RuleHeadAnalysis extends HeadAnalysis @Override protected @NonNull HeadNodeGroup createHeadNodeGroup(@NonNull List<@NonNull Node> headNodeGroup) { - return new RuleHeadNodeGroup(headNodeGroup); + return new RuleHeadNodeGroup(this, headNodeGroup); } private void setHeadNodes(@NonNull Set<@NonNull Node> reachableNodes, @NonNull List<@NonNull Node> headNodes) { diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/trace/TracedHeadAnalysis.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/trace/TracedHeadAnalysis.java index f04de3e46..795693d29 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/trace/TracedHeadAnalysis.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/trace/TracedHeadAnalysis.java @@ -99,6 +99,17 @@ public class TracedHeadAnalysis extends HeadAnalysis super(mappingRegion); } + @Override + protected boolean canBeSameGroup(@NonNull Edge source2targetEdge) { + Node sourceNode = QVTscheduleUtil.getSourceNode(source2targetEdge); + Node targetNode = source2targetEdge.getEdgeTarget(); + TypedModel sourceTypedModel = QVTscheduleUtil.getReferredTypedModel(QVTscheduleUtil.getClassDatum(sourceNode)); + // assert (typedModel == sourceTypedModel) || sourceTypedModel.isIsPrimitive(); + TypedModel targetTypedModel = QVTscheduleUtil.getReferredTypedModel(QVTscheduleUtil.getClassDatum(targetNode)); + // return (typedModel == targetTypedModel) || targetTypedModel.isIsPrimitive(); + return sourceTypedModel.isIsPrimitive() || targetTypedModel.isIsPrimitive() || (sourceTypedModel== targetTypedModel); + } + private @NonNull Map<@NonNull Node, @NonNull Set<@NonNull Node>> computeTracedTargetFromSources(@NonNull Set<@NonNull Node> excludedNodes) { Map<@NonNull Node, @NonNull Set<@NonNull Node>> targetFromSources = new HashMap<>(); for (@NonNull Node targetNode : QVTscheduleUtil.getOwnedNodes(mappingRegion)) { @@ -113,7 +124,7 @@ public class TracedHeadAnalysis extends HeadAnalysis } for (@NonNull Edge edge : QVTscheduleUtil.getIncomingEdges(targetNode)) { Node sourceNode = edge.getEdgeSource(); - if (!excludedNodes.contains(sourceNode) && !sourceNode.isConditional() && !sourceNode.isConstant()) { + if (!excludedNodes.contains(sourceNode) && !sourceNode.isConditional() && !sourceNode.isConstant() && canBeSameGroup(edge)) { if (edge instanceof NavigationEdge) { if (!((NavigationEdge)edge).isPartial()) { sources.add(sourceNode); @@ -140,6 +151,6 @@ public class TracedHeadAnalysis extends HeadAnalysis @Override protected @NonNull HeadNodeGroup createHeadNodeGroup(@NonNull List<@NonNull Node> headNodeGroup) { - return new TracedHeadNodeGroup(headNodeGroup); + return new TracedHeadNodeGroup(this, headNodeGroup); } }
\ No newline at end of file diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/trace/TracedHeadNodeGroup.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/trace/TracedHeadNodeGroup.java index 3a08a6539..ccc56aa3d 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/trace/TracedHeadNodeGroup.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtb2qvts/trace/TracedHeadNodeGroup.java @@ -15,7 +15,6 @@ import java.util.List; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.qvtd.compiler.internal.qvtb2qvts.HeadNodeGroup; import org.eclipse.qvtd.pivot.qvtbase.TypedModel; -import org.eclipse.qvtd.pivot.qvtschedule.Edge; import org.eclipse.qvtd.pivot.qvtschedule.Node; import org.eclipse.qvtd.pivot.qvtschedule.utilities.QVTscheduleUtil; @@ -28,8 +27,8 @@ public class TracedHeadNodeGroup extends HeadNodeGroup { protected final @NonNull TypedModel typedModel; - public TracedHeadNodeGroup(@NonNull List<@NonNull Node> headGroupNodes) { - super(headGroupNodes); + public TracedHeadNodeGroup(@NonNull TracedHeadAnalysis tracedHeadAnalysis, @NonNull List<@NonNull Node> headGroupNodes) { + super(tracedHeadAnalysis, headGroupNodes); typedModel = QVTscheduleUtil.getReferredTypedModel(QVTscheduleUtil.getClassDatum(headGroupNodes.get(0))); for (@NonNull Node headGroupNode : headGroupNodes) { assert typedModel == QVTscheduleUtil.getReferredTypedModel(QVTscheduleUtil.getClassDatum(headGroupNode)); @@ -44,15 +43,6 @@ public class TracedHeadNodeGroup extends HeadNodeGroup } @Override - protected boolean canBeSameGroup(@NonNull Node sourceNode, @NonNull Edge source2targetEdge) { - Node targetNode = source2targetEdge.getEdgeTarget(); - TypedModel sourceTypedModel = QVTscheduleUtil.getReferredTypedModel(QVTscheduleUtil.getClassDatum(sourceNode)); - assert (typedModel == sourceTypedModel) || sourceTypedModel.isIsPrimitive(); - TypedModel targetTypedModel = QVTscheduleUtil.getReferredTypedModel(QVTscheduleUtil.getClassDatum(targetNode)); - return (typedModel == targetTypedModel) || targetTypedModel.isIsPrimitive(); - } - - @Override public String getName() { return typedModel.getName(); } diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/trace/Relation2TraceClass.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/trace/Relation2TraceClass.java index fd4f9dc21..6038ebd25 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/trace/Relation2TraceClass.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/trace/Relation2TraceClass.java @@ -127,13 +127,34 @@ public class Relation2TraceClass extends AbstractRelation2MiddleType } */ protected void analyzePatternNodes(@NonNull List<@NonNull HeadNodeGroup> headNodeGroups, @NonNull RelationAnalysis relationAnalysis) { - // String name = relation.getName(); + String name = relation.getName(); + if ("FtoN2_Daughter2DaughterPlan".equals(name)) { + getClass(); + } boolean manyTracesPerHead = headNodeGroups.size() > 2; Set<@NonNull Node> allHeadGroupNodes = new HashSet<>(); for (@NonNull HeadNodeGroup headNodeGroup : headNodeGroups) { Iterables.addAll(allHeadGroupNodes, headNodeGroup.getHeadNodes()); } + boolean compatibleRootVariable = true; List<@NonNull VariableDeclaration> rootVariables = QVTrelationUtil.getRootVariables(relation); + for (@NonNull VariableDeclaration rootVariable : rootVariables) { + boolean foundHeadGroup = false; + Node rootNode = relationAnalysis.getReferenceNode(rootVariable); + for (@NonNull HeadNodeGroup headNodeGroup : headNodeGroups) { + if (Iterables.contains(headNodeGroup.getHeadNodes(), rootNode)) { + foundHeadGroup = true; + } + else { + Iterable<@NonNull Node> uniqueNodes = headNodeGroup.getUniqueNodes(); + if ((uniqueNodes != null) && Iterables.contains(uniqueNodes, rootNode)) { + foundHeadGroup = true; + compatibleRootVariable = false; + } + } + } + assert foundHeadGroup; + } for (@NonNull Node node : QVTscheduleUtil.getOwnedNodes(relationAnalysis.getRegion())) { if (node.isThis()) { ; // Do not trace this diff --git a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/trace/Relation2TraceGroup.java b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/trace/Relation2TraceGroup.java index bbfe76065..fcbccf4cb 100644 --- a/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/trace/Relation2TraceGroup.java +++ b/plugins/org.eclipse.qvtd.compiler/src/org/eclipse/qvtd/compiler/internal/qvtr2qvts/trace/Relation2TraceGroup.java @@ -112,6 +112,10 @@ public class Relation2TraceGroup extends Rule2TraceGroup @Override public void analyzeTraceElements(@NonNull RuleAnalysis ruleAnalysis, @NonNull Set<@NonNull Node> excludedNodes) throws CompilerChainException { RelationAnalysis relationAnalysis = (RelationAnalysis)ruleAnalysis; + String name = relationAnalysis.getName(); + if ("ClassToClass_java".equals(name)) { + getClass(); + } // // Determine a head node for the minimum number of sub-regions that have a to-one path from the head. // |