View Javadoc
1   /*
2    * Copyright (c) 2011-2024 Qulice.com
3    *
4    * All rights reserved.
5    *
6    * Redistribution and use in source and binary forms, with or without
7    * modification, are permitted provided that the following conditions
8    * are met: 1) Redistributions of source code must retain the above
9    * copyright notice, this list of conditions and the following
10   * disclaimer. 2) Redistributions in binary form must reproduce the above
11   * copyright notice, this list of conditions and the following
12   * disclaimer in the documentation and/or other materials provided
13   * with the distribution. 3) Neither the name of the Qulice.com nor
14   * the names of its contributors may be used to endorse or promote
15   * products derived from this software without specific prior written
16   * permission.
17   *
18   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
20   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22   * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29   * OF THE POSSIBILITY OF SUCH DAMAGE.
30   */
31  package com.qulice.checkstyle;
32  
33  import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
34  import com.puppycrawl.tools.checkstyle.api.DetailAST;
35  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
36  
37  /**
38   * Checks that there is no empty line between a javadoc and it's subject.
39   *
40   * <p>You can't have empty lines between javadoc block and
41   * a class/method/variable. They should stay together, always.
42   *
43   * @since 0.3
44   */
45  public final class JavadocLocationCheck extends AbstractCheck {
46  
47      @Override
48      public int[] getDefaultTokens() {
49          return new int[] {
50              TokenTypes.CLASS_DEF,
51              TokenTypes.INTERFACE_DEF,
52              TokenTypes.VARIABLE_DEF,
53              TokenTypes.CTOR_DEF,
54              TokenTypes.METHOD_DEF,
55          };
56      }
57  
58      @Override
59      public int[] getAcceptableTokens() {
60          return this.getDefaultTokens();
61      }
62  
63      @Override
64      public int[] getRequiredTokens() {
65          return this.getDefaultTokens();
66      }
67  
68      @Override
69      public void visitToken(final DetailAST ast) {
70          if (!JavadocLocationCheck.isField(ast)) {
71              return;
72          }
73          final String[] lines = this.getLines();
74          int current = ast.getLineNo();
75          boolean found = false;
76          final int start = current;
77          --current;
78          while (true) {
79              if (current <= 0) {
80                  break;
81              }
82              final String line = lines[current - 1].trim();
83              if (line.endsWith("*/")) {
84                  found = true;
85                  break;
86              }
87              if (!line.isEmpty()) {
88                  break;
89              }
90              --current;
91          }
92          if (found) {
93              this.report(start, current);
94          }
95      }
96  
97      /**
98       * Report empty lines between current and end line.
99       * @param current Current line
100      * @param end Final line
101      */
102     private void report(final int current, final int end) {
103         final int diff = current - end;
104         if (diff > 1) {
105             for (int pos = 1; pos < diff; pos += 1) {
106                 this.log(
107                     end + pos,
108                     "Empty line between javadoc and subject"
109                 );
110             }
111         }
112     }
113 
114     /**
115      * Returns {@code TRUE} if a specified node is something that should have
116      * a Javadoc, which includes classes, interface, class methods, and
117      * class variables.
118      * @param node Node to check
119      * @return Is it a Javadoc-required entity?
120      */
121     private static boolean isField(final DetailAST node) {
122         boolean yes = true;
123         if (TokenTypes.VARIABLE_DEF == node.getType()) {
124             yes = TokenTypes.OBJBLOCK == node.getParent().getType();
125         }
126         return yes;
127     }
128 }