Implementation part1 for bug 318084: [compiler] cannot callin-bind a callout-defined method
- changes in compile order plus cleanup
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 8b34793..6f8d839 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -1958,9 +1958,9 @@
             // if decapsulation was actually used, try if that was legal:
             if (arg.type.getBaseclassDecapsulation().isAllowed() != previousDecapsulation.isAllowed())
             {
-            	ReferenceBinding baseclass = method.declaringClass.baseclass();
-            	if (   baseclass == null
-            		|| !parameterType.isCompatibleWith(baseclass))
+            	ReferenceBinding declaredBaseclass = method.declaringClass.baseclass();
+            	if (   declaredBaseclass == null
+            		|| !parameterType.isCompatibleWith(declaredBaseclass))
             	{
             		ProblemReferenceBinding problemBinding = new ProblemReferenceBinding(
             				parameterType.readableName(), (ReferenceBinding)parameterType, ProblemReasons.NotVisible);
@@ -2056,6 +2056,10 @@
 				typeParameters[i].binding = null;
 		return null;
 	}
+//{ObjectTeams: all types in resolved signatures may require wrapping:
+	if (this.isRole() || this.isTeam())
+		RoleTypeCreator.wrapTypesInMethodDeclSignature(method, methodDecl);
+// SH}
 	if (foundReturnTypeProblem)
 		return method; // but its still unresolved with a null return type & is still connected to its method declaration
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/AbstractMethodMappingDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/AbstractMethodMappingDeclaration.java
index f9833d3..d1630a9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/AbstractMethodMappingDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/AbstractMethodMappingDeclaration.java
@@ -46,7 +46,6 @@
 import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
@@ -331,7 +330,7 @@
 								checkParametersCompatibility(methodSpec);
 								checkReturnCompatibility(methodSpec);
 							}
-							checkVisibility(this.scope, methodSpec, baseType);
+							checkVisibility(methodSpec, baseType);
 							checkThrownExceptions(methodSpec);
 						}
 					}
@@ -374,7 +373,7 @@
 								checkResult(methodSpec);
 							}
 							// check these in both cases (?)
