View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.checks.javadoc;
21  
22  import com.puppycrawl.tools.checkstyle.StatelessCheck;
23  import com.puppycrawl.tools.checkstyle.api.DetailNode;
24  import com.puppycrawl.tools.checkstyle.api.JavadocCommentsTokenTypes;
25  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
26  
27  /**
28   * <div>
29   * Checks if the javadoc has
30   * <a href="https://docs.oracle.com/en/java/javase/14/docs/specs/javadoc/doc-comment-spec.html#leading-asterisks">
31   * leading asterisks</a> on each line.
32   * </div>
33   *
34   * <p>
35   * The check does not require asterisks on the first line, nor on the last line if it is blank.
36   * All other lines in a Javadoc should start with {@code *}, including blank lines and code blocks.
37   * </p>
38   *
39   * @since 8.38
40   */
41  @StatelessCheck
42  public class JavadocMissingLeadingAsteriskCheck extends AbstractJavadocCheck {
43  
44      /**
45       * A key is pointing to the warning message text in "messages.properties"
46       * file.
47       */
48      public static final String MSG_MISSING_ASTERISK = "javadoc.missing.asterisk";
49  
50      @Override
51      public int[] getRequiredJavadocTokens() {
52          return new int[] {
53              JavadocCommentsTokenTypes.NEWLINE,
54          };
55      }
56  
57      @Override
58      public int[] getAcceptableJavadocTokens() {
59          return getRequiredJavadocTokens();
60      }
61  
62      @Override
63      public int[] getDefaultJavadocTokens() {
64          return getRequiredJavadocTokens();
65      }
66  
67      @Override
68      public void visitJavadocToken(DetailNode detailNode) {
69          if (!isInsideHtmlComment(detailNode)) {
70              final DetailNode nextSibling = detailNode.getNextSibling();
71  
72              if (nextSibling != null && !isLeadingAsterisk(nextSibling)
73                          && !isLastLine(nextSibling)) {
74                  log(nextSibling.getLineNumber(), MSG_MISSING_ASTERISK);
75              }
76          }
77      }
78  
79      /**
80       * Checks whether the given node is inside an HTML comment.
81       *
82       * @param detailNode the node to process
83       * @return {@code true} if the node is inside an HTML comment
84       */
85      private static boolean isInsideHtmlComment(DetailNode detailNode) {
86          final int parentType = detailNode.getParent().getType();
87          return parentType == JavadocCommentsTokenTypes.HTML_COMMENT_CONTENT
88                  || parentType == JavadocCommentsTokenTypes.HTML_COMMENT;
89  
90      }
91  
92      /**
93       * Checks whether the given node is a leading asterisk.
94       *
95       * @param detailNode the node to process
96       * @return {@code true} if the node is {@link JavadocCommentsTokenTypes#LEADING_ASTERISK}
97       */
98      private static boolean isLeadingAsterisk(DetailNode detailNode) {
99          return detailNode.getType() == JavadocCommentsTokenTypes.LEADING_ASTERISK;
100     }
101 
102     /**
103      * Checks whether this node is the end of a Javadoc comment,
104      * optionally preceded by blank text.
105      *
106      * @param detailNode the node to process
107      * @return {@code true} if the node is {@code null}
108      */
109     private static boolean isLastLine(DetailNode detailNode) {
110         final DetailNode node;
111         if (CommonUtil.isBlank(detailNode.getText())) {
112             node = detailNode.getNextSibling();
113         }
114         else {
115             node = detailNode;
116         }
117         return node == null;
118     }
119 
120 }