8202471: Resolves generic receiver type for types with generic signatures

Rafael Winterhalter rafael.wth at gmail.com
Tue Jul 23 18:56:23 UTC 2019


I integrated the tests into the jtreg test suite (it seems to work for me,
please double check since this is my first attempt).

I will now also post a CSR to the corresponding list and reference this
patch.

Here comes the inline patch including the jtreg tests:

Index: src/java.base/share/classes/java/lang/reflect/Constructor.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/java.base/share/classes/java/lang/reflect/Constructor.java
(revision 55752:8ae33203d600a7c9f9b2be9b31a0eb8197270ab1)
+++ src/java.base/share/classes/java/lang/reflect/Constructor.java
(revision 55752+:8ae33203d600+)
@@ -32,6 +32,7 @@
 import jdk.internal.vm.annotation.ForceInline;
 import sun.reflect.annotation.TypeAnnotation;
 import sun.reflect.annotation.TypeAnnotationParser;
+import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
 import sun.reflect.generics.repository.ConstructorRepository;
 import sun.reflect.generics.factory.CoreReflectionFactory;
 import sun.reflect.generics.factory.GenericsFactory;
@@ -653,6 +654,15 @@
             // static nested
             return null;
         }
+
+        TypeVariable<?>[] v = enclosingClass.getTypeParameters();
+        Type o = resolveOwner(enclosingClass);
+        Type t;
+        if (o != null || v.length > 0) {
+            t = ParameterizedTypeImpl.make(enclosingClass, v, o);
+        } else {
+            t = enclosingClass;
+        }

         // A Constructor for an inner class
         return
TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
@@ -660,7 +670,7 @@
                     getConstantPool(thisDeclClass),
                 this,
                 thisDeclClass,
-                enclosingClass,
+                t,
                 TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
     }
 }
Index: src/java.base/share/classes/java/lang/reflect/Executable.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/java.base/share/classes/java/lang/reflect/Executable.java (revision
55752:8ae33203d600a7c9f9b2be9b31a0eb8197270ab1)
+++ src/java.base/share/classes/java/lang/reflect/Executable.java (revision
55752+:8ae33203d600+)
@@ -38,6 +38,7 @@
 import sun.reflect.annotation.AnnotationSupport;
 import sun.reflect.annotation.TypeAnnotationParser;
 import sun.reflect.annotation.TypeAnnotation;
