Bug 374841 - [refactoring] pull up does not work among (nested) roles
diff --git a/plugins/org.eclipse.objectteams.otdt.refactoring/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otdt.refactoring/META-INF/MANIFEST.MF
index 69eb95c..7aa2e02 100644
--- a/plugins/org.eclipse.objectteams.otdt.refactoring/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otdt.refactoring/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.objectteams.otdt.refactoring;singleton:=true
-Bundle-Version: 2.1.0.qualifier
+Bundle-Version: 2.2.0.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Require-Bundle: org.eclipse.jdt.ui;bundle-version="[3.7.0,4.0.0)",
diff --git a/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/pullup/PullUpAdaptor.java b/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/pullup/PullUpAdaptor.java
index ab73a61..74c104d 100644
--- a/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/pullup/PullUpAdaptor.java
+++ b/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/pullup/PullUpAdaptor.java
@@ -8,15 +8,21 @@
 import java.util.List;

 import java.util.Set;

 

+import org.eclipse.core.runtime.Assert;

 import org.eclipse.core.runtime.CoreException;

 import org.eclipse.core.runtime.IProgressMonitor;

 import org.eclipse.jdt.core.Flags;

+import org.eclipse.jdt.core.ICompilationUnit;

 import org.eclipse.jdt.core.IField;

+import org.eclipse.jdt.core.IJavaElement;

 import org.eclipse.jdt.core.IMember;

 import org.eclipse.jdt.core.IMethod;

+import org.eclipse.jdt.core.IPackageFragment;

 import org.eclipse.jdt.core.IType;

 import org.eclipse.jdt.core.ITypeHierarchy;

 import org.eclipse.jdt.core.JavaModelException;

+import org.eclipse.jdt.core.dom.Modifier;

+import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;

 import org.eclipse.jdt.core.search.IJavaSearchConstants;

 import org.eclipse.jdt.core.search.IJavaSearchScope;

 import org.eclipse.jdt.core.search.MethodDeclarationMatch;

@@ -34,7 +40,9 @@
 import org.eclipse.objectteams.otdt.core.ICalloutMapping;

 import org.eclipse.objectteams.otdt.core.ICalloutToFieldMapping;

 import org.eclipse.objectteams.otdt.core.IMethodMapping;

+import org.eclipse.objectteams.otdt.core.IOTJavaElement;

 import org.eclipse.objectteams.otdt.core.IOTType;

+import org.eclipse.objectteams.otdt.core.IRoleType;

 import org.eclipse.objectteams.otdt.core.OTModelManager;

 import org.eclipse.objectteams.otdt.core.TypeHelper;

 import org.eclipse.objectteams.otdt.core.hierarchy.OTTypeHierarchies;

@@ -45,6 +53,7 @@
 import org.eclipse.objectteams.otdt.internal.refactoring.util.RefactoringUtil;

 import org.eclipse.osgi.util.NLS;

 

