Skip to content

Commit

Permalink
Issue #14689: Resolve Javadoc summary false positives
Browse files Browse the repository at this point in the history
  • Loading branch information
patchwork01 committed Mar 28, 2024
1 parent 194a6f7 commit 617d911
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class InputIncorrectSummaryJavaDocCheck {

/**
* As of JDK 1.1, replaced by {@link #setBounds(int,int,int,int)}
* As of JDK 1.1, replaced by {@link #setBounds(int,int,int,int)}.
*/
void foo3() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import java.util.Arrays;
import java.util.BitSet;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Optional;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -218,13 +220,11 @@ private void validateUntaggedSummary(DetailNode ast) {
log(ast.getLineNumber(), MSG_SUMMARY_JAVADOC_MISSING);
}
else if (!period.isEmpty()) {
final String firstSentence = getFirstSentence(ast);
final int endOfSentence = firstSentence.lastIndexOf(period);
if (!summaryDoc.contains(period)) {
final String firstSentence = getFirstSentence(ast, period);
if (!summaryDoc.contains(period) || firstSentence.isEmpty()) {
log(ast.getLineNumber(), MSG_SUMMARY_FIRST_SENTENCE);
}
if (endOfSentence != -1
&& containsForbiddenFragment(firstSentence.substring(0, endOfSentence))) {
else if (containsForbiddenFragment(firstSentence)) {
log(ast.getLineNumber(), MSG_SUMMARY_JAVADOC);
}
}
Expand Down Expand Up @@ -579,28 +579,60 @@ private static String getStringInsideTag(String result, DetailNode detailNode) {
* Finds and returns first sentence.
*
* @param ast Javadoc root node.
* @param period Period character.
* @return first sentence.
*/
private static String getFirstSentence(DetailNode ast) {
private static String getFirstSentence(DetailNode ast, String period) {
final Deque<DetailNode> stack = new LinkedList<>();
stack.push(ast);
final StringBuilder result = new StringBuilder(256);
final String periodSuffix = DEFAULT_PERIOD + ' ';
for (DetailNode child : ast.getChildren()) {
final String text;
if (child.getChildren().length == 0) {
text = child.getText();
boolean foundPeriod = false;
while (!stack.isEmpty()) {
final DetailNode node = stack.pop();
if (node.getChildren().length == 0) {
final String text = node.getText();
final int periodIndex = findEndingPeriod(text, period);
if (periodIndex >= 0) {
foundPeriod = true;
result.append(text, 0, periodIndex);
break;
}
else {
result.append(text);
}
}
else {
text = getFirstSentence(child);
// Pushing last child first means it will be processed last
for (int childIndex = node.getChildren().length - 1; childIndex >= 0; childIndex--) {
stack.push(node.getChildren()[childIndex]);
}
}
if (!foundPeriod) {
result.setLength(0);
}
return result.toString();
}

if (text.contains(periodSuffix)) {
result.append(text, 0, text.indexOf(periodSuffix) + 1);
/**
* Find position of an ending period in the text. Ignores any period not followed by
* whitespace.
*
* @param text text to search
* @param period period character
* @return position of period character, or -1 if there is no ending period
*/
private static int findEndingPeriod(String text, String period) {
int periodIndex = text.indexOf(period);
while (periodIndex >= 0) {
final int afterPeriodIndex = periodIndex + period.length();
if (afterPeriodIndex >= text.length()
|| Character.isWhitespace(text.charAt(afterPeriodIndex))) {
break;
}

result.append(text);
else {
periodIndex = text.indexOf(period, afterPeriodIndex);
}
}
return result.toString();
return periodIndex;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ public void testPeriod() throws Exception {
"14: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
"19: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
"37: " + getCheckMessage(MSG_SUMMARY_MISSING_PERIOD),
"42: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
};

verifyWithInlineConfigParser(
Expand Down Expand Up @@ -230,12 +231,24 @@ public void testPeriodAtEnd() throws Exception {
"33: " + getCheckMessage(MSG_SUMMARY_JAVADOC_MISSING),
"40: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
"60: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
"70: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
};

verifyWithInlineConfigParser(
getPath("InputSummaryJavadocPeriodAtEnd.java"), expected);
}

@Test
public void testForbiddenFragmentRelativeToPeriod() throws Exception {
final String[] expected = {
"23: " + getCheckMessage(MSG_SUMMARY_JAVADOC),
"30: " + getCheckMessage(MSG_SUMMARY_JAVADOC),
};

verifyWithInlineConfigParser(
getPath("InputSummaryJavadocForbiddenFragmentRelativeToPeriod.java"), expected);
}

@Test
public void testHtmlFormatSummary() throws Exception {
final String[] expected = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
SummaryJavadoc
violateExecutionOnNonTightHtml = (default)false
forbiddenSummaryFragments = ^$|fail-summary-fragment
period = _
*/

package com.puppycrawl.tools.checkstyle.checks.javadoc.summaryjavadoc;

public class InputSummaryJavadocForbiddenFragmentRelativeToPeriod {

/**
* Summary sentence on its own line_
* <p>
* Another sentence that is not part of the summary,
* so this should not matter: fail-summary-fragment_
*/
void foo1() {}

// violation below 'Forbidden summary fragment.'
/**
* Summary sentence containing default period mentioning version 1.1, then ending with correct
* period after disallowed words, fail-summary-fragment_
*/
void foo2() {}

// violation below 'Forbidden summary fragment.'
/**
* Summary sentence containing correct period mid_word, then ending with correct period after
* disallowed words, fail-summary-fragment_
*/
void foo3() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
class InputSummaryJavadocIncorrect {

/**
* As of JDK 1.1, replaced by {@link #setBounds(int,int,int,int)}
* As of JDK 1.1, replaced by {@link #setBounds(int,int,int,int)}.
*/
void foo3() {}
// violation below 'Summary javadoc is missing.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
class InputSummaryJavadocIncorrect2 {

/**
* As of JDK 1.1, replaced by {@link #setBounds(int,int,int,int)}
* As of JDK 1.1, replaced by {@link #setBounds(int,int,int,int)}.
*/
void foo3() {}
// violation below 'Summary javadoc is missing.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,10 @@ void foo7(){}
* {@summary An especially short bit of Javadoc}
*/ // violation above 'Summary .* missing an ending period.'
void foo8() {}

// violation below 'First sentence .* missing an ending period.'
/**
* Summary sentence containing correct period mid_word, but not at the end
*/
void foo9() throws Exception {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

public class InputSummaryJavadocPeriodAtEnd {
/**
* JAXB 1.0 only default validation event handler
* JAXB 1.0 only default validation event handler.
*/
public static final byte NUL = 0;
// violation below 'Summary javadoc is missing.'
Expand Down Expand Up @@ -65,5 +65,18 @@ public void foo5(){
*/
public void foo6() {

}
// violation below 'First sentence .* missing an ending period.'
/**
* JAXB 1.0 missing end period
*/
public void foo7() {

}
/**
*.period at beginning of line, then summary sentence.
*/
public void foo8() {

}
}

0 comments on commit 617d911

Please sign in to comment.