+import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
 import sun.reflect.generics.repository.ConstructorRepository;

 /**
@@ -687,14 +688,29 @@
     public AnnotatedType getAnnotatedReceiverType() {
         if (Modifier.isStatic(this.getModifiers()))
             return null;
+        Class<?> c = getDeclaringClass();
+        TypeVariable<?>[] v = c.getTypeParameters();
+        Type o = resolveOwner(c);
+        Type t;
+        if (o != null || v.length > 0) {
+            t = ParameterizedTypeImpl.make(c, v, o);
+        } else {
+            t = c;
+        }
         return
TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
-                SharedSecrets.getJavaLangAccess().
-                        getConstantPool(getDeclaringClass()),
+                SharedSecrets.getJavaLangAccess().getConstantPool(c),
                 this,
-                getDeclaringClass(),
-                getDeclaringClass(),
+                c,
+                t,
                 TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
     }
+
+    static Type resolveOwner(Class<?> t) {
+        if (Modifier.isStatic(t.getModifiers()) || !(t.isLocalClass() ||
t.isMemberClass() || t.isAnonymousClass()))
+            return null;
+        Class<?> d = t.getDeclaringClass();
+        return ParameterizedTypeImpl.make(d, d.getTypeParameters(),
resolveOwner(d));
+    }

     /**
      * Returns an array of {@code AnnotatedType} objects that represent
the use
Index: test/jdk/java/lang/reflect/Method/TestReceiverTypeOwner.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- test/jdk/java/lang/reflect/Method/TestReceiverTypeOwner.java (revision
55752+:8ae33203d600+)
+++ test/jdk/java/lang/reflect/Method/TestReceiverTypeOwner.java (revision
55752+:8ae33203d600+)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8202471
+ * @summary Make sure a method of a type enclosed by a parameterized type
is represented by a parameterized receiver type
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.*;
+import java.lang.reflect.AnnotatedParameterizedType;
+import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.Method;
+
+public class TestReceiverTypeOwner {
+
+    public static void main(String[] args) throws NoSuchMethodException {
+        Method method =
TestReceiverTypeOwner.Inner.class.getDeclaredMethod("m");
+        AnnotatedType receiverType = method.getAnnotatedReceiverType();
+        AnnotatedParameterizedType parameterizedType =
(AnnotatedParameterizedType) receiverType;
+        AnnotatedType owner = parameterizedType.getAnnotatedOwnerType();
+        Annotation[] annotations = owner.getAnnotations();
+        if (annotations.length != 1 || !(annotations[0] instanceof
TypeAnnotation)) {
+            throw new AssertionError();
+        }
+    }
+
+    class Inner {
+        void m(@TypeAnnotation TestReceiverTypeOwner.Inner this) { }
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.TYPE_USE)
+    @interface TypeAnnotation { }
+}
Index:
test/jdk/java/lang/reflect/Constructor/TestReceiverTypeParameterized.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
---
test/jdk/java/lang/reflect/Constructor/TestReceiverTypeParameterized.java
(revision 55752+:8ae33203d600+)
+++
test/jdk/java/lang/reflect/Constructor/TestReceiverTypeParameterized.java
(revision 55752+:8ae33203d600+)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8202471
+ * @summary Make sure a method of a parameterized type is represented by a
parameterized receiver type
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.*;
+import java.lang.reflect.AnnotatedParameterizedType;
+import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.Constructor;
+
+public class TestReceiverTypeParameterized<T> {
+
+    public static void main(String[] args) throws NoSuchMethodException {
+        Constructor<?> constructor =
TestReceiverTypeParameterized.Inner.class.getDeclaredConstructor(TestReceiverTypeParameterized.class);
+        AnnotatedType receiverType =
constructor.getAnnotatedReceiverType();
+        AnnotatedParameterizedType parameterizedType =
(AnnotatedParameterizedType) receiverType;
+        AnnotatedType[] arguments =
parameterizedType.getAnnotatedActualTypeArguments();
+        Annotation[] annotations = arguments[0].getAnnotations();
+        if (annotations.length != 1 || !(annotations[0] instanceof
TypeAnnotation)) {
+            throw new AssertionError();
+        }
+    }
+
+    class Inner {
+        Inner(TestReceiverTypeParameterized<@TypeAnnotation T>
TestReceiverTypeParameterized.this) { }
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.TYPE_USE)
+    @interface TypeAnnotation { }
+}
Index: test/jdk/java/lang/reflect/Method/TestReceiverTypeParameterized.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- test/jdk/java/lang/reflect/Method/TestReceiverTypeParameterized.java
(revision 55752+:8ae33203d600+)
+++ test/jdk/java/lang/reflect/Method/TestReceiverTypeParameterized.java
(revision 55752+:8ae33203d600+)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8202471
+ * @summary Make sure a method of a parameterized type is represented by a
parameterized receiver type
+ */
+
+import java.lang.annotation.Target;
+import java.lang.annotation.*;
+import java.lang.reflect.AnnotatedParameterizedType;
+import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.Method;
+
+public class TestReceiverTypeParameterized<T> {
+
+    void m(TestReceiverTypeParameterized<@TypeAnnotation T> this) { }
+
+    public static void main(String[] args) throws NoSuchMethodException {
+        Method method =
TestReceiverTypeParameterized.class.getDeclaredMethod("m");
+        AnnotatedType receiverType = method.getAnnotatedReceiverType();
+        AnnotatedParameterizedType parameterizedType =
(AnnotatedParameterizedType) receiverType;
+        AnnotatedType[] arguments =
parameterizedType.getAnnotatedActualTypeArguments();
+        Annotation[] annotations = arguments[0].getAnnotations();
+        if (annotations.length != 1 || !(annotations[0] instanceof
TypeAnnotation)) {
+            throw new AssertionError();
+        }
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.TYPE_USE)
+    @interface TypeAnnotation { }
+}


More information about the core-libs-dev mailing list