8332858: References with escapes have broken positions after they are transformed

Reviewed-by: vromero, jjg
This commit is contained in:
Jan Lahoda 2024-05-31 05:54:39 +00:00
parent 1b7d59f171
commit 2ab8ab5613
2 changed files with 72 additions and 6 deletions

View File

@ -803,8 +803,9 @@ public class MarkdownTransformer implements JavacTrees.DocCommentTreeTransformer
// determine whether to use {@link ... } or {@linkplain ...} // determine whether to use {@link ... } or {@linkplain ...}
// based on whether the "link text" is the same as the "link destination" // based on whether the "link text" is the same as the "link destination"
String ref = dest.substring(autorefScheme.length()); String ref = dest.substring(autorefScheme.length());
int refPos = sourcePosToTreePos(getRefPos(ref, link)); int[] span = getRefSpan(ref, link);
var newRefTree = m.at(refPos).newReferenceTree(ref).setEndPos(refPos + ref.length()); int refPos = sourcePosToTreePos(span[0]);
var newRefTree = m.at(refPos).newReferenceTree(ref).setEndPos(sourcePosToTreePos(span[1]));
Node child = link.getFirstChild(); Node child = link.getFirstChild();
DocTree.Kind linkKind = child.getNext() == null DocTree.Kind linkKind = child.getNext() == null
@ -835,7 +836,7 @@ public class MarkdownTransformer implements JavacTrees.DocCommentTreeTransformer
* @param ref the reference to find * @param ref the reference to find
* @param link the link containing the reference * @param link the link containing the reference
*/ */
private int getRefPos(String ref, Link link) { private int[] getRefSpan(String ref, Link link) {
var spans = link.getSourceSpans(); var spans = link.getSourceSpans();
var revSpanIter = spans.listIterator(spans.size()); var revSpanIter = spans.listIterator(spans.size());
while (revSpanIter.hasPrevious()) { while (revSpanIter.hasPrevious()) {
@ -845,11 +846,19 @@ public class MarkdownTransformer implements JavacTrees.DocCommentTreeTransformer
var s = source.substring(start, end); var s = source.substring(start, end);
var index = s.lastIndexOf(ref); var index = s.lastIndexOf(ref);
if (index != -1) { if (index != -1) {
return start + index; return new int[] {start + index, start + index + ref.length()};
} else {
String escapedRef = ref.replace("[]", "\\[\\]");
var escapedIndex = s.lastIndexOf(escapedRef);
if (escapedIndex != -1) {
return new int[] {start + escapedIndex,
start + escapedIndex + escapedRef.length()};
} }
} }
return NOPOS;
} }
return NOSPAN;
}
private static final int[] NOSPAN = new int[] {NOPOS, NOPOS};
/** /**
* {@return the position in the original comment for a position in {@code source}, * {@return the position in the original comment for a position in {@code source},

View File

@ -23,13 +23,16 @@
/* /*
* @test * @test
* @bug 8332858
* @summary test case for Markdown positions * @summary test case for Markdown positions
* @run main/othervm --limit-modules jdk.compiler MarkdownTransformerPositionTest * @run main/othervm --limit-modules jdk.compiler MarkdownTransformerPositionTest
* @run main MarkdownTransformerPositionTest * @run main MarkdownTransformerPositionTest links
*/ */
import com.sun.source.doctree.DocCommentTree; import com.sun.source.doctree.DocCommentTree;
import com.sun.source.doctree.LinkTree;
import com.sun.source.doctree.RawTextTree; import com.sun.source.doctree.RawTextTree;
import com.sun.source.doctree.ReferenceTree;
import com.sun.source.tree.*; import com.sun.source.tree.*;
import com.sun.source.util.*; import com.sun.source.util.*;
@ -50,6 +53,10 @@ public class MarkdownTransformerPositionTest {
t.simpleTest(); t.simpleTest();
t.testWithReplacements(); t.testWithReplacements();
if (args.length > 0 && "links".equals(args[0])) {
t.linkWithEscapes();
}
} }
private void simpleTest() throws Exception { private void simpleTest() throws Exception {
@ -76,6 +83,16 @@ public class MarkdownTransformerPositionTest {
"testAuthor"); "testAuthor");
} }
private void linkWithEscapes() throws Exception {
runConvertedLinksTest("""
/// Markdown comment.
/// [java.util.Arrays#asList(Object\\[\\])]
public class Test {
}
""",
"java.util.Arrays#asList(Object\\[\\])");
}
private void runTest(String source, String... expectedRawSpans) throws Exception { private void runTest(String source, String... expectedRawSpans) throws Exception {
JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
JavacTask task = (JavacTask)comp.getTask(null, null, null, null, null, Arrays.asList(new JavaSource(source))); JavacTask task = (JavacTask)comp.getTask(null, null, null, null, null, Arrays.asList(new JavaSource(source)));
@ -107,6 +124,46 @@ public class MarkdownTransformerPositionTest {
System.err.println("Test result: success, boot modules: " + ModuleLayer.boot().modules()); System.err.println("Test result: success, boot modules: " + ModuleLayer.boot().modules());
} }
private void runConvertedLinksTest(String source, String... expectedRawSpans) throws Exception {
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
JavacTask task = (JavacTask)comp.getTask(null, null, null, null, null, Arrays.asList(new JavaSource(source)));
CompilationUnitTree cu = task.parse().iterator().next();
task.analyze();
DocTrees trees = DocTrees.instance(task);
List<String> rawSpans = new ArrayList<>();
TreePath clazzTP = new TreePath(new TreePath(cu), cu.getTypeDecls().get(0));
Element clazz = trees.getElement(clazzTP);
DocCommentTree docComment = trees.getDocCommentTree(clazz);
new DocTreeScanner<Void, Void>() {
@Override
public Void visitLink(LinkTree node, Void p) {
int start = (int) trees.getSourcePositions().getStartPosition(cu, docComment, node);
if (start != (-1)) {
throw new AssertionError("UNexpected start position for synthetic link: " + start);
}
return super.visitLink(node, p);
}
@Override
public Void visitReference(ReferenceTree node, Void p) {
int start = (int) trees.getSourcePositions().getStartPosition(cu, docComment, node);
int end = (int) trees.getSourcePositions().getEndPosition(cu, docComment, node);
rawSpans.add(source.substring(start, end));
return super.visitReference(node, p);
}
}.scan(docComment, null);
List<String> expectedRawSpansList = List.of(expectedRawSpans);
if (!expectedRawSpansList.equals(rawSpans)) {
throw new AssertionError("Incorrect raw text spans, should be: " +
expectedRawSpansList + ", but is: " + rawSpans);
}
System.err.println("Test result: success, boot modules: " + ModuleLayer.boot().modules());
}
static class JavaSource extends SimpleJavaFileObject { static class JavaSource extends SimpleJavaFileObject {
private final String source; private final String source;