+import base org.eclipse.jdt.internal.corext.refactoring.structure.MemberVisibilityAdjustor;

 import base org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoringProcessor;

 
 /**

@@ -420,7 +429,97 @@
 		needsVisibilityAdjustment <- replace needsVisibilityAdjustment;

 			

 	}

-	

+

+	protected class Visibility playedBy MemberVisibilityAdjustor {

+

+		IJavaElement getFReferencing() -> get IJavaElement fReferencing;

+

+		void adjustOutgoingVisibility(IMember member, ModifierKeyword threshold, String template)

+		-> void adjustOutgoingVisibility(IMember member, ModifierKeyword threshold, String template);

+

+		ModifierKeyword thresholdTypeToMethod(IType referencing, IMethod referenced, IProgressMonitor monitor)

+		-> ModifierKeyword thresholdTypeToMethod(IType referencing, IMethod referenced, IProgressMonitor monitor);

+		

+		checkOTMember <- replace adjustOutgoingVisibilityChain;

+

+		@SuppressWarnings("basecall")

+		callin void checkOTMember(IMember member, IProgressMonitor monitor) throws JavaModelException {

+			try {

+				base.checkOTMember(member, monitor);

+			} catch (JavaModelException jme) {

+				if (jme.getJavaModelStatus().isDoesNotExist()) {

+					IType type = member.getDeclaringType();

+					IOTType ottype = OTModelManager.getOTElement(type);

+					if (ottype != null) {

+						if (ottype.isRole() && member instanceof IMethod) {

+							for (IMethodMapping map : ((IRoleType)ottype).getMethodMappings()) {

+								if (map.getElementType() != IMethodMapping.CALLIN_MAPPING

+										&& member.equals(map.getCorrespondingJavaElement())) 

+								{

+									if (!Modifier.isPublic(map.getFlags())) {

+										final ModifierKeyword threshold= computeOutgoingVisibilityThreshold(map, monitor);

+										adjustOutgoingVisibility(map, threshold, RefactoringCoreMessages.MemberVisibilityAdjustor_change_visibility_method_warning);

+									}

+									if (member.getDeclaringType() != null)

+										base.checkOTMember(member.getDeclaringType(), monitor);

+									return;

+								}

+							}

+						}

+					}

+				}

+				throw jme;

+			}

+		}

+		// adjusted copy, base version cannot handle OT elements

+		private ModifierKeyword computeOutgoingVisibilityThreshold(final IMember referenced, final IProgressMonitor monitor) throws JavaModelException {

+			final IJavaElement referencing = getFReferencing();

+			Assert.isTrue(referencing instanceof ICompilationUnit || referencing instanceof IType || referencing instanceof IPackageFragment);

+			ModifierKeyword keyword= ModifierKeyword.PUBLIC_KEYWORD;

+			try {

+				monitor.beginTask("", 1); //$NON-NLS-1$

+				monitor.setTaskName(RefactoringCoreMessages.MemberVisibilityAdjustor_checking);

+				final int referencingType= referencing.getElementType();

+				final int referencedType= referenced.getElementType();

+				switch (referencedType) {

+					case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING:

+					case IOTJavaElement.CALLOUT_MAPPING: {

+						final IMethodMapping calloutReferenced= (IMethodMapping) referenced;

+						final ICompilationUnit referencedUnit= calloutReferenced.getCompilationUnit();

+						switch (referencingType) {

+							case IJavaElement.COMPILATION_UNIT: {

+								final ICompilationUnit unit= (ICompilationUnit) referencing;

+								if (referencedUnit != null && referencedUnit.equals(unit))

+									keyword= ModifierKeyword.PRIVATE_KEYWORD;

+								else if (referencedUnit != null && referencedUnit.getParent().equals(unit.getParent()))

+									keyword= null;

+								break;

+							}

+							case IJavaElement.TYPE: {

+								keyword= thresholdTypeToMethod((IType) referencing, 

+										(IMethod) calloutReferenced.getCorrespondingJavaElement(), monitor);

+								break;

+							}

+							case IJavaElement.PACKAGE_FRAGMENT: {

+								final IPackageFragment fragment= (IPackageFragment) referencing;

+								if (calloutReferenced.getDeclaringType().getPackageFragment().equals(fragment))

+									keyword= null;

+								break;

+							}

+							default:

+								Assert.isTrue(false);

+						}

+						break;

+					}

+					default:

+						Assert.isTrue(false);

+				}

+			} finally {

+				monitor.done();

+			}

+			return keyword;

+		}

+	}

 }

 

 

diff --git a/releng/map/otdt.map b/releng/map/otdt.map
index a93aa91..1ba80b6 100644
--- a/releng/map/otdt.map
+++ b/releng/map/otdt.map
@@ -36,7 +36,7 @@
 plugin@org.eclipse.objectteams.otdt.apt,2.0.0=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otdt.apt,tag=builds/201105161939

 plugin@org.eclipse.objectteams.otdt.compiler.adaptor,2.1.0=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otdt.compiler.adaptor,tag=builds/201203201248

 plugin@org.eclipse.objectteams.otdt.debug.adaptor,2.1.0=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otdt.debug.adaptor,tag=builds/201205081843

-plugin@org.eclipse.objectteams.otdt.refactoring,2.1.0=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otdt.refactoring,tag=builds/201203201248

+plugin@org.eclipse.objectteams.otdt.refactoring,2.2.0=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otdt.refactoring

 plugin@org.eclipse.objectteams.otdt.pde.ui,2.1.0=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otdt.pde.ui,tag=builds/201203201248

 plugin@org.eclipse.objectteams.otdt.samples,2.1.0=GIT,repo=git://git.eclipse.org/gitroot/objectteams/org.eclipse.objectteams.git,path=plugins/org.eclipse.objectteams.otdt.samples,tag=builds/201108142105

 

diff --git a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/src/org/eclipse/objectteams/otdt/ui/tests/refactoring/pullup/PullUpTests.java b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/src/org/eclipse/objectteams/otdt/ui/tests/refactoring/pullup/PullUpTests.java
index ff621e2..0c1ada3 100644
--- a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/src/org/eclipse/objectteams/otdt/ui/tests/refactoring/pullup/PullUpTests.java
+++ b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/src/org/eclipse/objectteams/otdt/ui/tests/refactoring/pullup/PullUpTests.java
@@ -327,4 +327,9 @@
 	public void testPullUpFieldToImplicitSuperclass() throws Exception {
 		performPullUp_pass(new String[] { "T", "TSuper" }, new String[] {}, new String[][] { new String[0] }, new String[] { "f" }, true, false, 0, "R");
 	}
+	
+	// Bug 374841 - [refactoring] pull up does not work among (nested) roles
+	public void testPullUpWithReferenceToCallout()  throws Exception {
+		performPullUp_pass(new String[] {"T", "B"}, new String[]{"foo"}, new String[][] { new String[0] }, new String[0], true, true, 0, "RSub");
+	}
 }
diff --git a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/in/B.java b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/in/B.java
new file mode 100644
index 0000000..2f8b930
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/in/B.java
@@ -0,0 +1,4 @@
+public class B {
+	String s;
+	String getS() { return s; }
+}
\ No newline at end of file
diff --git a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/in/T.java b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/in/T.java
new file mode 100644
index 0000000..b2af6c4
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/in/T.java
@@ -0,0 +1,13 @@
+public team class T {
+	protected class RSuper {
+		
+	}
+	protected class RSub extends RSuper playedBy B {
+		String getS1() -> get String s;
+		String getS2() -> String getS();
+		void foo()
+		{
+			System.out.println(getS1()+getS2());
+		}
+	}
+}
\ No newline at end of file
diff --git a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/out/B.java b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/out/B.java
new file mode 100644
index 0000000..2f8b930
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/out/B.java
@@ -0,0 +1,4 @@
+public class B {
+	String s;
+	String getS() { return s; }
+}
\ No newline at end of file
diff --git a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/out/T.java b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/out/T.java
new file mode 100644
index 0000000..f4ec07e
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/PullUp/testPullUpWithReferenceToCallout/out/T.java
@@ -0,0 +1,17 @@
+public team class T {
+	protected abstract class RSuper {
+
+		void foo()
+		{
+			System.out.println(getS1()+getS2());
+		}
+		
+		abstract String getS1();
+		
+		abstract String getS2();
+	}
+	protected class RSub extends RSuper playedBy B {
+		String getS1() -> get String s;
+		String getS2() -> String getS();
+	}
+}
\ No newline at end of file