Skip to content

Commit 82c256e

Browse files
committed
8259499: Handling type arguments from outer classes for inner class in javadoc
Reviewed-by: jjg
1 parent e5db9a9 commit 82c256e

12 files changed

Lines changed: 188 additions & 20 deletions

File tree

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,13 @@ protected void addInheritedSummaryLink(TypeElement te, Element member, Content l
133133
/**
134134
* Add the parameter for the executable member.
135135
*
136-
* @param member the member to write parameter for.
137136
* @param param the parameter that needs to be written.
137+
* @param paramType the type of the parameter.
138138
* @param isVarArg true if this is a link to var arg.
139139
* @param tree the content tree to which the parameter information will be added.
140140
*/
141-
protected void addParam(ExecutableElement member, VariableElement param, TypeMirror paramType,
142-
boolean isVarArg, Content tree) {
141+
protected void addParam(VariableElement param, TypeMirror paramType, boolean isVarArg,
142+
Content tree) {
143143
Content link = writer.getLink(new HtmlLinkInfo(configuration, EXECUTABLE_MEMBER_PARAM,
144144
paramType).varargs(isVarArg));
145145
tree.add(link);
@@ -249,7 +249,7 @@ protected Content getParameters(ExecutableElement member, boolean includeAnnotat
249249
.add(" ");
250250
}
251251
}
252-
addParam(member, param, paramType,
252+
addParam(param, paramType,
253253
(paramstart == parameters.size() - 1) && member.isVarArgs(), paramTree);
254254
break;
255255
}
@@ -268,7 +268,7 @@ protected Content getParameters(ExecutableElement member, boolean includeAnnotat
268268
.add(" ");
269269
}
270270
}
271-
addParam(member, parameters.get(i), instMeth.getParameterTypes().get(i),
271+
addParam(parameters.get(i), instMeth.getParameterTypes().get(i),
272272
(i == parameters.size() - 1) && member.isVarArgs(),
273273
paramTree);
274274
}

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,13 +1075,11 @@ public Content seeTagToContent(Element element, DocTree see, TagletWriterImpl.Co
10751075
} else if (refMemName == null) {
10761076
// Must be a class reference since refClass is not null and refMemName is null.
10771077
if (labelContent.isEmpty()) {
1078-
if (!refClass.getTypeParameters().isEmpty() && seeText.contains("<")) {
1079-
// If this is a generic type link try to use the TypeMirror representation.
1080-
TypeMirror refType = ch.getReferencedType(see);
1081-
if (refType != null) {
1082-
return plainOrCode(isLinkPlain, getLink(
1083-
new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, refType)));
1084-
}
1078+
TypeMirror referencedType = ch.getReferencedType(see);
1079+
if (utils.isGenericType(referencedType)) {
1080+
// This is a generic type link, use the TypeMirror representation.
1081+
return plainOrCode(isLinkPlain, getLink(
1082+
new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, referencedType)));
10851083
}
10861084
labelContent = plainOrCode(isLinkPlain, Text.of(utils.getSimpleName(refClass)));
10871085
}

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ protected Content getClassLink(LinkInfo linkInfo) {
107107
if (utils.isIncluded(typeElement)) {
108108
if (configuration.isGeneratedDoc(typeElement) && !utils.hasHiddenTag(typeElement)) {
109109
DocPath filename = getPath(classLinkInfo);
110-
if (linkInfo.linkToSelf ||
111-
!(docPaths.forName(typeElement)).equals(m_writer.filename)) {
110+
if (linkInfo.linkToSelf || typeElement != m_writer.getCurrentPageElement()) {
112111
link.add(m_writer.links.createLink(
113112
filename.fragment(classLinkInfo.where),
114113
label,

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ Element getElement(ReferenceTree rtree) {
192192
}
193193

194194
public TypeMirror getType(ReferenceTree rtree) {
195+
// Workaround for JDK-8269706
196+
if (path == null || dcTree == null || rtree == null)
197+
return null;
195198
DocTreePath docTreePath = DocTreePath.getPath(path, dcTree, rtree);
196199
if (docTreePath != null) {
197200
DocTrees doctrees = configuration.docEnv.getDocTrees();

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,21 @@ public TypeElement findClassInPackageElement(PackageElement pkg, String classNam
973973
return null;
974974
}
975975

976+
/**
977+
* Returns true if {@code type} or any of its enclosing types has non-empty type arguments.
978+
* @param type the type
979+
* @return {@code true} if type arguments were found
980+
*/
981+
public boolean isGenericType(TypeMirror type) {
982+
while (type instanceof DeclaredType dt) {
983+
if (!dt.getTypeArguments().isEmpty()) {
984+
return true;
985+
}
986+
type = dt.getEnclosingType();
987+
}
988+
return false;
989+
}
990+
976991
/**
977992
* TODO: FIXME: port to javax.lang.model
978993
* Find a class within the context of this class. Search order: qualified name, in this class

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ public Content visitTypeVariable(TypeVariable type, LinkInfo linkInfo) {
166166

167167
@Override
168168
public Content visitDeclared(DeclaredType type, LinkInfo linkInfo) {
169+
TypeMirror enc = type.getEnclosingType();
170+
if (enc instanceof DeclaredType dt && utils.isGenericType(dt)) {
171+
// If an enclosing type has type parameters render them as separate links as
172+
// otherwise this information is lost. On the other hand, plain enclosing types
173+
// are not linked separately as they are easy to reach from the nested type.
174+
setEnclosingTypeLinkInfo(linkInfo, dt);
175+
visitDeclared(dt, linkInfo);
176+
link.add(".");
177+
setEnclosingTypeLinkInfo(linkInfo, type);
178+
}
169179
link.add(getTypeAnnotationLinks(linkInfo));
170180
linkInfo.typeElement = utils.asTypeElement(type);
171181
link.add(getClassLink(linkInfo));
@@ -195,6 +205,12 @@ private void setBoundsLinkInfo(LinkInfo linkInfo, TypeMirror bound) {
195205
linkInfo.skipPreview = false;
196206
}
197207

208+
private void setEnclosingTypeLinkInfo(LinkInfo linkinfo, DeclaredType enclosing) {
209+
linkinfo.typeElement = null;
210+
linkinfo.label = null;
211+
linkinfo.type = enclosing;
212+
}
213+
198214
/**
199215
* Returns a link to the given class.
200216
*

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727

2828
import javax.lang.model.element.ExecutableElement;
2929
import javax.lang.model.element.TypeElement;
30+
import javax.lang.model.type.DeclaredType;
3031
import javax.lang.model.type.TypeMirror;
3132

3233
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
3334
import jdk.javadoc.internal.doclets.toolkit.Content;
35+
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
3436

3537
/**
3638
* Encapsulates information about a link.
@@ -125,7 +127,11 @@ public Content getClassLinkLabel(BaseConfiguration configuration) {
125127
return label;
126128
} else if (isLinkable()) {
127129
Content tlabel = newContent();
128-
tlabel.add(configuration.utils.getSimpleName(typeElement));
130+
Utils utils = configuration.utils;
131+
tlabel.add(type instanceof DeclaredType dt && utils.isGenericType(dt.getEnclosingType())
132+
// If enclosing type is rendered as separate links only use own class name
133+
? typeElement.getSimpleName().toString()
134+
: configuration.utils.getSimpleName(typeElement));
129135
return tlabel;
130136
} else {
131137
Content tlabel = newContent();

test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8177280 8262992
26+
* @bug 8177280 8262992 8259499
2727
* @summary see and link tag syntax should allow generic types
2828
* @library ../../lib
2929
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -118,6 +118,40 @@ s or interface in java.util" class="external-link"><code>Link to generic type wi
118118
</dd>
119119
</dl>"""
120120
);
121+
checkOutput("pkg1/A.Inner.html", true,
122+
"""
123+
<dl class="notes">
124+
<dt>See Also:</dt>
125+
<dd>
126+
<ul class="see-list-long">
127+
<li><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="http://exampl\
128+
e.com/docs/api/java.base/java/lang/String.html" title="class or interface in jav\
129+
a.lang" class="external-link">String</a>,<wbr><a href="http://example.com/docs/a\
130+
pi/java.base/java/lang/RuntimeException.html" title="class or interface in java.\
131+
lang" class="external-link">RuntimeException</a>&gt;.<a href="A.Inner.html" titl\
132+
e="class in pkg1">Inner</a></code></li>
133+
<li><code><a href="A.html" title="class in pkg1">A</a>&lt;<a href="A.html" title\
134+
="class in pkg1">A</a>&lt;<a href="http://example.com/docs/api/java.base/java/la\
135+
ng/String.html" title="class or interface in java.lang" class="external-link">St\
136+
ring</a>,<wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeEx\
137+
ception.html" title="class or interface in java.lang" class="external-link">Runt\
138+
imeException</a>&gt;.<a href="A.Inner.html" title="class in pkg1">Inner</a>,<wbr\
139+
><a href="A.SomeException.html" title="class in pkg1">A.SomeException</a>&gt;</c\
140+
ode></li>
141+
</ul>
142+
</dd>
143+
</dl>""");
144+
145+
checkOutput("pkg1/C.html", true,
146+
"""
147+
Description copied from class:&nbsp;<code><a href="A.html#overriddenMethod()">A<\
148+
/a></code></span></div>
149+
<div class="block">Here's a generic link: <code><a href="A.html" title="class in\
150+
pkg1">A</a>&lt;<a href="http://example.com/docs/api/java.base/java/lang/Object.\
151+
html" title="class or interface in java.lang" class="external-link">Object</a>,<\
152+
wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeException.ht\
153+
ml" title="class or interface in java.lang" class="external-link">RuntimeExcepti\
154+
on</a>&gt;.<a href="A.Inner.html" title="class in pkg1">Inner</a>""");
121155
}
122156

123157
/**

test/langtools/jdk/javadoc/doclet/testGenericTypeLink/pkg1/A.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -60,6 +60,16 @@ public void someMethod(List<? extends Number> list, int i) {}
6060
*/
6161
public void otherMethod(Map<String, ?> list, double d) {}
6262

63+
/**
64+
* Here's a generic link: {@link A<Object, RuntimeException>.Inner}
65+
*/
66+
public void overriddenMethod() {}
67+
68+
/**
69+
* @see A<String, java.lang.RuntimeException>.Inner
70+
* @see A<A<String, java.lang.RuntimeException>.Inner, A.SomeException>
71+
*/
72+
class Inner {}
6373

6474
}
6575

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
package pkg1;
25+
26+
import java.util.Map;
27+
28+
public class C<T, E extends Exception> extends A {
29+
30+
@Override
31+
public void overriddenMethod() {}
32+
33+
}

0 commit comments

Comments
 (0)