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 }