diff options
author | Laurent Delaigue | 2016-10-14 14:45:12 +0000 |
---|---|---|
committer | Laurent Delaigue | 2016-10-17 06:12:05 +0000 |
commit | fcdec72a8076a82bb99a3e24a295ac7446864b7a (patch) | |
tree | eb5c5e2d2024a545f1c8e10c8595fdeaed96d485 | |
parent | 85571f4a0b0ce4ea1edea21d0c817f44a694816a (diff) | |
download | org.eclipse.emf.compare-fcdec72a8076a82bb99a3e24a295ac7446864b7a.tar.gz org.eclipse.emf.compare-fcdec72a8076a82bb99a3e24a295ac7446864b7a.tar.xz org.eclipse.emf.compare-fcdec72a8076a82bb99a3e24a295ac7446864b7a.zip |
[505994] Fix cascading filter on refined diffs
Refined diffs that are not in direct conflict but have at least on
refining diff in REAL conflict should not be filtered out by the
cascading filter.
bug: 505994
Change-Id: Ife2ccc3d6319e381c16d5d2a5a68295e7a73ac6a
Signed-off-by: Laurent Delaigue <laurent.delaigue@obeo.fr>
6 files changed, 225 insertions, 3 deletions
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/CascadingDiffFilterTest.java b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/CascadingDiffFilterTest.java new file mode 100644 index 000000000..cc5a92e01 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/CascadingDiffFilterTest.java @@ -0,0 +1,206 @@ +/******************************************************************************* + * Copyright (c) 2016 Obeo. + * 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: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.emf.compare.rcp.ui.tests.structuremergeviewer.filters; + +import static org.eclipse.emf.compare.ConflictKind.PSEUDO; +import static org.eclipse.emf.compare.ConflictKind.REAL; +import static org.eclipse.emf.compare.rcp.ui.tests.structuremergeviewer.groups.provider.AbstractTestTreeNodeItemProviderAdapter.getComparison; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.eclipse.emf.compare.CompareFactory; +import org.eclipse.emf.compare.Comparison; +import org.eclipse.emf.compare.Conflict; +import org.eclipse.emf.compare.ConflictKind; +import org.eclipse.emf.compare.Diff; +import org.eclipse.emf.compare.Match; +import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.impl.CascadingDifferencesFilter; +import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.impl.BasicDifferenceGroupImpl; +import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.nodes.DiffNode; +import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.nodes.MatchNode; +import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.nodes.MatchResourceNode; +import org.eclipse.emf.compare.tests.edit.data.ResourceScopeProvider; +import org.eclipse.emf.compare.tests.framework.AbstractInputData; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.ECrossReferenceAdapter; +import org.eclipse.emf.edit.tree.TreePackage; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.base.Predicates; + +@SuppressWarnings("restriction") +public class CascadingDiffFilterTest { + + private Comparison comp; + + private CascadingDifferencesFilter filter; + + private TestECrossReferenceAdapter crossReferenceAdapter; + + /** + * Basic test to make sure the 1st addition is not filtered and its children are. + */ + @Test + public void testWithoutRefiningDiffs() { + BasicDifferenceGroupImpl group = new BasicDifferenceGroupImpl(comp, Predicates.alwaysTrue(), + crossReferenceAdapter); + group.buildSubTree(); + assertEquals(2, group.getChildren().size()); + MatchNode rootNode = (MatchNode)group.getChildren().get(0); + assertTrue(group.getChildren().get(1) instanceof MatchResourceNode); + + assertEquals(1, rootNode.getChildren().size()); + MatchNode cNode = (MatchNode)rootNode.getChildren().get(0); + assertEquals(2, cNode.getChildren().size()); + + DiffNode addClassNode = (DiffNode)cNode.getChildren().get(0); + assertFalse(filter.getPredicateWhenSelected().apply(addClassNode)); + assertFalse(filter.getPredicateWhenUnselected().apply(addClassNode)); + + MatchNode attNode = (MatchNode)cNode.getChildren().get(1); + assertEquals(1, attNode.getChildren().size()); + + DiffNode addAttNode = (DiffNode)attNode.getChildren().get(0); + assertTrue(filter.getPredicateWhenSelected().apply(addAttNode)); + assertFalse(filter.getPredicateWhenUnselected().apply(addAttNode)); + } + + /** + * A non-conflicting cascading refined diff is not filtered if it has a real conflict diff among its + * refining diffs. + */ + @Test + public void testWithRealConflictRefiningDiffs() { + Match rootMatch = comp.getMatches().get(0); + Match cMatch = rootMatch.getSubmatches().get(0); + Match attMatch = cMatch.getSubmatches().get(0); + Diff attAddition = cMatch.getDifferences().get(0); + + // Create a refinedDiff refined by the att addition + createRefinedDiff(attMatch, attAddition); + + // Create a real conflict on the refining diff + createConflict(attAddition, REAL); + + BasicDifferenceGroupImpl group = new BasicDifferenceGroupImpl(comp, Predicates.alwaysTrue(), + crossReferenceAdapter); + group.buildSubTree(); + assertEquals(2, group.getChildren().size()); + MatchNode rootNode = (MatchNode)group.getChildren().get(0); + assertTrue(group.getChildren().get(1) instanceof MatchResourceNode); + + assertEquals(1, rootNode.getChildren().size()); + MatchNode cNode = (MatchNode)rootNode.getChildren().get(0); + assertEquals(2, cNode.getChildren().size()); + + DiffNode addClassNode = (DiffNode)cNode.getChildren().get(0); + assertFalse(filter.getPredicateWhenSelected().apply(addClassNode)); + assertFalse(filter.getPredicateWhenUnselected().apply(addClassNode)); + + MatchNode attNode = (MatchNode)cNode.getChildren().get(1); + assertEquals(1, attNode.getChildren().size()); + + DiffNode refinedDiffNode = (DiffNode)attNode.getChildren().get(0); + assertFalse(filter.getPredicateWhenSelected().apply(refinedDiffNode)); + assertFalse(filter.getPredicateWhenUnselected().apply(refinedDiffNode)); + assertEquals(1, refinedDiffNode.getChildren().size()); + + // It's useless to test on the refining diff since filters are not applied on refining diffs + } + + /** + * A non-conflicting cascading refined diff is filtered if it has some pseudo but no real conflict diff + * among its refining diffs. + */ + @Test + public void testWithPseudoConflictRefiningDiffs() { + Match rootMatch = comp.getMatches().get(0); + Match cMatch = rootMatch.getSubmatches().get(0); + Match attMatch = cMatch.getSubmatches().get(0); + Diff attAddition = cMatch.getDifferences().get(0); + + createRefinedDiff(attMatch, attAddition); + + createConflict(attAddition, PSEUDO); + + BasicDifferenceGroupImpl group = new BasicDifferenceGroupImpl(comp, Predicates.alwaysTrue(), + crossReferenceAdapter); + group.buildSubTree(); + assertEquals(2, group.getChildren().size()); + MatchNode rootNode = (MatchNode)group.getChildren().get(0); + assertTrue(group.getChildren().get(1) instanceof MatchResourceNode); + + assertEquals(1, rootNode.getChildren().size()); + MatchNode cNode = (MatchNode)rootNode.getChildren().get(0); + assertEquals(2, cNode.getChildren().size()); + + DiffNode addClassNode = (DiffNode)cNode.getChildren().get(0); + assertFalse(filter.getPredicateWhenSelected().apply(addClassNode)); + assertFalse(filter.getPredicateWhenUnselected().apply(addClassNode)); + + MatchNode attNode = (MatchNode)cNode.getChildren().get(1); + assertEquals(1, attNode.getChildren().size()); + + DiffNode refinedDiffNode = (DiffNode)attNode.getChildren().get(0); + assertTrue(filter.getPredicateWhenSelected().apply(refinedDiffNode)); + assertFalse(filter.getPredicateWhenUnselected().apply(refinedDiffNode)); + assertEquals(1, refinedDiffNode.getChildren().size()); + + // It's useless to test on the refining diff since filters are not applied on refining diffs + } + + protected void createConflict(Diff attAddition, ConflictKind kind) { + Conflict conflict = CompareFactory.eINSTANCE.createConflict(); + conflict.setKind(kind); + conflict.getDifferences().add(attAddition); + comp.getConflicts().add(conflict); + } + + protected void createRefinedDiff(Match attMatch, Diff attAddition) { + Diff refinedDiff = CompareFactory.eINSTANCE.createDiff(); + refinedDiff.getRefinedBy().add(attAddition); + attMatch.getDifferences().add(refinedDiff); + } + + @Before + public void setUp() throws Exception { + comp = getComparison(new CascadingScope()); + crossReferenceAdapter = new TestECrossReferenceAdapter(); + filter = new CascadingDifferencesFilter(); + } + + private class TestECrossReferenceAdapter extends ECrossReferenceAdapter { + @Override + protected boolean isIncluded(EReference eReference) { + return eReference == TreePackage.Literals.TREE_NODE__DATA; + } + } + + public class CascadingScope extends AbstractInputData implements ResourceScopeProvider { + + public Resource getOrigin() throws IOException { + return loadFromClassLoader("data/cascading/ancestor.ecore");//$NON-NLS-1$ + } + + public Resource getLeft() throws IOException { + return loadFromClassLoader("data/cascading/left.ecore");//$NON-NLS-1$ + } + + public Resource getRight() throws IOException { + return loadFromClassLoader("data/cascading/right.ecore");//$NON-NLS-1$ + } + } +} diff --git a/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/data/cascading/ancestor.ecore b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/data/cascading/ancestor.ecore new file mode 100644 index 000000000..8dbb83c21 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/data/cascading/ancestor.ecore @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" + name="root" xmi:id="_root"/> diff --git a/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/data/cascading/left.ecore b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/data/cascading/left.ecore new file mode 100644 index 000000000..70ad02ab5 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/data/cascading/left.ecore @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="root" xmi:id="_root"> + <eClassifiers xsi:type="ecore:EClass" name="c" xmi:id="_c"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="att" xmi:id="_att"/> + </eClassifiers> +</ecore:EPackage> diff --git a/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/data/cascading/right.ecore b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/data/cascading/right.ecore new file mode 100644 index 000000000..8dbb83c21 --- /dev/null +++ b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/filters/data/cascading/right.ecore @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" + name="root" xmi:id="_root"/> diff --git a/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/provider/AbstractTestTreeNodeItemProviderAdapter.java b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/provider/AbstractTestTreeNodeItemProviderAdapter.java index 4db1cb666..b204c8e0e 100644 --- a/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/provider/AbstractTestTreeNodeItemProviderAdapter.java +++ b/plugins/org.eclipse.emf.compare.rcp.ui.tests/src/org/eclipse/emf/compare/rcp/ui/tests/structuremergeviewer/groups/provider/AbstractTestTreeNodeItemProviderAdapter.java @@ -61,7 +61,7 @@ public class AbstractTestTreeNodeItemProviderAdapter { * @return the comparison * @throws IOException */ - protected static Comparison getComparison(ResourceScopeProvider scopeProvider) throws IOException { + public static Comparison getComparison(ResourceScopeProvider scopeProvider) throws IOException { final IComparisonScope scope = new DefaultComparisonScope(scopeProvider.getLeft(), scopeProvider.getRight(), scopeProvider.getOrigin()); final Builder builder = EMFCompare.builder(); diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/filters/impl/CascadingDifferencesFilter.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/filters/impl/CascadingDifferencesFilter.java index c40ea814b..aa2fb2562 100644 --- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/filters/impl/CascadingDifferencesFilter.java +++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/filters/impl/CascadingDifferencesFilter.java @@ -12,6 +12,7 @@ package org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.filters.imp import static com.google.common.base.Predicates.and; import static com.google.common.base.Predicates.or; +import static org.eclipse.emf.compare.ConflictKind.REAL; import static org.eclipse.emf.compare.DifferenceKind.ADD; import static org.eclipse.emf.compare.DifferenceKind.DELETE; import static org.eclipse.emf.compare.DifferenceKind.MOVE; @@ -19,6 +20,7 @@ import static org.eclipse.emf.compare.DifferenceSource.LEFT; import static org.eclipse.emf.compare.DifferenceSource.RIGHT; import static org.eclipse.emf.compare.utils.EMFComparePredicates.CONTAINMENT_REFERENCE_CHANGE; import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide; +import static org.eclipse.emf.compare.utils.EMFComparePredicates.hasNoDirectOrIndirectConflict; import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind; import com.google.common.base.Predicate; @@ -41,7 +43,7 @@ import org.eclipse.emf.edit.tree.TreeNode; * Differences hidden are all those that match the following criteria: * <ul> * <li>this.kind != MOVE</li> - * <li>this.conflict == null</li> + * <li>this.conflict == null && this.'indirect real conflicts' is empty</li> * <li>this.refines is empty</li> * <li>this is located inside a TreeNode that represents a Match that is either ADDed or DELETEd, and for * which the diff that represents this addition or deletion is not refined by this.</li> @@ -63,7 +65,8 @@ public class CascadingDifferencesFilter extends AbstractDifferenceFilter { EObject data = treeNode.getData(); if (data instanceof Diff && !(data instanceof ResourceAttachmentChange)) { Diff diff = (Diff)data; - if (diff.getKind() != MOVE && diff.getConflict() == null && diff.getRefines().isEmpty()) { + if (diff.getKind() != MOVE && hasNoDirectOrIndirectConflict(REAL).apply(diff) + && diff.getRefines().isEmpty()) { TreeNode parent = treeNode.getParent(); if (parent != null && parent.getData() instanceof Match) { Match parentMatch = (Match)parent.getData(); |