Test & fix for Bug 355259 - Cannot declare role-typed field in an
enum-as-team-member
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index a3c2f5d..ec46137 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -161,6 +161,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.TypeModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance;
+import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance.RoleConstructorCall;
 import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.MethodSignatureEnhancer;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstEdit;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
@@ -3494,10 +3495,14 @@
 			break;
 //{ObjectTeams: for roles we detect this earlier than JDT
 		case ProblemReasons.NonStaticReferenceInConstructorInvocation:
+		case ProblemReasons.NonStaticReferenceInStaticContext:
 			if (   targetConstructor.declaringClass != null
 				&& targetConstructor.declaringClass.isRole())
 			{
-				noSuchEnclosingInstance(targetConstructor.declaringClass.enclosingType(), statement, true);
+				if (statement instanceof CopyInheritance.RoleConstructorCall)
+					statement = ((RoleConstructorCall)statement).allocationOrig;
+				noSuchEnclosingInstance(targetConstructor.declaringClass.enclosingType(), statement, 
+						targetConstructor.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation);
 				return;
 			}
 			break;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
index 61ec1ac..63af192 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
@@ -66,6 +66,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.MethodVerifier;
 import org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
+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;
@@ -91,6 +92,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config.NotConfiguredException;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.Lifting;
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.AnchorMapping;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticBaseCallSurrogate;
@@ -1613,6 +1615,63 @@
 			}
 		}
 	}
