View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2026 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      /**
51       * Creates a new {@code JavadocMissingLeadingAsteriskCheck} instance.
52       */
53      public JavadocMissingLeadingAsteriskCheck() {
54          // no code by default
55      }
56  
57      @Override
58      public int[] getRequiredJavadocTokens() {
59          return new int[] {
60              JavadocCommentsTokenTypes.NEWLINE,
61          };
62      }
63  
64      @Override
65      public int[] getAcceptableJavadocTokens() {
66          return getRequiredJavadocTokens();
67      }
68  
69      @Override
70      public int[] getDefaultJavadocTokens() {
71          return getRequiredJavadocTokens();
72      }
73  
74      @Override
75      public void visitJavadocToken(DetailNode detailNode) {
76          if (!isInsideHtmlComment(detailNode)) {
77              final DetailNode nextSibling = detailNode.getNextSibling();
78  
79              if (nextSibling != null && !isLeadingAsterisk(nextSibling)
80                          && !isLastLine(nextSibling)) {
81                  log(nextSibling.getLineNumber(), MSG_MISSING_ASTERISK);
82              }
83          }
84      }
85  
86      /**
87       * Checks whether the given node is inside an HTML comment.
88       *
89       * @param detailNode the node to process
90       * @return {@code true} if the node is inside an HTML comment
91       */
92      private static boolean isInsideHtmlComment(DetailNode detailNode) {
93          final int parentType = detailNode.getParent().getType();
94          return parentType == JavadocCommentsTokenTypes.HTML_COMMENT_CONTENT
95                  || parentType == JavadocCommentsTokenTypes.HTML_COMMENT;
96  
97      }
98  
99      /**
100      * Checks whether the given node is a leading asterisk.
101      *
102      * @param detailNode the node to process
103      * @return {@code true} if the node is a leading asterisk
104      */
105     private static boolean isLeadingAsterisk(DetailNode detailNode) {
106         return detailNode.getType() == JavadocCommentsTokenTypes.LEADING_ASTERISK
107                 || detailNode.getType() == JavadocCommentsTokenTypes.LEADING_ASTERISKS;
108     }
109 
110     /**
111      * Checks whether this node is the end of a Javadoc comment,
112      * optionally preceded by blank text.
113      *
114      * @param detailNode the node to process
115      * @return {@code true} if the node is {@code null}
116      */
117     private static boolean isLastLine(DetailNode detailNode) {
118         final DetailNode node;
119         if (CommonUtil.isBlank(detailNode.getText())) {
120             node = detailNode.getNextSibling();
121         }
122         else {
123             node = detailNode;
124         }
125         return node == null;
126     }
127 
128 }