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
64
65
66
67 public void setOrderByIncreasingParameterCount(boolean orderByIncreasingParameterCount) {
68 this.orderByIncreasingParameterCount = orderByIncreasingParameterCount;
69 }
70
71 @Override
72 public int[] getDefaultTokens() {
73 return getRequiredTokens();
74 }
75
76 @Override
77 public int[] getAcceptableTokens() {
78 return getRequiredTokens();
79 }
80
81 @Override
82 public int[] getRequiredTokens() {
83 return new int[] {
84 TokenTypes.OBJBLOCK,
85 TokenTypes.COMPACT_COMPILATION_UNIT,
86 };
87 }
88
89 @Override
90 public void visitToken(DetailAST ast) {
91 final int[] objectBlockParentTypes = {
92 TokenTypes.CLASS_DEF,
93 TokenTypes.ENUM_DEF,
94 TokenTypes.INTERFACE_DEF,
95 TokenTypes.LITERAL_NEW,
96 TokenTypes.RECORD_DEF,
97 };
98
99 if (ast.getType() == TokenTypes.COMPACT_COMPILATION_UNIT
100 || TokenUtil.isOfType(ast.getParent().getType(), objectBlockParentTypes)) {
101 checkOverloadMethodsGrouping(ast);
102 }
103 }
104
105
106
107
108
109
110
111
112
113 private void checkOverloadMethodsGrouping(DetailAST objectBlock) {
114 final int allowedDistance = 1;
115 DetailAST currentToken = objectBlock.getFirstChild();
116 final Map<String, Integer> methodIndexMap = new HashMap<>();
117 final Map<String, Integer> methodLineNumberMap = new HashMap<>();
118
119 final Map<String, Integer> methodParameterCountMap = new HashMap<>();
120 final Map<String, Boolean> methodIsOrderedMap = new HashMap<>();
121
122 int currentIndex = 0;
123 while (currentToken != null) {
124 if (currentToken.getType() == TokenTypes.METHOD_DEF) {
125 currentIndex++;
126 final String methodName =
127 currentToken.findFirstToken(TokenTypes.IDENT).getText();
128 final Integer previousIndex = methodIndexMap.get(methodName);
129
130 if (previousIndex != null) {
131 final DetailAST previousSibling = currentToken.getPreviousSibling();
132 final boolean isMethod = previousSibling.getType() == TokenTypes.METHOD_DEF;
133
134 if (!isMethod || currentIndex - previousIndex > allowedDistance) {
135 final int previousLineWithOverloadMethod =
136 methodLineNumberMap.get(methodName);
137 log(currentToken, MSG_KEY,
138 previousLineWithOverloadMethod);
139 }
140
141 if (orderByIncreasingParameterCount) {
142 checkMethodOrdering(currentToken, methodName,
143 methodIsOrderedMap, methodParameterCountMap);
144 }
145 }
146 methodIsOrderedMap.putIfAbsent(methodName, Boolean.TRUE);
147 methodIndexMap.put(methodName, currentIndex);
148 methodLineNumberMap.put(methodName, currentToken.getLineNo());
149 methodParameterCountMap.put(methodName, getParameterCount(currentToken));
150 }
151 currentToken = currentToken.getNextSibling();
152 }
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167 private void checkMethodOrdering(DetailAST currentMethod, String methodName,
168 Map<String, Boolean> methodIsOrderedMap, Map<String, Integer> methodParameterCountMap) {
169
170 final int currentParamCount = getParameterCount(currentMethod);
171 final boolean isOrdered = methodIsOrderedMap.get(methodName)
172 && currentParamCount >= methodParameterCountMap.get(methodName);
173 if (!isOrdered) {
174 methodIsOrderedMap.put(methodName, Boolean.FALSE);
175 log(currentMethod, MSG_ORDER);
176 }
177 }
178
179
180
181
182
183
184
185 private static int getParameterCount(DetailAST method) {
186 final DetailAST params = method.findFirstToken(TokenTypes.PARAMETERS);
187 return params.getChildCount(TokenTypes.PARAMETER_DEF);
188 }
189 }