mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8177280: @see {@link} syntax should allow generic types
8237826: DocTrees should provide getType(DocTreePath) method Reviewed-by: jjg
This commit is contained in:
parent
c0a1a4e4fc
commit
b43f356288
15 changed files with 371 additions and 191 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, 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
|
||||
|
@ -32,6 +32,7 @@ import java.util.List;
|
|||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.JavaCompiler.CompilationTask;
|
||||
|
@ -152,6 +153,21 @@ public abstract class DocTrees extends Trees {
|
|||
*/
|
||||
public abstract Element getElement(DocTreePath path);
|
||||
|
||||
/**
|
||||
* Returns the language model type referred to by the leaf node of the given
|
||||
* {@link DocTreePath}, or {@code null} if unknown. This method usually
|
||||
* returns the same value as {@code getElement(path).asType()} for a
|
||||
* {@code path} argument for which {@link #getElement(DocTreePath)} returns
|
||||
* a non-null value, but may return a type that includes additional
|
||||
* information, such as a parameterized generic type instead of a raw type.
|
||||
*
|
||||
* @param path the path for the tree node
|
||||
* @return the referenced type, or null
|
||||
*
|
||||
* @since 15
|
||||
*/
|
||||
public abstract TypeMirror getType(DocTreePath path);
|
||||
|
||||
/**
|
||||
* Returns the list of {@link DocTree} representing the first sentence of
|
||||
* a comment.
|
||||
|
|
|
@ -915,14 +915,9 @@ public class Checker extends DocTreePathScanner<Void, Void> {
|
|||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public Void visitReference(ReferenceTree tree, Void ignore) {
|
||||
String sig = tree.getSignature();
|
||||
if (sig.contains("<") || sig.contains(">")) {
|
||||
env.messages.error(REFERENCE, tree, "dc.type.arg.not.allowed");
|
||||
} else {
|
||||
Element e = env.trees.getElement(getCurrentPath());
|
||||
if (e == null)
|
||||
env.messages.error(REFERENCE, tree, "dc.ref.not.found");
|
||||
}
|
||||
Element e = env.trees.getElement(getCurrentPath());
|
||||
if (e == null)
|
||||
env.messages.error(REFERENCE, tree, "dc.ref.not.found");
|
||||
return super.visitReference(tree, ignore);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,6 @@ dc.tag.start.unmatched = end tag missing: </{0}>
|
|||
dc.tag.unknown = unknown tag: {0}
|
||||
dc.tag.not.supported = tag not supported in the generated HTML version: {0}
|
||||
dc.text.not.allowed = text not allowed in <{0}> element
|
||||
dc.type.arg.not.allowed = type arguments not allowed here
|
||||
dc.unexpected.comment=documentation comment not expected here
|
||||
dc.value.not.allowed.here='{@value}' not allowed here
|
||||
dc.value.not.a.constant=value does not refer to a constant
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2020, 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
|
||||
|
@ -431,6 +431,31 @@ public class JavacTrees extends DocTrees {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public TypeMirror getType(DocTreePath path) {
|
||||
DocTree tree = path.getLeaf();
|
||||
if (tree instanceof DCReference) {
|
||||
JCTree qexpr = ((DCReference)tree).qualifierExpression;
|
||||
if (qexpr != null) {
|
||||
Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
|
||||
new Log.DeferredDiagnosticHandler(log);
|
||||
try {
|
||||
Env<AttrContext> env = getAttrContext(path.getTreePath());
|
||||
Type t = attr.attribType(((DCReference) tree).qualifierExpression, env);
|
||||
if (t != null && !t.isErroneous()) {
|
||||
return t;
|
||||
}
|
||||
} catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
|
||||
return null;
|
||||
} finally {
|
||||
log.popDiagnosticHandler(deferredDiagnosticHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
Element e = getElement(path);
|
||||
return e == null ? null : e.asType();
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public java.util.List<DocTree> getFirstSentence(java.util.List<? extends DocTree> list) {
|
||||
return docTreeMaker.getFirstSentence(list);
|
||||
|
@ -721,78 +746,15 @@ public class JavacTrees extends DocTrees {
|
|||
if (method.params().size() != paramTypes.size())
|
||||
return false;
|
||||
|
||||
List<Type> methodParamTypes = types.erasureRecursive(method.asType()).getParameterTypes();
|
||||
List<Type> methodParamTypes = method.asType().getParameterTypes();
|
||||
if (!Type.isErroneous(paramTypes) && types.isSubtypes(paramTypes, methodParamTypes)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (Type.isErroneous(paramTypes))
|
||||
? fuzzyMatch(paramTypes, methodParamTypes)
|
||||
: types.isSameTypes(paramTypes, methodParamTypes);
|
||||
methodParamTypes = types.erasureRecursive(methodParamTypes);
|
||||
return types.isSameTypes(paramTypes, methodParamTypes);
|
||||
}
|
||||
|
||||
boolean fuzzyMatch(List<Type> paramTypes, List<Type> methodParamTypes) {
|
||||
List<Type> l1 = paramTypes;
|
||||
List<Type> l2 = methodParamTypes;
|
||||
while (l1.nonEmpty()) {
|
||||
if (!fuzzyMatch(l1.head, l2.head))
|
||||
return false;
|
||||
l1 = l1.tail;
|
||||
l2 = l2.tail;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean fuzzyMatch(Type paramType, Type methodParamType) {
|
||||
Boolean b = fuzzyMatcher.visit(paramType, methodParamType);
|
||||
return (b == Boolean.TRUE);
|
||||
}
|
||||
|
||||
TypeRelation fuzzyMatcher = new TypeRelation() {
|
||||
@Override
|
||||
public Boolean visitType(Type t, Type s) {
|
||||
if (t == s)
|
||||
return true;
|
||||
|
||||
if (s.isPartial())
|
||||
return visit(s, t);
|
||||
|
||||
switch (t.getTag()) {
|
||||
case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
|
||||
case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE:
|
||||
return t.hasTag(s.getTag());
|
||||
default:
|
||||
throw new AssertionError("fuzzyMatcher " + t.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitArrayType(ArrayType t, Type s) {
|
||||
if (t == s)
|
||||
return true;
|
||||
|
||||
if (s.isPartial())
|
||||
return visit(s, t);
|
||||
|
||||
return s.hasTag(ARRAY)
|
||||
&& visit(t.elemtype, types.elemtype(s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitClassType(ClassType t, Type s) {
|
||||
if (t == s)
|
||||
return true;
|
||||
|
||||
if (s.isPartial())
|
||||
return visit(s, t);
|
||||
|
||||
return t.tsym == s.tsym;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitErrorType(ErrorType t, Type s) {
|
||||
return s.hasTag(CLASS)
|
||||
&& t.tsym.name == ((ClassType) s).tsym.name;
|
||||
}
|
||||
};
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public TypeMirror getTypeMirror(TreePath path) {
|
||||
Tree t = path.getLeaf();
|
||||
|
|
|
@ -1047,19 +1047,15 @@ public class HtmlDocletWriter {
|
|||
} else if (refMemName == null) {
|
||||
// Must be a class reference since refClass is not null and refMemName is null.
|
||||
if (label.isEmpty()) {
|
||||
/*
|
||||
* it seems to me this is the right thing to do, but it causes comparator failures.
|
||||
*/
|
||||
if (!configuration.backwardCompatibility) {
|
||||
StringContent content = utils.isEnclosingPackageIncluded(refClass)
|
||||
? new StringContent(utils.getSimpleName(refClass))
|
||||
: new StringContent(utils.getFullyQualifiedName(refClass));
|
||||
label = plainOrCode(isLinkPlain, content);
|
||||
} else {
|
||||
label = plainOrCode(isLinkPlain,
|
||||
new StringContent(utils.getSimpleName(refClass)));
|
||||
if (!refClass.getTypeParameters().isEmpty() && seetext.contains("<")) {
|
||||
// If this is a generic type link try to use the TypeMirror representation.
|
||||
TypeMirror refType = ch.getReferencedType(see);
|
||||
if (refType != null) {
|
||||
return plainOrCode(isLinkPlain, getLink(
|
||||
new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, refType)));
|
||||
}
|
||||
}
|
||||
|
||||
label = plainOrCode(isLinkPlain, new StringContent(utils.getSimpleName(refClass)));
|
||||
}
|
||||
return getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, refClass)
|
||||
.label(label));
|
||||
|
|
|
@ -136,7 +136,7 @@ public class LinkFactoryImpl extends LinkFactory {
|
|||
vars.addAll(((DeclaredType) linkInfo.type).getTypeArguments());
|
||||
} else if (ctype != null && utils.isDeclaredType(ctype)) {
|
||||
vars.addAll(((DeclaredType) ctype).getTypeArguments());
|
||||
} else if (linkInfo.typeElement != null) {
|
||||
} else if (ctype == null && linkInfo.typeElement != null) {
|
||||
linkInfo.typeElement.getTypeParameters().forEach(t -> vars.add(t.asType()));
|
||||
} else {
|
||||
// Nothing to document.
|
||||
|
|
|
@ -47,11 +47,6 @@ public class LinkInfoImpl extends LinkInfo {
|
|||
public enum Kind {
|
||||
DEFAULT,
|
||||
|
||||
/**
|
||||
* Indicate that the link appears in a class list.
|
||||
*/
|
||||
ALL_CLASSES_FRAME,
|
||||
|
||||
/**
|
||||
* Indicate that the link appears in a class documentation.
|
||||
*/
|
||||
|
@ -187,11 +182,6 @@ public class LinkInfoImpl extends LinkInfo {
|
|||
*/
|
||||
ANNOTATION,
|
||||
|
||||
/**
|
||||
* The header for field documentation copied from parent.
|
||||
*/
|
||||
VARIABLE_ELEMENT_COPY,
|
||||
|
||||
/**
|
||||
* The parent nodes in the class tree.
|
||||
*/
|
||||
|
@ -350,12 +340,10 @@ public class LinkInfoImpl extends LinkInfo {
|
|||
public final void setContext(Kind c) {
|
||||
//NOTE: Put context specific link code here.
|
||||
switch (c) {
|
||||
case ALL_CLASSES_FRAME:
|
||||
case PACKAGE_FRAME:
|
||||
case IMPLEMENTED_CLASSES:
|
||||
case SUBCLASSES:
|
||||
case EXECUTABLE_ELEMENT_COPY:
|
||||
case VARIABLE_ELEMENT_COPY:
|
||||
case PROPERTY_COPY:
|
||||
case CLASS_USE_HEADER:
|
||||
includeTypeInClassLinkLabel = false;
|
||||
|
|
|
@ -97,11 +97,6 @@ public abstract class BaseConfiguration {
|
|||
*/
|
||||
public static final String DEFAULT_BUILDER_XML = "resources/doclet.xml";
|
||||
|
||||
/**
|
||||
* Maintain backward compatibility with previous javadoc version
|
||||
*/
|
||||
public boolean backwardCompatibility = true;
|
||||
|
||||
/**
|
||||
* The meta tag keywords instance.
|
||||
*/
|
||||
|
|
|
@ -191,6 +191,15 @@ public class CommentHelper {
|
|||
return doctrees.getElement(docTreePath);
|
||||
}
|
||||
|
||||
public TypeMirror getType(ReferenceTree rtree) {
|
||||
DocTreePath docTreePath = DocTreePath.getPath(path, dcTree, rtree);
|
||||
if (docTreePath != null) {
|
||||
DocTrees doctrees = configuration.docEnv.getDocTrees();
|
||||
return doctrees.getType(docTreePath);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Element getException(DocTree dtree) {
|
||||
if (dtree.getKind() == THROWS || dtree.getKind() == EXCEPTION) {
|
||||
ThrowsTree tt = (ThrowsTree)dtree;
|
||||
|
@ -423,48 +432,19 @@ public class CommentHelper {
|
|||
}
|
||||
|
||||
private Element getReferencedElement(DocTree dtree) {
|
||||
return new SimpleDocTreeVisitor<Element, Void>() {
|
||||
@Override
|
||||
public Element visitSee(SeeTree node, Void p) {
|
||||
for (DocTree dt : node.getReference()) {
|
||||
return visit(dt, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element visitLink(LinkTree node, Void p) {
|
||||
return visit(node.getReference(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element visitProvides(ProvidesTree node, Void p) {
|
||||
return visit(node.getServiceType(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element visitValue(ValueTree node, Void p) {
|
||||
return visit(node.getReference(), null);
|
||||
}
|
||||
|
||||
return new ReferenceDocTreeVisitor<Element>() {
|
||||
@Override
|
||||
public Element visitReference(ReferenceTree node, Void p) {
|
||||
return getElement(node);
|
||||
}
|
||||
}.visit(dtree, null);
|
||||
}
|
||||
|
||||
public TypeMirror getReferencedType(DocTree dtree) {
|
||||
return new ReferenceDocTreeVisitor<TypeMirror>() {
|
||||
@Override
|
||||
public Element visitSerialField(SerialFieldTree node, Void p) {
|
||||
return visit(node.getType(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element visitUses(UsesTree node, Void p) {
|
||||
return visit(node.getServiceType(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Element defaultAction(DocTree node, Void p) {
|
||||
return null;
|
||||
public TypeMirror visitReference(ReferenceTree node, Void p) {
|
||||
return getType(node);
|
||||
}
|
||||
}.visit(dtree, null);
|
||||
}
|
||||
|
@ -479,42 +459,54 @@ public class CommentHelper {
|
|||
}
|
||||
|
||||
public String getReferencedSignature(DocTree dtree) {
|
||||
return new SimpleDocTreeVisitor<String, Void>() {
|
||||
@Override
|
||||
public String visitSee(SeeTree node, Void p) {
|
||||
for (DocTree dt : node.getReference()) {
|
||||
return visit(dt, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitLink(LinkTree node, Void p) {
|
||||
return visit(node.getReference(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitValue(ValueTree node, Void p) {
|
||||
return visit(node.getReference(), null);
|
||||
}
|
||||
|
||||
return new ReferenceDocTreeVisitor<String>() {
|
||||
@Override
|
||||
public String visitReference(ReferenceTree node, Void p) {
|
||||
return node.getSignature();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitSerialField(SerialFieldTree node, Void p) {
|
||||
return visit(node.getType(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String defaultAction(DocTree node, Void p) {
|
||||
return null;
|
||||
}
|
||||
}.visit(dtree, null);
|
||||
}
|
||||
|
||||
private static class ReferenceDocTreeVisitor<R> extends SimpleDocTreeVisitor<R, Void> {
|
||||
@Override
|
||||
public R visitSee(SeeTree node, Void p) {
|
||||
for (DocTree dt : node.getReference()) {
|
||||
return visit(dt, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R visitLink(LinkTree node, Void p) {
|
||||
return visit(node.getReference(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R visitProvides(ProvidesTree node, Void p) {
|
||||
return visit(node.getServiceType(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R visitValue(ValueTree node, Void p) {
|
||||
return visit(node.getReference(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R visitSerialField(SerialFieldTree node, Void p) {
|
||||
return visit(node.getType(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R visitUses(UsesTree node, Void p) {
|
||||
return visit(node.getServiceType(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected R defaultAction(DocTree node, Void p) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<? extends DocTree> getReference(DocTree dtree) {
|
||||
return dtree.getKind() == SEE ? ((SeeTree)dtree).getReference() : null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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 8177280
|
||||
* @summary see and link tag syntax should allow generic types
|
||||
* @library ../../lib
|
||||
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
||||
* @build javadoc.tester.*
|
||||
* @run main TestGenericTypeLink
|
||||
*/
|
||||
|
||||
import javadoc.tester.JavadocTester;
|
||||
|
||||
public class TestGenericTypeLink extends JavadocTester {
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
TestGenericTypeLink test = new TestGenericTypeLink();
|
||||
test.runTests();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test valid internal and external links to generic types.
|
||||
*/
|
||||
@Test
|
||||
public void testValidLinks() {
|
||||
javadoc("-d", "out1",
|
||||
"-sourcepath", testSrc,
|
||||
"-linkoffline", "http://example.com/docs/api/", testSrc,
|
||||
"-package", "pkg1");
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("pkg1/A.html", true,
|
||||
"<div class=\"block\"><code><a href=\"http://example.com/docs/api/java.base"
|
||||
+ "/java/util/List.html\" title=\"class or interface in java.util\" "
|
||||
+ "class=\"external-link\">List</a><<a href=\"http://example.com/docs/api/"
|
||||
+ "java.base/java/lang/String.html\" title=\"class or interface in java.lang\" "
|
||||
+ "class=\"external-link\">String</a>></code>\n"
|
||||
+ " <a href=\"http://example.com/docs/api/java.base/java/util/"
|
||||
+ "List.html\" title=\"class or interface in java.util\" class=\"external-link\">"
|
||||
+ "List</a><? extends <a href=\"http://example.com/docs/api/java.base/"
|
||||
+ "java/lang/CharSequence.html\" title=\"class or interface in java.lang\" "
|
||||
+ "class=\"external-link\">CharSequence</a>>\n"
|
||||
+ " <a href=\"#someMethod(java.util.List,int)\"><code>someMethod("
|
||||
+ "ArrayList<Integer>, int)</code></a>\n"
|
||||
+ " <a href=\"#otherMethod(java.util.Map,double)\"><code>otherMethod("
|
||||
+ "Map<String, StringBuilder>, double)</code></a></div>\n",
|
||||
|
||||
"<dl class=\"notes\">\n"
|
||||
+ "<dt>See Also:</dt>\n"
|
||||
+ "<dd><code><a href=\"http://example.com/docs/api/java.base/"
|
||||
+ "java/util/Map.html\" title=\"class or interface in java.util\" "
|
||||
+ "class=\"external-link\">Map</a><<a href=\"http://example.com/"
|
||||
+ "docs/api/java.base/java/lang/String.html\" title=\"class or interface "
|
||||
+ "in java.lang\" class=\"external-link\">String</a>,​? extends "
|
||||
+ "<a href=\"http://example.com/docs/api/java.base/"
|
||||
+ "java/lang/CharSequence.html\" title=\"class or interface in "
|
||||
+ "java.lang\" class=\"external-link\">CharSequence</a>></code>, \n"
|
||||
+ "<code><a href=\"http://example.com/docs/api/java.base/"
|
||||
+ "java/util/Map.html\" title=\"class or interface in java.util\" "
|
||||
+ "class=\"external-link\">Map</a><<a href=\"http://example.com/docs/api/"
|
||||
+ "java.base/java/lang/String.html\" title=\"class or interface in java.lang\" "
|
||||
+ "class=\"external-link\">String</a>,​? super <a href=\"A.html\" title=\"class in pkg1\">"
|
||||
+ "A</a><<a href=\"http://example.com/docs/api/java.base/"
|
||||
+ "java/lang/String.html\" title=\"class or interface in java.lang\" "
|
||||
+ "class=\"external-link\">String</a>,​? extends <a href=\"http://example.com/docs/api"
|
||||
+ "/java.base/java/lang/RuntimeException.html\" "
|
||||
+ "title=\"class or interface in java.lang\" class=\"external-link\">RuntimeException</a>"
|
||||
+ ">></code>, \n"
|
||||
+ "<a href=\"#someMethod(java.util.List,int)\"><code>someMethod"
|
||||
+ "(List<Number>, int)</code></a>, \n"
|
||||
+ "<a href=\"#otherMethod(java.util.Map,double)\"><code>otherMethod"
|
||||
+ "(Map<String, ? extends CharSequence>, double)</code></a></dd>\n"
|
||||
+ "</dl>");
|
||||
checkOutput("pkg1/A.SomeException.html", true,
|
||||
"<div class=\"block\"><code><a href=\"A.html\" title=\"class in pkg1\">A</a><"
|
||||
+ "<a href=\"http://example.com/docs/api/java.base/java/lang/String.html"
|
||||
+ "\" title=\"class or interface in java.lang\" class=\"external-link\">String</a>"
|
||||
+ ",​<a href=\"A.SomeException.html\" title=\"class in pkg1\">A.SomeException</a>></code>\n"
|
||||
+ " <a href=\"http://example.com/docs/api/java.base/java/util/Map.html"
|
||||
+ "\" title=\"class or interface in java.util\" class=\"external-link\">"
|
||||
+ "link to generic type with label</a></div>",
|
||||
|
||||
"<dl class=\"notes\">\n"
|
||||
+ "<dt>See Also:</dt>\n"
|
||||
+ "<dd><code><a href=\"A.html\" title=\"class in pkg1\">A</a><<a href=\"http://example.com/docs/api"
|
||||
+ "/java.base/java/lang/String.html\" "
|
||||
+ "title=\"class or interface in java.lang\" class=\"external-link\">String</a>"
|
||||
+ ",​<a href=\"A.SomeException.html\" title=\"class in pkg1\">A.SomeException</a>></code>, \n"
|
||||
+ "<a href=\"http://example.com/docs/api/java.base/"
|
||||
+ "java/util/List.html\" title=\"class or interface in java.util\" "
|
||||
+ "class=\"external-link\"><code>Link to generic type with label</code></a></dd>\n"
|
||||
+ "</dl>"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test invalid links to generic types.
|
||||
*/
|
||||
@Test
|
||||
public void testInvalidLinks() {
|
||||
javadoc("-d", "out2",
|
||||
"-sourcepath", testSrc,
|
||||
"-linkoffline", "http://example.com/docs/api/", testSrc,
|
||||
"-package", "pkg2");
|
||||
checkExit(Exit.ERROR);
|
||||
checkOutput("pkg2/B.html", true,
|
||||
"<div class=\"block\"><code>java.util.Foo<String></code>\n"
|
||||
+ " Baz<Object>\n"
|
||||
+ " <code>#b(List<Integer>)</code></div>",
|
||||
|
||||
"<dl class=\"notes\">\n"
|
||||
+ "<dt>See Also:</dt>\n"
|
||||
+ "<dd><code>java.util.List<Bar></code>, \n"
|
||||
+ "<code>Baz<Object, String></code>, \n"
|
||||
+ "<code>B#b(List<Baz>)</code></dd>\n</dl>");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module:java.base
|
||||
java.io
|
||||
java.lang
|
||||
java.util
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link List<String>}
|
||||
* {@linkplain List<? extends CharSequence>}
|
||||
* {@link #someMethod(ArrayList<Integer>, int)}
|
||||
* {@link A#otherMethod(Map<String, StringBuilder>, double)}
|
||||
*
|
||||
* @see Map<String, ? extends CharSequence>
|
||||
* @see Map<String, ? super A<String, ? extends RuntimeException>>
|
||||
* @see #someMethod(List<Number>, int)
|
||||
* @see #otherMethod(Map<String, ? extends CharSequence>, double)
|
||||
*/
|
||||
public class A<T, E extends Exception> {
|
||||
|
||||
/**
|
||||
* {@link A<String, A.SomeException>}
|
||||
* {@linkplain Map<String, ? extends CharSequence> link to generic type with label}
|
||||
*
|
||||
* @see A<String, A.SomeException>
|
||||
* @see List<String> Link to generic type with label
|
||||
*/
|
||||
static class SomeException extends Exception {}
|
||||
|
||||
/**
|
||||
* @param list a list
|
||||
* @param i an int
|
||||
*/
|
||||
public void someMethod(List<? extends Number> list, int i) {}
|
||||
|
||||
/**
|
||||
* @param list a list
|
||||
* @param d a double
|
||||
*/
|
||||
public void otherMethod(Map<String, ?> list, double d) {}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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 pkg2;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link java.util.Foo<String>}
|
||||
* {@linkplain Baz<Object>}
|
||||
* {@link #b(List<Integer>)}
|
||||
*
|
||||
* @see java.util.List<Bar>
|
||||
* @see Baz<Object, String>
|
||||
* @see B#b(List<Baz>)
|
||||
*/
|
||||
public class B {
|
||||
|
||||
public static void b(List<? extends CharSequence> l) {}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8004832 8020556 8002154 8200432
|
||||
* @bug 8004832 8020556 8002154 8200432 8177280
|
||||
* @summary Add new doclint package
|
||||
* @modules jdk.compiler/com.sun.tools.doclint
|
||||
* @build DocLintTester
|
||||
|
|
|
@ -25,22 +25,10 @@ ReferenceTest.java:44: error: invalid use of @return
|
|||
ReferenceTest.java:49: error: exception not thrown: java.lang.Exception
|
||||
* @throws Exception description
|
||||
^
|
||||
ReferenceTest.java:60: error: type arguments not allowed here
|
||||
* {@link java.util.List<String>}
|
||||
^
|
||||
ReferenceTest.java:61: error: type arguments not allowed here
|
||||
* {@link java.util.List<String>#equals}
|
||||
^
|
||||
ReferenceTest.java:62: error: type arguments not allowed here
|
||||
ReferenceTest.java:62: error: reference not found
|
||||
* {@link not.Found<String>}
|
||||
^
|
||||
ReferenceTest.java:63: error: type arguments not allowed here
|
||||
* @see java.util.List<String>
|
||||
^
|
||||
ReferenceTest.java:64: error: type arguments not allowed here
|
||||
* @see java.util.List<String>#equals
|
||||
^
|
||||
ReferenceTest.java:65: error: type arguments not allowed here
|
||||
ReferenceTest.java:65: error: reference not found
|
||||
* @see not.Found<String>
|
||||
^
|
||||
ReferenceTest.java:72: error: reference not found
|
||||
|
@ -49,6 +37,6 @@ ReferenceTest.java:72: error: reference not found
|
|||
ReferenceTest.java:75: error: reference not found
|
||||
* @see not.Found[]
|
||||
^
|
||||
16 errors
|
||||
12 errors
|
||||
1 warning
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue