8259499: Handling type arguments from outer classes for inner class in javadoc
Reviewed-by: jjg
This commit is contained in:
parent
e5db9a9405
commit
82c256eb61
@ -133,13 +133,13 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
|
|||||||
/**
|
/**
|
||||||
* Add the parameter for the executable member.
|
* Add the parameter for the executable member.
|
||||||
*
|
*
|
||||||
* @param member the member to write parameter for.
|
|
||||||
* @param param the parameter that needs to be written.
|
* @param param the parameter that needs to be written.
|
||||||
|
* @param paramType the type of the parameter.
|
||||||
* @param isVarArg true if this is a link to var arg.
|
* @param isVarArg true if this is a link to var arg.
|
||||||
* @param tree the content tree to which the parameter information will be added.
|
* @param tree the content tree to which the parameter information will be added.
|
||||||
*/
|
*/
|
||||||
protected void addParam(ExecutableElement member, VariableElement param, TypeMirror paramType,
|
protected void addParam(VariableElement param, TypeMirror paramType, boolean isVarArg,
|
||||||
boolean isVarArg, Content tree) {
|
Content tree) {
|
||||||
Content link = writer.getLink(new HtmlLinkInfo(configuration, EXECUTABLE_MEMBER_PARAM,
|
Content link = writer.getLink(new HtmlLinkInfo(configuration, EXECUTABLE_MEMBER_PARAM,
|
||||||
paramType).varargs(isVarArg));
|
paramType).varargs(isVarArg));
|
||||||
tree.add(link);
|
tree.add(link);
|
||||||
@ -249,7 +249,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
|
|||||||
.add(" ");
|
.add(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addParam(member, param, paramType,
|
addParam(param, paramType,
|
||||||
(paramstart == parameters.size() - 1) && member.isVarArgs(), paramTree);
|
(paramstart == parameters.size() - 1) && member.isVarArgs(), paramTree);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -268,7 +268,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
|
|||||||
.add(" ");
|
.add(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addParam(member, parameters.get(i), instMeth.getParameterTypes().get(i),
|
addParam(parameters.get(i), instMeth.getParameterTypes().get(i),
|
||||||
(i == parameters.size() - 1) && member.isVarArgs(),
|
(i == parameters.size() - 1) && member.isVarArgs(),
|
||||||
paramTree);
|
paramTree);
|
||||||
}
|
}
|
||||||
|
@ -1075,13 +1075,11 @@ public class HtmlDocletWriter {
|
|||||||
} else if (refMemName == null) {
|
} else if (refMemName == null) {
|
||||||
// Must be a class reference since refClass is not null and refMemName is null.
|
// Must be a class reference since refClass is not null and refMemName is null.
|
||||||
if (labelContent.isEmpty()) {
|
if (labelContent.isEmpty()) {
|
||||||
if (!refClass.getTypeParameters().isEmpty() && seeText.contains("<")) {
|
TypeMirror referencedType = ch.getReferencedType(see);
|
||||||
// If this is a generic type link try to use the TypeMirror representation.
|
if (utils.isGenericType(referencedType)) {
|
||||||
TypeMirror refType = ch.getReferencedType(see);
|
// This is a generic type link, use the TypeMirror representation.
|
||||||
if (refType != null) {
|
return plainOrCode(isLinkPlain, getLink(
|
||||||
return plainOrCode(isLinkPlain, getLink(
|
new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, referencedType)));
|
||||||
new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, refType)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
labelContent = plainOrCode(isLinkPlain, Text.of(utils.getSimpleName(refClass)));
|
labelContent = plainOrCode(isLinkPlain, Text.of(utils.getSimpleName(refClass)));
|
||||||
}
|
}
|
||||||
|
@ -107,8 +107,7 @@ public class HtmlLinkFactory extends LinkFactory {
|
|||||||
if (utils.isIncluded(typeElement)) {
|
if (utils.isIncluded(typeElement)) {
|
||||||
if (configuration.isGeneratedDoc(typeElement) && !utils.hasHiddenTag(typeElement)) {
|
if (configuration.isGeneratedDoc(typeElement) && !utils.hasHiddenTag(typeElement)) {
|
||||||
DocPath filename = getPath(classLinkInfo);
|
DocPath filename = getPath(classLinkInfo);
|
||||||
if (linkInfo.linkToSelf ||
|
if (linkInfo.linkToSelf || typeElement != m_writer.getCurrentPageElement()) {
|
||||||
!(docPaths.forName(typeElement)).equals(m_writer.filename)) {
|
|
||||||
link.add(m_writer.links.createLink(
|
link.add(m_writer.links.createLink(
|
||||||
filename.fragment(classLinkInfo.where),
|
filename.fragment(classLinkInfo.where),
|
||||||
label,
|
label,
|
||||||
|
@ -192,6 +192,9 @@ public class CommentHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TypeMirror getType(ReferenceTree rtree) {
|
public TypeMirror getType(ReferenceTree rtree) {
|
||||||
|
// Workaround for JDK-8269706
|
||||||
|
if (path == null || dcTree == null || rtree == null)
|
||||||
|
return null;
|
||||||
DocTreePath docTreePath = DocTreePath.getPath(path, dcTree, rtree);
|
DocTreePath docTreePath = DocTreePath.getPath(path, dcTree, rtree);
|
||||||
if (docTreePath != null) {
|
if (docTreePath != null) {
|
||||||
DocTrees doctrees = configuration.docEnv.getDocTrees();
|
DocTrees doctrees = configuration.docEnv.getDocTrees();
|
||||||
|
@ -973,6 +973,21 @@ public class Utils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if {@code type} or any of its enclosing types has non-empty type arguments.
|
||||||
|
* @param type the type
|
||||||
|
* @return {@code true} if type arguments were found
|
||||||
|
*/
|
||||||
|
public boolean isGenericType(TypeMirror type) {
|
||||||
|
while (type instanceof DeclaredType dt) {
|
||||||
|
if (!dt.getTypeArguments().isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
type = dt.getEnclosingType();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: FIXME: port to javax.lang.model
|
* TODO: FIXME: port to javax.lang.model
|
||||||
* Find a class within the context of this class. Search order: qualified name, in this class
|
* Find a class within the context of this class. Search order: qualified name, in this class
|
||||||
|
@ -166,6 +166,16 @@ public abstract class LinkFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Content visitDeclared(DeclaredType type, LinkInfo linkInfo) {
|
public Content visitDeclared(DeclaredType type, LinkInfo linkInfo) {
|
||||||
|
TypeMirror enc = type.getEnclosingType();
|
||||||
|
if (enc instanceof DeclaredType dt && utils.isGenericType(dt)) {
|
||||||
|
// If an enclosing type has type parameters render them as separate links as
|
||||||
|
// otherwise this information is lost. On the other hand, plain enclosing types
|
||||||
|
// are not linked separately as they are easy to reach from the nested type.
|
||||||
|
setEnclosingTypeLinkInfo(linkInfo, dt);
|
||||||
|
visitDeclared(dt, linkInfo);
|
||||||
|
link.add(".");
|
||||||
|
setEnclosingTypeLinkInfo(linkInfo, type);
|
||||||
|
}
|
||||||
link.add(getTypeAnnotationLinks(linkInfo));
|
link.add(getTypeAnnotationLinks(linkInfo));
|
||||||
linkInfo.typeElement = utils.asTypeElement(type);
|
linkInfo.typeElement = utils.asTypeElement(type);
|
||||||
link.add(getClassLink(linkInfo));
|
link.add(getClassLink(linkInfo));
|
||||||
@ -195,6 +205,12 @@ public abstract class LinkFactory {
|
|||||||
linkInfo.skipPreview = false;
|
linkInfo.skipPreview = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setEnclosingTypeLinkInfo(LinkInfo linkinfo, DeclaredType enclosing) {
|
||||||
|
linkinfo.typeElement = null;
|
||||||
|
linkinfo.label = null;
|
||||||
|
linkinfo.type = enclosing;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a link to the given class.
|
* Returns a link to the given class.
|
||||||
*
|
*
|
||||||
|
@ -27,10 +27,12 @@ package jdk.javadoc.internal.doclets.toolkit.util.links;
|
|||||||
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
|
||||||
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
|
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
|
||||||
import jdk.javadoc.internal.doclets.toolkit.Content;
|
import jdk.javadoc.internal.doclets.toolkit.Content;
|
||||||
|
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates information about a link.
|
* Encapsulates information about a link.
|
||||||
@ -125,7 +127,11 @@ public abstract class LinkInfo {
|
|||||||
return label;
|
return label;
|
||||||
} else if (isLinkable()) {
|
} else if (isLinkable()) {
|
||||||
Content tlabel = newContent();
|
Content tlabel = newContent();
|
||||||
tlabel.add(configuration.utils.getSimpleName(typeElement));
|
Utils utils = configuration.utils;
|
||||||
|
tlabel.add(type instanceof DeclaredType dt && utils.isGenericType(dt.getEnclosingType())
|
||||||
|
// If enclosing type is rendered as separate links only use own class name
|
||||||
|
? typeElement.getSimpleName().toString()
|
||||||
|
: configuration.utils.getSimpleName(typeElement));
|
||||||
return tlabel;
|
return tlabel;
|
||||||
} else {
|
} else {
|
||||||
Content tlabel = newContent();
|
Content tlabel = newContent();
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8177280 8262992
|
* @bug 8177280 8262992 8259499
|
||||||
* @summary see and link tag syntax should allow generic types
|
* @summary see and link tag syntax should allow generic types
|
||||||
* @library ../../lib
|
* @library ../../lib
|
||||||
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
||||||
@ -118,6 +118,40 @@ public class TestGenericTypeLink extends JavadocTester {
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>"""
|
</dl>"""
|
||||||
);
|
);
|
||||||
|
checkOutput("pkg1/A.Inner.html", true,
|
||||||
|
"""
|
||||||
|
<dl class="notes">
|
||||||
|
<dt>See Also:</dt>
|
||||||
|
<dd>
|
||||||
|
<ul class="see-list-long">
|
||||||
|
<li><code><a href="A.html" title="class in pkg1">A</a><<a href="http://exampl\
|
||||||
|
e.com/docs/api/java.base/java/lang/String.html" title="class or interface in jav\
|
||||||
|
a.lang" class="external-link">String</a>,<wbr><a href="http://example.com/docs/a\
|
||||||
|
pi/java.base/java/lang/RuntimeException.html" title="class or interface in java.\
|
||||||
|
lang" class="external-link">RuntimeException</a>>.<a href="A.Inner.html" titl\
|
||||||
|
e="class in pkg1">Inner</a></code></li>
|
||||||
|
<li><code><a href="A.html" title="class in pkg1">A</a><<a href="A.html" title\
|
||||||
|
="class in pkg1">A</a><<a href="http://example.com/docs/api/java.base/java/la\
|
||||||
|
ng/String.html" title="class or interface in java.lang" class="external-link">St\
|
||||||
|
ring</a>,<wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeEx\
|
||||||
|
ception.html" title="class or interface in java.lang" class="external-link">Runt\
|
||||||
|
imeException</a>>.<a href="A.Inner.html" title="class in pkg1">Inner</a>,<wbr\
|
||||||
|
><a href="A.SomeException.html" title="class in pkg1">A.SomeException</a>></c\
|
||||||
|
ode></li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
</dl>""");
|
||||||
|
|
||||||
|
checkOutput("pkg1/C.html", true,
|
||||||
|
"""
|
||||||
|
Description copied from class: <code><a href="A.html#overriddenMethod()">A<\
|
||||||
|
/a></code></span></div>
|
||||||
|
<div class="block">Here's a generic link: <code><a href="A.html" title="class in\
|
||||||
|
pkg1">A</a><<a href="http://example.com/docs/api/java.base/java/lang/Object.\
|
||||||
|
html" title="class or interface in java.lang" class="external-link">Object</a>,<\
|
||||||
|
wbr><a href="http://example.com/docs/api/java.base/java/lang/RuntimeException.ht\
|
||||||
|
ml" title="class or interface in java.lang" class="external-link">RuntimeExcepti\
|
||||||
|
on</a>>.<a href="A.Inner.html" title="class in pkg1">Inner</a>""");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -60,6 +60,16 @@ public class A<T, E extends Exception> {
|
|||||||
*/
|
*/
|
||||||
public void otherMethod(Map<String, ?> list, double d) {}
|
public void otherMethod(Map<String, ?> list, double d) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Here's a generic link: {@link A<Object, RuntimeException>.Inner}
|
||||||
|
*/
|
||||||
|
public void overriddenMethod() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see A<String, java.lang.RuntimeException>.Inner
|
||||||
|
* @see A<A<String, java.lang.RuntimeException>.Inner, A.SomeException>
|
||||||
|
*/
|
||||||
|
class Inner {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021, 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 pkg1;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class C<T, E extends Exception> extends A {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void overriddenMethod() {}
|
||||||
|
|
||||||
|
}
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8214126 8241470
|
* @bug 8214126 8241470 8259499
|
||||||
* @summary Method signatures not formatted correctly in browser
|
* @summary Method signatures not formatted correctly in browser
|
||||||
* @library ../../lib/
|
* @library ../../lib/
|
||||||
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
||||||
@ -123,7 +123,32 @@ public class TestMethodSignature extends JavadocTester {
|
|||||||
throws <span class="exc\
|
throws <span class="exc\
|
||||||
eptions">java.lang.IllegalArgumentException,
|
eptions">java.lang.IllegalArgumentException,
|
||||||
java.lang.IllegalStateException</span></div>
|
java.lang.IllegalStateException</span></div>
|
||||||
<div class="block">Generic method with eight type args and annotation.</div>""");
|
<div class="block">Generic method with eight type args and annotation.</div>""",
|
||||||
|
"""
|
||||||
|
<div class="member-signature"><span class="modifiers">public</span> <span c\
|
||||||
|
lass="return-type"><a href="C.Generic.html" title="class in pkg">C.Generic</a>&l\
|
||||||
|
t;java.lang.Integer>.<a href="C.Generic.Inner.html" title="class in pkg">Inne\
|
||||||
|
r</a></span> <span class="element-name">nestedGeneric1</span><wbr><span cla\
|
||||||
|
ss="parameters">(<a href="C.Generic.html" title="class in pkg">C.Generic</a><\
|
||||||
|
java.lang.Integer>.<a href="C.Generic.Inner.html" title="class in pkg">Inner<\
|
||||||
|
/a> i,
|
||||||
|
<a href="C.Generic.html" title="class in pkg">C.Generic</a><<a href="C.html"\
|
||||||
|
title="class in pkg">C</a>>.<a href="C.Generic.Inner.html" title="class in p\
|
||||||
|
kg">Inner</a> j)</span></div>""",
|
||||||
|
"""
|
||||||
|
<div class="member-signature"><span class="modifiers">public</span> <span c\
|
||||||
|
lass="return-type"><a href="C.Generic.html" title="class in pkg">C.Generic</a>&l\
|
||||||
|
t;<a href="C.F0.html" title="interface in pkg">C.F0</a><<a href="C.html" titl\
|
||||||
|
e="class in pkg">C</a>>>.<a href="C.Generic.Inner.html" title="class in pk\
|
||||||
|
g">Inner</a>.<a href="C.Generic.Inner.Foo.html" title="class in pkg">Foo</a></sp\
|
||||||
|
an> <span class="element-name">nestedGeneric2</span><wbr><span class="param\
|
||||||
|
eters">(<a href="C.Generic.html" title="class in pkg">C.Generic</a><java.lang\
|
||||||
|
.Integer>.<a href="C.Generic.Inner.html" title="class in pkg">Inner</a>.<a hr\
|
||||||
|
ef="C.Generic.Inner.Foo.html" title="class in pkg">Foo</a> f,
|
||||||
|
<a href="C.Generic.html" title="class in pkg">C.Generic</a><<a href="C.F0.ht\
|
||||||
|
ml" title="interface in pkg">C.F0</a><<a href="C.html" title="class in pkg">C\
|
||||||
|
</a>>>.<a href="C.Generic.Inner.html" title="class in pkg">Inner</a>.<a hr\
|
||||||
|
ef="C.Generic.Inner.Foo.html" title="class in pkg">Foo</a> g)</span></div>""");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -156,4 +156,33 @@ public class C {
|
|||||||
F0<? extends T7> t7,
|
F0<? extends T7> t7,
|
||||||
F0<? extends T8> t8)
|
F0<? extends T8> t8)
|
||||||
throws IllegalArgumentException, IllegalStateException { return null; }
|
throws IllegalArgumentException, IllegalStateException { return null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inner classes with type arguments in enclosing classes.
|
||||||
|
*
|
||||||
|
* @param i param i
|
||||||
|
* @param j param j
|
||||||
|
* @return return value
|
||||||
|
*/
|
||||||
|
public Generic<Integer>.Inner nestedGeneric1(Generic<Integer>.Inner i, Generic<C>.Inner j) { return i; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inner classes with type arguments in enclosing classes.
|
||||||
|
*
|
||||||
|
* @param f param f
|
||||||
|
* @param g param g
|
||||||
|
* @return return value
|
||||||
|
*/
|
||||||
|
public Generic<C.F0<C>>.Inner.Foo nestedGeneric2(Generic<Integer>.Inner.Foo f, Generic<C.F0<C>>.Inner.Foo g) { return g; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic class with multiple inner classes.
|
||||||
|
* @param <T> type parameter
|
||||||
|
*/
|
||||||
|
public static class Generic<T> {
|
||||||
|
public class Inner {
|
||||||
|
T data;
|
||||||
|
public class Foo {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user