1
2
3
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
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public final class RedundantSuperConstructorCheck extends AbstractCheck {
37
38
39
40
41 public RedundantSuperConstructorCheck() {
42
43 }
44
45 @Override
46 public int[] getDefaultTokens() {
47 return new int[] {TokenTypes.CTOR_DEF};
48 }
49
50 @Override
51 public int[] getAcceptableTokens() {
52 return this.getDefaultTokens();
53 }
54
55 @Override
56 public int[] getRequiredTokens() {
57 return this.getDefaultTokens();
58 }
59
60 @Override
61 public void visitToken(final DetailAST ast) {
62 final DetailAST clazz = RedundantSuperConstructorCheck.enclosingClass(ast);
63 if (clazz != null
64 && clazz.findFirstToken(TokenTypes.EXTENDS_CLAUSE) == null) {
65 final DetailAST body = ast.findFirstToken(TokenTypes.SLIST);
66 if (body != null) {
67 this.reportSuperCalls(body);
68 }
69 }
70 }
71
72 private static DetailAST enclosingClass(final DetailAST ctor) {
73 DetailAST result = null;
74 final DetailAST block = ctor.getParent();
75 if (block != null && block.getType() == TokenTypes.OBJBLOCK) {
76 final DetailAST owner = block.getParent();
77 if (owner != null && owner.getType() == TokenTypes.CLASS_DEF) {
78 result = owner;
79 }
80 }
81 return result;
82 }
83
84 private void reportSuperCalls(final DetailAST node) {
85 for (DetailAST child = node.getFirstChild();
86 child != null; child = child.getNextSibling()) {
87 final int type = child.getType();
88 if (type == TokenTypes.LAMBDA
89 || type == TokenTypes.OBJBLOCK
90 || type == TokenTypes.CLASS_DEF) {
91 continue;
92 }
93 if (type == TokenTypes.SUPER_CTOR_CALL) {
94 this.log(
95 child.getLineNo(),
96 "Redundant super() call when class does not extend any other class"
97 );
98 }
99 this.reportSuperCalls(child);
100 }
101 }
102 }