Bug 374822 - [refactoring] change method signature in a callin method
should adjust base-calls accordingly
- support searching for base and tsuper message sends
- adapt org.eclipse.jdt.internal.corext.refactoring.code.Invocations
- avoid bad interaction in the InlineCallin refactoring

diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseCallMessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseCallMessageSend.java
index 4c824f3..9926077 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseCallMessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseCallMessageSend.java
@@ -78,7 +78,7 @@
 public class BaseCallMessageSend extends AbstractExpressionWrapper
 {
 	public char[] sourceSelector;
-	Expression[] sourceArgs;
+	public Expression[] sourceArgs;
 	// keep a reference to the original send in case the _wrappee is replaced by some transformation
 	// (e.g., CollectedReplacementsTransformer wrapping _wrappee with a cast).
 	protected MessageSend _sendOrig;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseCallMessageSend.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseCallMessageSend.java
index 884cbda..000b73e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseCallMessageSend.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseCallMessageSend.java
@@ -38,7 +38,7 @@
  * @author mkr
  * @version $Id: BaseCallMessageSend.java 23416 2010-02-03 19:59:31Z stephan $
  */
-public class BaseCallMessageSend extends Expression
+public class BaseCallMessageSend extends Expression implements Invocation
 {
     /**
      * The "name" structural property of this node type.
@@ -116,6 +116,10 @@
 		super(ast);
 	}
 
+	public ChildListPropertyDescriptor getArgumentsProperty() {
+		return ARGUMENTS_PROPERTY;
+	}
+	
 	final List internalStructuralPropertiesForType(int apiLevel)
 	{
 		return propertyDescriptors(apiLevel);
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseConstructorInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseConstructorInvocation.java
index 0a7b15a..b4030c4 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseConstructorInvocation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BaseConstructorInvocation.java
@@ -45,7 +45,7 @@
  * @author mkr
  * @version $Id: BaseConstructorInvocation.java 23416 2010-02-03 19:59:31Z stephan $
  */
-public class BaseConstructorInvocation extends Statement
+public class BaseConstructorInvocation extends Statement implements Invocation
 {
     /**
      * The "arguments" structural property of this node type.
@@ -113,6 +113,10 @@
         return this.arguments;
     }
 
+    public ChildListPropertyDescriptor getArgumentsProperty() {
+    	return ARGUMENTS_PROPERTY;
+    }
+
 	final List internalStructuralPropertiesForType(int apiLevel)
 	{
 		return propertyDescriptors(apiLevel);
@@ -180,5 +184,7 @@
         return this.ast.getBindingResolver().resolveConstructor(this);
     }
 
-
+	public IMethodBinding resolveMethodBinding() {
+		return resolveConstructorBinding();
+	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Invocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Invocation.java
new file mode 100644
index 0000000..51a86d3
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Invocation.java
@@ -0,0 +1,29 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2013 GK Software AG, Germany,
+ *
+ * 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
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * 		Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.List;
+
+/**
+ * Simplify access to all implementing classes (OT-specific method invocations).
+ * Cf. <code>org.eclipse.jdt.internal.corext.refactoring.code.Invocations</code>
+ * and <code>org.eclipse.objectteams.otdt.internal.refactoring.adaptor.CorextAdaptor.Invocations</code>.
+ */
+public interface Invocation {
+	List getArguments();
+	ChildListPropertyDescriptor getArgumentsProperty();
+	IMethodBinding resolveMethodBinding();
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperConstructorInvocation.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperConstructorInvocation.java
index bee92ef..3bc6883 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperConstructorInvocation.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperConstructorInvocation.java
@@ -39,7 +39,7 @@
  *
  * @author mkr
  */
-public class TSuperConstructorInvocation extends Statement
+public class TSuperConstructorInvocation extends Statement implements Invocation
 {
 	/**
 	 * The "arguments" structural property of this node type.
@@ -100,8 +100,12 @@
     {
 		super(ast);
 	}
+	
+	public ChildListPropertyDescriptor getArgumentsProperty() {
+		return ARGUMENTS_PROPERTY;
+	}
 
-    /**
+	/**
      * Returns the live ordered list of argument expressions in this
      * base constructor invocation expression.
      *
@@ -182,4 +186,7 @@
 		return this.ast.getBindingResolver().resolveConstructor(this);
 	}
 
+	public IMethodBinding resolveMethodBinding() {
+		return resolveConstructorBinding();
+	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperMessageSend.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperMessageSend.java
index 2df191d..8c17d07 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperMessageSend.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TSuperMessageSend.java
@@ -40,7 +40,7 @@
  *
  * @author mkr
  */
-public class TSuperMessageSend extends Expression
+public class TSuperMessageSend extends Expression implements Invocation
 {
        /**
      * The "name" structural property of this node type.
@@ -133,6 +133,10 @@
 		super(ast);
 	}
 
+	public ChildListPropertyDescriptor getArgumentsProperty() {
+		return ARGUMENTS_PROPERTY;
+	}
+
 	@SuppressWarnings("rawtypes")
 	final List internalStructuralPropertiesForType(int apiLevel)
 	{
@@ -331,5 +335,4 @@
     public IMethodBinding resolveMethodBinding() {
         return this.ast.getBindingResolver().resolveMethod(this);
     }
-
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
index ffa27f6..a18ac2f 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.objectteams.otdt.core.compiler.OTNameUtils;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseCallMessageSend;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.FieldAccessSpec;
@@ -517,7 +518,28 @@
 		this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
 	}
 }
-//{ObjectTeams:
+//{ObjectTeams: more kinds of message sends:
+@Override
+protected void consumeMethodInvocationBase(boolean isSuperAccess)
+{
+    super.consumeMethodInvocationBase(isSuperAccess);
+    //this is always a BaseCallMessageSend
+    this.patternLocator.match((BaseCallMessageSend)this.expressionStack[this.expressionPtr], this.nodeSet);
+}
+@Override
+protected void consumeMethodInvocationBaseWithTypeArguments(boolean isSuperAccess) {
+	super.consumeMethodInvocationBaseWithTypeArguments(isSuperAccess);
+	BaseCallMessageSend messageSend = (BaseCallMessageSend) this.expressionStack[this.expressionPtr];
+	if (this.patternFineGrain == 0) {
+		this.patternLocator.match(messageSend, this.nodeSet);
+	} else {
+		// receiver is always implicit this
+		if ((this.patternFineGrain & IJavaSearchConstants.IMPLICIT_THIS_REFERENCE) != 0) {
+			this.patternLocator.match(messageSend, this.nodeSet);
+		}
+	}
+}
+@Override
 protected void consumeMethodInvocationTSuper(int kind)
 {
     super.consumeMethodInvocationTSuper(kind);
@@ -525,6 +547,19 @@
     this.patternLocator.match((MessageSend)this.expressionStack[this.expressionPtr], this.nodeSet);
 }
 @Override
+protected void consumeMethodInvocationTSuperWithTypeArguments(int kind) {
+	super.consumeMethodInvocationTSuperWithTypeArguments(kind);
+	MessageSend messageSend = (MessageSend) this.expressionStack[this.expressionPtr];
+	if (this.patternFineGrain == 0) {
+		this.patternLocator.match(messageSend, this.nodeSet);
+	} else {
+		// receiver is always implicit this
+		if ((this.patternFineGrain & IJavaSearchConstants.IMPLICIT_THIS_REFERENCE) != 0) {
+			this.patternLocator.match(messageSend, this.nodeSet);
+		}
+	}
+}
+@Override
 protected void consumeMethodSpecLong(boolean hasPlus)
 {
 	super.consumeMethodSpecLong(hasPlus);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
index e5d0f87..8f76c45 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
@@ -56,8 +56,10 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.util.SimpleSet;
 import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseCallMessageSend;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TSuperMessageSend;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticBaseCallSurrogate;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.MethodSignatureEnhancer;
 
@@ -317,6 +319,19 @@
     
     return nodeSet.addMatch(methodSpec, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
 }
+public int match(BaseCallMessageSend node, MatchingNodeSet nodeSet) {
+	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
+
+	if (!matchesName(this.pattern.selector, node.sourceSelector)) return IMPOSSIBLE_MATCH;
+	if (this.pattern.parameterSimpleNames != null && (!this.pattern.varargs || ((node.bits & ASTNode.InsideJavadoc) != 0))) {
+		int length = this.pattern.parameterSimpleNames.length;
+		ASTNode[] args = node.sourceArgs; // that's why we need special treatment: don't use raw arguments (includes isSuperAccess flag)
+		int argsLength = args == null ? 0 : args.length;
+		if (length != argsLength) return IMPOSSIBLE_MATCH;
+	}
+
+	return nodeSet.addMatch(node._wrappee, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+}
 //gbr,carp}
 public int match(MessageSend node, MatchingNodeSet nodeSet) {
 	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
@@ -877,6 +892,10 @@
 }
 protected int resolveLevel(MessageSend messageSend) {
 	MethodBinding method = messageSend.binding;
+//{ObjectTeams: base call?
+	if (method instanceof SyntheticBaseCallSurrogate)
+		method = ((SyntheticBaseCallSurrogate)method).targetMethod;
+// SH}
 	if (method == null) {
 		return INACCURATE_MATCH;
 	}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
index 42a2e0f..01e07b7 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseCallMessageSend;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.FieldAccessSpec;
@@ -271,7 +272,11 @@
     // each subtype should override if needed
     return IMPOSSIBLE_MATCH;
 }
-//gbr}
+public int match(BaseCallMessageSend node, MatchingNodeSet nodeSet) {
+    // each subtype should override if needed
+    return IMPOSSIBLE_MATCH;
+}
+//gbr+SH}
 public int match(MemberValuePair node, MatchingNodeSet nodeSet) {
 	// each subtype should override if needed
 	return IMPOSSIBLE_MATCH;
diff --git a/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/CorextAdaptor.java b/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/CorextAdaptor.java
index 58c5a06..2997568 100644
--- a/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/CorextAdaptor.java
+++ b/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/adaptor/CorextAdaptor.java
@@ -34,15 +34,33 @@
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.BaseCallMessageSend;
+import org.eclipse.jdt.core.dom.BaseConstructorInvocation;
 import org.eclipse.jdt.core.dom.CallinMappingDeclaration;
+import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
+import org.eclipse.jdt.core.dom.ClassInstanceCreation;
+import org.eclipse.jdt.core.dom.ConstructorInvocation;
+import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
+import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.Invocation;
 import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.MethodInvocation;
 import org.eclipse.jdt.core.dom.MethodSpec;
 import org.eclipse.jdt.core.dom.RoleTypeDeclaration;
+import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
+import org.eclipse.jdt.core.dom.SuperMethodInvocation;
+import org.eclipse.jdt.core.dom.TSuperConstructorInvocation;
+import org.eclipse.jdt.core.dom.TSuperMessageSend;
+import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
+import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
 import org.eclipse.jdt.internal.core.JavaProject;
 import org.eclipse.jdt.internal.core.search.JavaSearchScope;
 import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
+
+import base org.eclipse.jdt.internal.corext.refactoring.code.Invocations;
+
 import org.eclipse.jdt.internal.corext.util.JdtFlags;
 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
 import org.eclipse.objectteams.otdt.core.IOTJavaElement;
@@ -63,6 +81,55 @@
 @SuppressWarnings("restriction")
 public team class CorextAdaptor 
 {
+	/**
+	 * Support access to arguments of base call and tsuper message sends.
+	 */
+	@SuppressWarnings("basecall")
+	protected class Invocations playedBy Invocations {
+
+		getArguments <- replace getArguments;
+		getArgumentsProperty <- replace getArgumentsProperty;
+		getInferredTypeArguments <- replace getInferredTypeArguments;
+		isInvocation <- replace isInvocation;
+		isInvocationWithArguments <- replace isInvocationWithArguments;
+		getExpression <- replace getExpression;
+		// don't replace this one, our invocations have not type arguments
+		// getInferredTypeArgumentsRewrite <- replace getInferredTypeArgumentsRewrite;
+		
+		static callin List<Expression> getArguments(ASTNode invocation) {
+			if (invocation instanceof Invocation)
+				return ((Invocation)invocation).getArguments();
+			return base.getArguments(invocation);
+		}
+
+		static callin ChildListPropertyDescriptor getArgumentsProperty( ASTNode invocation) {
+			if (invocation instanceof Invocation)
+				return ((Invocation)invocation).getArgumentsProperty(); 
+			return base.getArgumentsProperty(invocation);
+		}
+
+		static callin ITypeBinding[] getInferredTypeArguments(Expression invocation) {
+			if (invocation instanceof Invocation) {
+				IMethodBinding methodBinding= ((Invocation) invocation).resolveMethodBinding();
+				return methodBinding == null ? null : methodBinding.getTypeArguments();
+			}
+			return base.getInferredTypeArguments(invocation);
+		}
+
+		static callin Expression getExpression(ASTNode astNode) {
+			if (astNode instanceof Invocation) return null;
+			return base.getExpression(astNode);
+		}
+
+		static callin boolean isInvocation(ASTNode node) {
+			return node instanceof Invocation || base.isInvocation(node);
+		}		
+
+		static callin boolean isInvocationWithArguments(ASTNode node) {
+			return node instanceof Invocation || base.isInvocationWithArguments(node);			
+		}
+	}
+
 	protected class TypedSource playedBy TypedSource
 	{
 		static callin boolean canCreateForType(int type){
diff --git a/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/otrefactorings/inlinecallin/InlineCallinRefactoring.java b/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/otrefactorings/inlinecallin/InlineCallinRefactoring.java
index d09d5dd..e0bdbc7 100644
--- a/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/otrefactorings/inlinecallin/InlineCallinRefactoring.java
+++ b/plugins/org.eclipse.objectteams.otdt.refactoring/src/org/eclipse/objectteams/otdt/internal/refactoring/otrefactorings/inlinecallin/InlineCallinRefactoring.java
@@ -23,6 +23,7 @@
 import org.eclipse.jdt.core.IJavaProject;

 import org.eclipse.jdt.core.IMember;

 import org.eclipse.jdt.core.IMethod;

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

 import org.eclipse.jdt.core.IType;

 import org.eclipse.jdt.core.JavaConventions;

 import org.eclipse.jdt.core.JavaCore;

@@ -332,6 +333,13 @@
 		engine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, new SearchRequestor() {

 			@Override

 			public void acceptSearchMatch(SearchMatch match) throws CoreException {

+				if (match.getResource().equals(fRoleCUnit.getResource())) {

+					// check if the reference is from within (self- or base-call).

+					int matchOffset = match.getOffset();

+					ISourceRange methodRange = fRoleMethod.getSourceRange();

+					if (matchOffset > methodRange.getOffset() && matchOffset < methodRange.getOffset()+methodRange.getLength())

+						return;

+				}

 				if (match.getAccuracy() == SearchMatch.A_ACCURATE && !match.isInsideDocComment()) {

 					references.add(match);

 				}

diff --git a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/src/org/eclipse/objectteams/otdt/ui/tests/refactoring/misc/ChangeSignatureTests.java b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/src/org/eclipse/objectteams/otdt/ui/tests/refactoring/misc/ChangeSignatureTests.java
index 12eb2ab..91f0f88 100644
--- a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/src/org/eclipse/objectteams/otdt/ui/tests/refactoring/misc/ChangeSignatureTests.java
+++ b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/src/org/eclipse/objectteams/otdt/ui/tests/refactoring/misc/ChangeSignatureTests.java
@@ -392,6 +392,15 @@
 		helperDelete(cu, roleR, new String[]{"I", "I"}, deleteIndices, false/*delegate*/, "Affected method binding has no signatures; consider adding signatures first so that the refactoring can absorb incompatible changes using parameter mappings"/*expectInfo*/);
 	}
 
+	// delete argument at role side of callin with base call
+	public void testDelete04()throws Exception{
+		ICompilationUnit cu= createCUfromTestFile(getPackageP(), true, true);
+		IType roleR= getType(cu, "MyTeam").getType("R");
+		int[] deleteIndices= {1};
+		helperDelete(cu, roleR, new String[]{"I", "I"}, deleteIndices, false/*delegate*/, "Removed parameter 'x' is used in method 'm' declared in type 'R'.");
+		// see https://bugs.eclipse.org/408387 regarding the bogus error
+	}
+
 	public void testReorder01() throws Exception {
 		helperPermute(new String[]{"ignore", "b", "a"}, new String[]{"I", "Z", "QString;"}, false);
 	}
diff --git a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/ChangeSignature/canModify/A_testDelete04_in.java b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/ChangeSignature/canModify/A_testDelete04_in.java
new file mode 100644
index 0000000..2c47984
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/ChangeSignature/canModify/A_testDelete04_in.java
@@ -0,0 +1,13 @@
+package p;
+class A{
+	private void m(int i, int x){
+	}
+}
+team class MyTeam {
+	protected class R playedBy A {
+		void m(int i, int x) <- replace void m(int i, int x);
+		callin void m(int i, int x) {
+			base.m(i, x);
+		}
+	}
+}
\ No newline at end of file
diff --git a/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/ChangeSignature/canModify/A_testDelete04_out.java b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/ChangeSignature/canModify/A_testDelete04_out.java
new file mode 100644
index 0000000..385a5b8
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.ui.tests.refactoring/testdata/ChangeSignature/canModify/A_testDelete04_out.java
@@ -0,0 +1,13 @@
+package p;
+class A{
+	private void m(int i, int x){
+	}
+}
+team class MyTeam {
+	protected class R playedBy A {
+		void m(int i) <- replace void m(int i, int x);
+		callin void m(int i) {
+			base.m(i);
+		}
+	}
+}
\ No newline at end of file