View Javadoc
1   /*
2    * SPDX-FileCopyrightText: Copyright (c) 2011-2026 Yegor Bugayenko
3    * SPDX-License-Identifier: MIT
4    */
5   package com.qulice.checkstyle;
6   
7   import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
8   import com.puppycrawl.tools.checkstyle.api.DetailAST;
9   import com.puppycrawl.tools.checkstyle.api.TokenTypes;
10  
11  /**
12   * Detects unnecessary semicolons placed after the closing brace
13   * of a class, interface, record, method or constructor declaration.
14   *
15   * <p>Such semicolons form empty declarations that carry no meaning and
16   * clutter the code, for example:
17   *
18   * <pre>
19   * class Semicolons {
20   *     Semicolons() {
21   *     };
22   *     void act() {
23   *     };
24   * };
25   * </pre>
26   *
27   * <p>This check flags every {@code SEMI} token that appears as a
28   * direct child of an {@code OBJBLOCK} (a class, interface or record
29   * body) or of the root {@code COMPILATION_UNIT}. Enum bodies are
30   * excluded because the {@code ;} separator between enum constants and
31   * member declarations is mandated by the Java grammar.
32   *
33   * @since 0.24
34   */
35  public final class ExtraSemicolonCheck extends AbstractCheck {
36  
37      @Override
38      public int[] getDefaultTokens() {
39          return new int[] {
40              TokenTypes.OBJBLOCK,
41              TokenTypes.COMPILATION_UNIT,
42          };
43      }
44  
45      @Override
46      public int[] getAcceptableTokens() {
47          return this.getDefaultTokens();
48      }
49  
50      @Override
51      public int[] getRequiredTokens() {
52          return this.getDefaultTokens();
53      }
54  
55      @Override
56      public void visitToken(final DetailAST ast) {
57          if (ast.getType() == TokenTypes.COMPILATION_UNIT
58              || ast.getParent() == null
59              || ast.getParent().getType() != TokenTypes.ENUM_DEF) {
60              this.reportSemis(ast);
61          }
62      }
63  
64      /**
65       * Report every {@code SEMI} token that is a direct child of the node.
66       * @param node The parent node whose children are inspected
67       */
68      private void reportSemis(final DetailAST node) {
69          for (DetailAST child = node.getFirstChild(); child != null;
70              child = child.getNextSibling()) {
71              if (child.getType() == TokenTypes.SEMI) {
72                  this.log(
73                      child.getLineNo(),
74                      child.getColumnNo(),
75                      "Unnecessary semicolon"
76                  );
77              }
78          }
79      }
80  }