Bug 437767 - [java8][null] semantically integrate null type annotations
with anchored role types
- combination of type anchor and type annotation
- support RoleTypeBinding with type annotations
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
index 7556278..d9e4fd1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
@@ -244,8 +244,12 @@
 								 this.typeArguments = new TypeReference[len], 0, len); // FIXME(SH): reducing this array conflicts with loop condition
 	
 				// note: handling of arrays differs for role and regular types
-				if (len == 0)
+				if (len == 0) {
+					resolveAnnotations(scope, location);
+					if (checkBounds)
+						checkNullConstraints(scope, this.typeArguments);
 					return this.resolvedType; // we're done
+				}
 
 				// proceed with a word of warning:
 				scope.problemReporter().experimentalFeature(this, "Implementation for mixed type and value parameters is experimental.");
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/RoleTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/RoleTypeBinding.java
index 7289081..c914805 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/RoleTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/lookup/RoleTypeBinding.java
@@ -235,6 +235,11 @@
 		// record as known role type at teamAnchor and in our own cache
         registerAnchor();
     }
+    
+    public TypeBinding clone(TypeBinding outerType) {
+    	RoleTypeBinding clone = new RoleTypeBinding(this.type, typeArguments(), this._teamAnchor, (ReferenceBinding) outerType, this.environment);
+    	return clone;
+    }
 
     // hook of maybeInstantiate
     TypeBinding forAnchor(ITeamAnchor anchor, int dimensions) {
@@ -956,20 +961,18 @@
     	return super.attributeName();
     }
     public String toString() {
-    	String anchorStr = ""; //$NON-NLS-1$
+    	StringBuilder sb = new StringBuilder();
+    	sb.append(annotatedDebugName());
+    	sb.append('<').append('@');
     	ITeamAnchor[] bestNamePath = this._teamAnchor.getBestNamePath(false);
 		for (int i = 0; i < bestNamePath.length; i++) {
     		if (i>0)
-    			anchorStr += '.';
-			anchorStr += new String(bestNamePath[i].readableName());
+    			sb.append('.');
+			sb.append(bestNamePath[i].readableName());
 		}
-    	String staticTeam = ""; //$NON-NLS-1$
-    	if (!(this._teamAnchor instanceof TThisBinding))
-    		staticTeam = '['+new String(this._staticallyKnownTeam.sourceName())+']';
-        return
-            anchorStr
-            +staticTeam
-            +'.'
-            +new String(sourceName());
+		if (!(this._teamAnchor instanceof TThisBinding))
+			sb.append('[').append(this._staticallyKnownTeam.sourceName()).append(']');
+		sb.append('>');
+		return sb.toString();
     }
 }
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/Java8.java b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/Java8.java
index 8a43d15..ab5cd0e 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/Java8.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/Java8.java
@@ -264,7 +264,7 @@
 			"	public class R {}\n" +
 			"}\n",
 		"C1.java",
-			"public abstract class C1 {\n" +
+			"public abstract team class C1 {\n" +
 			"	final T1 t = new T1();\n" +
 			"	abstract void test1(final C1 a, R<@a.t> c);\n" +
 			"	abstract void test2(final Object o, C2<java.lang.@p1.Marker Object> c);\n" + // bug, should be java.lang. @p1.Marker Object
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/OTNullTypeAnnotationTest.java b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/OTNullTypeAnnotationTest.java
index 35c7a58..b4dd521 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/OTNullTypeAnnotationTest.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/other/OTNullTypeAnnotationTest.java
@@ -31,7 +31,7 @@
 	// Static initializer to specify tests subset using TESTS_* static variables
 	// All specified tests which do not belong to the class are skipped...
 	static {
-//			TESTS_NAMES = new String[] { "testLiftingType2" };
+//			TESTS_NAMES = new String[] { "testExplicitTeamAnchor1" };
 //			TESTS_NUMBERS = new int[] { 561 };
 //			TESTS_RANGE = new int[] { 1, 2049 };
 	}
@@ -102,6 +102,35 @@
 			"----------\n");
 	}
 
+	public void testExplicitTeamAnchor1() {
+		if (this.weavingScheme == WeavingScheme.OTRE) return;
+		runNegativeTestWithLibs(
+			new String[] {
+				"Main.java",
+				"import org.eclipse.jdt.annotation.*;\n" +
+				"import java.util.*;\n" +
+				"public class Main {\n" +
+				"	void test(final MyTeam t, List<@Nullable MyRole<@t>> someRoles) {\n" +
+				"		@NonNull MyRole<@t> role = someRoles.get(0);\n" + 
+				"		role.print();\n" + 
+				"	}\n" +
+				"}\n",
+				"MyTeam.java",
+				"public team class MyTeam {\n" +
+				"	public class MyRole {\n" +
+				"		public void print() {}\n" +
+				"	}\n" +
+				"}\n"
+			},
+			getCompilerOptions(),
+			"----------\n" + 
+			"1. ERROR in Main.java (at line 5)\n" + 
+			"	@NonNull MyRole<@t> role = someRoles.get(0);\n" + 
+			"	                           ^^^^^^^^^^^^^^^^\n" + 
+			"Null type mismatch (type annotations): required \'MyTeam.@NonNull MyRole\' but this expression has type \'MyTeam.@Nullable MyRole\'\n" + 
+			"----------\n");
+	}
+
 	public void testLiftingType1() {
 		if (this.weavingScheme == WeavingScheme.OTRE) return;
 		runNegativeTestWithLibs(