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:</p>
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.</p>
32   *
33   * @since 0.24
34   */
35  public final class ExtraSemicolonCheck extends AbstractCheck {
36  
37      /**
38       * Default constructor.
39       */
40      public ExtraSemicolonCheck() {
41          // nothing to initialize
42      }
43  
44      @Override
45      public int[] getDefaultTokens() {
46          return new int[] {
47              TokenTypes.OBJBLOCK,
48              TokenTypes.COMPILATION_UNIT,
49          };
50      }
51  
52      @Override
53      public int[] getAcceptableTokens() {
54          return this.getDefaultTokens();
55      }
56  
57      @Override
58      public int[] getRequiredTokens() {
59          return this.getDefaultTokens();
60      }
61  
62      @Override
63      public void visitToken(final DetailAST ast) {
64          if (ast.getType() == TokenTypes.COMPILATION_UNIT
65              || ast.getParent() == null
66              || ast.getParent().getType() != TokenTypes.ENUM_DEF) {
67              this.reportSemis(ast);
68          }
69      }
70  
71      private void reportSemis(final DetailAST node) {
72          for (DetailAST child = node.getFirstChild(); child != null;
73              child = child.getNextSibling()) {
74              if (child.getType() == TokenTypes.SEMI) {
75                  this.log(
76                      child.getLineNo(),
77                      child.getColumnNo(),
78                      "Unnecessary semicolon"
79                  );
80              }
81          }
82      }
83  }