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 import java.util.ArrayList;
11 import java.util.List;
12
13
14
15
16
17
18
19
20
21
22
23
24
25 public final class ConstructorsOrderCheck extends AbstractCheck {
26
27
28
29
30 public ConstructorsOrderCheck() {
31
32 }
33
34 @Override
35 public int[] getDefaultTokens() {
36 return new int[] {
37 TokenTypes.CLASS_DEF,
38 TokenTypes.ENUM_DEF,
39 TokenTypes.RECORD_DEF,
40 };
41 }
42
43 @Override
44 public int[] getAcceptableTokens() {
45 return this.getDefaultTokens();
46 }
47
48 @Override
49 public int[] getRequiredTokens() {
50 return this.getDefaultTokens();
51 }
52
53 @Override
54 public void visitToken(final DetailAST ast) {
55 final DetailAST obj = ast.findFirstToken(TokenTypes.OBJBLOCK);
56 if (obj != null) {
57 this.checkOrder(obj);
58 }
59 }
60
61 private void checkOrder(final DetailAST obj) {
62 boolean primary = false;
63 for (final DetailAST ctor : ConstructorsOrderCheck.constructors(obj)) {
64 if (primary) {
65 this.log(
66 ctor.getLineNo(),
67 "Primary constructor must be the last one declared"
68 );
69 } else if (!ConstructorsOrderCheck.delegates(ctor)) {
70 primary = true;
71 }
72 }
73 }
74
75 private static List<DetailAST> constructors(final DetailAST obj) {
76 final List<DetailAST> ctors = new ArrayList<>(0);
77 for (DetailAST child = obj.getFirstChild();
78 child != null; child = child.getNextSibling()) {
79 if (child.getType() == TokenTypes.CTOR_DEF) {
80 ctors.add(child);
81 }
82 }
83 return ctors;
84 }
85
86 private static boolean delegates(final DetailAST ctor) {
87 boolean delegates = false;
88 final DetailAST body = ctor.findFirstToken(TokenTypes.SLIST);
89 if (body != null) {
90 for (DetailAST stmt = body.getFirstChild();
91 stmt != null; stmt = stmt.getNextSibling()) {
92 if (stmt.getType() == TokenTypes.CTOR_CALL) {
93 delegates = true;
94 break;
95 }
96 }
97 }
98 return delegates;
99 }
100 }