8281969: Bad result for the snippet @link tag if substring/regex consists of whitespace
Reviewed-by: jjg
This commit is contained in:
parent
c8e0315114
commit
15d3329edd
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html
test/langtools/jdk/javadoc/doclet/testSnippetTag
@ -425,24 +425,13 @@ public class TagletWriterImpl extends TagletWriter {
|
|||||||
return;
|
return;
|
||||||
} else if (linkEncountered) {
|
} else if (linkEncountered) {
|
||||||
assert e != null;
|
assert e != null;
|
||||||
String line = sequence.toString();
|
|
||||||
String strippedLine = line.strip();
|
|
||||||
int idx = line.indexOf(strippedLine);
|
|
||||||
assert idx >= 0; // because the stripped line is a substring of the line being stripped
|
|
||||||
Text whitespace = Text.of(utils.normalizeNewlines(line.substring(0, idx)));
|
|
||||||
//disable preview tagging inside the snippets:
|
//disable preview tagging inside the snippets:
|
||||||
PreviewFlagProvider prevPreviewProvider = utils.setPreviewFlagProvider(el -> false);
|
PreviewFlagProvider prevPreviewProvider = utils.setPreviewFlagProvider(el -> false);
|
||||||
try {
|
try {
|
||||||
// If the leading whitespace is not excluded from the link,
|
c = new ContentBuilder(htmlWriter.linkToContent(element, e, t, sequence.toString()));
|
||||||
// browsers might exhibit unwanted behavior. For example, a
|
|
||||||
// browser might display hand-click cursor while user hovers
|
|
||||||
// over that whitespace portion of the line; or use
|
|
||||||
// underline decoration.
|
|
||||||
c = new ContentBuilder(whitespace, htmlWriter.linkToContent(element, e, t, strippedLine));
|
|
||||||
} finally {
|
} finally {
|
||||||
utils.setPreviewFlagProvider(prevPreviewProvider);
|
utils.setPreviewFlagProvider(prevPreviewProvider);
|
||||||
}
|
}
|
||||||
// We don't care about trailing whitespace.
|
|
||||||
} else {
|
} else {
|
||||||
c = HtmlTree.SPAN(Text.of(text));
|
c = HtmlTree.SPAN(Text.of(text));
|
||||||
classes.forEach(((HtmlTree) c)::addStyle);
|
classes.forEach(((HtmlTree) c)::addStyle);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, 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 8266666
|
* @bug 8266666 8281969
|
||||||
* @summary Implementation for snippets
|
* @summary Implementation for snippets
|
||||||
* @library /tools/lib ../../lib
|
* @library /tools/lib ../../lib
|
||||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||||
@ -180,7 +180,28 @@ public class TestSnippetMarkup extends SnippetTester {
|
|||||||
link(First) link(line)
|
link(First) link(line)
|
||||||
Second line
|
Second line
|
||||||
""", "link\\((.+?)\\)", r -> link(true, "java.lang.Object#Object", r.group(1)))
|
""", "link\\((.+?)\\)", r -> link(true, "java.lang.Object#Object", r.group(1)))
|
||||||
));
|
),
|
||||||
|
new TestCase(
|
||||||
|
"""
|
||||||
|
First line
|
||||||
|
Second line // @link substring=" " target="java.lang.System#out"
|
||||||
|
""",
|
||||||
|
replace("""
|
||||||
|
First line
|
||||||
|
link( )Secondlink( )line
|
||||||
|
""", "link\\((.+?)\\)", r -> link(true, "java.lang.System#out", r.group(1)))
|
||||||
|
),
|
||||||
|
new TestCase(
|
||||||
|
"""
|
||||||
|
First line
|
||||||
|
Second line // @link regex=" " target="java.lang.System#in"
|
||||||
|
""",
|
||||||
|
replace("""
|
||||||
|
First line
|
||||||
|
link( )Secondlink( )line
|
||||||
|
""", "link\\((.+?)\\)", r -> link(true, "java.lang.System#in", r.group(1)))
|
||||||
|
)
|
||||||
|
);
|
||||||
testPositive(base, testCases);
|
testPositive(base, testCases);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,7 +596,7 @@ First line // @highlight :
|
|||||||
""",
|
""",
|
||||||
replace("""
|
replace("""
|
||||||
First line
|
First line
|
||||||
link(Third line)
|
link( Third line)
|
||||||
""", "link\\((.+?)\\)", r -> link(true, "java.lang.Object#equals(Object)", r.group(1)))
|
""", "link\\((.+?)\\)", r -> link(true, "java.lang.Object#equals(Object)", r.group(1)))
|
||||||
),
|
),
|
||||||
new TestCase("""
|
new TestCase("""
|
||||||
@ -717,19 +738,29 @@ First line // @highlight :
|
|||||||
String content)
|
String content)
|
||||||
throws UncheckedIOException {
|
throws UncheckedIOException {
|
||||||
|
|
||||||
// The HTML <a> tag generated from the @link snippet markup tag is the
|
// The HTML A element generated for the @link snippet markup tag is
|
||||||
// same as that of the {@link} Standard doclet tag. This is specified
|
// the same as that for the similar Standard doclet {@link} tag.
|
||||||
// and can be used for comparison and testing.
|
// This fact can be used for comparison and testing.
|
||||||
|
|
||||||
// generate documentation for {@link} to grab its HTML <a> tag;
|
// Generate documentation for {@link} to grab its HTML A element.
|
||||||
// generate documentation at low cost and do not interfere with the
|
// Generate documentation cheaply and do not interfere with the
|
||||||
// calling test state; for that, do not create file trees, do not write
|
// calling test state; for that: do not create file trees, do not write
|
||||||
// to std out/err, and generally try to keep everything in memory
|
// to std out/err, and generally try to keep everything in memory.
|
||||||
|
|
||||||
String source = """
|
// Caveat: a label used in snippet's @link tag can start, end, or both,
|
||||||
|
// with whitespace. In this regard, snippet's @link differs from
|
||||||
|
// {@link} and {@linkplain} Standard doclet tags, which trim whitespace
|
||||||
|
// from labels. In particular, {@link} and {@linkplain} treat
|
||||||
|
// whitespace after the reference as an absent label, whereas
|
||||||
|
// snippet's @link does not. To avoid whitespace problems,
|
||||||
|
// LABEL_PLACEHOLDER is used. It is later substituted with "content",
|
||||||
|
// which might be an empty or blank string.
|
||||||
|
|
||||||
|
var LABEL_PLACEHOLDER = "label";
|
||||||
|
var source = """
|
||||||
/** {@link %s %s} */
|
/** {@link %s %s} */
|
||||||
public interface A { }
|
public interface A { }
|
||||||
""".formatted(targetReference, content);
|
""".formatted(targetReference, LABEL_PLACEHOLDER);
|
||||||
|
|
||||||
JavaFileObject src = new JavaFileObject() {
|
JavaFileObject src = new JavaFileObject() {
|
||||||
@Override
|
@Override
|
||||||
@ -850,12 +881,12 @@ First line // @highlight :
|
|||||||
}
|
}
|
||||||
String output = fileManager.getFileString(DOCUMENTATION_OUTPUT, "A.html");
|
String output = fileManager.getFileString(DOCUMENTATION_OUTPUT, "A.html");
|
||||||
// use the [^<>] regex to select HTML elements that immediately enclose "content"
|
// use the [^<>] regex to select HTML elements that immediately enclose "content"
|
||||||
Matcher m = Pattern.compile("(?is)<a href=\"[^<>]*\" title=\"[^<>]*\" class=\"[^<>]*\"><code>"
|
Matcher m = Pattern.compile("(?is)(<a href=\"[^<>]*\" title=\"[^<>]*\" class=\"[^<>]*\"><code>)"
|
||||||
+ content + "</code></a>").matcher(output);
|
+ LABEL_PLACEHOLDER + "(</code></a>)").matcher(output);
|
||||||
if (!m.find()) {
|
if (!m.find()) {
|
||||||
throw new IOException(output);
|
throw new IOException(output);
|
||||||
}
|
}
|
||||||
return m.group(0);
|
return m.group(1) + content + m.group(2);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UncheckedIOException(e);
|
throw new UncheckedIOException(e);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user