Skip to content

Commit adc3441

Browse files
[Markdown] Snippet tag failed to generate javadoc
The @snippet tag content was not being rendered in the Javadoc view because plain snippet text was not captured during parsing. This change ensures snippet content is properly extracted and displayed, similar to standard Javadoc elements. Fix: #4968
1 parent ff9337d commit adc3441

2 files changed

Lines changed: 111 additions & 4 deletions

File tree

org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2024 IBM Corporation and others.
2+
* Copyright (c) 2000, 2026 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -548,7 +548,7 @@ protected boolean commentParse() {
548548
if (this.lineStarted && this.textStart != -1 && this.textStart < textEndPosition) {
549549
pushText(this.textStart, textEndPosition);
550550
}
551-
refreshInlineTagPosition(textEndPosition);
551+
refreshInlineTagPosition((this.markdown && this.tagValue == TAG_SNIPPET_VALUE) ? textEndPosition - 2 : textEndPosition);
552552
setInlineTagStarted(false);
553553
} else if (this.lineStarted && this.textStart != -1 && this.textStart <= textEndPosition && (this.textStart < this.starPosition || this.starPosition == lastStarPosition || this.markdown)) {
554554
if (!(invalidInlineTagLineEnd > 0 && nextCharacter == '}' && this.markdown && this.index == this.javadocEnd))
@@ -1663,6 +1663,7 @@ protected boolean parseSnippet() throws InvalidInputException {
16631663
int openBraces = 1;
16641664
boolean parsingJava18Plus = this.scanner != null ? this.scanner.sourceLevel >= ClassFileConstants.JDK18 : false;
16651665
boolean valid = true;
1666+
boolean markdownSnippetIsValid = false;
16661667
if (!parsingJava18Plus) {
16671668
throw Scanner.invalidInput();
16681669
}
@@ -1713,6 +1714,9 @@ protected boolean parseSnippet() throws InvalidInputException {
17131714
}
17141715
}
17151716
if (snippetTag != null) {
1717+
if (snippetType.toString().equals(FILE) && this.markdown) {
1718+
valid = true;
1719+
}
17161720
this.setSnippetIsValid(snippetTag, valid);
17171721
}
17181722
break;
@@ -1746,6 +1750,9 @@ protected boolean parseSnippet() throws InvalidInputException {
17461750
}
17471751
}
17481752
if (snippetTag != null) {
1753+
if (snippetType.toString().equals(CLASS) && this.markdown) {
1754+
valid = true;
1755+
}
17491756
this.setSnippetIsValid(snippetTag, valid);
17501757
}
17511758
break;
@@ -1855,6 +1862,36 @@ protected boolean parseSnippet() throws InvalidInputException {
18551862
this.textStart = -1;
18561863
}
18571864
break;
1865+
case TokenNameCOMMENT_MARKDOWN:
1866+
if (this.markdown) {
1867+
String markdownTokenString = this.scanner.getCurrentTokenString();
1868+
String[] elements = markdownTokenString.split("\\r?\\n", -1); //$NON-NLS-1$
1869+
int elmentStart = this.scanner.getCurrentTokenStartPosition();
1870+
int elementEnd = 0;
1871+
try {
1872+
for (int i = 0; i < elements.length; i++) {
1873+
if (elementEnd != 0 ) {
1874+
elmentStart = elementEnd + 1; // +1 because of new line
1875+
}
1876+
int pos = elements[i].indexOf("///"); //$NON-NLS-1$
1877+
if (pos != -1) {
1878+
elmentStart = elmentStart + 3 + pos;
1879+
String element = elements[i].substring(3 + pos);
1880+
elementEnd = elmentStart + element.length();
1881+
if (element.stripLeading().startsWith("}")) { //$NON-NLS-1$
1882+
break;
1883+
}
1884+
}
1885+
pushText(elmentStart, elementEnd);
1886+
}
1887+
if (elements.length > 0)
1888+
markdownSnippetIsValid = true;
1889+
} catch (Exception e) {
1890+
markdownSnippetIsValid = false;
1891+
}
1892+
1893+
}
1894+
break;
18581895
case TokenNameCOMMENT_LINE:
18591896
String tokenString = this.scanner.getCurrentTokenString();
18601897
boolean handleNow = handleCommentLineForCurrentLine(tokenString);
@@ -1868,6 +1905,9 @@ protected boolean parseSnippet() throws InvalidInputException {
18681905
this.inlineTagCount = 0;
18691906
}
18701907
Object innerTag = parseSnippetInlineTags(indexOfLastComment == -1 ? tokenString : tokenString.substring(indexOfLastComment+2), snippetTag, this.scanner);
1908+
if (this.markdown) {
1909+
markdownSnippetIsValid = true;
1910+
}
18711911
if (innerTag != null) {
18721912
lvalid = true;
18731913
}
@@ -1898,7 +1938,6 @@ protected boolean parseSnippet() throws InvalidInputException {
18981938
addSnippetInnerTag(innerTag, snippetTag);
18991939
this.snippetInlineTagStarted = true;
19001940
}
1901-
//valid = valid & lvalid;
19021941
break;
19031942
default:
19041943
if (!this.lineStarted || this.textStart == -1) {
@@ -1936,7 +1975,7 @@ protected boolean parseSnippet() throws InvalidInputException {
19361975
this.index = lastRBracePosition - 1;
19371976
}
19381977
if (snippetTag != null) {
1939-
this.setSnippetIsValid(snippetTag, retVal);
1978+
this.setSnippetIsValid(snippetTag, (markdownSnippetIsValid) ? markdownSnippetIsValid : retVal);
19401979
}
19411980
return retVal;
19421981
}

