Skip to content

Commit

Permalink
8281969: Bad result for the snippet @link tag if substring/regex cons…
Browse files Browse the repository at this point in the history
…ists of whitespace

Reviewed-by: jjg
  • Loading branch information
pavelrappo committed Jul 14, 2022
1 parent c8e0315 commit 15d3329
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 30 deletions.
Expand Up @@ -425,24 +425,13 @@ protected Content snippetTagOutput(Element element, SnippetTree tag, StyledText
return;
} else if (linkEncountered) {
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:
PreviewFlagProvider prevPreviewProvider = utils.setPreviewFlagProvider(el -> false);
try {
// If the leading whitespace is not excluded from the link,
// 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));
c = new ContentBuilder(htmlWriter.linkToContent(element, e, t, sequence.toString()));
} finally {
utils.setPreviewFlagProvider(prevPreviewProvider);
}
// We don't care about trailing whitespace.
} else {
c = HtmlTree.SPAN(Text.of(text));
classes.forEach(((HtmlTree) c)::addStyle);
Expand Down
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -23,7 +23,7 @@

/*
* @test
* @bug 8266666
* @bug 8266666 8281969
* @summary Implementation for snippets
* @library /tools/lib ../../lib
* @modules jdk.compiler/com.sun.tools.javac.api
Expand Down Expand Up @@ -180,7 +180,28 @@ public void testLink(Path base) throws Exception {
link(First) link(line)
Second line
""", "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);
}

Expand Down Expand Up @@ -575,7 +596,7 @@ public void testPositiveInlineTagMarkup_BlankLinesFromNextLineMarkup(Path base)
""",
replace("""
First line
link(Third line)
link( Third line)
""", "link\\((.+?)\\)", r -> link(true, "java.lang.Object#equals(Object)", r.group(1)))
),
new TestCase("""
Expand Down Expand Up @@ -717,19 +738,29 @@ private static String link(boolean linkPlain,
String content)
throws UncheckedIOException {

// The HTML <a> tag generated from the @link snippet markup tag is the
// same as that of the {@link} Standard doclet tag. This is specified
// and can be used for comparison and testing.

// generate documentation for {@link} to grab its HTML <a> tag;
// generate documentation at low cost and do not interfere with the
// 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

String source = """
// The HTML A element generated for the @link snippet markup tag is
// the same as that for the similar Standard doclet {@link} tag.
// This fact can be used for comparison and testing.

// Generate documentation for {@link} to grab its HTML A element.
// Generate documentation cheaply and do not interfere with the
// 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.

// 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} */
public interface A { }
""".formatted(targetReference, content);
""".formatted(targetReference, LABEL_PLACEHOLDER);

JavaFileObject src = new JavaFileObject() {
@Override
Expand Down Expand Up @@ -850,12 +881,12 @@ public FileObject getFileForOutput(Location location,
}
String output = fileManager.getFileString(DOCUMENTATION_OUTPUT, "A.html");
// use the [^<>] regex to select HTML elements that immediately enclose "content"
Matcher m = Pattern.compile("(?is)<a href=\"[^<>]*\" title=\"[^<>]*\" class=\"[^<>]*\"><code>"
+ content + "</code></a>").matcher(output);
Matcher m = Pattern.compile("(?is)(<a href=\"[^<>]*\" title=\"[^<>]*\" class=\"[^<>]*\"><code>)"
+ LABEL_PLACEHOLDER + "(</code></a>)").matcher(output);
if (!m.find()) {
throw new IOException(output);
}
return m.group(0);
return m.group(1) + content + m.group(2);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand Down

0 comments on commit 15d3329

Please sign in to comment.