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