Skip to content

Commit e3a46d5

Browse files
javadoc code tag language is not converted to markdown (#1129)
* javadoc code tag language is not converted to markdown * Place code fence on its own line so the first code line is not consumed as the info string Co-authored-by: Tim te Beek <tim@moderne.io> --------- Co-authored-by: Tim te Beek <tim@moderne.io>
1 parent 68767e1 commit e3a46d5

2 files changed

Lines changed: 172 additions & 1 deletion

File tree

src/main/java/org/openrewrite/java/migrate/lang/JavadocToMarkdownDocComment.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,15 @@ private void convertLink(Javadoc.Link link) {
237237
private void convertStartElement(Javadoc.StartElement element) {
238238
String name = element.getName().toLowerCase();
239239
if (inPre && !"pre".equals(name)) {
240+
if ("code".equals(name)) {
241+
// Place the fence (and optional language) on its own line so the
242+
// code content starts fresh; otherwise the first code line would be
243+
// consumed as the fenced code block's info string.
244+
currentLine.append(extractCodeLanguage(element));
245+
lines.add(currentLine.toString());
246+
currentLine = new StringBuilder();
247+
return;
248+
}
240249
renderHtmlStartElement(element);
241250
return;
242251
}
@@ -293,6 +302,31 @@ private void convertStartElement(Javadoc.StartElement element) {
293302
}
294303
}
295304

305+
private String extractCodeLanguage(Javadoc.StartElement element) {
306+
return element.getAttributes().stream()
307+
.filter(attr -> attr instanceof Javadoc.Attribute)
308+
.map(attr -> (Javadoc.Attribute) attr)
309+
.filter(a -> "class".equalsIgnoreCase(a.getName()))
310+
.filter(a -> a.getValue() != null)
311+
.map(a -> renderInline(a.getValue()).trim())
312+
.map(JavadocToMarkdownConverter::stripAttributeQuotes)
313+
.findFirst()
314+
.orElse("");
315+
}
316+
317+
private static String stripAttributeQuotes(String value) {
318+
if (value.length() < 2) {
319+
return value;
320+
}
321+
322+
char first = value.charAt(0);
323+
char last = value.charAt(value.length() - 1);
324+
if ((first == '\'' && last == '\'') || (first == '"' && last == '"')) {
325+
return value.substring(1, value.length() - 1);
326+
}
327+
return value;
328+
}
329+
296330
private void renderHtmlStartElement(Javadoc.StartElement element) {
297331
currentLine.append('<').append(element.getName());
298332
for (Javadoc attr : element.getAttributes()) {
@@ -314,12 +348,21 @@ private void renderHtmlStartElement(Javadoc.StartElement element) {
314348
private void convertEndElement(Javadoc.EndElement element) {
315349
String name = element.getName().toLowerCase();
316350
if (inPre && !"pre".equals(name)) {
317-
currentLine.append("</").append(element.getName()).append('>');
351+
if (!"code".equals(name)) {
352+
currentLine.append("</").append(element.getName()).append('>');
353+
}
318354
return;
319355
}
320356
switch (name) {
321357
case "pre":
322358
inPre = false;
359+
// Flush any trailing inline code (e.g. `...);</code></pre>`) so the
360+
// closing fence sits on its own line, as Markdown requires. Only flush
361+
// real content; a whitespace-only line means the fence is already alone.
362+
if (!currentLine.toString().trim().isEmpty()) {
363+
lines.add(currentLine.toString());
364+
currentLine = new StringBuilder();
365+
}
323366
currentLine.append("```");
324367
break;
325368
case "code":

src/test/java/org/openrewrite/java/migrate/lang/JavadocToMarkdownDocCommentTest.java

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,134 @@ public void m() {}
496496
);
497497
}
498498

499+
@Test
500+
public void codeTagConverted() {
501+
rewriteRun(
502+
spec -> spec.recipe(new JavadocToMarkdownDocComment()),
503+
java(
504+
"""
505+
class Test {
506+
/**
507+
* <pre><code> public class TolkienCharacter {
508+
* String name;
509+
* double height;
510+
* }
511+
* </code></pre>
512+
*/
513+
public void withErrorMessageForFields() {
514+
}
515+
}
516+
""",
517+
"""
518+
class Test {
519+
/// ```
520+
/// public class TolkienCharacter {
521+
/// String name;
522+
/// double height;
523+
/// }
524+
/// ```
525+
public void withErrorMessageForFields() {
526+
}
527+
}
528+
""")
529+
);
530+
}
531+
532+
@Test
533+
public void codeTagWithEmptyLanguageConverted() {
534+
rewriteRun(
535+
spec -> spec.recipe(new JavadocToMarkdownDocComment()),
536+
java(
537+
"""
538+
class Test {
539+
/**
540+
* <pre><code class=''> public class TolkienCharacter {
541+
* String name;
542+
* double height;
543+
* }
544+
* </code></pre>
545+
*/
546+
public void withErrorMessageForFields() {
547+
}
548+
}
549+
""",
550+
"""
551+
class Test {
552+
/// ```
553+
/// public class TolkienCharacter {
554+
/// String name;
555+
/// double height;
556+
/// }
557+
/// ```
558+
public void withErrorMessageForFields() {
559+
}
560+
}
561+
""")
562+
);
563+
}
564+
565+
@Test
566+
public void codeTagLanguageNotConverted() {
567+
rewriteRun(
568+
spec -> spec.recipe(new JavadocToMarkdownDocComment()),
569+
java(
570+
"""
571+
class Test {
572+
/**
573+
* <pre><code class='java'> public class TolkienCharacter {
574+
* String name;
575+
* double height;
576+
* }
577+
* </code></pre>
578+
*/
579+
public void withErrorMessageForFields() {
580+
}
581+
}
582+
""",
583+
"""
584+
class Test {
585+
/// ```java
586+
/// public class TolkienCharacter {
587+
/// String name;
588+
/// double height;
589+
/// }
590+
/// ```
591+
public void withErrorMessageForFields() {
592+
}
593+
}
594+
""")
595+
);
596+
}
597+
598+
@Test
599+
public void codeTagClosedInline() {
600+
rewriteRun(
601+
spec -> spec.recipe(new JavadocToMarkdownDocComment()),
602+
java(
603+
"""
604+
class Test {
605+
/**
606+
* <pre><code class='java'> // assertion will pass
607+
* assertThat("abc").contains("ab");</code></pre>
608+
*/
609+
public void withErrorMessageForFields() {
610+
}
611+
}
612+
""",
613+
"""
614+
class Test {
615+
/// ```java
616+
/// // assertion will pass
617+
/// assertThat("abc").contains("ab");
618+
/// ```
619+
public void withErrorMessageForFields() {
620+
}
621+
}
622+
""")
623+
);
624+
}
625+
626+
499627
@Nested
500628
class Jep467FlagshipExamples {
501629

0 commit comments

Comments
 (0)