Skip to content

Commit a0bec61

Browse files
kluevergoogle-java-format Team
authored andcommitted
Fix NullPointerException when visitListItem encounters a non-paragraph first child.
`visitListItem` in `MarkdownPositions` previously used a pattern-matching `switch` on `listItem.getFirstChild()`. If a Markdown `ListItem` starts with a non-paragraph child (such as when an empty or unfinished bullet item `/// -` has `null` as its first child), the `switch` statement throws a `NullPointerException` because it does not explicitly handle `null`. This change replaces the `switch` with `if (listItem.getFirstChild() instanceof Paragraph paragraph)` to safely return `false` on `null` or non-`Paragraph` children without throwing an exception. It also updates `LIST_ITEM_START_PATTERN` to allow list markers without trailing whitespace at the end of the input (`$`). Tested: Added `markdownEmptyListItem` in `JavadocFormattingTest.java` and ran `blaze test //third_party/java_src/google_java_format/...`. PiperOrigin-RevId: 945788396
1 parent 77bee2d commit a0bec61

2 files changed

Lines changed: 25 additions & 12 deletions

File tree

core/src/main/java/com/google/googlejavaformat/java/javadoc/MarkdownPositions.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,15 @@ private boolean visitListItem(ListItem listItem) {
129129
verify(matcher.lookingAt());
130130
ListItemOpenTag openToken = new ListItemOpenTag(matcher.group(1));
131131
addSpan(listItem, openToken, LIST_ITEM_CLOSE_TOKEN);
132-
return switch (listItem.getFirstChild()) {
133-
case Paragraph paragraph -> {
134-
// A ListItem typically contains a Paragraph, but we don't want to visit that Paragraph
135-
// because that would lead us to introduce a line break after the list introduction
136-
// (the `-` or whatever). So we visit the children and siblings of the Paragraph instead.
137-
visitNodeList(paragraph.getFirstChild());
138-
visitNodeList(paragraph.getNext());
139-
yield true;
140-
}
141-
default -> false;
142-
};
132+
if (listItem.getFirstChild() instanceof Paragraph paragraph) {
133+
// A ListItem typically contains a Paragraph, but we don't want to visit that Paragraph
134+
// because that would lead us to introduce a line break after the list introduction
135+
// (the `-` or whatever). So we visit the children and siblings of the Paragraph instead.
136+
visitNodeList(paragraph.getFirstChild());
137+
visitNodeList(paragraph.getNext());
138+
return true;
139+
}
140+
return false;
143141
}
144142

145143
private void visitHeading(Heading heading) {
@@ -258,5 +256,5 @@ public String toString() {
258256
// The leading \s here works around what appears to be a CommonMark bug. We shouldn't ever see
259257
// space at the purported start of a list item?
260258
private static final Pattern LIST_ITEM_START_PATTERN =
261-
Pattern.compile("(?:\\s*)(([-+*]|[0-9]+[.)])\\s)");
259+
Pattern.compile("(?:\\s*)(([-+*]|[0-9]+[.)])(?:\\s|$))");
262260
}

core/src/test/java/com/google/googlejavaformat/java/JavadocFormattingTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,6 +1714,21 @@ class Test {}
17141714
doFormatTest(input, expected);
17151715
}
17161716

1717+
@Test
1718+
public void markdownEmptyListItem() {
1719+
assume().that(MARKDOWN_JAVADOC_SUPPORTED).isTrue();
1720+
String input =
1721+
"""
1722+
/// A list with an empty item:
1723+
/// - `foo`: enabled by default
1724+
/// - `bar`: disabled by default
1725+
/// -
1726+
class Test {}
1727+
""";
1728+
String expected = input;
1729+
doFormatTest(input, expected);
1730+
}
1731+
17171732
@Test
17181733
public void markdownFencedCodeBlocks() {
17191734
assume().that(MARKDOWN_JAVADOC_SUPPORTED).isTrue();

0 commit comments

Comments
 (0)