org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterMarkdownTest.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2433,4 +2433,72 @@ public class Markdown {}
24332433
assertEquals("Invalid content", "**Bold**", ((TextElement)frags.get(0)).getText());
24342434
}
24352435
}
2436+
2437+
public void testInvalidSnippetForMarkdown_01() throws JavaModelException {
2438+
String source = """
2439+
/// {@snippet file:Example.java region:main}
2440+
public class Markdown {}
2441+
""";
2442+
this.workingCopies = new ICompilationUnit[1];
2443+
this.workingCopies[0] = getWorkingCopy("/Converter_25/src/markdown/Markdown.java", source, null);
2444+
if (this.docCommentSupport.equals(JavaCore.ENABLED)) {
2445+
CompilationUnit compilUnit = (CompilationUnit) runConversion(this.workingCopies[0], true);
2446+
TypeDeclaration typedeclaration = (TypeDeclaration) compilUnit.types().get(0);
2447+
Javadoc javadoc = typedeclaration.getJavadoc();
2448+
List<TagElement> tags = javadoc.tags();
2449+
List<TagElement> innerTag = tags.get(0).fragments();
2450+
TagElement snippetTag = innerTag.get(0);
2451+
assertTrue((boolean) snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID));
2452+
assertEquals("Invalid snippet tag name", "@snippet", snippetTag.getTagName());
2453+
}
2454+
}
2455+
2456+
public void testInvalidSnippetForMarkdown_02() throws JavaModelException {
2457+
String source = """
2458+
/// {@snippet class:com.example.Example region:main}
2459+
public class Markdown {}
2460+
""";
2461+
this.workingCopies = new ICompilationUnit[1];
2462+
this.workingCopies[0] = getWorkingCopy("/Converter_25/src/markdown/Markdown.java", source, null);
2463+
if (this.docCommentSupport.equals(JavaCore.ENABLED)) {
2464+
CompilationUnit compilUnit = (CompilationUnit) runConversion(this.workingCopies[0], true);
2465+
TypeDeclaration typedeclaration = (TypeDeclaration) compilUnit.types().get(0);
2466+
Javadoc javadoc = typedeclaration.getJavadoc();
2467+
List<TagElement> tags = javadoc.tags();
2468+
List<TagElement> innerTag = tags.get(0).fragments();
2469+
TagElement snippetTag = innerTag.get(0);
2470+
assertTrue((boolean) snippetTag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID));
2471+
assertEquals("Invalid snippet tag name", "@snippet", snippetTag.getTagName());
2472+
}
2473+
}
2474+
2475+
public void testInvalidSnippetForMarkdown_03() throws JavaModelException {
2476+
String source = """
2477+
/// {@snippet :
2478+
/// var s = "";
2479+
/// int x = 2;
2480+
/// String name = "eclipse";
2481+
/// }
2482+
public class Markdown {}
2483+
""";
2484+
this.workingCopies = new ICompilationUnit[1];
2485+
this.workingCopies[0] = getWorkingCopy("/Converter_25/src/markdown/Markdown.java", source, null);
2486+
if (this.docCommentSupport.equals(JavaCore.ENABLED)) {
2487+
CompilationUnit compilUnit = (CompilationUnit) runConversion(this.workingCopies[0], true);
2488+
TypeDeclaration typedeclaration = (TypeDeclaration) compilUnit.types().get(0);
2489+
Javadoc javadoc = typedeclaration.getJavadoc();
2490+
List<TagElement> tags = javadoc.tags();
2491+
List<TagElement> parentTagFrags = tags.get(0).fragments();
2492+
List<TextElement> texts = parentTagFrags.get(0).fragments();
2493+
assertTrue(texts.get(0) != null);
2494+
assertTrue(texts.get(1) != null);
2495+
assertTrue(texts.get(2) != null);
2496+
assertEquals("invalid first Text", " var s = \"\";", texts.get(0).getText());
2497+
assertEquals("invalid second Text", " int x = 2;", texts.get(1).getText());
2498+
assertEquals("invalid third Text", " String name = \"eclipse\";", texts.get(2).getText());
2499+
assertTrue((boolean) parentTagFrags.get(0).getProperty(TagProperty.TAG_PROPERTY_SNIPPET_IS_VALID));
2500+
assertEquals("Invalid snippet tag name", "@snippet", parentTagFrags.get(0).getTagName());
2501+
}
2502+
2503+
}
24362504
}

0 commit comments

Comments
 (0)