8164408: Add module support for @see, @link and @linkplain javadoc tags
Reviewed-by: jjg
This commit is contained in:
parent
9a8ace2c0a
commit
ac2828ddf1
src
jdk.compiler/share/classes/com/sun/tools/javac
jdk.javadoc/share/classes/jdk/javadoc/internal/doclets
test/langtools/jdk/javadoc/doclet
@ -464,31 +464,50 @@ public class JavacTrees extends DocTrees {
|
||||
private Symbol attributeDocReference(TreePath path, DCReference ref) {
|
||||
Env<AttrContext> env = getAttrContext(path);
|
||||
if (env == null) return null;
|
||||
|
||||
if (ref.moduleName != null && ref.qualifierExpression == null && ref.memberName != null) {
|
||||
// module name and member name without type
|
||||
return null;
|
||||
}
|
||||
Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
|
||||
new Log.DeferredDiagnosticHandler(log);
|
||||
try {
|
||||
final TypeSymbol tsym;
|
||||
final Name memberName;
|
||||
final ModuleSymbol mdlsym;
|
||||
|
||||
if (ref.moduleName != null) {
|
||||
mdlsym = modules.modulesInitialized() ?
|
||||
modules.getObservableModule(names.fromString(ref.moduleName.toString()))
|
||||
: null;
|
||||
if (mdlsym == null) {
|
||||
return null;
|
||||
} else if (ref.qualifierExpression == null) {
|
||||
return mdlsym;
|
||||
}
|
||||
} else {
|
||||
mdlsym = modules.getDefaultModule();
|
||||
}
|
||||
|
||||
if (ref.qualifierExpression == null) {
|
||||
tsym = env.enclClass.sym;
|
||||
memberName = (Name) ref.memberName;
|
||||
} else {
|
||||
// newSeeTree if the qualifierExpression is a type or package name.
|
||||
// javac does not provide the exact method required, so
|
||||
// we first check if qualifierExpression identifies a type,
|
||||
// and if not, then we check to see if it identifies a package.
|
||||
Type t = attr.attribType(ref.qualifierExpression, env);
|
||||
if (t.isErroneous()) {
|
||||
// Check if qualifierExpression is a type or package, using the methods javac provides.
|
||||
// If no module name is given we check if qualifierExpression identifies a type.
|
||||
// If that fails or we have a module name, use that to resolve qualifierExpression to
|
||||
// a package or type.
|
||||
Type t = ref.moduleName == null ? attr.attribType(ref.qualifierExpression, env) : null;
|
||||
|
||||
if (t == null || t.isErroneous()) {
|
||||
JCCompilationUnit toplevel =
|
||||
treeMaker.TopLevel(List.nil());
|
||||
final ModuleSymbol msym = modules.getDefaultModule();
|
||||
toplevel.modle = msym;
|
||||
toplevel.packge = msym.unnamedPackage;
|
||||
toplevel.modle = mdlsym;
|
||||
toplevel.packge = mdlsym.unnamedPackage;
|
||||
Symbol sym = attr.attribIdent(ref.qualifierExpression, toplevel);
|
||||
|
||||
if (sym == null)
|
||||
if (sym == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
sym.complete();
|
||||
|
||||
@ -500,7 +519,15 @@ public class JavacTrees extends DocTrees {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT)) {
|
||||
if (modules.modulesInitialized() && ref.moduleName == null && ref.memberName == null) {
|
||||
// package/type does not exist, check if there is a matching module
|
||||
ModuleSymbol moduleSymbol = modules.getObservableModule(names.fromString(ref.signature));
|
||||
if (moduleSymbol != null) {
|
||||
return moduleSymbol;
|
||||
}
|
||||
}
|
||||
if (ref.qualifierExpression.hasTag(JCTree.Tag.IDENT) && ref.moduleName == null
|
||||
&& ref.memberName == null) {
|
||||
// fixup: allow "identifier" instead of "#identifier"
|
||||
// for compatibility with javadoc
|
||||
tsym = env.enclClass.sym;
|
||||
@ -513,7 +540,7 @@ public class JavacTrees extends DocTrees {
|
||||
Type e = t;
|
||||
// If this is an array type convert to element type
|
||||
while (e instanceof ArrayType)
|
||||
e = ((ArrayType)e).elemtype;
|
||||
e = ((ArrayType) e).elemtype;
|
||||
tsym = e.tsym;
|
||||
memberName = (Name) ref.memberName;
|
||||
}
|
||||
|
@ -428,9 +428,9 @@ public class DocCommentParser {
|
||||
* Matching pairs of {@literal < >} are skipped. The text is terminated by the first
|
||||
* unmatched }. It is an error if the beginning of the next tag is detected.
|
||||
*/
|
||||
// TODO: allowMember is currently ignored
|
||||
// TODO: boolean allowMember should be enum FORBID, ALLOW, REQUIRE
|
||||
// TODO: improve quality of parse to forbid bad constructions.
|
||||
// TODO: update to use ReferenceParser
|
||||
@SuppressWarnings("fallthrough")
|
||||
protected DCReference reference(boolean allowMember) throws ParseException {
|
||||
int pos = bp;
|
||||
@ -485,91 +485,17 @@ public class DocCommentParser {
|
||||
|
||||
String sig = newString(pos, bp);
|
||||
|
||||
// Break sig apart into qualifiedExpr member paramTypes.
|
||||
JCTree qualExpr;
|
||||
Name member;
|
||||
List<JCTree> paramTypes;
|
||||
|
||||
Log.DeferredDiagnosticHandler deferredDiagnosticHandler
|
||||
= new Log.DeferredDiagnosticHandler(fac.log);
|
||||
|
||||
try {
|
||||
int hash = sig.indexOf("#");
|
||||
int lparen = sig.indexOf("(", hash + 1);
|
||||
if (hash == -1) {
|
||||
if (lparen == -1) {
|
||||
qualExpr = parseType(sig);
|
||||
member = null;
|
||||
} else {
|
||||
qualExpr = null;
|
||||
member = parseMember(sig.substring(0, lparen));
|
||||
}
|
||||
} else {
|
||||
qualExpr = (hash == 0) ? null : parseType(sig.substring(0, hash));
|
||||
if (lparen == -1)
|
||||
member = parseMember(sig.substring(hash + 1));
|
||||
else
|
||||
member = parseMember(sig.substring(hash + 1, lparen));
|
||||
}
|
||||
|
||||
if (lparen < 0) {
|
||||
paramTypes = null;
|
||||
} else {
|
||||
int rparen = sig.indexOf(")", lparen);
|
||||
if (rparen != sig.length() - 1)
|
||||
throw new ParseException("dc.ref.bad.parens");
|
||||
paramTypes = parseParams(sig.substring(lparen + 1, rparen));
|
||||
}
|
||||
|
||||
if (!deferredDiagnosticHandler.getDiagnostics().isEmpty())
|
||||
throw new ParseException("dc.ref.syntax.error");
|
||||
|
||||
} finally {
|
||||
fac.log.popDiagnosticHandler(deferredDiagnosticHandler);
|
||||
ReferenceParser.Reference ref = new ReferenceParser(fac).parse(sig);
|
||||
return m.at(pos).newReferenceTree(sig,
|
||||
ref.moduleName, ref.qualExpr,
|
||||
ref.member, ref.paramTypes)
|
||||
.setEndPos(bp);
|
||||
} catch (ReferenceParser.ParseException parseException) {
|
||||
throw new ParseException(parseException.getMessage());
|
||||
}
|
||||
|
||||
return m.at(pos).newReferenceTree(sig, qualExpr, member, paramTypes).setEndPos(bp);
|
||||
}
|
||||
|
||||
JCTree parseType(String s) throws ParseException {
|
||||
JavacParser p = fac.newParser(s, false, false, false);
|
||||
JCTree tree = p.parseType();
|
||||
if (p.token().kind != TokenKind.EOF)
|
||||
throw new ParseException("dc.ref.unexpected.input");
|
||||
return tree;
|
||||
}
|
||||
|
||||
Name parseMember(String s) throws ParseException {
|
||||
JavacParser p = fac.newParser(s, false, false, false);
|
||||
Name name = p.ident();
|
||||
if (p.token().kind != TokenKind.EOF)
|
||||
throw new ParseException("dc.ref.unexpected.input");
|
||||
return name;
|
||||
}
|
||||
|
||||
List<JCTree> parseParams(String s) throws ParseException {
|
||||
if (s.trim().isEmpty())
|
||||
return List.nil();
|
||||
|
||||
JavacParser p = fac.newParser(s.replace("...", "[]"), false, false, false);
|
||||
ListBuffer<JCTree> paramTypes = new ListBuffer<>();
|
||||
paramTypes.add(p.parseType());
|
||||
|
||||
if (p.token().kind == TokenKind.IDENTIFIER)
|
||||
p.nextToken();
|
||||
|
||||
while (p.token().kind == TokenKind.COMMA) {
|
||||
p.nextToken();
|
||||
paramTypes.add(p.parseType());
|
||||
|
||||
if (p.token().kind == TokenKind.IDENTIFIER)
|
||||
p.nextToken();
|
||||
}
|
||||
|
||||
if (p.token().kind != TokenKind.EOF)
|
||||
throw new ParseException("dc.ref.unexpected.input");
|
||||
|
||||
return paramTypes.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,6 +47,7 @@ public class ReferenceParser {
|
||||
* Any, but not all, of the member fields may be null.
|
||||
*/
|
||||
static public class Reference {
|
||||
public final JCTree.JCExpression moduleName;
|
||||
/** The type, if any, in the signature. */
|
||||
public final JCTree qualExpr;
|
||||
/** The member name, if any, in the signature. */
|
||||
@ -54,7 +55,8 @@ public class ReferenceParser {
|
||||
/** The parameter types, if any, in the signature. */
|
||||
public final List<JCTree> paramTypes;
|
||||
|
||||
Reference(JCTree qualExpr, Name member, List<JCTree> paramTypes) {
|
||||
Reference(JCTree.JCExpression moduleName, JCTree qualExpr, Name member, List<JCTree> paramTypes) {
|
||||
this.moduleName = moduleName;
|
||||
this.qualExpr = qualExpr;
|
||||
this.member = member;
|
||||
this.paramTypes = paramTypes;
|
||||
@ -89,7 +91,8 @@ public class ReferenceParser {
|
||||
*/
|
||||
public Reference parse(String sig) throws ParseException {
|
||||
|
||||
// Break sig apart into qualifiedExpr member paramTypes.
|
||||
// Break sig apart into moduleName qualifiedExpr member paramTypes.
|
||||
JCTree.JCExpression moduleName;
|
||||
JCTree qualExpr;
|
||||
Name member;
|
||||
List<JCTree> paramTypes;
|
||||
@ -98,18 +101,27 @@ public class ReferenceParser {
|
||||
= new Log.DeferredDiagnosticHandler(fac.log);
|
||||
|
||||
try {
|
||||
int hash = sig.indexOf("#");
|
||||
int lparen = sig.indexOf("(", hash + 1);
|
||||
if (hash == -1) {
|
||||
int slash = sig.indexOf("/");
|
||||
int hash = sig.indexOf("#", slash + 1);
|
||||
int lparen = sig.indexOf("(", Math.max(slash, hash) + 1);
|
||||
if (slash > -1) {
|
||||
moduleName = parseModule(sig.substring(0, slash));
|
||||
} else {
|
||||
moduleName = null;
|
||||
}
|
||||
if (slash > 0 && sig.length() == slash + 1) {
|
||||
qualExpr = null;
|
||||
member = null;
|
||||
} else if (hash == -1) {
|
||||
if (lparen == -1) {
|
||||
qualExpr = parseType(sig);
|
||||
qualExpr = parseType(sig.substring(slash + 1));
|
||||
member = null;
|
||||
} else {
|
||||
qualExpr = null;
|
||||
member = parseMember(sig.substring(0, lparen));
|
||||
member = parseMember(sig.substring(slash + 1, lparen));
|
||||
}
|
||||
} else {
|
||||
qualExpr = (hash == 0) ? null : parseType(sig.substring(0, hash));
|
||||
qualExpr = (hash == slash + 1) ? null : parseType(sig.substring(slash + 1, hash));
|
||||
if (lparen == -1)
|
||||
member = parseMember(sig.substring(hash + 1));
|
||||
else
|
||||
@ -132,7 +144,15 @@ public class ReferenceParser {
|
||||
fac.log.popDiagnosticHandler(deferredDiagnosticHandler);
|
||||
}
|
||||
|
||||
return new Reference(qualExpr, member, paramTypes);
|
||||
return new Reference(moduleName, qualExpr, member, paramTypes);
|
||||
}
|
||||
|
||||
private JCTree.JCExpression parseModule(String s) throws ParseException {
|
||||
JavacParser p = fac.newParser(s, false, false, false);
|
||||
JCTree.JCExpression expr = p.qualident(false);
|
||||
if (p.token().kind != TokenKind.EOF)
|
||||
throw new ParseException("dc.ref.unexpected.input");
|
||||
return expr;
|
||||
}
|
||||
|
||||
private JCTree parseType(String s) throws ParseException {
|
||||
|
@ -647,13 +647,15 @@ public abstract class DCTree implements DocTree {
|
||||
|
||||
// The following are not directly exposed through ReferenceTree
|
||||
// use DocTrees.getElement(DocTreePath)
|
||||
public final JCTree.JCExpression moduleName;
|
||||
public final JCTree qualifierExpression;
|
||||
public final Name memberName;
|
||||
public final List<JCTree> paramTypes;
|
||||
|
||||
|
||||
DCReference(String signature, JCTree qualExpr, Name member, List<JCTree> paramTypes) {
|
||||
DCReference(String signature, JCTree.JCExpression moduleName, JCTree qualExpr, Name member, List<JCTree> paramTypes) {
|
||||
this.signature = signature;
|
||||
this.moduleName = moduleName;
|
||||
qualifierExpression = qualExpr;
|
||||
memberName = member;
|
||||
this.paramTypes = paramTypes;
|
||||
|
@ -378,7 +378,7 @@ public class DocTreeMaker implements DocTreeFactory {
|
||||
public DCReference newReferenceTree(String signature) {
|
||||
try {
|
||||
ReferenceParser.Reference ref = referenceParser.parse(signature);
|
||||
DCReference tree = new DCReference(signature, ref.qualExpr, ref.member, ref.paramTypes);
|
||||
DCReference tree = new DCReference(signature, ref.moduleName, ref.qualExpr, ref.member, ref.paramTypes);
|
||||
tree.pos = pos;
|
||||
return tree;
|
||||
} catch (ReferenceParser.ParseException e) {
|
||||
@ -386,8 +386,8 @@ public class DocTreeMaker implements DocTreeFactory {
|
||||
}
|
||||
}
|
||||
|
||||
public DCReference newReferenceTree(String signature, JCTree qualExpr, Name member, List<JCTree> paramTypes) {
|
||||
DCReference tree = new DCReference(signature, qualExpr, member, paramTypes);
|
||||
public DCReference newReferenceTree(String signature, JCTree.JCExpression moduleName, JCTree qualExpr, Name member, List<JCTree> paramTypes) {
|
||||
DCReference tree = new DCReference(signature, moduleName, qualExpr, member, paramTypes);
|
||||
tree.pos = pos;
|
||||
return tree;
|
||||
}
|
||||
|
@ -998,7 +998,7 @@ public class HtmlDocletWriter {
|
||||
|
||||
CommentHelper ch = utils.getCommentHelper(element);
|
||||
String tagName = ch.getTagName(see);
|
||||
String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see)).toString());
|
||||
String seetext = replaceDocRootDir(removeTrailingSlash(utils.normalizeNewlines(ch.getText(see)).toString()));
|
||||
// Check if @see is an href or "string"
|
||||
if (seetext.startsWith("<") || seetext.startsWith("\"")) {
|
||||
return new RawHtml(seetext);
|
||||
@ -1010,7 +1010,6 @@ public class HtmlDocletWriter {
|
||||
Content text = plainOrCode(kind == LINK_PLAIN, new RawHtml(seetext));
|
||||
|
||||
TypeElement refClass = ch.getReferencedClass(see);
|
||||
String refClassName = ch.getReferencedClassName(see);
|
||||
Element refMem = ch.getReferencedMember(see);
|
||||
String refMemName = ch.getReferencedMemberName(see);
|
||||
|
||||
@ -1018,6 +1017,10 @@ public class HtmlDocletWriter {
|
||||
refMemName = refMem.toString();
|
||||
}
|
||||
if (refClass == null) {
|
||||
ModuleElement refModule = ch.getReferencedModule(see);
|
||||
if (refModule != null && utils.isIncluded(refModule)) {
|
||||
return getModuleLink(refModule, label.isEmpty() ? text : label);
|
||||
}
|
||||
//@see is not referencing an included class
|
||||
PackageElement refPackage = ch.getReferencedPackage(see);
|
||||
if (refPackage != null && utils.isIncluded(refPackage)) {
|
||||
@ -1028,9 +1031,11 @@ public class HtmlDocletWriter {
|
||||
return getPackageLink(refPackage, label);
|
||||
} else {
|
||||
// @see is not referencing an included class, module or package. Check for cross links.
|
||||
DocLink elementCrossLink = (configuration.extern.isModule(refClassName))
|
||||
? getCrossModuleLink(utils.elementUtils.getModuleElement(refClassName)) :
|
||||
(refPackage != null) ? getCrossPackageLink(refPackage) : null;
|
||||
String refModuleName = ch.getReferencedModuleName(see);
|
||||
DocLink elementCrossLink = (refPackage != null) ? getCrossPackageLink(refPackage) :
|
||||
(configuration.extern.isModule(refModuleName))
|
||||
? getCrossModuleLink(utils.elementUtils.getModuleElement(refModuleName))
|
||||
: null;
|
||||
if (elementCrossLink != null) {
|
||||
// Element cross link found
|
||||
return links.createLink(elementCrossLink,
|
||||
@ -1118,6 +1123,10 @@ public class HtmlDocletWriter {
|
||||
}
|
||||
}
|
||||
|
||||
private String removeTrailingSlash(String s) {
|
||||
return s.endsWith("/") ? s.substring(0, s.length() -1) : s;
|
||||
}
|
||||
|
||||
private Content plainOrCode(boolean plain, Content body) {
|
||||
return (plain || body.isEmpty()) ? body : HtmlTree.CODE(body);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.ModuleElement;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
@ -376,23 +376,18 @@ public class CommentHelper {
|
||||
return null;
|
||||
} else if (utils.isTypeElement(e)) {
|
||||
return (TypeElement) e;
|
||||
} else if (!utils.isPackage(e)) {
|
||||
} else if (!utils.isPackage(e) && !utils.isModule(e)) {
|
||||
return utils.getEnclosingTypeElement(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getReferencedClassName(DocTree dtree) {
|
||||
Utils utils = configuration.utils;
|
||||
Element e = getReferencedClass(dtree);
|
||||
if (e != null) {
|
||||
return utils.isTypeElement(e) ? utils.getSimpleName(e) : null;
|
||||
}
|
||||
public String getReferencedModuleName(DocTree dtree) {
|
||||
String s = getReferencedSignature(dtree);
|
||||
if (s == null) {
|
||||
if (s == null || s.contains("#") || s.contains("(")) {
|
||||
return null;
|
||||
}
|
||||
int n = s.indexOf("#");
|
||||
int n = s.indexOf("/");
|
||||
return (n == -1) ? s : s.substring(0, n);
|
||||
}
|
||||
|
||||
@ -423,6 +418,15 @@ public class CommentHelper {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModuleElement getReferencedModule(DocTree dtree) {
|
||||
Element e = getReferencedElement(dtree);
|
||||
if (e != null && configuration.utils.isModule(e)) {
|
||||
return (ModuleElement) e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public List<? extends DocTree> getFirstSentenceTrees(List<? extends DocTree> body) {
|
||||
return configuration.docEnv.getDocTrees().getFirstSentence(body);
|
||||
}
|
||||
|
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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 8164408
|
||||
* @summary Add module support for see, link and linkplain javadoc tags
|
||||
* @library /tools/lib ../../lib
|
||||
* @modules
|
||||
* jdk.javadoc/jdk.javadoc.internal.tool
|
||||
* jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
* @build javadoc.tester.*
|
||||
* @run main TestLinkTagletWithModule
|
||||
*/
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import builder.ClassBuilder;
|
||||
import builder.ClassBuilder.*;
|
||||
import toolbox.ModuleBuilder;
|
||||
import toolbox.ToolBox;
|
||||
|
||||
import javadoc.tester.JavadocTester;
|
||||
|
||||
public class TestLinkTagletWithModule extends JavadocTester {
|
||||
|
||||
final ToolBox tb;
|
||||
private final Path src;
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
TestLinkTagletWithModule tester = new TestLinkTagletWithModule();
|
||||
tester.runTests(m -> new Object[]{Paths.get(m.getName())});
|
||||
}
|
||||
|
||||
TestLinkTagletWithModule() throws Exception {
|
||||
tb = new ToolBox();
|
||||
src = Paths.get("src");
|
||||
generateSources();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkModuleInternal(Path base) throws Exception {
|
||||
Path out = base.resolve("out");
|
||||
|
||||
javadoc("-d", out.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "m1,m2,m3",
|
||||
"m2/com.m2.lib");
|
||||
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("m3/com/m3/app/App.html", true,
|
||||
"""
|
||||
<div class="block"><a href="../../../../m1/module-summary.html"><code>m1</code></a>
|
||||
<a href="../../../../m1/module-summary.html"><code>m1</code></a>
|
||||
<a href="../../../../m1/com/m1/lib/package-summary.html"><code>package link</code></a>
|
||||
<a href="../../../../m1/com/m1/lib/Lib.html" title="class in com.m1.lib"><code>Lib</code></a>
|
||||
<a href="../../../../m1/com/m1/lib/Lib.html#method(java.lang.String)"><code>Lib.method(java.lang.String)</code></a>
|
||||
<a href="../../../../m1/com/m1/lib/Lib.html#method(java.lang.String)"><code>Lib.method(String)</code></a>
|
||||
<a href="../../../../m2/module-summary.html">m2</a>
|
||||
<a href="../../../../m2/module-summary.html">m2</a>
|
||||
<a href="../../../../m2/com/m2/lib/package-summary.html">com.m2.lib</a>
|
||||
<a href="../../../../m2/com/m2/lib/Lib.html" title="class in com.m2.lib">Lib</a>
|
||||
<a href="../../../../m2/com/m2/lib/Lib.html#method(java.lang.String)">class link</a>
|
||||
<a href="../../../../m2/com/m2/lib/Lib.html#method(java.lang.String)">Lib.method(String)</a></div>
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkModuleExternal(Path base) throws Exception {
|
||||
Path out1 = base.resolve("out1"), out2 = base.resolve("out2");
|
||||
|
||||
javadoc("-d", out1.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "m1,m2",
|
||||
"m2/com.m2.lib");
|
||||
javadoc("-d", out2.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--add-modules", "m2",
|
||||
"--module", "m3",
|
||||
"-link", "../" + out1.getFileName());
|
||||
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("m3/com/m3/app/App.html", true,
|
||||
"""
|
||||
<div class="block"><a href="../../../../../out1/m1/module-summary.html" class="external-link"><code>m1</code></a>
|
||||
<a href="../../../../../out1/m1/module-summary.html" class="external-link"><code>m1</code></a>
|
||||
<a href="../../../../../out1/m1/com/m1/lib/package-summary.html" class="external-link"><code>package link</code></a>
|
||||
<a href="../../../../../out1/m1/com/m1/lib/Lib.html" title="class or interface in com.m1.lib"\
|
||||
class="external-link"><code>Lib</code></a>
|
||||
<a href="../../../../../out1/m1/com/m1/lib/Lib.html#method(java.lang.String)" title="class or\
|
||||
interface in com.m1.lib" class="external-link"><code>Lib.method(java.lang.String)</code></a>
|
||||
<a href="../../../../../out1/m1/com/m1/lib/Lib.html#method(java.lang.String)" title="class or\
|
||||
interface in com.m1.lib" class="external-link"><code>Lib.method(String)</code></a>
|
||||
<a href="../../../../../out1/m2/module-summary.html" class="external-link">m2</a>
|
||||
<a href="../../../../../out1/m2/module-summary.html" class="external-link">m2</a>
|
||||
<a href="../../../../../out1/m2/com/m2/lib/package-summary.html" class="external-link">m2/com.m2.lib</a>
|
||||
<a href="../../../../../out1/m2/com/m2/lib/Lib.html" title="class or interface in com.m2.lib" class="external-link">Lib</a>
|
||||
<a href="../../../../../out1/m2/com/m2/lib/Lib.html#method(java.lang.String)" title="class or\
|
||||
interface in com.m2.lib" class="external-link">class link</a>
|
||||
<a href="../../../../../out1/m2/com/m2/lib/Lib.html#method(java.lang.String)" title="class or\
|
||||
interface in com.m2.lib" class="external-link">Lib.method(String)</a></div>
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkModuleSameNameInternal(Path base) throws Exception {
|
||||
Path out = base.resolve("out");
|
||||
|
||||
javadoc("-d", out.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "com.ex1,com.ex2");
|
||||
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("com.ex2/com/ex2/B.html", true,
|
||||
"""
|
||||
<div class="block"><a href="../../../com.ex1/com/ex1/package-summary.html"><code>package link</code></a>
|
||||
<a href="../../../com.ex1/module-summary.html"><code>module link</code></a>
|
||||
<a href="../../../com.ex1/com/ex1/package-summary.html"><code>com.ex1</code></a>
|
||||
<a href="../../../com.ex1/com/ex1/A.html" title="class in com.ex1"><code>class link</code></a>
|
||||
<a href="../../../com.ex1/com/ex1/A.html#m()"><code>A.m()</code></a>
|
||||
<a href="../../../com.ex1/com/ex1/A.html#m()"><code>A.m()</code></a>
|
||||
<a href="package-summary.html"><code>com.ex2</code></a>
|
||||
<a href="../../module-summary.html"><code>com.ex2</code></a></div>
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkModuleSameNameExternal(Path base) throws Exception {
|
||||
Path out1 = base.resolve("out1"), out2 = base.resolve("out2");
|
||||
|
||||
javadoc("-d", out1.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "com.ex1");
|
||||
javadoc("-d", out2.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "com.ex2",
|
||||
"-link", "../" + out1.getFileName());
|
||||
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("com.ex2/com/ex2/B.html", true,
|
||||
"""
|
||||
<div class="block"><a href="../../../../out1/com.ex1/com/ex1/package-summary.html" class="external-link"><code>package link</code></a>
|
||||
<a href="../../../../out1/com.ex1/module-summary.html" class="external-link"><code>module link</code></a>
|
||||
<a href="../../../../out1/com.ex1/com/ex1/package-summary.html" class="external-link"><code>com.ex1/com.ex1</code></a>
|
||||
<a href="../../../../out1/com.ex1/com/ex1/A.html" title="class or interface in com.ex1" class="external-link"><code>class link</code></a>
|
||||
<a href="../../../../out1/com.ex1/com/ex1/A.html#m()" title="class or interface in com.ex1" class="external-link"><code>A.m()</code></a>
|
||||
<a href="../../../../out1/com.ex1/com/ex1/A.html#m()" title="class or interface in com.ex1" class="external-link"><code>A.m()</code></a>
|
||||
<a href="package-summary.html"><code>com.ex2</code></a>
|
||||
<a href="../../module-summary.html"><code>com.ex2</code></a></div>
|
||||
""");
|
||||
}
|
||||
void generateSources() throws Exception {
|
||||
new ModuleBuilder(tb, "m1")
|
||||
.exports("com.m1.lib")
|
||||
.classes("""
|
||||
package com.m1.lib;
|
||||
public class Lib {
|
||||
public String method(String s) {
|
||||
return s;
|
||||
}
|
||||
}""")
|
||||
.write(src);
|
||||
new ModuleBuilder(tb, "m2")
|
||||
.classes("""
|
||||
package com.m2.lib;
|
||||
public class Lib {
|
||||
public String method(String s) {
|
||||
return s;
|
||||
}
|
||||
}""")
|
||||
.write(src);
|
||||
new ModuleBuilder(tb, "m3")
|
||||
.exports("com.m3.app")
|
||||
.requires("m1")
|
||||
.classes("""
|
||||
package com.m3.app;\s
|
||||
public class App{
|
||||
/**
|
||||
* {@link m1}
|
||||
* {@link m1/}
|
||||
* {@link m1/com.m1.lib package link}
|
||||
* {@link m1/com.m1.lib.Lib}
|
||||
* {@link m1/com.m1.lib.Lib#method}
|
||||
* {@link m1/com.m1.lib.Lib#method(String)}
|
||||
* {@linkplain m2}
|
||||
* {@linkplain m2/}
|
||||
* {@linkplain m2/com.m2.lib}
|
||||
* {@linkplain m2/com.m2.lib.Lib}
|
||||
* {@linkplain m2/com.m2.lib.Lib#method class link}
|
||||
* {@linkplain m2/com.m2.lib.Lib#method(String)}
|
||||
*/
|
||||
public App(){}
|
||||
}
|
||||
""")
|
||||
.write(src);
|
||||
|
||||
new ModuleBuilder(tb, "com.ex1")
|
||||
.exports("com.ex1")
|
||||
.classes("""
|
||||
package com.ex1;
|
||||
public class A{
|
||||
public void m() {}
|
||||
}""",
|
||||
"""
|
||||
package com.ex1;
|
||||
public class B {}""")
|
||||
.write(src);
|
||||
|
||||
new ModuleBuilder(tb, "com.ex2")
|
||||
.requires("com.ex1")
|
||||
.exports("com.ex2")
|
||||
.classes("""
|
||||
package com.ex2;\s
|
||||
import com.ex1.A;
|
||||
public class B{
|
||||
/**
|
||||
* {@link com.ex1 package link}
|
||||
* {@link com.ex1/ module link}
|
||||
* {@link com.ex1/com.ex1}
|
||||
* {@link com.ex1/com.ex1.A class link}
|
||||
* {@link com.ex1/com.ex1.A#m}
|
||||
* {@link com.ex1/com.ex1.A#m()}
|
||||
* {@link com.ex2}
|
||||
* {@link com.ex2/}
|
||||
*/
|
||||
public B(A obj){}
|
||||
}
|
||||
""")
|
||||
.write(src);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* 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 8164408
|
||||
* @summary Add module support for see, link and linkplain javadoc tags
|
||||
* @library /tools/lib ../../lib
|
||||
* @modules
|
||||
* jdk.javadoc/jdk.javadoc.internal.tool
|
||||
* jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
* @build javadoc.tester.*
|
||||
* @run main TestSeeTagWithModule
|
||||
*/
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import builder.ClassBuilder;
|
||||
import builder.ClassBuilder.*;
|
||||
import toolbox.ModuleBuilder;
|
||||
import toolbox.ToolBox;
|
||||
|
||||
import javadoc.tester.JavadocTester;
|
||||
|
||||
public class TestSeeTagWithModule extends JavadocTester {
|
||||
|
||||
final ToolBox tb;
|
||||
private final Path src;
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
TestSeeTagWithModule tester = new TestSeeTagWithModule();
|
||||
tester.runTests(m -> new Object[]{Paths.get(m.getName())});
|
||||
}
|
||||
|
||||
TestSeeTagWithModule() throws Exception {
|
||||
tb = new ToolBox();
|
||||
src = Paths.get("src");
|
||||
generateSources();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeeModuleInternal(Path base) throws Exception {
|
||||
Path out = base.resolve("out");
|
||||
|
||||
javadoc("-d", out.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "m1,m2,m3",
|
||||
"m2/com.m2.lib");
|
||||
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("m3/com/m3/app/App.html", true,
|
||||
"""
|
||||
<dt>See Also:</dt>
|
||||
<dd><a href="../../../../m1/module-summary.html"><code>m1</code></a>,\s
|
||||
<a href="../../../../m1/module-summary.html"><code>m1</code></a>,\s
|
||||
<a href="../../../../m1/com/m1/lib/package-summary.html"><code>com.m1.lib</code></a>,\s
|
||||
<a href="../../../../m1/com/m1/lib/Lib.html" title="class in com.m1.lib"><code>Lib</code></a>,\s
|
||||
<a href="../../../../m1/com/m1/lib/Lib.html#method(java.lang.String)"><code>Lib.method(java.lang.String)</code></a>,\s
|
||||
<a href="../../../../m1/com/m1/lib/Lib.html#method(java.lang.String)"><code>Lib.method(String)</code></a>,\s
|
||||
<a href="../../../../m2/module-summary.html"><code>m2</code></a>,\s
|
||||
<a href="../../../../m2/module-summary.html"><code>m2</code></a>,\s
|
||||
<a href="../../../../m2/com/m2/lib/package-summary.html"><code>com.m2.lib</code></a>,\s
|
||||
<a href="../../../../m2/com/m2/lib/Lib.html" title="class in com.m2.lib"><code>Lib</code></a>,\s
|
||||
<a href="../../../../m2/com/m2/lib/Lib.html#method(java.lang.String)"><code>Lib.method(java.lang.String)</code></a>,\s
|
||||
<a href="../../../../m2/com/m2/lib/Lib.html#method(java.lang.String)"><code>Lib.method(String)</code></a></dd>
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeeModuleExternal(Path base) throws Exception {
|
||||
Path out1 = base.resolve("out1"), out2 = base.resolve("out2");
|
||||
|
||||
javadoc("-d", out1.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "m1,m2",
|
||||
"m2/com.m2.lib");
|
||||
javadoc("-d", out2.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--add-modules", "m2",
|
||||
"--module", "m3",
|
||||
"-link", "../" + out1.getFileName());
|
||||
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("m3/com/m3/app/App.html", true,
|
||||
"""
|
||||
<dt>See Also:</dt>
|
||||
<dd><a href="../../../../../out1/m1/module-summary.html" class="external-link"><code>m1</code></a>,\s
|
||||
<a href="../../../../../out1/m1/module-summary.html" class="external-link"><code>m1</code></a>,\s
|
||||
<a href="../../../../../out1/m1/com/m1/lib/package-summary.html" class="external-link"><code>m1/com.m1.lib</code></a>,\s
|
||||
<a href="../../../../../out1/m1/com/m1/lib/Lib.html" title="class or interface in com.m1.lib" class="external-link"><code>Lib</code></a>,\s
|
||||
<a href="../../../../../out1/m1/com/m1/lib/Lib.html#method(java.lang.String)" title="class or \
|
||||
interface in com.m1.lib" class="external-link"><code>Lib.method(java.lang.String)</code></a>,\s
|
||||
<a href="../../../../../out1/m1/com/m1/lib/Lib.html#method(java.lang.String)" title="class or \
|
||||
interface in com.m1.lib" class="external-link"><code>Lib.method(String)</code></a>,\s
|
||||
<a href="../../../../../out1/m2/module-summary.html" class="external-link"><code>m2</code></a>,\s
|
||||
<a href="../../../../../out1/m2/module-summary.html" class="external-link"><code>m2</code></a>,\s
|
||||
<a href="../../../../../out1/m2/com/m2/lib/package-summary.html" class="external-link"><code>m2/com.m2.lib</code></a>,\s
|
||||
<a href="../../../../../out1/m2/com/m2/lib/Lib.html" title="class or interface in com.m2.lib" class="external-link"><code>Lib</code></a>,\s
|
||||
<a href="../../../../../out1/m2/com/m2/lib/Lib.html#method(java.lang.String)" title="class or \
|
||||
interface in com.m2.lib" class="external-link"><code>Lib.method(java.lang.String)</code></a>,\s
|
||||
<a href="../../../../../out1/m2/com/m2/lib/Lib.html#method(java.lang.String)" title="class or \
|
||||
interface in com.m2.lib" class="external-link"><code>Lib.method(String)</code></a></dd>
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeeModuleSameNameInternal(Path base) throws Exception {
|
||||
Path out = base.resolve("out");
|
||||
|
||||
javadoc("-d", out.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "com.ex1,com.ex2");
|
||||
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("com.ex2/com/ex2/B.html", true,
|
||||
"""
|
||||
<dt>See Also:</dt>
|
||||
<dd><a href="../../../com.ex1/com/ex1/package-summary.html"><code>com.ex1</code></a>,\s
|
||||
<a href="../../../com.ex1/module-summary.html"><code>com.ex1</code></a>,\s
|
||||
<a href="../../../com.ex1/com/ex1/package-summary.html"><code>com.ex1</code></a>,\s
|
||||
<a href="../../../com.ex1/com/ex1/A.html" title="class in com.ex1"><code>A</code></a>,\s
|
||||
<a href="../../../com.ex1/com/ex1/A.html#m()"><code>A.m()</code></a>,\s
|
||||
<a href="../../../com.ex1/com/ex1/A.html#m()"><code>A.m()</code></a>,\s
|
||||
<a href="package-summary.html"><code>com.ex2</code></a>,\s
|
||||
<a href="../../module-summary.html"><code>com.ex2</code></a></dd>
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeeModuleSameNameExternal(Path base) throws Exception {
|
||||
Path out1 = base.resolve("out1"), out2 = base.resolve("out2");
|
||||
|
||||
javadoc("-d", out1.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "com.ex1");
|
||||
javadoc("-d", out2.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "com.ex2",
|
||||
"-link", "../" + out1.getFileName());
|
||||
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("com.ex2/com/ex2/B.html", true,
|
||||
"""
|
||||
<dt>See Also:</dt>
|
||||
<dd><a href="../../../../out1/com.ex1/com/ex1/package-summary.html" class="external-link"><code>com.ex1</code></a>,\s
|
||||
<a href="../../../../out1/com.ex1/module-summary.html" class="external-link"><code>com.ex1</code></a>,\s
|
||||
<a href="../../../../out1/com.ex1/com/ex1/package-summary.html" class="external-link"><code>com.ex1/com.ex1</code></a>,\s
|
||||
<a href="../../../../out1/com.ex1/com/ex1/A.html" title="class or interface in com.ex1" class="external-link"><code>A</code></a>,\s
|
||||
<a href="../../../../out1/com.ex1/com/ex1/A.html#m()" title="class or interface in com.ex1" class="external-link"><code>A.m()</code></a>,\s
|
||||
<a href="../../../../out1/com.ex1/com/ex1/A.html#m()" title="class or interface in com.ex1" class="external-link"><code>A.m()</code></a>,\s
|
||||
<a href="package-summary.html"><code>com.ex2</code></a>,\s
|
||||
<a href="../../module-summary.html"><code>com.ex2</code></a></dd>
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingType(Path base) throws Exception {
|
||||
Path out = base.resolve("outMissingType");
|
||||
|
||||
javadoc("-d", out.toString(),
|
||||
"--module-source-path", src.toString(),
|
||||
"--module", "fail");
|
||||
|
||||
checkExit(Exit.ERROR);
|
||||
}
|
||||
|
||||
void generateSources() throws Exception {
|
||||
new ModuleBuilder(tb, "m1")
|
||||
.exports("com.m1.lib")
|
||||
.classes("""
|
||||
package com.m1.lib;
|
||||
public class Lib {
|
||||
public String method(String s) {
|
||||
return s;
|
||||
}
|
||||
}""")
|
||||
.write(src);
|
||||
new ModuleBuilder(tb, "m2")
|
||||
.classes("""
|
||||
package com.m2.lib;
|
||||
public class Lib {
|
||||
public String method(String s) {
|
||||
return s;
|
||||
}
|
||||
}""")
|
||||
.write(src);
|
||||
new ModuleBuilder(tb, "m3")
|
||||
.exports("com.m3.app")
|
||||
.requires("m1")
|
||||
.classes("""
|
||||
package com.m3.app;\s
|
||||
public class App{
|
||||
/**
|
||||
* @see m1
|
||||
* @see m1/
|
||||
* @see m1/com.m1.lib
|
||||
* @see m1/com.m1.lib.Lib
|
||||
* @see m1/com.m1.lib.Lib#method
|
||||
* @see m1/com.m1.lib.Lib#method(String)
|
||||
* @see m2
|
||||
* @see m2/
|
||||
* @see m2/com.m2.lib
|
||||
* @see m2/com.m2.lib.Lib
|
||||
* @see m2/com.m2.lib.Lib#method
|
||||
* @see m2/com.m2.lib.Lib#method(String)
|
||||
*/
|
||||
public App(){}
|
||||
}
|
||||
""")
|
||||
.write(src);
|
||||
|
||||
new ModuleBuilder(tb, "com.ex1")
|
||||
.exports("com.ex1")
|
||||
.classes("""
|
||||
package com.ex1;
|
||||
public class A{
|
||||
public void m() {}
|
||||
}""",
|
||||
"""
|
||||
package com.ex1;
|
||||
public class B {}""")
|
||||
.write(src);
|
||||
|
||||
new ModuleBuilder(tb, "com.ex2")
|
||||
.requires("com.ex1")
|
||||
.exports("com.ex2")
|
||||
.classes("""
|
||||
package com.ex2;\s
|
||||
import com.ex1.A;
|
||||
public class B{
|
||||
/**
|
||||
* @see com.ex1
|
||||
* @see com.ex1/
|
||||
* @see com.ex1/com.ex1
|
||||
* @see com.ex1/com.ex1.A
|
||||
* @see com.ex1/com.ex1.A#m
|
||||
* @see com.ex1/com.ex1.A#m()
|
||||
* @see com.ex2
|
||||
* @see com.ex2/
|
||||
*/
|
||||
public B(A obj){}
|
||||
}
|
||||
""")
|
||||
.write(src);
|
||||
|
||||
new ModuleBuilder(tb, "fail")
|
||||
.exports("pkg.fail")
|
||||
.classes("""
|
||||
package pkg.fail;
|
||||
/**
|
||||
* @see fail/#foo()
|
||||
*/
|
||||
public class F {
|
||||
public void foo() {}
|
||||
}
|
||||
""")
|
||||
.write(src);
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user