Repository: checkstyle/checkstyle

Problem statement:
JavadocParagraph does not work when paragraphs have their corresponding closing tag
I have read check documentation: https://checkstyle.org/checks/javadoc/javadocparagraph.html
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

Detected at: https://github.com/checkstyle/checkstyle/issues/15503#issuecomment-2362869286

In [JavadocParagraph](https://checkstyle.org/checks/javadoc/javadocparagraph.html)'s implementation, we're only checking for `P` tags which aren't closed, i.e we're checking only for `<p>` which doesn't have corresponding `</p>`.

There is a difference in parsed AST when `P` have its corresponding closing tag and when it doesn't have it. As explained in the above referenced comment, AST for `P` when it is not closed looks like this:

```
    |   |   |       |--HTML_ELEMENT -> HTML_ELEMENT [4:3]
    |   |   |       |   `--P_TAG_START -> P_TAG_START [4:3]
```

and when it is properly closed, it looks like this:

```
    |   |   |       |--HTML_ELEMENT -> HTML_ELEMENT [4:3]
    |   |   |       |   `--PARAGRAPH -> PARAGRAPH [4:3]
    |   |   |       |       |--P_TAG_START -> P_TAG_START [4:3]
```

A new `PARAGRAPH ` appears between the token.

What we do in the Check's implementation:

https://github.com/checkstyle/checkstyle/blob/d07072b179330e40357c7c8852883af815d6978c/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheck.java#L147-L156

We check if after `HTML_ELEMENT` is there a `P_TAG_START` token? This token is for opening paragraph tag ( `<p>` ). If yes then move further.

This case is only valid for `<p>` tags which does not have their corresponding `</p>`, so when we encounter a proper pair of paragraph tag (`<p></p>`), our check ignores that paragraph as a new token ( `PARAGRAPH` ) appears between `HTML_ELEMENT` & `P_TAG_START`.

Example:

```xml
$ cat .\javadocparagraph_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="JavadocParagraph"/>
  </module>
</module>
```

```java
$ cat .\InvalidParagraphTagPosition.java
/**
 * Some summary.
 *
 * <p>  Some Javadoc.
 *
 * <p>  Some Javadoc. </p> // false-negative
 */
public class InvalidParagraphTagPosition {
    /**
     * some javadoc.
     * <p>
     *
     * <p></p> // false-negative
     */
    int a;

    /**
     * Some Javadoc.<P>
     * Some Javadoc.<P></P> // false-negative
     */
    int b;
}
```

```
$ java -jar .\checkstyle-10.18.1-all.jar -c .\javadocparagraph_config.xml .\InvalidParagraphTagPosition.java
Starting audit...
[ERROR] C:\checkstyle testing\.\InvalidParagraphTagPosition.java:4: <p> tag should be placed immediately before the first word, with no space after. [JavadocParagraph]
[ERROR] C:\checkstyle testing\.\InvalidParagraphTagPosition.java:11: <p> tag should be placed immediately before the first word, with no space after. [JavadocParagraph]
[ERROR] C:\checkstyle testing\.\InvalidParagraphTagPosition.java:11: <p> tag should be preceded with an empty line. [JavadocParagraph]
[ERROR] C:\checkstyle testing\.\InvalidParagraphTagPosition.java:18: <p> tag should be placed immediately before the first word, with no space after. [JavadocParagraph]
[ERROR] C:\checkstyle testing\.\InvalidParagraphTagPosition.java:18: <p> tag should be preceded with an empty line. [JavadocParagraph]
Audit done.
Checkstyle ends with 5 errors.
```

We get errors only for `<p>` which are not closed, we don't get any violations for `<p>` which are closed properly. We expect the same errors as we got for `<p>`

---

**Describe what you expect in detail.**

Fix the check's implementation to check for both types of tags: `<p>` & `<p></p>`



Hints:

Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/TokenTypes.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/TokenTypes.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/api/TokenTypes.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/TokenTypes.java
@@ -1215,7 +1215,7 @@ public final class TokenTypes {
      * <pre>
      * new ArrayList(50);
      * </pre>
-     * <p> parses as:</p>
+     * <p>parses as:</p>
      * <pre>
      * |--EXPR -&gt; EXPR
      * |   `--LITERAL_NEW -&gt; new
@@ -5184,7 +5184,7 @@ public final class TokenTypes {
 
     /**
      * The type that refers to all types. This node has no children.
-     * <p> For example: </p>
+     * <p>For example: </p>
      * <pre>
      *
      * List&lt;?&gt; list;
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheck.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheck.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheck.java
@@ -44,6 +44,10 @@
  * <a href="https://www.w3schools.com/html/html_blocks.asp">HTML block-tag</a>,
  * nested paragraph tags are allowed to do that.</li>
  * </ul>
+ * <p><b>ATTENTION:</b></p>
+ * <p>This Check ignores HTML comments.</p>
+ * <p>The Check ignores all the nested paragraph tags,
+ * it will not give any kind of violation if the paragraph tag is nested.</p>
  * <ul>
  * <li>
  * Property {@code allowNewlineParagraph} - Control whether the &lt;p&gt; tag
@@ -174,7 +178,8 @@ public void visitJavadocToken(DetailNode ast) {
             checkEmptyLine(ast);
         }
         else if (ast.getType() == JavadocTokenTypes.HTML_ELEMENT
-                && JavadocUtil.getFirstChild(ast).getType() == JavadocTokenTypes.P_TAG_START) {
+                && (JavadocUtil.getFirstChild(ast).getType() == JavadocTokenTypes.P_TAG_START
+                    || JavadocUtil.getFirstChild(ast).getType() == JavadocTokenTypes.PARAGRAPH)) {
             checkParagraphTag(ast);
         }
     }
@@ -198,25 +203,49 @@ private void checkEmptyLine(DetailNode newline) {
      * @param tag html tag.
      */
     private void checkParagraphTag(DetailNode tag) {
-        final DetailNode newLine = getNearestEmptyLine(tag);
-        if (isFirstParagraph(tag)) {
-            log(tag.getLineNumber(), tag.getColumnNumber(), MSG_REDUNDANT_PARAGRAPH);
-        }
-        else if (newLine == null || tag.getLineNumber() - newLine.getLineNumber() != 1) {
-            log(tag.getLineNumber(), tag.getColumnNumber(), MSG_LINE_BEFORE);
-        }
+        if (!isNestedParagraph(tag)) {
+            final DetailNode newLine = getNearestEmptyLine(tag);
+            if (isFirstParagraph(tag)) {
+                log(tag.getLineNumber(), tag.getColumnNumber(), MSG_REDUNDANT_PARAGRAPH);
+            }
+            else if (newLine == null || tag.getLineNumber() - newLine.getLineNumber() != 1) {
+                log(tag.getLineNumber(), tag.getColumnNumber(), MSG_LINE_BEFORE);
+            }
 
-        final String blockTagName = findFollowedBlockTagName(tag);
-        if (blockTagName != null) {
-            log(tag.getLineNumber(), tag.getColumnNumber(), MSG_PRECEDED_BLOCK_TAG, blockTagName);
-        }
+            final String blockTagName = findFollowedBlockTagName(tag);
+            if (blockTagName != null) {
+                log(tag.getLineNumber(), tag.getColumnNumber(),
+                        MSG_PRECEDED_BLOCK_TAG, blockTagName);
+            }
 
-        if (!allowNewlineParagraph && isImmediatelyFollowedByNewLine(tag)) {
-            log(tag.getLineNumber(), tag.getColumnNumber(), MSG_MISPLACED_TAG);
+            if (!allowNewlineParagraph && isImmediatelyFollowedByNewLine(tag)) {
+                log(tag.getLineNumber(), tag.getColumnNumber(), MSG_MISPLACED_TAG);
+            }
+            if (isImmediatelyFollowedByText(tag)) {
+                log(tag.getLineNumber(), tag.getColumnNumber(), MSG_MISPLACED_TAG);
+            }
         }
-        if (isImmediatelyFollowedByText(tag)) {
-            log(tag.getLineNumber(), tag.getColumnNumber(), MSG_MISPLACED_TAG);
+    }
+
+    /**
+     * Determines whether the paragraph tag is nested.
+     *
+     * @param tag html tag.
+     * @return true, if the paragraph tag is nested.
+     */
+    private static boolean isNestedParagraph(DetailNode tag) {
+        boolean nested = false;
+        DetailNode parent = tag;
+
+        while (parent != null) {
+            if (parent.getType() == JavadocTokenTypes.PARAGRAPH) {
+                nested = true;
+                break;
+            }
+            parent = parent.getParent();
         }
+
+        return nested;
     }
 
     /**
@@ -245,9 +274,11 @@ private static String findFollowedBlockTagName(DetailNode tag) {
      */
     @Nullable
     private static DetailNode findFirstHtmlElementAfter(DetailNode tag) {
-        DetailNode htmlElement = JavadocUtil.getNextSibling(tag);
+        DetailNode htmlElement = getNextSibling(tag);
 
-        while (htmlElement != null && htmlElement.getType() != JavadocTokenTypes.HTML_ELEMENT) {
+        while (htmlElement != null
+                && htmlElement.getType() != JavadocTokenTypes.HTML_ELEMENT
+                && htmlElement.getType() != JavadocTokenTypes.HTML_TAG) {
             if ((htmlElement.getType() == JavadocTokenTypes.TEXT
                     || htmlElement.getType() == JavadocTokenTypes.JAVADOC_INLINE_TAG)
                     && !CommonUtil.isBlank(htmlElement.getText())) {
@@ -268,7 +299,13 @@ private static DetailNode findFirstHtmlElementAfter(DetailNode tag) {
      */
     @Nullable
     private static String getHtmlElementName(DetailNode htmlElement) {
-        final DetailNode htmlTag = JavadocUtil.getFirstChild(htmlElement);
+        final DetailNode htmlTag;
+        if (htmlElement.getType() == JavadocTokenTypes.HTML_TAG) {
+            htmlTag = htmlElement;
+        }
+        else {
+            htmlTag = JavadocUtil.getFirstChild(htmlElement);
+        }
         final DetailNode htmlTagFirstChild = JavadocUtil.getFirstChild(htmlTag);
         final DetailNode htmlTagName =
                 JavadocUtil.findFirstToken(htmlTagFirstChild, JavadocTokenTypes.HTML_TAG_NAME);
@@ -364,7 +401,8 @@ private static DetailNode getNearestEmptyLine(DetailNode node) {
      * @return true, if the paragraph tag is immediately followed by the text.
      */
     private static boolean isImmediatelyFollowedByText(DetailNode tag) {
-        final DetailNode nextSibling = JavadocUtil.getNextSibling(tag);
+        final DetailNode nextSibling = getNextSibling(tag);
+
         return nextSibling.getType() == JavadocTokenTypes.EOF
                 || nextSibling.getText().startsWith(" ");
     }
@@ -373,10 +411,35 @@ private static boolean isImmediatelyFollowedByText(DetailNode tag) {
      * Tests whether the paragraph tag is immediately followed by the new line.
      *
      * @param tag html tag.
-     * @return true, if the paragraph tag is immediately followed by the text.
+     * @return true, if the paragraph tag is immediately followed by the new line.
      */
     private static boolean isImmediatelyFollowedByNewLine(DetailNode tag) {
-        final DetailNode nextSibling = JavadocUtil.getNextSibling(tag);
-        return nextSibling.getType() == JavadocTokenTypes.NEWLINE;
+        return getNextSibling(tag).getType() == JavadocTokenTypes.NEWLINE;
+    }
+
+    /**
+     * Custom getNextSibling method to handle different types of paragraph tag.
+     * It works for both {@code <p>} and {@code <p></p>} tags.
+     *
+     * @param tag HTML_ELEMENT tag.
+     * @return next sibling of the tag.
+     */
+    private static DetailNode getNextSibling(DetailNode tag) {
+        DetailNode nextSibling;
+
+        if (JavadocUtil.getFirstChild(tag).getType() == JavadocTokenTypes.PARAGRAPH) {
+            final DetailNode paragraphToken = JavadocUtil.getFirstChild(tag);
+            final DetailNode paragraphStartTagToken = JavadocUtil.getFirstChild(paragraphToken);
+            nextSibling = JavadocUtil.getNextSibling(paragraphStartTagToken);
+        }
+        else {
+            nextSibling = JavadocUtil.getNextSibling(tag);
+        }
+
+        if (nextSibling.getType() == JavadocTokenTypes.HTML_COMMENT) {
+            nextSibling = JavadocUtil.getNextSibling(nextSibling);
+        }
+
+        return nextSibling;
     }
 }


Test patch:
diff --git a/src/it/resources/com/google/checkstyle/test/chapter7javadoc/rule712paragraphs/InputIncorrectJavadocParagraph.java b/src/it/resources/com/google/checkstyle/test/chapter7javadoc/rule712paragraphs/InputIncorrectJavadocParagraph.java
--- a/src/it/resources/com/google/checkstyle/test/chapter7javadoc/rule712paragraphs/InputIncorrectJavadocParagraph.java
+++ b/src/it/resources/com/google/checkstyle/test/chapter7javadoc/rule712paragraphs/InputIncorrectJavadocParagraph.java
@@ -33,8 +33,7 @@ class InputIncorrectJavadocParagraph {
    *
    * <p>Some Javadoc.
    *
-   * @see <a href="example.com">
-   *     Documentation about GWT emulated source</a>
+   * @see <a href="example.com">Documentation about GWT emulated source</a>
    */
   boolean emulated() {
     return false;
@@ -82,13 +81,12 @@ class InnerInputCorrectJavaDocParagraphCheck {
      *
      * <p>
      *   Some Javadoc.<p>
-     * @see <a href="example.com">
-     *     Documentation about GWT emulated source</a>
+     * @see <a href="example.com">Documentation about GWT emulated source</a>
      */
-    // 2 violations 4 lines above:
+    // 2 violations 3 lines above:
     //  '<p> tag should be placed immediately before the first word'
     //  '<p> tag should be preceded with an empty line.'
-    // violation 6 lines above 'Javadoc tag '@see' should be preceded with an empty line.'
+    // violation 5 lines above 'Javadoc tag '@see' should be preceded with an empty line.'
     boolean emulated() {
       return false;
     }
@@ -116,8 +114,7 @@ boolean emulated() {
          *
          *  <p>  Some Javadoc.
          *
-         * @see <a href="example.com">
-         *     Documentation about <p> GWT emulated source</a>
+         * @see <a href="example.com">Documentation about <p> GWT emulated source</a>
          */
         // 2 violations 2 lines above:
         //  '<p> tag should be placed immediately before the first word'
@@ -127,14 +124,16 @@ boolean emulated() {
         }
       };
 
-  /* 4 lines below, no violation until #15685 */
   /**
    * Some summary.
    *
    * <p><h1>Testing...</h1></p>
    */
+  // violation 2 lines above '<p> tag should not precede HTML block-tag '<h1>''
   class InnerPrecedingPtag {
-    /* 5 lines below, no violation until #15685 */
+    // 2 violations 6 lines below:
+    //  '<p> tag should be placed immediately before the first word'
+    //  '<p> tag should not precede HTML block-tag '<ul>''
     /**
      * Some summary.
      *
@@ -148,7 +147,9 @@ class InnerPrecedingPtag {
      */
     public void foo() {}
 
-    /* 5 lines below, no violation until #15685 */
+    // 2 violations 6 lines below:
+    //  '<p> tag should be placed immediately before the first word'
+    //  '<p> tag should not precede HTML block-tag '<table>''
     /**
      *  Some summary.
      *
@@ -159,7 +160,9 @@ public void foo() {}
      */
     public void fooo() {}
 
-    /* 5 lines below, no violation until #15685 */
+    // 2 violations 6 lines below:
+    //  '<p> tag should be placed immediately before the first word'
+    //  '<p> tag should not precede HTML block-tag '<pre>''
     /**
      * Some summary.
      *
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheckTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheckTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheckTest.java
@@ -188,10 +188,82 @@ public void testAllowNewlineParagraph3() throws Exception {
     public void testJavadocParagraph() throws Exception {
         final String[] expected = {
             "19:4: " + getCheckMessage(MSG_LINE_BEFORE),
-            "30:7: " + getCheckMessage(MSG_LINE_BEFORE),
+            "28:7: " + getCheckMessage(MSG_REDUNDANT_PARAGRAPH),
+            "31:7: " + getCheckMessage(MSG_LINE_BEFORE),
+            "50:7: " + getCheckMessage(MSG_PRECEDED_BLOCK_TAG, "ul"),
+            "65:8: " + getCheckMessage(MSG_LINE_BEFORE),
+            "76:8: " + getCheckMessage(MSG_PRECEDED_BLOCK_TAG, "table"),
+            "87:8: " + getCheckMessage(MSG_PRECEDED_BLOCK_TAG, "pre"),
         };
 
         verifyWithInlineConfigParser(
                 getPath("InputJavadocParagraphCheck1.java"), expected);
     }
+
+    @Test
+    public void testJavadocParagraphOpenClosedTag() throws Exception {
+        final String[] expected = {
+            "14:4: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "21:7: " + getCheckMessage(MSG_LINE_BEFORE),
+            "28:20: " + getCheckMessage(MSG_LINE_BEFORE),
+            "29:20: " + getCheckMessage(MSG_LINE_BEFORE),
+            "35:8: " + getCheckMessage(MSG_REDUNDANT_PARAGRAPH),
+            "36:6: " + getCheckMessage(MSG_TAG_AFTER),
+            "38:6: " + getCheckMessage(MSG_TAG_AFTER),
+            "58:7: " + getCheckMessage(MSG_PRECEDED_BLOCK_TAG, "ul"),
+            "73:7: " + getCheckMessage(MSG_PRECEDED_BLOCK_TAG, "h1"),
+            "85:7: " + getCheckMessage(MSG_PRECEDED_BLOCK_TAG, "h1"),
+        };
+
+        verifyWithInlineConfigParser(
+                getPath("InputJavadocParagraphIncorrectOpenClosedTag.java"), expected);
+    }
+
+    @Test
+    public void testJavadocParagraphOpenClosedTag2() throws Exception {
+        final String[] expected = {
+            "14:4: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "21:7: " + getCheckMessage(MSG_LINE_BEFORE),
+            "30:20: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "30:20: " + getCheckMessage(MSG_LINE_BEFORE),
+            "31:20: " + getCheckMessage(MSG_LINE_BEFORE),
+            "37:8: " + getCheckMessage(MSG_REDUNDANT_PARAGRAPH),
+            "38:6: " + getCheckMessage(MSG_TAG_AFTER),
+            "40:6: " + getCheckMessage(MSG_TAG_AFTER),
+            "50:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "63:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "63:7: " + getCheckMessage(MSG_PRECEDED_BLOCK_TAG, "ul"),
+            "78:7: " + getCheckMessage(MSG_PRECEDED_BLOCK_TAG, "h1"),
+            "87:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "91:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "91:7: " + getCheckMessage(MSG_PRECEDED_BLOCK_TAG, "h1"),
+        };
+
+        verifyWithInlineConfigParser(
+                getPath("InputJavadocParagraphIncorrectOpenClosedTag2.java"), expected);
+    }
+
+    @Test
+    public void testJavadocParagraphOpenClosedTag3() throws Exception {
+        final String[] expected = {
+            "15:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "23:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "31:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+        };
+
+        verifyWithInlineConfigParser(
+                getPath("InputJavadocParagraphIncorrectOpenClosedTag3.java"), expected);
+    }
+
+    @Test
+    public void testIncorrect3() throws Exception {
+        final String[] expected = {
+            "15:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "23:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+            "31:7: " + getCheckMessage(MSG_MISPLACED_TAG),
+        };
+
+        verifyWithInlineConfigParser(
+                getPath("InputJavadocParagraphIncorrect6.java"), expected);
+    }
 }
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphCheck1.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphCheck1.java
--- a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphCheck1.java
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphCheck1.java
@@ -23,6 +23,7 @@ public class InputJavadocParagraphCheck1 {
 // violation 4 lines above '<p> tag should be preceded with an empty line'
 class Check {
 
+   // violation 2 lines below 'Redundant <p> tag.'
    /**
     * <p>
     * Checks whether file contains code. Files which are considered to have no code:
@@ -31,4 +32,62 @@ class Check {
     */
    // violation 2 lines above '<p> tag should be preceded with an empty line.'
     void inheritDocWithThrows() {}
+
+    /**
+     * Some summary.
+     *
+     * <p>The following package declaration:</p>
+     * <pre>
+     * package com.puppycrawl.tools.checkstyle;
+     * </pre>
+     */
+    int iamtoolazyyyyyyy = 45;
+
+    // violation 4 lines below '<p> tag should not precede HTML block-tag '<ul>''
+    /**
+     * Some summary.
+     *
+     *<p>
+     *  <ul> // ok until #15762
+     *    <p> // ok until #15762
+     *      <li>1</li> should NOT give violation as there is not empty line before
+     *    </p> // false-negative on this line & above until #15762
+     *  </ul> // ok until #15762
+     *</p>
+     */
+    public void foo() {}
+
+    // violation 5 lines below '<p> tag should be preceded with an empty line.'
+    /**
+     * Some summary.
+     *
+     * <b>
+     * <p>
+     *  <br/>
+     * </p>
+     * </b>
+     */
+    public void fooo() {}
+
+    // violation 4 lines below '<p> tag should not precede HTML block-tag '<table>''
+    /**
+     *  Some summary.
+     *
+     * <p>
+     *  <table> // ok until #15762
+     *  </table> // ok until #15762
+     * </p>
+     */
+    public void foooo() {}
+
+    // violation 4 lines below '<p> tag should not precede HTML block-tag '<pre>''
+    /**
+     * Some summary.
+     *
+     * <p>
+     *   <pre>testing...</pre> // ok until #15762
+     *   <pre>testing...</pre> // ok until #15762
+     * </p>
+     */
+    public void fooooo() {}
 }
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrect6.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrect6.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrect6.java
@@ -0,0 +1,42 @@
+/*
+JavadocParagraph
+violateExecutionOnNonTightHtml = (default)false
+allowNewlineParagraph = (default)true
+
+
+*/
+
+package com.puppycrawl.tools.checkstyle.checks.javadoc.javadocparagraph;
+
+public class InputJavadocParagraphIncorrect6 {
+    /**
+    * Some Summary.
+    *
+    * <p><!-- comment is required --> extra space in paragraph after comment is violation
+    */
+    // violation 2 lines above '<p> tag should be placed immediately before the first word'
+    int a;
+
+    /**
+    * Some Summary.
+    *
+    * <p> <!-- comment is required -->extra space in paragraph before comment is violation
+    */
+    // violation 2 lines above '<p> tag should be placed immediately before the first word'
+    int b;
+
+    /**
+    * Some Summary.
+    *
+    * <p> <!-- comment is required --> both cases combined, this is also violation
+    */
+    // violation 2 lines above '<p> tag should be placed immediately before the first word'
+    int c;
+
+    /**
+    * Some Summary.
+    *
+    * <p><!-- comment is required -->no extra spaces, this is okay
+    */
+    int d;
+}
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrectOpenClosedTag.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrectOpenClosedTag.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrectOpenClosedTag.java
@@ -0,0 +1,91 @@
+/*
+JavadocParagraph
+violateExecutionOnNonTightHtml = (default)false
+allowNewlineParagraph = (default)true
+
+
+*/
+
+package com.puppycrawl.tools.checkstyle.checks.javadoc.javadocparagraph;
+
+/**
+ * Some summary.
+ *
+ * <p>  Some Javadoc. </p>
+ */
+// violation 2 lines above '<p> tag should be placed immediately before the first word'
+public class InputJavadocParagraphIncorrectOpenClosedTag {
+
+    /**
+    * some javadoc.
+    * <p></p>
+    */
+    // violation 2 lines above '<p> tag should be preceded with an empty line.'
+    int a;
+
+    // violation 2 lines below '<p> tag should be preceded with an empty line.'
+    /**
+    * Some Javadoc.<P>
+    * Some Javadoc.<P></P>
+    */
+    // violation 2 lines above '<p> tag should be preceded with an empty line.'
+    int b;
+
+    // violation below 'Redundant <p> tag.'
+    /**<p>some javadoc.</p>
+    *
+    * Some <p>Javadoc.</p>
+    *
+    * Some <p>Javadoc.</p>
+    */
+    // violation 5 lines above 'Empty line should be followed by <p> tag on the next line.'
+    // violation 4 lines above 'Empty line should be followed by <p> tag on the next line.'
+    int c;
+
+    /**
+    * Some Summary.
+    *
+    * <p>
+    *   Some Javadoc. // ok until #15762
+    * </p>
+    */
+    int d;
+
+    // violation 4 lines below '<p> tag should not precede HTML block-tag '<ul>''
+    /**
+    * Some Summary.
+    *
+    * <p>
+    *   <ul> // ok until #15762
+    *     <li>Item 1</li> // ok until #15762
+    *     <li>Item 2</li> // ok until #15762
+    *     <li>Item 3</li> // ok until #15762
+    *   </ul> // ok until #15762
+    * </p>
+    */
+    int e;
+
+    /**
+    * Some Summary.
+    *
+    * <p><b>testing....</b></p>
+    *
+    * <p><h1>testing....</h1></p>
+    */
+    // violation 2 lines above '<p> tag should not precede HTML block-tag '<h1>''
+    int f;
+
+    /**
+    * Some Summary.
+    *
+    * <p>
+    *     <b>testing....</b> // ok until #15762
+    * </p>
+    *
+    * <p>
+    *     <h1>testing....</h1> // ok until #15762
+    * </p>
+    */
+    // violation 4 lines above '<p> tag should not precede HTML block-tag '<h1>''
+    int g;
+}
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrectOpenClosedTag2.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrectOpenClosedTag2.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrectOpenClosedTag2.java
@@ -0,0 +1,99 @@
+/*
+JavadocParagraph
+violateExecutionOnNonTightHtml = (default)false
+allowNewlineParagraph = false
+
+
+*/
+
+package com.puppycrawl.tools.checkstyle.checks.javadoc.javadocparagraph;
+
+/**
+ * Some summary.
+ *
+ * <p>  Some Javadoc. </p>
+ */
+// violation 2 lines above '<p> tag should be placed immediately before the first word'
+public class InputJavadocParagraphIncorrectOpenClosedTag2 {
+
+    /**
+    * some javadoc.
+    * <p></p>
+    */
+    // violation 2 lines above '<p> tag should be preceded with an empty line.'
+    int a;
+
+    // 2 violations 4 lines below:
+    //  '<p> tag should be placed immediately before the first word'
+    //  '<p> tag should be preceded with an empty line.'
+    /**
+    * Some Javadoc.<P>
+    * Some Javadoc.<P></P>
+    */
+    // violation 2 lines above '<p> tag should be preceded with an empty line.'
+    int b;
+
+    // violation below 'Redundant <p> tag.'
+    /**<p>some javadoc.</p>
+    *
+    * Some <p>Javadoc.</p>
+    *
+    * Some <p>Javadoc.</p>
+    */
+    // violation 5 lines above 'Empty line should be followed by <p> tag on the next line.'
+    // violation 4 lines above 'Empty line should be followed by <p> tag on the next line.'
+    int c;
+
+    /**
+    * Some Summary.
+    *
+    * <p>
+    *   Some Javadoc. // ok until #15762
+    * </p>
+    */
+    // violation 4 lines above '<p> tag should be placed immediately before the first word'
+    int d;
+
+    // 2 violations 6 lines below:
+    //  '<p> tag should be placed immediately before the first word'
+    //  '<p> tag should not precede HTML block-tag '<ul>''
+    /**
+    * Some Summary.
+    *
+    * <p>
+    *   <ul> // ok until #15762
+    *     <li>Item 1</li> // ok until #15762
+    *     <li>Item 2</li> // ok until #15762
+    *     <li>Item 3</li> // ok until #15762
+    *   </ul> // ok until #15762
+    * </p>
+    */
+    int e;
+
+    /**
+    * Some Summary.
+    *
+    * <p><b>testing....</b></p>
+    *
+    * <p><h1>testing....</h1></p>
+    */
+    // violation 2 lines above '<p> tag should not precede HTML block-tag '<h1>''
+    int f;
+
+    // violation 4 lines below '<p> tag should be placed immediately before the first word'
+    /**
+    * Some Summary.
+    *
+    * <p>
+    *     <b>testing....</b>
+    * </p>
+    *
+    * <p>
+    *     <h1>testing....</h1>
+    * </p>
+    */
+    // 2 violations 4 lines above:
+    //  '<p> tag should be placed immediately before the first word'
+    //  '<p> tag should not precede HTML block-tag '<h1>''
+    int g;
+}
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrectOpenClosedTag3.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrectOpenClosedTag3.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/javadocparagraph/InputJavadocParagraphIncorrectOpenClosedTag3.java
@@ -0,0 +1,42 @@
+/*
+JavadocParagraph
+violateExecutionOnNonTightHtml = (default)false
+allowNewlineParagraph = (default)true
+
+
+*/
+
+package com.puppycrawl.tools.checkstyle.checks.javadoc.javadocparagraph;
+
+public class InputJavadocParagraphIncorrectOpenClosedTag3 {
+    /**
+    * Some Summary.
+    *
+    * <p><!-- comment is required --> extra space in paragraph after comment is violation</p>
+    */
+    // violation 2 lines above '<p> tag should be placed immediately before the first word'
+    int a;
+
+    /**
+    * Some Summary.
+    *
+    * <p> <!-- comment is required -->extra space in paragraph before comment is violation</p>
+    */
+    // violation 2 lines above '<p> tag should be placed immediately before the first word'
+    int b;
+
+    /**
+    * Some Summary.
+    *
+    * <p> <!-- comment is required --> both cases combined, this is also violation</p>
+    */
+    // violation 2 lines above '<p> tag should be placed immediately before the first word'
+    int c;
+
+    /**
+    * Some Summary.
+    *
+    * <p><!-- comment is required -->no extra spaces, this is okay</p>
+    */
+    int d;
+}