Repository: checkstyle/checkstyle

Problem statement:
False positive: SummaryJavadocCheck
From [comment1](https://github.com/checkstyle/checkstyle/pull/11051/files#r775167621) and [comment2](https://github.com/checkstyle/checkstyle/pull/11051/files#r775200466)
I have read check documentation: https://checkstyle.sourceforge.io/config_javadoc.html#SummaryJavadoc
I have downloaded the latest checkstyle from: https://checkstyle.org/cmdline.html#Download_and_Run
I have executed the cli and showed it below, as cli describes the problem better than 1,000 words

```bash
/var/tmp $ javac Test2.java

/var/tmp $ cat config.xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
        "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
        "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
    <module name="TreeWalker">
        <module name="SummaryJavadocCheck"/>
    </module>
</module>

/var/tmp $ cat Test2.java
// unexpected violation below
/**
 * This is the actual summary.
 * {@summary This is wrong usage}
 */
public class Test2 {
}

// expected violation below
/**
 * This is summary
 */
class foo {
}

/var/tmp $ RUN_LOCALE="-Duser.language=en -Duser.country=US"
/var/tmp $ java $RUN_LOCALE -jar checkstyle-9.2.1-all.jar -c config.xml Test2.java
Starting audit...
[ERROR] /home/vyom/IdeaProjects/ConfigCheckstyle/src/TestP/Test2.java:2: Summary of Javadoc is missing an ending period. [SummaryJavadoc]
[ERROR] /home/vyom/IdeaProjects/ConfigCheckstyle/src/TestP/Test2.java:10: First sentence of Javadoc is missing an ending period. [SummaryJavadoc]
Audit done.
Checkstyle ends with 2 errors.
```
---

**Describe what you expect in detail.**
```
Starting audit...
[ERROR] /home/vyom/IdeaProjects/ConfigCheckstyle/src/TestP/Test2.java:10: First sentence of Javadoc is missing an ending period. [SummaryJavadoc]
Audit done.
```

If the first line is present then `@summary` is ignored, though a warning is given by the Javadoc tool.
```
Test.java:4: warning: invalid use of @summary
     * {@summary This is wrong usage}
```
see all details at https://github.com/checkstyle/checkstyle/pull/11051#discussion_r775167621

Expected: only violation on second javadoc


Hints:
on it.

Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheck.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheck.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheck.java
@@ -251,8 +251,8 @@ public class SummaryJavadocCheck extends AbstractJavadocCheck {
     private static final Pattern HTML_ELEMENTS =
             Pattern.compile("<[^>]*>");
 
-    /** Period literal. */
-    private static final String PERIOD = ".";
+    /** Default period literal. */
+    private static final String DEFAULT_PERIOD = ".";
 
     /** Summary tag text. */
     private static final String SUMMARY_TEXT = "@summary";
@@ -274,7 +274,7 @@ public class SummaryJavadocCheck extends AbstractJavadocCheck {
     /**
      * Specify the period symbol at the end of first javadoc sentence.
      */
-    private String period = PERIOD;
+    private String period = DEFAULT_PERIOD;
 
     /**
      * Setter to specify the regexp for forbidden summary fragments.
@@ -309,11 +309,14 @@ public int[] getRequiredJavadocTokens() {
     @Override
     public void visitJavadocToken(DetailNode ast) {
         final Optional<DetailNode> inlineTag = getInlineTagNode(ast);
-        if (inlineTag.isPresent() && isSummaryTag(inlineTag.get())) {
-            validateSummaryTag(inlineTag.get());
+        final DetailNode inlineTagNode = inlineTag.orElse(null);
+        if (inlineTag.isPresent()
+            && isSummaryTag(inlineTagNode)
+            && isDefinedFirst(inlineTagNode)) {
+            validateSummaryTag(inlineTagNode);
         }
-        else if (inlineTag.isPresent() && isInlineReturnTag(inlineTag.get())) {
-            validateInlineReturnTag(inlineTag.get());
+        else if (inlineTag.isPresent() && isInlineReturnTag(inlineTagNode)) {
+            validateInlineReturnTag(inlineTagNode);
         }
         else if (!startsWithInheritDoc(ast)) {
             validateUntaggedSummary(ast);
@@ -356,6 +359,61 @@ private static Optional<DetailNode> getInlineTagNode(DetailNode javadoc) {
             .map(SummaryJavadocCheck::getInlineTagNodeWithinHtmlElement);
     }
 
+    /**
+     * Whether the {@code {@summary}} tag is defined first in the javadoc.
+     *
+     * @param inlineSummaryTag node of type {@link JavadocTokenTypes#JAVADOC_INLINE_TAG}
+     * @return {@code true} if the {@code {@summary}} tag is defined first in the javadoc
+     */
+    private static boolean isDefinedFirst(DetailNode inlineSummaryTag) {
+        boolean isDefinedFirst = true;
+        DetailNode previousSibling = JavadocUtil.getPreviousSibling(inlineSummaryTag);
+        while (previousSibling != null && isDefinedFirst) {
+            switch (previousSibling.getType()) {
+                case JavadocTokenTypes.TEXT:
+                    isDefinedFirst = previousSibling.getText().isBlank();
+                    break;
+                case JavadocTokenTypes.HTML_ELEMENT:
+                    isDefinedFirst = !isTextPresentInsideHtmlTag(previousSibling);
+                    break;
+                default:
+                    break;
+            }
+            previousSibling = JavadocUtil.getPreviousSibling(previousSibling);
+        }
+        return isDefinedFirst;
+    }
+
+    /**
+     * Whether some text is present inside the HTML element or tag.
+     *
+     * @param node DetailNode of type {@link JavadocTokenTypes#HTML_TAG}
+     *             or {@link JavadocTokenTypes#HTML_ELEMENT}
+     * @return {@code true} if some text is present inside the HTML element or tag
+     */
+    public static boolean isTextPresentInsideHtmlTag(DetailNode node) {
+        DetailNode nestedChild = JavadocUtil.getFirstChild(node);
+        if (node.getType() == JavadocTokenTypes.HTML_ELEMENT) {
+            nestedChild = JavadocUtil.getFirstChild(nestedChild);
+        }
+        boolean isTextPresentInsideHtmlTag = false;
+        while (nestedChild != null && !isTextPresentInsideHtmlTag) {
+            switch (nestedChild.getType()) {
+                case JavadocTokenTypes.TEXT:
+                    isTextPresentInsideHtmlTag = !nestedChild.getText().isBlank();
+                    break;
+                case JavadocTokenTypes.HTML_TAG:
+                case JavadocTokenTypes.HTML_ELEMENT:
+                    isTextPresentInsideHtmlTag = isTextPresentInsideHtmlTag(nestedChild);
+                    break;
+                default:
+                    break;
+            }
+            nestedChild = JavadocUtil.getNextSibling(nestedChild);
+        }
+        return isTextPresentInsideHtmlTag;
+    }
+
     /**
      * Checks if the inline tag node is present.
      *
@@ -658,7 +716,7 @@ private static String getStringInsideTag(String result, DetailNode detailNode) {
      */
     private static String getFirstSentence(DetailNode ast) {
         final StringBuilder result = new StringBuilder(256);
-        final String periodSuffix = PERIOD + ' ';
+        final String periodSuffix = DEFAULT_PERIOD + ' ';
         for (DetailNode child : ast.getChildren()) {
             final String text;
             if (child.getChildren().length == 0) {


Test patch:
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheckTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheckTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheckTest.java
@@ -57,7 +57,9 @@ public void testCorrect() throws Exception {
 
     @Test
     public void testInlineCorrect() throws Exception {
-        final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
+        final String[] expected = {
+            "112: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
+        };
 
         verifyWithInlineConfigParser(
                 getPath("InputSummaryJavadocInlineCorrect.java"), expected);
@@ -81,7 +83,6 @@ public void testIncorrect() throws Exception {
             "142: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
             "147: " + getCheckMessage(MSG_SUMMARY_JAVADOC_MISSING),
             "150: " + getCheckMessage(MSG_SUMMARY_JAVADOC_MISSING),
-            "155: " + getCheckMessage(MSG_SUMMARY_MISSING_PERIOD),
         };
         verifyWithInlineConfigParser(
                 getPath("InputSummaryJavadocIncorrect.java"), expected);
@@ -100,7 +101,7 @@ public void testInlineForbidden() throws Exception {
             "80: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
             "94: " + getCheckMessage(MSG_SUMMARY_MISSING_PERIOD),
             "108: " + getCheckMessage(MSG_SUMMARY_JAVADOC_MISSING),
-            "115: " + getCheckMessage(MSG_SUMMARY_MISSING_PERIOD),
+            "114: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
         };
         verifyWithInlineConfigParser(
                 getPath("InputSummaryJavadocInlineForbidden.java"), expected);
@@ -148,6 +149,23 @@ public void testDefaultConfiguration() throws Exception {
                 getPath("InputSummaryJavadocIncorrect2.java"), expected);
     }
 
+    @Test
+    public void testIncorrectUsageOfSummaryTag() throws Exception {
+        final String[] expected = {
+            "34: " + getCheckMessage(MSG_SUMMARY_MISSING_PERIOD),
+            "41: " + getCheckMessage(MSG_SUMMARY_JAVADOC_MISSING),
+            "49: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
+            "57: " + getCheckMessage(MSG_SUMMARY_MISSING_PERIOD),
+            "64: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE),
+            "74: " + getCheckMessage(MSG_SUMMARY_MISSING_PERIOD),
+            // Until https://github.com/checkstyle/checkstyle/issues/11425
+            "82: " + getCheckMessage(MSG_SUMMARY_JAVADOC_MISSING),
+        };
+
+        verifyWithInlineConfigParser(
+            getPath("InputSummaryJavadocIncorrect3.java"), expected);
+    }
+
     @Test
     public void testInlineDefaultConfiguration() throws Exception {
         final String[] expected = {
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocIncorrect.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocIncorrect.java
--- a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocIncorrect.java
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocIncorrect.java
@@ -154,8 +154,6 @@ void foo7() {}
      * This is the summary.
      * {@summary This is NOT summary according to javadoc tool}
      */
-    // violation 2 lines above 'Summary .* missing an ending period.'
-    // until https://github.com/checkstyle/checkstyle/issues/11213
     void testMethod() {
     }
 }
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocIncorrect3.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocIncorrect3.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocIncorrect3.java
@@ -0,0 +1,90 @@
+/*
+SummaryJavadoc
+violateExecutionOnNonTightHtml = (default)false
+forbiddenSummaryFragments = (default)^$
+period = (default).
+
+
+*/
+
+package com.puppycrawl.tools.checkstyle.checks.javadoc.summaryjavadoc;
+
+/**
+ * This is the real summary.
+ * {@summary This is not the summary}
+ */
+public class InputSummaryJavadocIncorrect3 {
+
+    /**
+     * {@summary This is the real summary.}
+     * {@summary This is not the summary}
+     */
+    public void testAnotherSummaryTag() {
+    }
+
+    /**
+     * <p>This is summary.</p>
+     * {@summary This is not the summary}
+     */
+    public void testHtmlTags() {
+    }
+
+    /**
+     * <p><i></i></p>
+     * {@summary This is summary}
+     */
+    // violation 2 lines above 'Summary of Javadoc is missing an ending period'
+    public void testHtmlTags2() {
+    }
+
+    // violation below 'Summary javadoc is missing.'
+    /**
+     * @param a parameter
+     * {@summary Wrong usage}
+     */
+    public void method(int a) {
+    }
+
+    // violation below 'First sentence of Javadoc is missing an ending period'
+    /**
+     * <p> This is the summary {@summary This is not summary.}
+     */
+    public void testParagraphTag() {
+    }
+
+    /**
+     * <pre></pre>
+     * {@summary This is summary}
+     */
+    // violation 2 lines above 'Summary of Javadoc is missing an ending period'
+    public void testPreTag() {
+    }
+
+    // violation below 'First sentence of Javadoc is missing an ending period'
+    /**
+     * <i>This will be in italics and is the summary</i>
+     * {@summary This is not summary}
+     */
+    public void testOtherTags() {
+    }
+
+    /**
+     * <br>
+     * <br>
+     * {@summary Line breaks will be there but this will be the summary}
+     */
+    // violation 2 lines above 'Summary of Javadoc is missing an ending period.'
+    public void testBreakTag() {
+    }
+
+    // Until https://github.com/checkstyle/checkstyle/issues/11425
+    // violation below 'Summary javadoc is missing'
+    /**
+     * <ul>
+     *   <li><i>This is the summary</i></li>
+     * </ul>
+     * {@summary This is not the summary.}
+     */
+    public void testMultipleElements() {
+    }
+}
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocInlineCorrect.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocInlineCorrect.java
--- a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocInlineCorrect.java
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocInlineCorrect.java
@@ -108,6 +108,7 @@ public int validInlineJavadocReturn(int a) // ok
      */
     private void voidValidJavadoc() {} // ok
 
+    // violation below 'First sentence of Javadoc is missing an ending period'
     /**
      * Sentence starts as a plain text sentence
      * {@summary ... but ends in the summary tag.}
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocInlineForbidden.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocInlineForbidden.java
--- a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocInlineForbidden.java
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/summaryjavadoc/InputSummaryJavadocInlineForbidden.java
@@ -110,12 +110,11 @@ public void validInlineJavadoc()
     void foo12() {
     }
 
+    // violation below 'First sentence of Javadoc is missing an ending period'
     /**
      * Sentence starts as a plain text sentence
      * {@summary ... but ends in the summary tag}
      */
-    // violation 2 lines above 'Summary .* missing an ending period.'
-    // until https://github.com/checkstyle/checkstyle/issues/11213
     public class TestClass {}
 
     /**