-							checkVisibility(this.scope, methodSpec, baseType);
+							checkVisibility(methodSpec, baseType);
 							checkThrownExceptions(methodSpec);
 						}
 		    		} finally {
@@ -391,7 +390,7 @@
 		{
 			if (isCallin())
 				if (baseMethodSpecs[idx].resolvedMethod != null && baseMethodSpecs[idx].resolvedMethod.isDeprecated())
-					scope.problemReporter().callinToDeprecated(baseMethodSpecs[idx], baseMethodSpecs[idx].resolvedMethod);
+					this.scope.problemReporter().callinToDeprecated(baseMethodSpecs[idx], baseMethodSpecs[idx].resolvedMethod);
 			baseMethodSpecs[idx].resolveFinished();
 		}
 //haebor}
@@ -420,8 +419,8 @@
 									// yes, so we need a wrapper:
 									Expression wrappedExpr= new SingleNameReference(token,pos) {
 										@Override
-										public TypeBinding resolveType(BlockScope scope) {
-											TypeBinding result= super.resolveType(scope);
+										public TypeBinding resolveType(BlockScope blockScope) {
+											TypeBinding result= super.resolveType(blockScope);
 											if (this.binding instanceof ITeamAnchor)
 												if (((ITeamAnchor)this.binding).isValidAnchor())
 													arg.binding.shareBestName((ITeamAnchor)this.binding);
@@ -447,7 +446,7 @@
 		}
 	}
 
-	public boolean checkVisibility (Scope scope, MethodSpec spec, ReferenceBinding baseType)
+	public boolean checkVisibility (MethodSpec spec, ReferenceBinding baseType)
 	{
 		if (spec.isPrivate()) {
 			if (baseType.getRealClass() != spec.getDeclaringClass()) {
@@ -455,7 +454,7 @@
 				return false; // don't report decapsulation if this error is detected.
 			}
 		}
-		spec.checkDecapsulation(baseType, scope);
+		spec.checkDecapsulation(baseType, this.scope);
 		return true;
 	}
 
@@ -627,11 +626,9 @@
 	 * The method mapping contains parameter mappings and the index is within the
 	 * range of source code arguments, so let's lookup the argument expression.
 	 *
-	 * @param methodMapping
 	 * @param sourceMethodSpec
 	 * @param implIdx		   index into arguments of the implementation(target) method
 	 * @param targetArgName
-	 * @param mappedArgExpr
 	 * @return Pair:{the argument expression, the src arg position}
 	 */
 	Pair<Expression, Integer> getMappedArgument(MethodSpec  sourceMethodSpec,
@@ -686,11 +683,11 @@
 	 * For error reporting only, thus only the first occurrence is of interest.
 	 *
 	 * @param mappedArgExpr expression to investigate
-	 * @param scope         just to please the visitor
+	 * @param blockScope    just to please the visitor
 	 * @param arguments     base arguments to match against
 	 * @return a found reference or null.
 	 */
-	SingleNameReference findBaseArgName(Expression mappedArgExpr, BlockScope scope, final Argument[] arguments) {
+	SingleNameReference findBaseArgName(Expression mappedArgExpr, BlockScope blockScope, final Argument[] arguments) {
 		@SuppressWarnings("serial")
 		class FoundException extends RuntimeException {
 			SingleNameReference name;
@@ -698,7 +695,7 @@
 		}
 
 		ASTVisitor visitor = new ASTVisitor() {
-			public void endVisit(SingleNameReference nameRef, BlockScope blockScope) {
+			public void endVisit(SingleNameReference nameRef, BlockScope blockScope2) {
 				for (int i = 0; i < arguments.length; i++) {
 					if (CharOperation.equals(arguments[i].name, nameRef.token))
 						throw new FoundException(nameRef);
@@ -706,7 +703,7 @@
 			}
 		};
 		try {
-			mappedArgExpr.traverse(visitor, scope);
+			mappedArgExpr.traverse(visitor, blockScope);
 		} catch (FoundException e) {
 			return e.name;
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/CallinMappingDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/CallinMappingDeclaration.java
index 7288891..51aa70b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/CallinMappingDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/CallinMappingDeclaration.java
@@ -42,12 +42,12 @@
 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
@@ -186,7 +186,7 @@
 	}
 	boolean isDangerousMethod(MethodBinding method) {
 		if (CharOperation.equals(method.selector, "hashCode".toCharArray())) //$NON-NLS-1$
-			return method.parameters == MethodBinding.NO_PARAMETERS;
+			return method.parameters == Binding.NO_PARAMETERS;
 		if (CharOperation.equals(method.selector, "equals".toCharArray())) //$NON-NLS-1$
 			return (method.parameters.length == 1) && (method.parameters[0].id == TypeIds.T_JavaLangObject);
 		return false;
@@ -207,7 +207,8 @@
 
 	/**
      * In this case: check match of "replace" and "callin" flags, plus static-ness
-     * @param scope
+     * @param haveBaseMethods have base methods been resolved?
+     * @param baseClass       the role's bound base class
 	 */
 	@Override
 	protected void checkModifiers(boolean haveBaseMethods, ReferenceBinding baseClass) {
@@ -339,7 +340,7 @@
 					{
 						// success by translation
 						methodSpec.argNeedsTranslation[j] = true;
-						roleMethodSpec.argNeedsTranslation[j] = true;
+						this.roleMethodSpec.argNeedsTranslation[j] = true;
 						this.roleMethodSpec.parameters[j] = roleToLiftTo; // this applies to all bindings
 						continue;
 					}
@@ -392,9 +393,9 @@
 	}
 
 	@Override
-	public boolean checkVisibility(Scope scope, MethodSpec spec, ReferenceBinding baseType)
+	public boolean checkVisibility(MethodSpec spec, ReferenceBinding baseType)
 	{
-		if (!super.checkVisibility(scope, spec, baseType))
+		if (!super.checkVisibility(spec, baseType))
 			return false;
 		if (isReplaceCallin()) {
 			// create a faked invocationSite:
@@ -402,43 +403,15 @@
 			anticipatedBaseCall.receiver = new SingleNameReference("<fake>".toCharArray(), 0); //$NON-NLS-1$
 			anticipatedBaseCall.receiver.resolvedType =
 				     anticipatedBaseCall.actualReceiverType = baseType;
-			if (   !spec.resolvedMethod.canBeSeenBy(baseType, anticipatedBaseCall, scope.classScope())
+			if (   !spec.resolvedMethod.canBeSeenBy(baseType, anticipatedBaseCall, this.scope.classScope())
 				&& (spec.resolvedMethod.modifiers & ClassFileConstants.AccProtected) == 0) // protected is not a warning
-				scope.problemReporter().callinDecapsulation(spec, scope);
+				this.scope.problemReporter().callinDecapsulation(spec, this.scope);
 		}
 		return true;
 	}
 
 	/** Check whether the baseSpec has a result compatible via replace. */
 	public void checkResultForReplace(MethodSpec baseSpec) {
-		// for replace callins, a "result" mapping is not allowed,
-		// unless an expected result is otherwise missing.
-		if (this.mappings != null)
-		{
-			for (int i = 0; i < this.mappings.length; i++) {
-				if (CharOperation.equals(this.mappings[i].ident.token, IOTConstants.RESULT))
-				{
-					this.isResultMapped = true;
-					// OTJLD 4.4(b): "If the base method declares a result, then ...
-					if (baseSpec.resolvedType() != TypeBinding.VOID) {
-					//                * if the role method also declares a result,
-						if (this.roleMethodSpec.resolvedType() != TypeBinding.VOID) {
-							Expression resultExpr = this.mappings[i].expression;
-					//                  => result must be mapped to itself
-							if (! (resultExpr instanceof ResultReference))  {
-								this.scope.problemReporter().nonResultExpressionInReplaceResult(resultExpr);
-								this.binding.tagBits |= TagBits.HasMappingIncompatibility;
-							}
-						} // no else because:
-					//                * if the role method does not declare a result,
-				    //                  an arbitrary expression may be mapped to result
-	            	} else {
-	            		this.scope.problemReporter().resultMappingForVoidMethod(this, baseSpec, this.mappings[i]);
-	    				this.binding.tagBits |= TagBits.HasMappingIncompatibility;
-	            	}
-				}
-			}
-		}
 		boolean typeIdentityRequired= true; // default unless return is type variable
 		// covariant return requires a fresh type parameter for the role's return type:
 		if (baseSpec.covariantReturn && this.roleMethodSpec.returnType != null) {
@@ -570,6 +543,37 @@
 			}
 		}
 	}
+	/** Check OTJLD 4.4(b) "Callin parameter mapping / Restrictions for callin replace bindings" */
+	public void checkResultMapping() {
+		// for replace callins, a "result" mapping is not allowed,
+		// unless an expected result is otherwise missing.
+
+		for (MethodSpec baseSpec : this.baseMethodSpecs) {
+			for (int i = 0; i < this.mappings.length; i++) {
+				if (CharOperation.equals(this.mappings[i].ident.token, IOTConstants.RESULT))
+				{
+					this.isResultMapped = true;
+					// OTJLD 4.4(b): "If the base method declares a result, then ...
+					if (baseSpec.resolvedType() != TypeBinding.VOID) {
+					//                * if the role method also declares a result,
+						if (this.roleMethodSpec.resolvedType() != TypeBinding.VOID) {
+							Expression resultExpr = this.mappings[i].expression;
+					//                  => result must be mapped to itself
+							if (! (resultExpr instanceof ResultReference))  {
+								this.scope.problemReporter().nonResultExpressionInReplaceResult(resultExpr);
+								this.binding.tagBits |= TagBits.HasMappingIncompatibility;
+							}
+						} // no else because:
+					//                * if the role method does not declare a result,
+				    //                  an arbitrary expression may be mapped to result
+			    	} else {
+			    		this.scope.problemReporter().resultMappingForVoidMethod(this, baseSpec, this.mappings[i]);
+						this.binding.tagBits |= TagBits.HasMappingIncompatibility;
+			    	}
+				}
+			}
+		}
+	}
 	
 	private boolean typeUsesTypeVariable(TypeBinding type, TypeBinding variable) {
 		if (type.leafComponentType() == variable)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Dependencies.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Dependencies.java
index 98c49a6..9428927 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Dependencies.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/control/Dependencies.java
@@ -25,7 +25,6 @@
 
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Clinit;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
@@ -69,7 +68,6 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.TransformStatementsVisitor;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstEdit;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.RoleFileHelper;
-import org.eclipse.objectteams.otdt.internal.core.compiler.util.RoleTypeCreator;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.TSuperHelper;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.TypeAnalyzer;
 
@@ -1491,6 +1489,9 @@
      * Doing fault in types here and not via CompilationUnitScope
      * allows us to process single types without processing the whole
      * compilation unit!
+     * We also add some OT-specific transformantions:
+     * - faultInRoleImports
+     * - evaluateLateAttributes
 	 */
 	private static boolean establishFaultInTypes(TypeModel clazz) {
 		TypeDeclaration ast = clazz.getAst();
@@ -1521,6 +1522,21 @@
 			faultInRoleImports(roleType);
 		}
 	}
+	
+//        	if (teamDecl.isRole()) {
+//        		ensureRoleState(teamDecl.getRoleModel(), STATE_TYPES_ADJUSTED);
+//        	}
+
+//        	TeamModel superTeam = teamModel.getSuperTeam();
+//	        if (superTeam != null) {
+//	            if (!ensureTeamState(superTeam, STATE_TYPES_ADJUSTED))
+//	            {
+//	            	teamDecl.tagAsHavingErrors();
+//	                return;
+//	            }
+//	        }
+
+//	        CopyInheritance.weakenTeamMethodSignatures(teamDecl);
 
 	/* **** STATE_METHODS_CREATED (OT/J) ****
 	 * - generate methods relating to roles and implicit inheritance.
@@ -1535,6 +1551,7 @@
 	 * 3. add method from non-role superclasses to the interface part.
 	 * 4. cast methods (calls getTeam method)
 	 * 5. abstract _OT$getBase() method for unbound lowerable role
+	 * 6. callout methods
 	 */
 	private static boolean establishMethodsCreated(TeamModel teamModel) {
 		if (teamModel.getBinding().isRole())
@@ -1702,6 +1719,10 @@
         // 5. special case roles which need an abstract _OT$getBase() method:
 		StandardElementGenerator.createGetBaseForUnboundLowerable(clazz);
         
+		// 6. resolve method mappings and create callout methods:
+		resolveMethodMappings(clazz);
+		transformCallouts(clazz);
+
         clazz.setState(STATE_METHODS_CREATED);
         return true;
     }
@@ -1742,15 +1763,6 @@
 
 	        CopyInheritance.weakenTeamMethodSignatures(teamDecl);
 	        
-		    AbstractMethodDeclaration[] methods = teamDecl.methods;
-		    if (methods != null) {
-		    	for (int i=0; i<methods.length; i++)
-		    	{
-		    		if (   ! (methods[i] instanceof Clinit)
-		    			&& !methods[i].isCopied) // copied roles are already wrapped if needed.
-		    			RoleTypeCreator.wrapTypesInMethodDeclSignature(methods[i].binding, methods[i]);
-		    	}
-		    }
 		}
 		teamModel.setState(STATE_TYPES_ADJUSTED);
 		return true;
@@ -1774,30 +1786,6 @@
 
         SourceTypeBinding subTeam = teamType.binding;
 
-        // 1. Wrap role types in signatures:
-        // Try method ASTs first:
-        AbstractMethodDeclaration[] srcMethods = null;
-        if (subRoleDecl != null)
-            srcMethods  = subRoleDecl.methods;
-
-        if (srcMethods != null) {
-        	subRole.methods(); // need resolved types in method bindings below.
-            for (int i=0; i<srcMethods.length; i++)
-            {
-                if (srcMethods[i].binding != null) {
-                	// copied methods are already wrapped during addMethod.
-                	// copied synthetic methods must not be wrapped alltogether.
-                	if (!srcMethods[i].isCopied) 
-                        RoleTypeCreator.wrapTypesInMethodDeclSignature(srcMethods[i].binding, srcMethods[i]);
-                }
-                else
-                    assert(  srcMethods[i].ignoreFurtherInvestigation
-                           ||srcMethods[i].isClinit() );
-                    // why does clinit have no binding (not a problem, but funny)?
-            }
-        }
-
-
         // Remaining translations only for source types (no role nested types)
         if (   subRoleDecl != null
         	&& subRole.isDirectRole())
@@ -1891,8 +1879,13 @@
      */
 	private static boolean establishMethodMappingsResolved(RoleModel role)
 	{
-		boolean success = true;
-
+		// FIXME(SH): remove this state
+		role.setState(ITranslationStates.STATE_MAPPINGS_RESOLVED);
+		return true;
+	}
+	
+	private static void resolveMethodMappings(RoleModel role) 
+	{
 		ReferenceBinding roleBinding = role.getBinding();
 
 		TypeDeclaration roleDecl = role.getAst();
@@ -1906,16 +1899,16 @@
 				if (baseclass != null && !role._playedByEnclosing)
 					// some methods accessible to callout/callin might be added during
 					// callout transformation.
-					ensureBindingState(baseclass, STATE_MAPPINGS_TRANSFORMED);
+					ensureBindingState(baseclass, STATE_METHODS_CREATED);
 			}
 			ReferenceBinding[] tsuperRoles = role.getTSuperRoleBindings();
 			for (int i = 0; i < tsuperRoles.length; i++) {
 				// need the generated wrappers to determine abstractness of methods
-				ensureBindingState(tsuperRoles[i], STATE_MAPPINGS_TRANSFORMED);
+				ensureBindingState(tsuperRoles[i], STATE_METHODS_CREATED);
 			}
 			// same reason as for tsuper roles:
 			if (roleBinding.superclass() != null)
-				ensureBindingState(roleBinding.superclass(), STATE_MAPPINGS_TRANSFORMED);
+				ensureBindingState(roleBinding.superclass(), STATE_METHODS_CREATED);
 
 			// make sure tsuper wrappers are copied to current role:
 			CopyInheritance.copyGeneratedFeatures(role);
@@ -1923,12 +1916,10 @@
 			// actually need to proceed even with no base class, because
 			// method mappings without baseclass are reported within resolve() below:
 			MethodMappingResolver resolver = new MethodMappingResolver(role);
-			success = resolver.resolve(!hasBaseclassProblem && needMethodBodies(roleDecl));
+			resolver.resolve(!hasBaseclassProblem && needMethodBodies(roleDecl));
 			if (roleDecl.isDirectRole() && !roleDecl.isInterface())
 				SyntheticBaseCallSurrogate.addFakedBaseCallSurrogates((SourceTypeBinding)roleBinding);
 		}
-		role.setState(ITranslationStates.STATE_MAPPINGS_RESOLVED);
-		return success;
 	}
 
     /* **** STATE_MAPPINGS_TRANSFORMED (OT/J) ***
@@ -1953,6 +1944,21 @@
 		return true;
 	}
 
+	private static boolean transformCallouts(RoleModel role) {
+		// FIXME(SH): move to CalloutImplementor
+		boolean success = true;
+		TypeDeclaration roleDecl = role.getAst();
+		if (roleDecl != null && !roleDecl.isPurelyCopied) { // no source level bindings present any way
+	    	boolean needMethodBodies = needMethodBodies(roleDecl) && !role.hasBaseclassProblem() && !role.isIgnoreFurtherInvestigation();
+	    	if (!roleDecl.binding.isSynthInterface()) {
+	    		// synth interfaces have no callouts anyway ;-)
+	            CalloutImplementor calloutImplementor = new CalloutImplementor(role);
+	            success &= calloutImplementor.transform(needMethodBodies);
+	    	}
+		}
+    	return success;
+	}
+
 	private static boolean establishMethodMappingsTransformed(RoleModel role)
 	{
         boolean success = true;
@@ -1971,10 +1977,7 @@
 			} else if (!roleDecl.isPurelyCopied) { // no source level bindings present any way
 	        	boolean needMethodBodies = needMethodBodies(roleDecl) && !role.hasBaseclassProblem() && !role.isIgnoreFurtherInvestigation();
 	        	if (!roleDecl.binding.isSynthInterface()) {
-	        		// synth interfaces have no callouts anyway ;-)
-		            CalloutImplementor calloutImplementor = new CalloutImplementor(role);
-		            success = calloutImplementor.transform(needMethodBodies);
-
+	        		// synth interfaces have no callins anyway ;-)
 		            if (needMethodBodies) {  // not translating callin bindings will cause no secondary errors -> skip if no body needed
 //{OTDyn:
 		            	if (CallinImplementorDyn.DYNAMIC_WEAVING) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
index a57014c..46c84f4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
@@ -1103,7 +1103,7 @@
 		callout.baseMethodSpec = fromMethodBinding(candidate, gen);
 
 		// now we have all information for checking 3.4(d) (see Trac #96):
-		if (!callout.checkVisibility(callout.scope, callout.baseMethodSpec, baseType))
+		if (!callout.checkVisibility(callout.baseMethodSpec, baseType))
 			return false; // don't generate illegal access.
 
 		CallinCalloutBinding calloutBinding;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/MethodMappingImplementor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/MethodMappingImplementor.java
index 2205a3b..8f54a35 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/MethodMappingImplementor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/MethodMappingImplementor.java
@@ -40,6 +40,7 @@
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
+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;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.MethodSpec;
@@ -47,12 +48,12 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
+import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.ReplaceResultReferenceVisitor;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstClone;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.RoleTypeCreator;
 
 /**
- * MIGRATION_STATE: complete.
  * moved here from package org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.resolve
  *
  * Generalize some functions of implementing callout and callin.
@@ -89,6 +90,13 @@
 			boolean                isFieldAccess,
 			boolean                hasResultArgument)
 	{
+		// prepare parameter mappings:
+		if (methodMapping.mappings != null) {
+			methodMapping.traverse(new ReplaceResultReferenceVisitor(methodMapping), methodMapping.scope.classScope());
+			if (methodMapping.isReplaceCallin())
+				((CallinMappingDeclaration)methodMapping).checkResultMapping();
+		}
+		
 	    Argument[]   wrapperMethodArguments = wrapperMethodDeclaration.arguments;
 	    Expression[] arguments;
 
@@ -321,7 +329,7 @@
 				} else {
 					// from role method:
 					TypeVariableBinding[] typeVariables = rrrBinding.typeVariables;
-					if (typeVariables != MethodBinding.NO_TYPE_VARIABLES) {
+					if (typeVariables != Binding.NO_TYPE_VARIABLES) {
 						typeParams= new TypeParameter[typeVariables.length];
 						for (int i = 0; i < typeVariables.length; i++)
 							typeParams[i]= gen.typeParameter(typeVariables[i]);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/ReplaceResultReferenceVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/ReplaceResultReferenceVisitor.java
new file mode 100644
index 0000000..9c7b4af
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/ReplaceResultReferenceVisitor.java
@@ -0,0 +1,89 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2010 GK Software AG.
+ *
+ * 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
+ * $Id$
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * 		Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ParameterMapping;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ResultReference;
+import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
+
+
+/**
+ * This visitor replaces SingleNameReference("result") in param mappings
+ * with ResultReferences, provided they are on the correct side of the binding token. 
+ *
+ * @author stephan
+ */
+public class ReplaceResultReferenceVisitor
+    extends StackTransformStatementsVisitor
+    implements IOTConstants
+{
+
+    private final AbstractMethodMappingDeclaration _methodMapping;
+    private int _bindingDirection    = 0; // while traversing a ParameterMapping record its direction here
+
+    public ReplaceResultReferenceVisitor(AbstractMethodMappingDeclaration mapping) {
+    	this._methodMapping = mapping;
+    }
+
+    public boolean visit(ParameterMapping mapping, BlockScope scope)
+    {
+        this._bindingDirection = mapping.direction;
+        return true;
+    }
+    public void endVisit(ParameterMapping mapping, BlockScope scope)
+    {
+        this._bindingDirection = 0;
+        super.endVisit(mapping, scope);
+    }
+    /**
+     * Translate "result" in the expression of a parameter mapping.
+     * Upgrade the SingleNameReference to a ResultReference.
+     */
+    public boolean visit(SingleNameReference ref, BlockScope scope)
+    {
+        if (CharOperation.equals(ref.token, IOTConstants.RESULT))
+        {
+            boolean isResultDir = false;
+            if (this._methodMapping.isCallin()) {
+                isResultDir = this._bindingDirection == TerminalTokens.TokenNameBINDOUT;
+                if (   !isResultDir
+                	&& 	((CallinMappingDeclaration)this._methodMapping).callinModifier
+					     == TerminalTokens.TokenNameafter)
+                {
+                	isResultDir = true;
+                }
+            } else
+                isResultDir = this._bindingDirection == TerminalTokens.TokenNameBINDIN;
+            if (isResultDir) {
+            	AstGenerator gen = new AstGenerator(ref.sourceStart, ref.sourceEnd);
+                ResultReference resultRef = gen.resultReference(ref, this._methodMapping);
+                enterExpression(ref, resultRef, ref);
+            } else {
+                scope.problemReporter().illegalDirectionForResult(ref, this._methodMapping.isCallout());
+                return false;
+            }
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TransformStatementsVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TransformStatementsVisitor.java
index 62ed397..ebf6c16 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TransformStatementsVisitor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/transformer/TransformStatementsVisitor.java
@@ -31,7 +31,6 @@
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
 import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
-import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.ast.ThisReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -39,16 +38,10 @@
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
-import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
 import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
-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.BaseReference;
-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.ParameterMapping;
-import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ResultReference;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
 import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CallinImplementorDyn;
@@ -64,9 +57,7 @@
  *
  * (1) Each tsuper(...) call -> this(..., markerArg)
  *     Works for constructor calls only.
- * (2) Withing parameter mappings:
- *     replace SingleNameReference("result") by a ResultReference.
- * (3) Adjust according to signature enhancing of callin methods:
+ * (2) Adjust according to signature enhancing of callin methods:
  *     - 'recursive' calls need more arguments
  *     - return expressions need to be generalized wrt their type.
  *
@@ -83,8 +74,6 @@
 {
 
     // -- fields and methods for scope management ---
-    private AbstractMethodMappingDeclaration _methodMapping = null;
-    private int _bindingDirection    = 0;
     private Stack<MethodDeclaration> _methodDeclarationStack = new Stack<MethodDeclaration>();
 
     /**
@@ -292,70 +281,6 @@
     	super.endVisit(methodDecl, scope);
     }
 
-    // === Follows: infrastructure for translating parameter mappings
-
-    public boolean visit(CalloutMappingDeclaration mapping, ClassScope scope)
-    {
-        this._methodMapping = mapping;
-        return true;
-    }
-    public void endVisit(CalloutMappingDeclaration mapping, ClassScope scope)
-    {
-        this._methodMapping = null;
-        super.endVisit(mapping, scope);
-    }
-
-    public boolean visit(CallinMappingDeclaration mapping, ClassScope scope)
-    {
-        this._methodMapping = mapping;
-        return true;
-    }
-    public void endVisit(CallinMappingDeclaration mapping, ClassScope scope)
-    {
-        this._methodMapping = null;
-        super.endVisit(mapping, scope);
-    }
-    public boolean visit(ParameterMapping mapping, BlockScope scope)
-    {
-        this._bindingDirection = mapping.direction;
-        return true;
-    }
-    public void endVisit(ParameterMapping mapping, BlockScope scope)
-    {
-        this._bindingDirection = 0;
-        super.endVisit(mapping, scope);
-    }
-    /**
-     * Translate "result" in the expression of a parameter mapping.
-     * Upgrade the SingleNameReference to a ResultReference.
-     */
-    public boolean visit(SingleNameReference ref, BlockScope scope)
-    {
-        if (this._methodMapping != null && CharOperation.equals(ref.token, IOTConstants.RESULT))
-        {
-            boolean isResultDir = false;
-            if (this._methodMapping.isCallin()) {
-                isResultDir = this._bindingDirection == TerminalTokens.TokenNameBINDOUT;
-                if (   !isResultDir
-                	&& 	((CallinMappingDeclaration)this._methodMapping).callinModifier
-					     == TerminalTokens.TokenNameafter)
-                {
-                	isResultDir = true;
-                }
-            } else
-                isResultDir = this._bindingDirection == TerminalTokens.TokenNameBINDIN;
-            if (isResultDir) {
-            	AstGenerator gen = new AstGenerator(ref.sourceStart, ref.sourceEnd);
-                ResultReference resultRef = gen.resultReference(ref, this._methodMapping);
-                enterExpression(ref, resultRef, ref);
-            } else {
-                scope.problemReporter().illegalDirectionForResult(ref, this._methodMapping.isCallout());
-                return false;
-            }
-        }
-        return true;
-    }
-
     /**
      * Cut traversal for types without a scope.
      */