+	
+	public static class RoleConstructorCall extends MessageSend {
+    	public AllocationExpression allocationOrig;
+
+		public RoleConstructorCall(AllocationExpression allocationExpr) {
+			this.allocationOrig = allocationExpr;
+		}
+
+		// specialized MessageSend to perform analysis for unsafe role instantiation:
+    	@Override
+    	public TypeBinding resolveType(BlockScope blockScope) {
+    		TypeBinding result = super.resolveType(blockScope);
+    		ReferenceBinding roleType = (ReferenceBinding)this.resolvedType;
+    		if (roleType != null && roleType.isValidBinding()) {
+        		MethodBinding ctor = roleType.getExactConstructor(this.binding.parameters);
+        		if (Lifting.isLiftToConstructor(ctor, roleType)) // implies role is bound
+        		{
+					if (this.arguments != null && this.arguments.length > 0) {
+						Expression currentArg = this.arguments[0];
+						while (currentArg instanceof CastExpression)
+							currentArg = ((CastExpression)currentArg).expression; // unwrap
+						if (   (currentArg instanceof AllocationExpression)
+							|| (   (currentArg instanceof MessageSend)
+								 && isCreator(((MessageSend)currentArg).binding)))
+						{
+							// need to check if arg is compatible without lowering
+							TypeBinding allocType = currentArg.resolvedType;
+							Config confBak = Config.createOrResetConfig(this);
+							try {
+								if (   allocType.isCompatibleWith(roleType.baseclass())
+									&& !Config.getLoweringRequired()) // TODO(SH): could potentially ask the expression if conversions were involved?
+									return result; // we're clean
+							} finally {
+								Config.removeOrRestore(confBak, this);
+							}
+						}
+						blockScope.problemReporter().liftCtorArgNotAllocation(ctor, this, roleType.baseclass());
+						this.binding.roleCreatorRequiringRuntimeCheck = true;
+					}
+        		}
+    		}
+    		return result;
+    	}
+    	@Override
+    	protected TypeBinding afterMethodLookup(Scope scope, AnchorMapping anchorMapping, TypeBinding[] argumentTypes,
+    			TypeBinding returnType) {
+    		this.allocationOrig.binding = this.binding; // secure this for error reporting
+    		if (this.binding instanceof ProblemMethodBinding)
+    			this.allocationOrig.binding = ((ProblemMethodBinding)this.binding).closestMatch;
+    		if (this.allocationOrig.binding != null) {
+    			MethodModel model = this.allocationOrig.binding.model;
+    			if (model != null && model._srcCtor != null)
+    				this.allocationOrig.binding = model._srcCtor;
+    		}
+    		return super.afterMethodLookup(scope, anchorMapping, argumentTypes, returnType);
+    	}
+	}
     /**
      * Create an invocation of a creation method, which will replace a given
      * allocation expression, i.e.,
@@ -1674,43 +1733,7 @@
         } else {
         	receiver = ThisReference.implicitThis();
         }
-        MessageSend message = new MessageSend() {
-        	// specialized MessageSend to perform analysis for unsafe role instantiation:
-        	@Override
-        	public TypeBinding resolveType(BlockScope blockScope) {
-        		TypeBinding result = super.resolveType(blockScope);
-        		ReferenceBinding roleType = (ReferenceBinding)this.resolvedType;
-        		if (roleType != null && roleType.isValidBinding()) {
-	        		MethodBinding ctor = roleType.getExactConstructor(this.binding.parameters);
-	        		if (Lifting.isLiftToConstructor(ctor, roleType)) // implies role is bound
-	        		{
-						if (this.arguments != null && this.arguments.length > 0) {
-							Expression currentArg = this.arguments[0];
-							while (currentArg instanceof CastExpression)
-								currentArg = ((CastExpression)currentArg).expression; // unwrap
-							if (   (currentArg instanceof AllocationExpression)
-								|| (   (currentArg instanceof MessageSend)
-									 && isCreator(((MessageSend)currentArg).binding)))
-							{
-								// need to check if arg is compatible without lowering
-								TypeBinding allocType = currentArg.resolvedType;
-								Config confBak = Config.createOrResetConfig(this);
-								try {
-									if (   allocType.isCompatibleWith(roleType.baseclass())
-										&& !Config.getLoweringRequired()) // TODO(SH): could potentially ask the expression if conversions were involved?
-										return result; // we're clean
-								} finally {
-									Config.removeOrRestore(confBak, this);
-								}
-							}
-							blockScope.problemReporter().liftCtorArgNotAllocation(ctor, this, roleType.baseclass());
-							this.binding.roleCreatorRequiringRuntimeCheck = true;
-						}
-	        		}
-        		}
-        		return result;
-        	}
-        };
+        MessageSend message = new RoleConstructorCall(allocationExpr);
         gen.setPos(message);
         message.nameSourcePosition = gen.pos;
         message.selector = selector;
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/Java5.java b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/Java5.java
index 0a402d1..23bb407 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/Java5.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/Java5.java
@@ -5041,6 +5041,32 @@
             null/*requestor*/);
     }
 
+    // An enum-in-a-team tries to refer to a role
+    // Bug 355259 - Cannot declare role-typed field in an enum-as-team-member
+    public void testA120_enumInTeam5() {
+    	runConformTest(
+    		new String[] {
+    	"TeamA120eit5.java",
+	    		"public team class TeamA120eit5 {\n" +
+	    		"   protected class R {}\n" +
+	    		"   protected enum Values {\n" +
+	    		"       V1, V2;\n" +
+	    		"       public R r = new R();\n" +
+	    		"   }\n" +
+	    		"	public static void main(String[] args) {\n" +
+	    		"		for (Values v : Values.values())\n" +
+	    		"			System.out.print(v);\n" +
+	    		"	}\n" +
+	    		"}"
+    		},
+    		"----------\n" + 
+			"1. ERROR in TeamA120eit5.java (at line 5)\n" + 
+			"	public R r = new R();\n" + 
+			"	             ^^^^^^^\n" + 
+			"No enclosing instance of type TeamA120eit5 is accessible. Must qualify the allocation with an enclosing instance of type TeamA120eit5 (e.g. x.new A() where x is an instance of TeamA120eit5).\n" + 
+			"----------\n");
+    }
+
     public void testA121_genericNestedTeam1() {
     	runConformTest(
     		new String[] {