Skip to content

Commit

Permalink
[23] Parsing details for markdown comments eclipse-jdt#2824
Browse files Browse the repository at this point in the history
+ escaping of [] inside reference

fixes eclipse-jdt#2824
  • Loading branch information
stephan-herrmann committed Aug 18, 2024
1 parent 31052e2 commit b219429
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -653,12 +653,12 @@ protected Object parseArguments(Object receiver, boolean checkVerifySpaceOrEndCo
// Read possible additional type info
dim = 0;
isVarargs = false;
if (readToken() == TerminalTokens.TokenNameLBRACKET) {
if (readMarkdownEscapedToken(TerminalTokens.TokenNameLBRACKET)) {
// array declaration
while (readToken() == TerminalTokens.TokenNameLBRACKET) {
while (readMarkdownEscapedToken(TerminalTokens.TokenNameLBRACKET)) {
int dimStart = this.scanner.getCurrentTokenStartPosition();
consumeToken();
if (readToken() != TerminalTokens.TokenNameRBRACKET) {
if (!readMarkdownEscapedToken(TerminalTokens.TokenNameRBRACKET)) {
break nextArg;
}
consumeToken();
Expand Down Expand Up @@ -734,6 +734,10 @@ protected Object parseArguments(Object receiver, boolean checkVerifySpaceOrEndCo
}

// Something wrong happened => Invalid input
if (this.markdown) {
// skip over bogus token
this.currentTokenType = -1;
}
throw Scanner.invalidInput();
} finally {
// we have to make sure that this is reset to the previous value even if an exception occurs
Expand Down Expand Up @@ -3336,6 +3340,26 @@ protected int readToken() throws InvalidInputException {
return this.currentTokenType;
}

protected boolean readMarkdownEscapedToken(int expectedToken) throws InvalidInputException {
if (!this.markdown)
return readToken() == expectedToken;
if (this.currentTokenType < 0) {
this.tokenPreviousPosition = this.scanner.currentPosition;
if (peekChar() != '\\')
return false;
this.scanner.currentPosition++;
this.currentTokenType = this.scanner.getNextToken();
if (this.currentTokenType != expectedToken) {
this.scanner.currentPosition = this.tokenPreviousPosition;
this.currentTokenType = -1;
return false;
}
this.index = this.scanner.currentPosition;
this.lineStarted = true; // after having read a token, line is obviously started...
}
return this.currentTokenType == expectedToken;
}

protected int readTokenAndConsume() throws InvalidInputException {
int token = readToken();
consumeToken();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ public void test010() {
public class X {
/// Some text here without the necessary tags for main method
/// @param arguments array of strings
/// @return java.lang.Str -- should not raise an error
/// no tags here
public static void main(String[] arguments) {
Expand All @@ -309,7 +310,7 @@ public static void main(String[] arguments) {
}
""", },
"----------\n" +
"1. ERROR in X.java (at line 6)\n" +
"1. ERROR in X.java (at line 7)\n" +
" public static void main(String[] arguments) {\n" +
" ^^^^^^^^^\n" +
"Javadoc: Missing tag for parameter arguments\n" +
Expand Down Expand Up @@ -596,4 +597,32 @@ public static void main(String[] args) {
this.reportMissingJavadocTags = bkup;
}
}
public void test021() {
// arrays in method reference lack escaping.
// TODO specific error message?
String bkup = this.reportMissingJavadocTags;
try {
this.reportMissingJavadocTags = CompilerOptions.IGNORE;
this.runNegativeTest(new String[] { "X.java",
"""
///
/// Reference to method with array parameter: [#main(String[])]
///
public class X {
public static void main(String[] args) {
System.out.println("Hello");
}
}
""", },
"----------\n" +
"1. ERROR in X.java (at line 2)\n" +
" /// Reference to method with array parameter: [#main(String[])]\n" +
" ^^^^^^^^\n" +
"Javadoc: Invalid parameters declaration\n" +
"----------\n",
JavacTestOptions.Excuse.EclipseWarningConfiguredAsError);
} finally {
this.reportMissingJavadocTags = bkup;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,27 @@ private void verifyJavadoc(Javadoc docComment) {
}
*/

protected void assertTagsAndTexts(List<ASTNode> tagList, String[] tags, String[][] liness) {
assertEquals(this.prefix+"Wrong number of tags", tags.length, tagList.size());

for (int i = 0; i < liness.length; i++) {
ASTNode tagNode = tagList.get(i);
String tag = tags[i];
assertEquals(this.prefix+"Invalid type for fragment ["+tagNode+"]", ASTNode.TAG_ELEMENT, tagNode.getNodeType());
TagElement tagElement = (TagElement) tagNode;
assertEquals(this.prefix+"Invalid tag", tag, tagElement.getTagName());
List<? extends ASTNode> fragments = tagElement.fragments();
String[] lines = liness[i];
assertEquals(this.prefix+"Wrong number of fragments", lines.length, fragments.size());
for (int j = 0; j < lines.length; j++) {
ASTNode fragment = fragments.get(j);
String line = lines[j];
assertEquals(this.prefix+"Invalid type for fragment ["+fragment+"]", ASTNode.TEXT_ELEMENT, fragment.getNodeType());
assertEquals(this.prefix+"Wrong text content", line, ((TextElement) fragment).getText());
}
}
}

/**
* Check javadoc for MethodDeclaration
*/
Expand Down Expand Up @@ -3498,23 +3519,64 @@ void paraAfterCode() { }
}
}

protected void assertTagsAndTexts(List<ASTNode> tagList, String[] tags, String[][] liness) {
assertEquals(this.prefix+"Wrong number of tags", tags.length, tagList.size());
public void testGH2808_linkWithArrayReference() throws JavaModelException {
// for a negative variant see org.eclipse.jdt.core.tests.compiler.regression.MarkdownCommentsTest.test021()
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_23/src/markdown/gh2808/LinkWithArray.java",
"""
package markdown.gh2808;
for (int i = 0; i < liness.length; i++) {
ASTNode tagNode = tagList.get(i);
String tag = tags[i];
assertEquals(this.prefix+"Invalid type for fragment ["+tagNode+"]", ASTNode.TAG_ELEMENT, tagNode.getNodeType());
TagElement tagElement = (TagElement) tagNode;
assertEquals(this.prefix+"Invalid tag", tag, tagElement.getTagName());
List<? extends ASTNode> fragments = tagElement.fragments();
String[] lines = liness[i];
assertEquals(this.prefix+"Wrong number of fragments", lines.length, fragments.size());
for (int j = 0; j < lines.length; j++) {
ASTNode fragment = fragments.get(j);
String line = lines[j];
assertEquals(this.prefix+"Invalid type for fragment ["+fragment+"]", ASTNode.TEXT_ELEMENT, fragment.getNodeType());
assertEquals(this.prefix+"Wrong text content", line, ((TextElement) fragment).getText());
///
/// Simple escaped link [#m1(int\\[\\])].
/// Escaped link with custom text [method 1][#m1(int\\[\\])].
///
public class LinkWithArray {
public void m1(int[] i) {}
}
"""
);
CompilationUnit compilUnit = (CompilationUnit) runConversion(this.workingCopies[0], true);
if (this.docCommentSupport.equals(JavaCore.ENABLED)) {
List unitComments = compilUnit.getCommentList();
assertEquals("Wrong number of comments", 1, unitComments.size());

Comment comment = (Comment) unitComments.get(0);
assertEquals("Comment should be javadoc", comment.getNodeType(), ASTNode.JAVADOC);
List tagList = ((Javadoc) comment).tags();
assertEquals("Should be one tag element", 1, tagList.size());
TagElement tagElement = (TagElement) tagList.get(0);
tagList = tagElement.fragments();

String[] tags = {
null,
"@link",
null,
null,
"@link",
null
};
String[] lines = {
"Simple escaped link ",
"m1(int [])",
".",
"Escaped link with custom text ",
"method 1",
"."
};
for (int i = 0; i < lines.length; i++) {
String tag = tags[i];
String line = lines[i];
ASTNode elem = (ASTNode) tagList.get(i);
if (tag != null) {
assertEquals("Node type", ASTNode.TAG_ELEMENT, elem.getNodeType());
assertEquals("Tag name", tag, ((TagElement) elem).getTagName());
elem = (ASTNode) ((TagElement) elem).fragments().get(0);
if (!(elem instanceof TextElement))
continue; // @link without custom text
} else {
assertEquals("Node type", ASTNode.TEXT_ELEMENT, elem.getNodeType());
}
assertEquals("Text", line, ((TextElement) elem).getText());
}
}
}
Expand Down

0 comments on commit b219429

Please sign in to comment.