diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index 9bc64af8fb0..e0c83f01d9c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1093,22 +1093,8 @@ public class Utils { * be found. */ public TypeMirror getFirstVisibleSuperClass(TypeMirror type) { - return getFirstVisibleSuperClass(asTypeElement(type)); - } - - - /** - * Given a class, return the closest visible superclass. - * - * @param te the TypeElement to be interrogated - * @return the closest visible superclass. Return null if it cannot - * be found. - */ - public TypeMirror getFirstVisibleSuperClass(TypeElement te) { - TypeMirror superType = te.getSuperclass(); - if (isNoType(superType)) { - superType = getObjectType(); - } + List superTypes = typeUtils.directSupertypes(type); + TypeMirror superType = superTypes.isEmpty() ? getObjectType() : superTypes.get(0); TypeElement superClass = asTypeElement(superType); // skip "hidden" classes while ((superClass != null && hasHiddenTag(superClass)) @@ -1122,12 +1108,24 @@ public class Utils { superType = supersuperType; superClass = supersuperClass; } - if (typeUtils.isSameType(te.asType(), superType)) { + if (typeUtils.isSameType(type, superType)) { return null; } return superType; } + + /** + * Given a class, return the closest visible superclass. + * + * @param te the TypeElement to be interrogated + * @return the closest visible superclass. Return null if it cannot + * be found. + */ + public TypeMirror getFirstVisibleSuperClass(TypeElement te) { + return getFirstVisibleSuperClass(te.asType()); + } + /** * Returns the name of the kind of a type element (Class, Interface, etc.). * diff --git a/test/langtools/jdk/javadoc/doclet/testInheritance/TestInheritance.java b/test/langtools/jdk/javadoc/doclet/testInheritance/TestInheritance.java new file mode 100644 index 00000000000..fc08c53467c --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testInheritance/TestInheritance.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023, 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 8302324 + * @summary Inheritance tree does not show correct type parameters/arguments + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @run main TestInheritance + */ + +import java.nio.file.Path; + +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +public class TestInheritance extends JavadocTester { + + public static void main(String... args) throws Exception { + var test = new TestInheritance(); + test.runTests(); + } + + @Test + public void testInheritanceGeneric(Path base) throws Exception { + Path src = base.resolve("src"); + new ToolBox().writeJavaFiles(src, """ + package pkg; + /** + * Base class + * @param param M + * @param param N + */ + public class A { private A() { } } + """, + """ + package pkg; + /** + * First subclass + * @param param O + * @param

param P + */ + public class B extends A { private B() { } } + """, + """ + package pkg; + /** + * Second subclass + * @param param Q + */ + public class C extends B { private C() { } } + """, + """ + package pkg; + /** + * Second subclass + * @param param R + * @param param S + */ + public class D extends B { private D() { } } + """); + javadoc("-d", base.resolve("docs").toString(), + "-sourcepath", src.toString(), + "--no-platform-links", + "pkg"); + checkExit(Exit.OK); + checkOrder("pkg/A.html", """ +

java.lang.Object +
pkg.A<M,N>
"""); + checkOrder("pkg/B.html", """ +
java.lang.Object +
pkg.A<O,P> +
pkg.B<O,P>
"""); + checkOrder("pkg/C.html", """ +
java.lang.Object +
pkg.A<java.lang.String,Q> +
pkg.B<java.lang.String,Q> +
pkg.C<Q>
"""); + checkOrder("pkg/D.html", """ +
java.lang.Object +
pkg.A<S,B> +
pkg.B<S,B> +
pkg.D<R,S>
"""); + } +}