8271258: @param with non-ascii variable names produces incorrect results

Reviewed-by: hannesw
This commit is contained in:
Jonathan Gibbons 2021-08-24 14:41:24 +00:00
parent 7454306920
commit 94f5e441f6
3 changed files with 86 additions and 30 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 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
@ -67,10 +67,9 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
} }
/** /**
* Given an array of <code>Parameter</code>s, return * Given a list of parameters, return a name/rank number map.
* a name/rank number map. If the array is null, then * If the list is null, then null is returned.
* null is returned. * @param params The list of parameters (from type or executable member) to
* @param params The array of parameters (from type or executable member) to
* check. * check.
* @return a name-rank number map. * @return a name-rank number map.
*/ */
@ -245,28 +244,24 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
CommentHelper ch = writer.configuration().utils.getCommentHelper(e); CommentHelper ch = writer.configuration().utils.getCommentHelper(e);
for (ParamTree dt : paramTags) { for (ParamTree dt : paramTags) {
String name = ch.getParameterName(dt); String name = ch.getParameterName(dt);
String paramName = kind != ParamKind.TYPE_PARAMETER String paramName = kind == ParamKind.TYPE_PARAMETER ? "<" + name + ">" : name;
? name.toString()
: "<" + name + ">";
if (!rankMap.containsKey(name)) { if (!rankMap.containsKey(name)) {
String key; String key = switch (kind) {
switch (kind) { case PARAMETER -> "doclet.Parameters_warn";
case PARAMETER: key = "doclet.Parameters_warn" ; break; case TYPE_PARAMETER -> "doclet.TypeParameters_warn";
case TYPE_PARAMETER: key = "doclet.TypeParameters_warn" ; break; case RECORD_COMPONENT -> "doclet.RecordComponents_warn";
case RECORD_COMPONENT: key = "doclet.RecordComponents_warn" ; break; default -> throw new IllegalArgumentException(kind.toString());
default: throw new IllegalArgumentException(kind.toString()); };
}
messages.warning(ch.getDocTreePath(dt), key, paramName); messages.warning(ch.getDocTreePath(dt), key, paramName);
} }
String rank = rankMap.get(name); String rank = rankMap.get(name);
if (rank != null && alreadyDocumented.contains(rank)) { if (rank != null && alreadyDocumented.contains(rank)) {
String key; String key = switch (kind) {
switch (kind) { case PARAMETER -> "doclet.Parameters_dup_warn";
case PARAMETER: key = "doclet.Parameters_dup_warn" ; break; case TYPE_PARAMETER -> "doclet.TypeParameters_dup_warn";
case TYPE_PARAMETER: key = "doclet.TypeParameters_dup_warn" ; break; case RECORD_COMPONENT -> "doclet.RecordComponents_dup_warn";
case RECORD_COMPONENT: key = "doclet.RecordComponents_dup_warn" ; break; default -> throw new IllegalArgumentException(kind.toString());
default: throw new IllegalArgumentException(kind.toString()); };
}
messages.warning(ch.getDocTreePath(dt), key, paramName); messages.warning(ch.getDocTreePath(dt), key, paramName);
} }
result.add(processParamTag(e, kind, writer, dt, result.add(processParamTag(e, kind, writer, dt,

View File

@ -139,7 +139,7 @@ public class CommentHelper {
public String getParameterName(DocTree dtree) { public String getParameterName(DocTree dtree) {
if (dtree.getKind() == PARAM) { if (dtree.getKind() == PARAM) {
return ((ParamTree) dtree).getName().toString(); return ((ParamTree) dtree).getName().getName().toString();
} else { } else {
return null; return null;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 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
@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 8203176 * @bug 8203176 8271258
* @summary javadoc handles non-ASCII characters incorrectly * @summary javadoc handles non-ASCII characters incorrectly
* @library /tools/lib ../../lib * @library /tools/lib ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool * @modules jdk.javadoc/jdk.javadoc.internal.tool
@ -33,7 +33,6 @@
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import javadoc.tester.JavadocTester; import javadoc.tester.JavadocTester;
import toolbox.ToolBox; import toolbox.ToolBox;
@ -42,20 +41,20 @@ public class TestUnicode extends JavadocTester {
public static void main(String... args) throws Exception { public static void main(String... args) throws Exception {
TestUnicode tester = new TestUnicode(); TestUnicode tester = new TestUnicode();
tester.runTests(); tester.runTests(m -> new Object[] { Path.of(m.getName())});
} }
ToolBox tb = new ToolBox(); ToolBox tb = new ToolBox();
@Test @Test
public void test() throws Exception { public void testUnicode(Path base) throws Exception {
char ellipsis = '\u2026'; char ellipsis = '\u2026';
Path src = Files.createDirectories(Paths.get("src")); Path src = Files.createDirectories(base.resolve("src"));
tb.writeJavaFiles(src, tb.writeJavaFiles(src,
"/** Hel" + ellipsis + "lo {@code World(" + ellipsis + ")}. */\n" "/** Hel" + ellipsis + "lo {@code World(" + ellipsis + ")}. */\n"
+ "public class Code { }\n"); + "public class Code { }\n");
javadoc("-d", "out", javadoc("-d", base.resolve("out").toString(),
"-encoding", "utf-8", "-encoding", "utf-8",
src.resolve("Code.java").toString()); src.resolve("Code.java").toString());
checkExit(Exit.OK); checkExit(Exit.OK);
@ -65,4 +64,66 @@ public class TestUnicode extends JavadocTester {
checkOutput("Code.html", false, checkOutput("Code.html", false,
"\\u"); "\\u");
} }
@Test
public void testParam(Path base) throws Exception {
String chineseElephant = "\u5927\u8c61"; // taken from JDK-8271258
Path src = Files.createDirectories(base.resolve("src"));
tb.writeJavaFiles(src,
"""
/**
* Comment. ##.
* @param <##> the ##
*/
public class Code<##> {
/**
* Comment. ##.
* @param ## the ##
*/
public void set##(int ##) { }
}""".replaceAll("##", chineseElephant));
javadoc("-d", base.resolve("out").toString(),
"-encoding", "utf-8",
"--no-platform-links",
src.resolve("Code.java").toString());
checkExit(Exit.OK);
checkOutput("Code.html", true,
"""
<h1 title="Class Code" class="title">Class Code&lt;##&gt;</h1>
""".replaceAll("##", chineseElephant),
"""
<div class="inheritance" title="Inheritance Tree">java.lang.Object
<div class="inheritance">Code&lt;##&gt;</div>
</div>
""".replaceAll("##", chineseElephant),
"""
<dl class="notes">
<dt>Type Parameters:</dt>
<dd><code>##</code> - the ##</dd>
</dl>
""".replaceAll("##", chineseElephant),
"""
<section class="detail" id="set##(int)">
<h3>set##</h3>
<div class="member-signature"><span class="modifiers">public</span>&nbsp;<span c\
lass="return-type">void</span>&nbsp;<span class="element-name">set##</span><wbr>\
<span class="parameters">(int&nbsp;##)</span></div>
<div class="block">Comment. ##.</div>
<dl class="notes">
<dt>Parameters:</dt>
<dd><code>##</code> - the ##</dd>
</dl>
</section>
""".replaceAll("##", chineseElephant)
);
// The following checks for the numeric forms of the Unicode characters being tested:
// these numeric forms should not show up as literal character sequences.
checkOutput("Code.html", false,
Integer.toHexString(chineseElephant.charAt(0)),
Integer.toHexString(chineseElephant.charAt(1))
);
}
} }