8219147: Javadoc should expose covariant return type overrides
authorjjg
Tue, 28 May 2019 11:21:02 -0700
changeset 55064 cb35ce1770a0
parent 55061 d1fa0f8d8c9a
child 55065 103f9068c39f
8219147: Javadoc should expose covariant return type overrides Reviewed-by: hannesw
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java
test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java
test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg6/Base.java
test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg6/Sub.java
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java	Tue May 28 09:56:47 2019 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java	Tue May 28 11:21:02 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -29,6 +29,7 @@
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeKind;
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.Elements;
 import javax.lang.model.util.SimpleElementVisitor9;
@@ -564,7 +565,6 @@
     boolean allowInheritedMethods(ExecutableElement inheritedMethod,
                                   Map<ExecutableElement, List<ExecutableElement>> inheritedOverriddenTable,
                                   LocalMemberTable lmt) {
-
         if (!isInherited(inheritedMethod))
             return false;
 
@@ -598,7 +598,8 @@
 
         // Check the local methods in this type.
         List<Element> lMethods = lmt.getMembers(inheritedMethod, Kind.METHODS);
-        for (Element lMethod : lMethods) {
+        for (Element le : lMethods) {
+            ExecutableElement lMethod = (ExecutableElement) le;
             // Ignore private methods or those methods marked with
             // a "hidden" tag.
             if (utils.isPrivate(lMethod))
@@ -611,18 +612,26 @@
             }
 
             // Check for overriding methods.
-            if (elementUtils.overrides((ExecutableElement)lMethod, inheritedMethod,
+            if (elementUtils.overrides(lMethod, inheritedMethod,
                     utils.getEnclosingTypeElement(lMethod))) {
 
                 // Disallow package-private super methods to leak in
                 TypeElement encl = utils.getEnclosingTypeElement(inheritedMethod);
                 if (isUndocumentedEnclosure(encl)) {
-                    overriddenMethodTable.computeIfAbsent((ExecutableElement)lMethod,
+                    overriddenMethodTable.computeIfAbsent(lMethod,
                             l -> new OverridingMethodInfo(inheritedMethod, false));
                     return false;
                 }
-                boolean simpleOverride = utils.isSimpleOverride((ExecutableElement)lMethod);
-                overriddenMethodTable.computeIfAbsent((ExecutableElement)lMethod,
+
+                TypeMirror inheritedMethodReturn = inheritedMethod.getReturnType();
+                TypeMirror lMethodReturn = lMethod.getReturnType();
+                boolean covariantReturn =
+                        lMethodReturn.getKind() == TypeKind.DECLARED
+                        && inheritedMethodReturn.getKind() == TypeKind.DECLARED
+                        && !utils.typeUtils.isSameType(lMethodReturn, inheritedMethodReturn)
+                        && utils.typeUtils.isSubtype(lMethodReturn, inheritedMethodReturn);
+                boolean simpleOverride = covariantReturn ? false : utils.isSimpleOverride(lMethod);
+                overriddenMethodTable.computeIfAbsent(lMethod,
                         l -> new OverridingMethodInfo(inheritedMethod, simpleOverride));
                 return simpleOverride;
             }
@@ -987,5 +996,10 @@
             this.overrider = overrider;
             this.simpleOverride = simpleOverride;
         }
+
+        @Override
+        public String toString() {
+            return "OverridingMethodInfo[" + overrider + ",simple:" + simpleOverride + "]";
+        }
     }
 }
--- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java	Tue May 28 09:56:47 2019 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java	Tue May 28 11:21:02 2019 -0700
@@ -72,7 +72,7 @@
                 "-javafx",
                 "--disable-javafx-strict-checks",
                 "--override-methods=summary",
-                "pkg5");
+                "pkg5", "pkg6");
 
         checkExit(Exit.OK);
 
@@ -256,5 +256,32 @@
                 "Returns an array containing the constants of this enum type, in\n" +
                         "the order they are declared."
         );
+
+        // Check methods with covariant return types
+        // Only m2 should be shown in summary; m1 and m3 should listed as declared in Base
+        checkOutput("pkg6/Sub.html", true,
+                "<table aria-labelledby=\"t0\">\n"
+                + "<thead>\n"
+                + "<tr>\n"
+                + "<th class=\"colFirst\" scope=\"col\">Modifier and Type</th>\n"
+                + "<th class=\"colSecond\" scope=\"col\">Method</th>\n"
+                + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
+                + "</tr>\n"
+                + "</thead>\n"
+                + "<tbody>\n"
+                + "<tr class=\"altColor\" id=\"i0\">\n"
+                + "<td class=\"colFirst\"><code>java.lang.String</code></td>\n"
+                + "<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\"><a href=\"#m2()\">m2</a></span>()</code></th>\n"
+                + "<td class=\"colLast\">\n"
+                + "<div class=\"block\">This is Base::m2.</div>\n"
+                + "</td>\n"
+                + "</tr>\n"
+                + "</tbody>\n"
+                + "</table>\n",
+                "<div class=\"inheritedList\">\n"
+                + "<h3>Methods declared in class&nbsp;pkg6.<a href=\"Base.html\" title=\"class in pkg6\">Base</a></h3>\n"
+                + "<a id=\"methods.inherited.from.class.pkg6.Base\">\n"
+                + "<!--   -->\n"
+                + "</a><code><a href=\"Base.html#m1()\">m1</a>, <a href=\"Base.html#m3()\">m3</a></code></div>\n");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg6/Base.java	Tue May 28 11:21:02 2019 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package pkg6;
+
+public class Base<T> {
+    /**
+     *  This is Base::m1.
+     *  @return something
+     * */
+    public Object m1() { }
+    /**
+     *  This is Base::m2.
+     *  @return something
+     * */
+    public Object m2() { }
+
+    /**
+     *  This is Base::m3.
+     *  @return something
+     * */
+    public T m3() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg6/Sub.java	Tue May 28 11:21:02 2019 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package pkg6;
+
+public class Sub<T> extends Base<T> {
+    // simple override
+    @Override
+    public Object m1() { }
+    // covariant override
+    @Override
+    public String m2() { }
+    // not a covariant override
+    @Override
+    public T m3() { }
+}
+