1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.coding;
21
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import com.puppycrawl.tools.checkstyle.StatelessCheck;
26 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
27 import com.puppycrawl.tools.checkstyle.api.DetailAST;
28 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
29 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
30
31
32
33
34
35
36
37
38
39
40 @StatelessCheck
41 public class OverloadMethodsDeclarationOrderCheck extends AbstractCheck {
42
43
44
45
46
47 public static final String MSG_KEY = "overload.methods.declaration";
48
49
50
51
52
53 public static final String MSG_ORDER = "overload.methods.declaration.order";
54
55
56
57
58 private boolean orderByIncreasingParameterCount;
59
60
61
62
63 public OverloadMethodsDeclarationOrderCheck() {
64
65 }
66
67
68
69
70
71
72
73
74 public void setOrderByIncreasingParameterCount(boolean orderByIncreasingParameterCount) {
75 this.orderByIncreasingParameterCount = orderByIncreasingParameterCount;
76 }
77
78 @Override
79 public int[] getDefaultTokens() {
80 return getRequiredTokens();
81 }
82
83 @Override
84 public int[] getAcceptableTokens() {
85 return getRequiredTokens();
86 }
87
88 @Override
89 public int[] getRequiredTokens() {
90 return new int[] {
91 TokenTypes.OBJBLOCK,
92 TokenTypes.COMPACT_COMPILATION_UNIT,
93 };
94 }
95
96 @Override
97 public void visitToken(DetailAST ast) {
98 final int[] objectBlockParentTypes = {
99 TokenTypes.CLASS_DEF,
100 TokenTypes.ENUM_DEF,
101 TokenTypes.INTERFACE_DEF,
102 TokenTypes.LITERAL_NEW,
103 TokenTypes.RECORD_DEF,
104 };
105
106 if (ast.getType() == TokenTypes.COMPACT_COMPILATION_UNIT
107 || TokenUtil.isOfType(ast.getParent().getType(), objectBlockParentTypes)) {
108 checkOverloadMethodsGrouping(ast);
109 }
110 }
111
112
113
114
115
116
117
118
119
120 private void checkOverloadMethodsGrouping(DetailAST objectBlock) {
121 final int allowedDistance = 1;
122 DetailAST currentToken = objectBlock.getFirstChild();
123 final Map<String, Integer> methodIndexMap = new HashMap<>();
124 final Map<String, Integer> methodLineNumberMap = new HashMap<>();
125
126 final Map<String, Integer> methodParameterCountMap = new HashMap<>();
127 final Map<String, Boolean> methodIsOrderedMap = new HashMap<>();
128
129 int currentIndex = 0;
130 while (currentToken != null) {
131 if (currentToken.getType() == TokenTypes.METHOD_DEF) {
132 currentIndex++;
133 final String methodName =
134 currentToken.findFirstToken(TokenTypes.IDENT).getText();
135 final Integer previousIndex = methodIndexMap.get(methodName);
136
137 if (previousIndex != null) {
138 final DetailAST previousSibling = currentToken.getPreviousSibling();
139 final boolean isMethod = previousSibling.getType() == TokenTypes.METHOD_DEF;
140
141 if (!isMethod || currentIndex - previousIndex > allowedDistance) {
142 final int previousLineWithOverloadMethod =
143 methodLineNumberMap.get(methodName);
144 log(currentToken, MSG_KEY,
145 previousLineWithOverloadMethod);
146 }
147
148 if (orderByIncreasingParameterCount) {
149 checkMethodOrdering(currentToken, methodName,
150 methodIsOrderedMap, methodParameterCountMap);
151 }
152 }
153 methodIsOrderedMap.putIfAbsent(methodName, Boolean.TRUE);
154 methodIndexMap.put(methodName, currentIndex);
155 methodLineNumberMap.put(methodName, currentToken.getLineNo());
156 methodParameterCountMap.put(methodName, getParameterCount(currentToken));
157 }
158 currentToken = currentToken.getNextSibling();
159 }
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173
174 private void checkMethodOrdering(DetailAST currentMethod, String methodName,
175 Map<String, Boolean> methodIsOrderedMap, Map<String, Integer> methodParameterCountMap) {
176
177 final int currentParamCount = getParameterCount(currentMethod);
178 final boolean isOrdered = methodIsOrderedMap.get(methodName)
179 && currentParamCount >= methodParameterCountMap.get(methodName);
180 if (!isOrdered) {
181 methodIsOrderedMap.put(methodName, Boolean.FALSE);
182 log(currentMethod, MSG_ORDER);
183 }
184 }
185
186
187
188
189
190
191
192 private static int getParameterCount(DetailAST method) {
193 final DetailAST params = method.findFirstToken(TokenTypes.PARAMETERS);
194 return params.getChildCount(TokenTypes.PARAMETER_DEF);
195 }
196
197 }