8323698: Class use page does not include extends/implements type arguments

Reviewed-by: prappo, hannesw
This commit is contained in:
Chen Liang 2024-02-26 12:10:58 +00:00 committed by Pavel Rappo
parent f32f574004
commit 3a00fc732a
4 changed files with 145 additions and 12 deletions

View File

@ -60,6 +60,9 @@ public class ClassUseWriter extends SubWriterHolderWriter {
final TypeElement typeElement;
Set<PackageElement> pkgToPackageAnnotations = null;
final Map<PackageElement, List<Element>> pkgToClassTypeParameter;
final Map<PackageElement, List<Element>> pkgToSubclassTypeParameter;
final Map<PackageElement, List<Element>> pkgToSubinterfaceTypeParameter;
final Map<PackageElement, List<Element>> pkgToImplementsTypeParameter;
final Map<PackageElement, List<Element>> pkgToClassAnnotations;
final Map<PackageElement, List<Element>> pkgToMethodTypeParameter;
final Map<PackageElement, List<Element>> pkgToMethodArgTypeParameter;
@ -105,6 +108,9 @@ public class ClassUseWriter extends SubWriterHolderWriter {
configuration.currentTypeElement = typeElement;
this.pkgSet = new TreeSet<>(comparators.packageComparator());
this.pkgToClassTypeParameter = pkgDivide(mapper.classToClassTypeParam);
this.pkgToSubclassTypeParameter = pkgDivide(mapper.classToSubclassTypeParam);
this.pkgToSubinterfaceTypeParameter = pkgDivide(mapper.classToSubinterfaceTypeParam);
this.pkgToImplementsTypeParameter = pkgDivide(mapper.classToImplementsTypeParam);
this.pkgToClassAnnotations = pkgDivide(mapper.classToClassAnnotations);
this.pkgToMethodTypeParameter = pkgDivide(mapper.classToMethodTypeParam);
this.pkgToMethodArgTypeParameter = pkgDivide(mapper.classToMethodArgTypeParam);
@ -338,6 +344,15 @@ public class ClassUseWriter extends SubWriterHolderWriter {
classSubWriter.addUseInfo(pkgToImplementingClass.get(pkg),
contents.getContent("doclet.ClassUse_ImplementingClass", classLink,
pkgLink), content);
classSubWriter.addUseInfo(pkgToSubclassTypeParameter.get(pkg),
contents.getContent("doclet.ClassUse_SubclassTypeParameter", classLink,
pkgLink), content);
classSubWriter.addUseInfo(pkgToSubinterfaceTypeParameter.get(pkg),
contents.getContent("doclet.ClassUse_SubinterfaceTypeParameter", classLink,
pkgLink), content);
classSubWriter.addUseInfo(pkgToImplementsTypeParameter.get(pkg),
contents.getContent("doclet.ClassUse_ImplementsTypeParameter", classLink,
pkgLink), content);
fieldSubWriter.addUseInfo(pkgToField.get(pkg),
contents.getContent("doclet.ClassUse_Field", classLink,
pkgLink), content);

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2010, 2024, 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
@ -277,12 +277,14 @@ doclet.help.other_files.body=\
doclet.help.use.head=\
Use
doclet.help.use.body=\
Each documented package, class and interface has its own Use page. This page describes what \
packages, classes, methods, constructors and fields use any part of the given class or \
package. Given a class or interface A, its Use page includes subclasses of A, fields declared \
as A, methods that return A, and methods and constructors with parameters of type A. \
You can access this page by first going to the package, class or interface, then clicking on \
the USE link in the navigation bar.
Each documented package, class or interface has its own Use page, which lists \
packages, classes, interfaces, methods, constructors and fields that use any \
part of that package, class or interface. Given a class or interface A, its \
Use page includes subclasses or subinterfaces of A, fields declared as A, \
methods that return A, methods and constructors with parameters of type A, \
and subclasses or subinterfaces with parameters of type A. You can access \
this page by first going to the package, class or interface, then clicking \
on the USE link in the navigation bar.
doclet.help.tree.head=\
Tree (Class Hierarchy)
# 0: link to main Class Hierarchy page; 1: java.lang.Object
@ -380,6 +382,9 @@ doclet.ClassUse_Classes.in.0.used.by.1=Classes in {0} used by {1}
doclet.ClassUse_PackageAnnotation=Packages with annotations of type {0}
doclet.ClassUse_Annotation=Classes in {1} with annotations of type {0}
doclet.ClassUse_TypeParameter=Classes in {1} with type parameters of type {0}
doclet.ClassUse_SubclassTypeParameter=Subclasses with type arguments of type {0} in {1}
doclet.ClassUse_SubinterfaceTypeParameter=Subinterfaces with type arguments of type {0} in {1}
doclet.ClassUse_ImplementsTypeParameter=Classes in {1} that implement interfaces with type arguments of type {0}
doclet.ClassUse_MethodTypeParameter=Methods in {1} with type parameters of type {0}
doclet.ClassUse_FieldTypeParameter=Fields in {1} with type parameters of type {0}
doclet.ClassUse_FieldAnnotations=Fields in {1} with annotations of type {0}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, 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
@ -92,7 +92,22 @@ public class ClassUseMapper {
/**
* Mapping of TypeElements to list of TypeElements which implement this interface.
*/
public Map<TypeElement, List<TypeElement>> classToImplementingClass = new HashMap<>();
public final Map<TypeElement, List<TypeElement>> classToImplementingClass = new HashMap<>();
/**
* Mapping of TypeElements to list of TypeElements which use them in superclass type parameters.
*/
public final Map<TypeElement, List<TypeElement>> classToSubclassTypeParam = new HashMap<>();
/**
* Mapping of TypeElements to list of TypeElements which use them in superinterface type parameters.
*/
public final Map<TypeElement, List<TypeElement>> classToSubinterfaceTypeParam = new HashMap<>();
/**
* Mapping of TypeElements to list of TypeElements which use them in implemented interface type parameters.
*/
public final Map<TypeElement, List<TypeElement>> classToImplementsTypeParam = new HashMap<>();
/**
* Mapping of TypeElements to list of VariableElements declared as that class.
@ -214,6 +229,18 @@ public class ClassUseMapper {
PackageElement pkg = elementUtils.getPackageOf(aClass);
mapAnnotations(classToPackageAnnotations, pkg, pkg);
mapTypeParameters(classToClassTypeParam, aClass, aClass);
mapTypeParameters(classToSubclassTypeParam, aClass.getSuperclass(), aClass);
if (utils.isInterface(aClass)) {
for (var superinterface : aClass.getInterfaces()) {
mapTypeParameters(classToSubinterfaceTypeParam, superinterface, aClass);
}
} else {
for (var superinterface : aClass.getInterfaces()) {
mapTypeParameters(classToImplementsTypeParam, superinterface, aClass);
}
}
mapAnnotations(classToClassAnnotations, aClass, aClass);
VisibleMemberTable vmt = configuration.getVisibleMemberTable(aClass);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2024, 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
@ -24,15 +24,20 @@
/*
* @test
* @bug 4496290 4985072 7006178 7068595 8016328 8050031 8048351 8081854 8071982 8162363 8175200 8186332
* 8182765 8196202 8202626 8261976
* 8182765 8196202 8202626 8261976 8323698
* @summary A simple test to ensure class-use files are correct.
* @library ../../lib
* @library /tools/lib ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
* @build javadoc.tester.*
* @run main TestUseOption
*/
import javadoc.tester.JavadocTester;
import toolbox.ToolBox;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class TestUseOption extends JavadocTester {
@ -41,6 +46,8 @@ public class TestUseOption extends JavadocTester {
tester.runTests();
}
private final ToolBox tb = new ToolBox();
@Test
public void test1() {
javadoc("-d", "out-1",
@ -191,4 +198,83 @@ public class TestUseOption extends JavadocTester {
"""
<a href="../C1.html#%3Cinit%3E(unique.UseMe,unique.UseMe)" class="member-name-link">""");
}
@Test
public void testSuperclassAndInterfaceTypeArgument(Path base) throws IOException {
Path src = base.resolve("src");
Files.createDirectories(src);
tb.writeJavaFiles(src,
"""
public class One {}
""",
"""
import java.util.*;
public class Two extends ArrayList<One> implements Comparator<One> {
}
""",
"""
import java.util.*;
public interface Three extends Comparator<One> {
}
""");
javadoc(
"-use",
"-d", base.resolve("out").toString(),
src.resolve("One.java").toString(),
src.resolve("Two.java").toString(),
src.resolve("Three.java").toString()
);
checkExit(Exit.OK);
checkOrder("class-use/One.html",
"""
<div class="caption"><span>Subclasses with type arguments of \
type <a href="../One.html" title="class in Unnamed Package">One</a> \
in <a href="../package-summary.html">Unnamed Package</a></span></div>
""",
"""
<div class="summary-table three-column-summary">
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Class</div>
<div class="table-header col-last">Description</div>
<div class="col-first even-row-color"><code>class&nbsp;</code></div>
<div class="col-second even-row-color"><code><a href="../Two.html" class="type-name-link" \
title="class in Unnamed Package">Two</a></code></div>
<div class="col-last even-row-color">&nbsp;</div>
</div>
""",
"""
<div class="caption"><span>Subinterfaces with type arguments of \
type <a href="../One.html" title="class in Unnamed Package">One</a> \
in <a href="../package-summary.html">Unnamed Package</a></span></div>
""",
"""
<div class="summary-table three-column-summary">
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Interface</div>
<div class="table-header col-last">Description</div>
<div class="col-first even-row-color"><code>interface&nbsp;</code></div>
<div class="col-second even-row-color"><code><a href="../Three.html" class="type-name-link" title="interface in Unnamed Package">Three</a></code></div>
<div class="col-last even-row-color">&nbsp;</div>
</div>
""",
"""
<div class="caption"><span>Classes in <a href="../package-summary.html">\
Unnamed Package</a> that implement interfaces with type arguments of type \
<a href="../One.html" title="class in Unnamed Package">One</a></span></div>
""",
"""
<div class="summary-table three-column-summary">
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Class</div>
<div class="table-header col-last">Description</div>
<div class="col-first even-row-color"><code>class&nbsp;</code></div>
<div class="col-second even-row-color"><code><a href="../Two.html" class="type-name-link" \
title="class in Unnamed Package">Two</a></code></div>
<div class="col-last even-row-color">&nbsp;</div>
</div>
""");
}
}