Bug 468048 - IEclipseContext#setParent only clears direct value
computations

Change-Id: Id731bf005a866341c758413e28300a6b5ae4c7c2
diff --git a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java
index b49debb..0cecde5 100644
--- a/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java
+++ b/bundles/org.eclipse.e4.core.contexts/src/org/eclipse/e4/core/internal/contexts/EclipseContext.java
@@ -497,12 +497,21 @@
 				invalidate(name, ContextChangeEvent.ADDED, oldValue, newValue, scheduled);
 		}
 
+		invalidateLocalComputations(scheduled);
+	}
+
+	protected void invalidateLocalComputations(Set<Scheduled> scheduled) {
 		ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.ADDED, null, null, null);
 		for (Computation computation : localValueComputations.values()) {
 			weakListeners.remove(computation);
 			computation.handleInvalid(event, scheduled);
 		}
 		localValueComputations.clear();
+
+		// We need to cleanup computations recursively see bug 468048
+		for (EclipseContext c : getChildren()) {
+			c.invalidateLocalComputations(scheduled);
+		}
 	}
 
 	private void collectDependentNames(Set<String> usedNames) {
diff --git a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/ReparentingTest.java b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/ReparentingTest.java
index 3781bd3..14092c1 100644
--- a/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/ReparentingTest.java
+++ b/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/contexts/ReparentingTest.java
@@ -11,9 +11,8 @@
 
 package org.eclipse.e4.core.internal.tests.contexts;
 
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
+import javax.inject.Inject;
+import javax.inject.Named;
 
 import org.eclipse.e4.core.contexts.ContextFunction;
 import org.eclipse.e4.core.contexts.ContextInjectionFactory;
@@ -22,6 +21,10 @@
 import org.eclipse.e4.core.contexts.RunAndTrack;
 import org.eclipse.e4.core.internal.tests.contexts.inject.ObjectSuperClass;
 
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
 /**
  * Test for changing a context's parent.
  */
@@ -278,4 +281,64 @@
 		childContext.setParent(childContext.getParent());
 		assertEquals(1, testServiceCount[0]);
 	}
+
+	public void testBug468048_contextFunction() {
+		IEclipseContext p1 = EclipseContextFactory.create("parent1");
+		p1.set("sample", new ContextFunction() {
+			@Override
+			public Object compute(IEclipseContext context) {
+				return Integer.valueOf(1);
+			}
+		});
+
+		IEclipseContext p2 = EclipseContextFactory.create("parent2");
+		p2.set("sample", new ContextFunction() {
+			@Override
+			public Object compute(IEclipseContext context) {
+				return Integer.valueOf(2);
+			}
+		});
+
+		final IEclipseContext intermed = p1.createChild("intermed");
+
+		final IEclipseContext leaf = intermed.createChild("leaf");
+		assertEquals(Integer.valueOf(1), leaf.get("sample"));
+		intermed.setParent(p2);
+		assertEquals(Integer.valueOf(2), leaf.get("sample"));
+	}
+
+	public void testBug468048_injection() {
+		IEclipseContext p1 = EclipseContextFactory.create("parent1");
+		p1.set("sample", new ContextFunction() {
+			@Override
+			public Object compute(IEclipseContext context) {
+				return Integer.valueOf(1);
+			}
+		});
+
+		IEclipseContext p2 = EclipseContextFactory.create("parent2");
+		p2.set("sample", new ContextFunction() {
+			@Override
+			public Object compute(IEclipseContext context) {
+				return Integer.valueOf(2);
+			}
+		});
+
+		final IEclipseContext intermed = p1.createChild("intermed");
+
+		final IEclipseContext leaf = intermed.createChild("leaf");
+		Bug468048 b = ContextInjectionFactory.make(Bug468048.class, leaf);
+
+		assertEquals(Integer.valueOf(1), b.sample);
+		System.err.println("==========");
+		intermed.setParent(p2);
+		assertEquals(Integer.valueOf(2), b.sample);
+	}
+
+	public static class Bug468048 {
+		@Inject
+		@Named("sample")
+		public Integer sample;
+
+	}
 }