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.JavadocTokenTypes;
25  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
26  import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
27  
28  /**
29   * <div>
30   * Checks that the block tag is followed by description.
31   * </div>
32   *
33   * <ul>
34   * <li>
35   * Property {@code violateExecutionOnNonTightHtml} - Control when to print violations
36   * if the Javadoc being examined by this check violates the tight html rules defined at
37   * <a href="https://checkstyle.org/writingjavadocchecks.html#Tight-HTML_rules">Tight-HTML Rules</a>.
38   * Type is {@code boolean}.
39   * Default value is {@code false}.
40   * </li>
41   * <li>
42   * Property {@code javadocTokens} - javadoc tokens to check
43   * Type is {@code java.lang.String[]}.
44   * Validation type is {@code tokenSet}.
45   * Default value is
46   * Since version 7.3
47   * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/JavadocTokenTypes.html#PARAM_LITERAL">
48   * PARAM_LITERAL</a>,
49   * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/JavadocTokenTypes.html#RETURN_LITERAL">
50   * RETURN_LITERAL</a>,
51   * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/JavadocTokenTypes.html#THROWS_LITERAL">
52   * THROWS_LITERAL</a>,
53   * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/JavadocTokenTypes.html#EXCEPTION_LITERAL">
54   * EXCEPTION_LITERAL</a>,
55   * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/JavadocTokenTypes.html#DEPRECATED_LITERAL">
56   * DEPRECATED_LITERAL</a>.
57   * </li>
58   * </ul>
59   *
60   * <p>
61   * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker}
62   * </p>
63   *
64   * <p>
65   * Violation Message Keys:
66   * </p>
67   * <ul>
68   * <li>
69   * {@code javadoc.missed.html.close}
70   * </li>
71   * <li>
72   * {@code javadoc.parse.rule.error}
73   * </li>
74   * <li>
75   * {@code javadoc.unclosedHtml}
76   * </li>
77   * <li>
78   * {@code javadoc.wrong.singleton.html.tag}
79   * </li>
80   * <li>
81   * {@code non.empty.atclause}
82   * </li>
83   * </ul>
84   *
85   * @since 6.0
86   */
87  @StatelessCheck
88  public class NonEmptyAtclauseDescriptionCheck extends AbstractJavadocCheck {
89  
90      /**
91       * A key is pointing to the warning message text in "messages.properties"
92       * file.
93       */
94      public static final String MSG_KEY = "non.empty.atclause";
95  
96      @Override
97      public int[] getDefaultJavadocTokens() {
98          return new int[] {
99              JavadocTokenTypes.PARAM_LITERAL,
100             JavadocTokenTypes.RETURN_LITERAL,
101             JavadocTokenTypes.THROWS_LITERAL,
102             JavadocTokenTypes.EXCEPTION_LITERAL,
103             JavadocTokenTypes.DEPRECATED_LITERAL,
104         };
105     }
106 
107     @Override
108     public void visitJavadocToken(DetailNode ast) {
109         if (isEmptyTag(ast.getParent())) {
110             log(ast.getLineNumber(), MSG_KEY);
111         }
112     }
113 
114     /**
115      * Tests if block tag is empty.
116      *
117      * @param tagNode block tag.
118      * @return true, if block tag is empty.
119      */
120     private static boolean isEmptyTag(DetailNode tagNode) {
121         final DetailNode tagDescription =
122                 JavadocUtil.findFirstToken(tagNode, JavadocTokenTypes.DESCRIPTION);
123         return tagDescription == null
124             || hasOnlyEmptyText(tagDescription);
125     }
126 
127     /**
128      * Tests if description node is empty (has only new lines and blank strings).
129      *
130      * @param description description node.
131      * @return true, if description node has only new lines and blank strings.
132      */
133     private static boolean hasOnlyEmptyText(DetailNode description) {
134         boolean result = true;
135         for (DetailNode child : description.getChildren()) {
136             if (child.getType() != JavadocTokenTypes.LEADING_ASTERISK
137                     && !CommonUtil.isBlank(child.getText())) {
138                 result = false;
139                 break;
140             }
141         }
142         return result;
143     }
144 
145 }