Bug 571905 - [16] record - annotation not generated in .class file for
constructor and accessor

Change-Id: Ia141d61e2ede5941b7c952426ebd3112e592a156
Signed-off-by: Manoj Palat <manpalat@in.ibm.com>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
index 99d4c58..5048179 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
@@ -33,7 +33,7 @@
 	static {
 //		TESTS_NUMBERS = new int [] { 40 };
 //		TESTS_RANGE = new int[] { 1, -1 };
-//		TESTS_NAMES = new String[] { "testBug571765_001"};
+//		TESTS_NAMES = new String[] { "testBug571905"};
 	}
 
 	public static Class<?> testClass() {
@@ -8511,4 +8511,108 @@
 			"Syntax error on token \"record\", record expected\n" +
 	        "----------\n");
 }
+public void testBug571905_01() throws Exception {
+	runConformTest(
+		new String[] {
+			"X.java",
+			"import java.lang.annotation.*;\n" +
+			"record X( int @MyAnnot [] j) {\n" +
+			" public static void main(String[] args) {\n" +
+			"   System.out.println(\"helo\");\n" +
+			" }\n" +
+			"}\n" +
+			"@Target({ElementType.TYPE_USE})\n" +
+			"@Retention(RetentionPolicy.RUNTIME)\n" +
+			"@interface MyAnnot {}\n"
+		},
+	 "helo");
+	String expectedOutput = // constructor
+			"  \n" +
+			"  // Method descriptor #10 ([I)V\n" +
+			"  // Stack: 2, Locals: 2\n" +
+			"  X(int[] j);\n" +
+			"     0  aload_0 [this]\n" +
+			"     1  invokespecial java.lang.Record() [12]\n" +
+			"     4  aload_0 [this]\n" +
+			"     5  aload_1 [j]\n" +
+			"     6  putfield X.j : int[] [15]\n" +
+			"     9  return\n" +
+			"      Line numbers:\n" +
+			"        [pc: 0, line: 2]\n" +
+			"      Local variable table:\n" +
+			"        [pc: 0, pc: 10] local: this index: 0 type: X\n" +
+			"        [pc: 0, pc: 10] local: j index: 1 type: int[]\n" +
+			"      Method Parameters:\n" +
+			"        j\n" +
+			"    RuntimeVisibleTypeAnnotations: \n" +
+			"      #8 @MyAnnot(\n" +
+			"        target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+			"        method parameter index = 0\n" +
+			"      )\n";
+	RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "X.class", ClassFileBytesDisassembler.SYSTEM);
+	expectedOutput = // accessor
+			"  public int[] j();\n" +
+			"    0  aload_0 [this]\n" +
+			"    1  getfield X.j : int[] [15]\n" +
+			"    4  areturn\n" +
+			"      Line numbers:\n" +
+			"        [pc: 0, line: 2]\n" +
+			"    RuntimeVisibleTypeAnnotations: \n" +
+			"      #8 @MyAnnot(\n" +
+			"        target type = 0x14 METHOD_RETURN\n" +
+			"      )\n" ;
+	RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "X.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug571905_02() throws Exception {
+	runConformTest(
+		new String[] {
+			"X.java",
+			"import java.lang.annotation.*;\n" +
+			"record X( int @MyAnnot ... j) {\n" +
+			" public static void main(String[] args) {\n" +
+			"   System.out.println(\"helo\");\n" +
+			" }\n" +
+			"}\n" +
+			"@Target({ElementType.TYPE_USE})\n" +
+			"@Retention(RetentionPolicy.RUNTIME)\n" +
+			"@interface MyAnnot {}\n"
+		},
+	 "helo");
+	String expectedOutput = // constructor
+			"  \n" +
+			"  // Method descriptor #10 ([I)V\n" +
+			"  // Stack: 2, Locals: 2\n" +
+			"  X(int... j);\n" +
+			"     0  aload_0 [this]\n" +
+			"     1  invokespecial java.lang.Record() [12]\n" +
+			"     4  aload_0 [this]\n" +
+			"     5  aload_1 [j]\n" +
+			"     6  putfield X.j : int[] [15]\n" +
+			"     9  return\n" +
+			"      Line numbers:\n" +
+			"        [pc: 0, line: 2]\n" +
+			"      Local variable table:\n" +
+			"        [pc: 0, pc: 10] local: this index: 0 type: X\n" +
+			"        [pc: 0, pc: 10] local: j index: 1 type: int[]\n" +
+			"      Method Parameters:\n" +
+			"        j\n" +
+			"    RuntimeVisibleTypeAnnotations: \n" +
+			"      #8 @MyAnnot(\n" +
+			"        target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+			"        method parameter index = 0\n" +
+			"      )\n";
+	RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "X.class", ClassFileBytesDisassembler.SYSTEM);
+	expectedOutput = // accessor
+			"  public int[] j();\n" +
+			"    0  aload_0 [this]\n" +
+			"    1  getfield X.j : int[] [15]\n" +
+			"    4  areturn\n" +
+			"      Line numbers:\n" +
+			"        [pc: 0, line: 2]\n" +
+			"    RuntimeVisibleTypeAnnotations: \n" +
+			"      #8 @MyAnnot(\n" +
+			"        target type = 0x14 METHOD_RETURN\n" +
+			"      )\n" ;
+	RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "X.class", ClassFileBytesDisassembler.SYSTEM);
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index 502b6a7..a472ab8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -4124,16 +4124,21 @@
 						if (annotations != null) {
 							assert !methodBinding.isConstructor();
 							attributesNumber += generateRuntimeAnnotations(annotations, TagBits.AnnotationForMethod);
-							// Now type annotations
-							Supplier<List<AnnotationContext>> collector = () -> {
-								List<AnnotationContext> allTypeAnnotationContexts = new ArrayList<>();
+						}
+						if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) {
+							List<AnnotationContext> allTypeAnnotationContexts = new ArrayList<>();
+							if (annotations != null && (comp.bits & ASTNode.HasTypeAnnotations) != 0) {
 								comp.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN, allTypeAnnotationContexts);
-								return allTypeAnnotationContexts;
-							};
+							}
+							TypeReference compType = comp.type;
+							if (compType != null && ((compType.bits & ASTNode.HasTypeAnnotations) != 0)) {
+								compType.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN, allTypeAnnotationContexts);
+							}
+							int size = allTypeAnnotationContexts.size();
 							attributesNumber = completeRuntimeTypeAnnotations(attributesNumber,
-									comp,
-									(node) -> (comp.bits & ASTNode.HasTypeAnnotations) != 0,
-									collector);
+									null,
+									(node) -> size > 0,
+									() -> allTypeAnnotationContexts);
 						}
 					}
 				}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index 124ccb2..91a6287 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -367,6 +367,12 @@
 //	constructor.modifiers |= ClassFileConstants.AccPublic; // JLS 14 8.10.5
 	constructor.arguments = getArgumentsFromComponents(this.recordComponents);
 
+	for (int i = 0, max = constructor.arguments.length; i < max; i++) {
+		if ((constructor.arguments[i].bits & ASTNode.HasTypeAnnotations) != 0) {
+			constructor.bits |= ASTNode.HasTypeAnnotations;
+			break;
+		}
+	}
 	constructor.declarationSourceStart = constructor.sourceStart =
 			constructor.bodyStart = this.sourceStart;
 	constructor.declarationSourceEnd =