Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2024 IBM Corporation and others.
* Copyright (c) 2000, 2026 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -181,7 +181,6 @@ protected boolean commentParse() {
boolean isDomParser = (this.kind & DOM_PARSER) != 0;
boolean isFormatterParser = (this.kind & FORMATTER_COMMENT_PARSER) != 0;
int lastStarPosition = -1;
boolean isTagElementClose = false;

// Init scanner position
this.markdown = this.source[this.javadocStart + 1] == '/';
Expand Down Expand Up @@ -350,9 +349,6 @@ protected boolean commentParse() {
// Fix bug 51650
this.textStart = -1;
this.markdownHelper.resetAtLineEnd();
if (this.inlineTagStarted && this.markdown) {
isTagElementClose = true;
}
break;
case '}' :
if (verifText && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) {
Expand All @@ -366,6 +362,11 @@ protected boolean commentParse() {
}
}
boolean isLiteralOrCode = this.tagValue == TAG_LITERAL_VALUE || this.tagValue == TAG_CODE_VALUE;
boolean shouldCloseInlineTag =
this.inlineTagStarted
&& !considerTagAsPlainText
&& !(isLiteralOrCode && openingBraces != 0);

if (this.inlineTagStarted) {
textEndPosition = this.index - 1;
boolean treatAsText= considerTagAsPlainText || (this.inlineReturn && this.inlineReturnOpenBraces > 0);
Expand All @@ -380,12 +381,8 @@ protected boolean commentParse() {
}
if (!isFormatterParser && !treatAsText && (!this.inlineReturn || this.inlineReturnOpenBraces <= 0))
this.textStart = this.index;
if (!isTagElementClose && this.markdown) { //The comment parser should create a TagElement only if the previous one is closed - markdown.
if (shouldCloseInlineTag) {
setInlineTagStarted(false);
} else if (!this.markdown) {
if (!(isLiteralOrCode && openingBraces != 0)) {
setInlineTagStarted(false);
}
}
if (this.inlineReturn) {
if (this.inlineReturnOpenBraces > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1840,7 +1840,7 @@ public class ArrayInCode {
}
}

public void testIllegelTagElement_01() throws JavaModelException {
public void testIllegelTagElement() throws JavaModelException {
String source= """
///{@link #getValue()
///value}
Expand All @@ -1854,42 +1854,13 @@ class IllegelTagElement {}
Javadoc javadoc = typedeclaration.getJavadoc();
List<TagElement> te = javadoc.tags();
assertEquals("TagElement length is grater than one", 1, te.size());
List<TagElement> tes = (te.get(0)).fragments();
assertEquals("inner TagElement length is grater than one", 1, tes.size());
assertEquals("TagName", "@link", tes.get(0).getTagName());
List<?> fragments = tes.get(0).fragments();
List<?> tes = (te.get(0)).fragments();
assertEquals("TagName", "@link", ((TagElement)tes.get(0)).getTagName());
List<?> fragments = ((TagElement)tes.get(0)).fragments();
assertEquals("fragments count does not match", 2, fragments.size());
assertTrue(fragments.get(0) instanceof MethodRef);
assertTrue(fragments.get(1) instanceof TextElement);
assertEquals("Incorrect text", "value", fragments.get(1).toString());
assertEquals("Incorrect name", "#getValue()", fragments.get(0).toString());
}
}

//this is a malfound test. Need to to analysis how it works
public void testIllegelTagElement_02() throws JavaModelException {
String source= """
///{@link #getValue()
///value{}}
class IllegelTagElement {}
""";
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_23/src/markdown/gh3761/IllegelTagElement.java", source, null);
if (this.docCommentSupport.equals(JavaCore.ENABLED)) {
CompilationUnit compilUnit = (CompilationUnit) runConversion(this.workingCopies[0], true);
TypeDeclaration typedeclaration = (TypeDeclaration) compilUnit.types().get(0);
Javadoc javadoc = typedeclaration.getJavadoc();
List<TagElement> te = javadoc.tags();
assertEquals("TagElement length is grater than one", 1, te.size());
List<TagElement> tes = (te.get(0)).fragments();
// assertEquals("fragments count does not match", 1, tes.size());
assertEquals("TagName", "@link", tes.get(0).getTagName());
List<?> fragments = tes.get(0).fragments();
assertTrue(fragments.get(0) instanceof MethodRef);
assertTrue(fragments.get(1) instanceof TextElement);
assertEquals("Incorrect text", "value", fragments.get(1).toString());
assertEquals("Incorrect name", "#getValue()", fragments.get(0).toString());
assertTrue(te.get(0).getLength() < tes.get(0).getLength());
assertEquals("Incorrect TagElement", 1, ((TextElement) (tes.get(1))).getFlags() & ASTNode.MALFORMED); //MALFOUND flag
}
}

Expand Down Expand Up @@ -2314,4 +2285,105 @@ public class Markdown{}
assertEquals("invalid tag name","@literal" ,innerTag.getTagName());
}
}

public void testInconsistencyInCodeAndLiteralTagsMarkdown4609_01() throws JavaModelException {
String source = """
/// Performs:
///
/// {@code
/// for (String s : strings) {
/// if (s.equals(value)) {
/// return 0;
/// }
/// if (s.startsWith(value)) {
/// return 1;
/// }
/// return -1;
/// }
/// }
/// The general contract of `hashCode` is:
///
/// - Whenever it is invoked on the same object more than once during
/// an execution of a Java application, the `hashCode` method
/// must consistently return the same integer, provided no information
/// used in `equals` comparisons on the object is modified.
/// This integer need not remain consistent from one execution of an
/// application to another execution of the same application.
/// - If two objects are equal according to the
/// [equals][#equals(Object)] method, then calling the
/// `hashCode` method on each of the two objects must produce the
/// same integer result.
/// - It is _not_ required that if two objects are unequal
/// according to the [equals][#equals(Object)] method, then
/// calling the `hashCode` method on each of the two objects
/// must produce distinct integer results. However, the programmer
/// should be aware that producing distinct integer results for
/// unequal objects may improve the performance of hash tables.
public class Markdown{}
""";
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_25/src/markdown/Markdown.java", source, null);
if (this.docCommentSupport.equals(JavaCore.ENABLED)) {
CompilationUnit compilUnit = (CompilationUnit) runConversion(this.workingCopies[0], true);
TypeDeclaration typedeclaration = (TypeDeclaration) compilUnit.types().get(0);
Javadoc javadoc = typedeclaration.getJavadoc();
List<TagElement> tags = javadoc.tags();
List<ASTNode> frags = tags.get(0).fragments();

assertEquals("Incorrect Frags", 22, frags.size());
assertEquals("Invalid element", ASTNode.TAG_ELEMENT, frags.get(1).getNodeType());
assertEquals("Invalid Text element content", "The general contract of `hashCode` is:", frags.get(2).toString());
}

}

public void testInconsistencyInCodeAndLiteralTagsMarkdown4609_02() throws JavaModelException {
String source = """
/// Performs:
///
/// {@literal
/// for (String s : strings) {
/// if (s.equals(value)) {
/// return 0;
/// }
/// if (s.startsWith(value)) {
/// return 1;
/// }
/// return -1;
/// }
/// }
/// The general contract of `hashCode` is:
///
/// - Whenever it is invoked on the same object more than once during
/// an execution of a Java application, the `hashCode` method
/// must consistently return the same integer, provided no information
/// used in `equals` comparisons on the object is modified.
/// This integer need not remain consistent from one execution of an
/// application to another execution of the same application.
/// - If two objects are equal according to the
/// [equals][#equals(Object)] method, then calling the
/// `hashCode` method on each of the two objects must produce the
/// same integer result.
/// - It is _not_ required that if two objects are unequal
/// according to the [equals][#equals(Object)] method, then
/// calling the `hashCode` method on each of the two objects
/// must produce distinct integer results. However, the programmer
/// should be aware that producing distinct integer results for
/// unequal objects may improve the performance of hash tables.
public class Markdown{}
""";
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/Converter_25/src/markdown/Markdown.java", source, null);
if (this.docCommentSupport.equals(JavaCore.ENABLED)) {
CompilationUnit compilUnit = (CompilationUnit) runConversion(this.workingCopies[0], true);
TypeDeclaration typedeclaration = (TypeDeclaration) compilUnit.types().get(0);
Javadoc javadoc = typedeclaration.getJavadoc();
List<TagElement> tags = javadoc.tags();
List<ASTNode> frags = tags.get(0).fragments();

assertEquals("Incorrect Frags", 22, frags.size());
assertEquals("Invalid element", ASTNode.TAG_ELEMENT, frags.get(1).getNodeType());
assertEquals("Invalid Text element content", "The general contract of `hashCode` is:", frags.get(2).toString());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2025 IBM Corporation and others.
* Copyright (c) 2000, 2026 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -2425,7 +2425,11 @@ private Javadoc convert(org.eclipse.jdt.internal.compiler.ast.Javadoc javadoc) {
ASTNode prev = fragments.get(0);
for (int i = 1; i < fragments.size(); i++) {
ASTNode cur = fragments.get(i);
if (cur.getStartPosition() <= prev.getStartPosition()) cur.setFlags(ASTNode.MALFORMED);
if (cur.getStartPosition() <= prev.getStartPosition())
cur.setFlags(ASTNode.MALFORMED);
else if ((cur.getStartPosition() + cur.getLength()) == (prev.getStartPosition()
+ prev.getLength()))
cur.setFlags(ASTNode.MALFORMED);
prev = cur;
}
}
Expand Down
Loading