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.utils;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
24
25 import java.util.Optional;
26
27 import org.junit.jupiter.api.Test;
28
29 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
30 import com.puppycrawl.tools.checkstyle.DetailAstImpl;
31 import com.puppycrawl.tools.checkstyle.api.DetailAST;
32 import com.puppycrawl.tools.checkstyle.api.Scope;
33 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
34
35 public class ScopeUtilTest
36 extends AbstractModuleTestSupport {
37
38 @Override
39 public String getPackageLocation() {
40 return "com/puppycrawl/tools/checkstyle/utils/scopeutil";
41 }
42
43 @Test
44 public void testIsProperUtilsClass() throws ReflectiveOperationException {
45 assertWithMessage("Constructor is not private")
46 .that(isUtilsClassHasPrivateConstructor(ScopeUtil.class))
47 .isTrue();
48 }
49
50 @Test
51 public void testInClassBlock() {
52 assertWithMessage("Should return false when passed is not class")
53 .that(ScopeUtil.isInClassBlock(new DetailAstImpl()))
54 .isFalse();
55 assertWithMessage("Should return false when passed is not class")
56 .that(ScopeUtil
57 .isInClassBlock(getNode(TokenTypes.LITERAL_NEW, TokenTypes.MODIFIERS)))
58 .isFalse();
59 assertWithMessage("Should return true when passed is class")
60 .that(ScopeUtil.isInClassBlock(
61 getNode(TokenTypes.OBJBLOCK, TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS)))
62 .isTrue();
63 assertWithMessage("Should return false when passed is not class")
64 .that(ScopeUtil.isInClassBlock(getNode(TokenTypes.CLASS_DEF,
65 TokenTypes.INTERFACE_DEF, TokenTypes.MODIFIERS)))
66 .isFalse();
67 assertWithMessage("Should return false when passed is not class")
68 .that(ScopeUtil.isInClassBlock(getNode(TokenTypes.CLASS_DEF,
69 TokenTypes.ANNOTATION_DEF, TokenTypes.MODIFIERS)))
70 .isFalse();
71 assertWithMessage("Should return false when passed is not class")
72 .that(ScopeUtil.isInClassBlock(
73 getNode(TokenTypes.CLASS_DEF, TokenTypes.ENUM_DEF, TokenTypes.MODIFIERS)))
74 .isFalse();
75 assertWithMessage("Should return false when passed is not class")
76 .that(ScopeUtil.isInClassBlock(
77 getNode(TokenTypes.CLASS_DEF, TokenTypes.LITERAL_NEW, TokenTypes.IDENT)))
78 .isFalse();
79 assertWithMessage("Should return false when passed is not expected")
80 .that(ScopeUtil.isInClassBlock(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)))
81 .isFalse();
82 }
83
84 @Test
85 public void testInEnumBlock() {
86 assertWithMessage("Should return false when passed is not enum")
87 .that(ScopeUtil.isInEnumBlock(new DetailAstImpl()))
88 .isFalse();
89 assertWithMessage("Should return false when passed is not enum")
90 .that(ScopeUtil
91 .isInEnumBlock(getNode(TokenTypes.LITERAL_NEW, TokenTypes.MODIFIERS)))
92 .isFalse();
93 assertWithMessage("Should return true when passed is enum")
94 .that(ScopeUtil.isInEnumBlock(
95 getNode(TokenTypes.OBJBLOCK, TokenTypes.ENUM_DEF, TokenTypes.MODIFIERS)))
96 .isTrue();
97 assertWithMessage("Should return false when passed is not enum")
98 .that(ScopeUtil.isInEnumBlock(getNode(TokenTypes.ENUM_DEF, TokenTypes.INTERFACE_DEF,
99 TokenTypes.MODIFIERS)))
100 .isFalse();
101 assertWithMessage("Should return false when passed is not enum")
102 .that(ScopeUtil.isInEnumBlock(getNode(TokenTypes.ENUM_DEF,
103 TokenTypes.ANNOTATION_DEF, TokenTypes.MODIFIERS)))
104 .isFalse();
105 assertWithMessage("Should return false when passed is not enum")
106 .that(ScopeUtil.isInEnumBlock(
107 getNode(TokenTypes.ENUM_DEF, TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS)))
108 .isFalse();
109 assertWithMessage("Should return false when passed is not enum")
110 .that(ScopeUtil.isInEnumBlock(
111 getNode(TokenTypes.ENUM_DEF, TokenTypes.LITERAL_NEW, TokenTypes.IDENT)))
112 .isFalse();
113 assertWithMessage("Should return false when passed is not expected")
114 .that(ScopeUtil.isInEnumBlock(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)))
115 .isFalse();
116 }
117
118 @Test
119 public void testIsInCodeBlock() {
120 assertWithMessage("invalid result")
121 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.CLASS_DEF)))
122 .isFalse();
123 assertWithMessage("invalid result")
124 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.METHOD_DEF)))
125 .isFalse();
126 assertWithMessage("invalid result")
127 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.ASSIGN, TokenTypes.VARIABLE_DEF)))
128 .isFalse();
129 assertWithMessage("invalid result")
130 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.METHOD_DEF, TokenTypes.OBJBLOCK)))
131 .isTrue();
132 assertWithMessage("invalid result")
133 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.CTOR_DEF, TokenTypes.OBJBLOCK)))
134 .isTrue();
135 assertWithMessage("invalid result")
136 .that(ScopeUtil
137 .isInCodeBlock(getNode(TokenTypes.INSTANCE_INIT, TokenTypes.OBJBLOCK)))
138 .isTrue();
139 assertWithMessage("invalid result")
140 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.STATIC_INIT, TokenTypes.OBJBLOCK)))
141 .isTrue();
142 assertWithMessage("invalid result")
143 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.LAMBDA, TokenTypes.ASSIGN)))
144 .isTrue();
145 }
146
147 @Test
148 public void testIsInCodeBlockWithCompactCtor() throws Exception {
149 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
150 verifyWithInlineConfigParser(
151 getPath("InputScopeUtilJavadocVariableCompactCtor.java"), expected);
152 }
153
154 @Test
155 public void testInRecordBlock() {
156 assertWithMessage("Should return false when passed is not record")
157 .that(ScopeUtil.isInRecordBlock(new DetailAstImpl()))
158 .isFalse();
159 assertWithMessage("Should return false when passed is not record")
160 .that(ScopeUtil
161 .isInRecordBlock(getNode(TokenTypes.LITERAL_NEW, TokenTypes.MODIFIERS)))
162 .isFalse();
163 assertWithMessage("Should return true when passed is record")
164 .that(ScopeUtil.isInRecordBlock(
165 getNode(TokenTypes.OBJBLOCK, TokenTypes.RECORD_DEF, TokenTypes.MODIFIERS)))
166 .isTrue();
167 assertWithMessage("Should return false when passed is not record")
168 .that(ScopeUtil.isInRecordBlock(getNode(TokenTypes.RECORD_DEF,
169 TokenTypes.INTERFACE_DEF, TokenTypes.MODIFIERS)))
170 .isFalse();
171 assertWithMessage("Should return false when passed is not record")
172 .that(ScopeUtil.isInRecordBlock(getNode(TokenTypes.RECORD_DEF,
173 TokenTypes.ANNOTATION_DEF, TokenTypes.MODIFIERS)))
174 .isFalse();
175 assertWithMessage("Should return false when passed is not record")
176 .that(ScopeUtil.isInRecordBlock(
177 getNode(TokenTypes.RECORD_DEF, TokenTypes.ENUM_DEF, TokenTypes.MODIFIERS)))
178 .isFalse();
179 assertWithMessage("Should return false when passed is not record")
180 .that(ScopeUtil.isInRecordBlock(
181 getNode(TokenTypes.RECORD_DEF, TokenTypes.LITERAL_NEW, TokenTypes.IDENT)))
182 .isFalse();
183 assertWithMessage("Should return false when passed is not expected")
184 .that(ScopeUtil.isInRecordBlock(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)))
185 .isFalse();
186 }
187
188 @Test
189 public void testIsOuterMostTypeInterface() {
190 assertWithMessage("Should return false when passed is not outer most type")
191 .that(ScopeUtil
192 .isOuterMostType(getNode(TokenTypes.INTERFACE_DEF, TokenTypes.MODIFIERS)))
193 .isFalse();
194 }
195
196 @Test
197 public void testIsOuterMostTypeAnnotation() {
198 assertWithMessage("Should return false when passed is not outer most type")
199 .that(ScopeUtil
200 .isOuterMostType(getNode(TokenTypes.ANNOTATION_DEF, TokenTypes.MODIFIERS)))
201 .isFalse();
202 }
203
204 @Test
205 public void testIsOuterMostTypeEnum() {
206 assertWithMessage("Should return false when passed is not outer most type")
207 .that(ScopeUtil.isOuterMostType(getNode(TokenTypes.ENUM_DEF, TokenTypes.MODIFIERS)))
208 .isFalse();
209 }
210
211 @Test
212 public void testIsOuterMostTypeClass() {
213 assertWithMessage("Should return false when passed is not outer most type")
214 .that(ScopeUtil
215 .isOuterMostType(getNode(TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS)))
216 .isFalse();
217 }
218
219 @Test
220 public void testIsOuterMostTypePackageDef() {
221 assertWithMessage("Should return false when passed is not outer most type")
222 .that(ScopeUtil.isOuterMostType(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)))
223 .isTrue();
224 }
225
226 @Test
227 public void testIsLocalVariableDefCatch() {
228 assertWithMessage("Should return true when passed is variable def")
229 .that(ScopeUtil
230 .isLocalVariableDef(getNode(TokenTypes.LITERAL_CATCH, TokenTypes.PARAMETER_DEF)))
231 .isTrue();
232 }
233
234 @Test
235 public void testIsLocalVariableDefUnexpected() {
236 assertWithMessage("Should return false when passed is not variable def")
237 .that(ScopeUtil.isLocalVariableDef(getNode(TokenTypes.LITERAL_CATCH)))
238 .isFalse();
239 assertWithMessage("Should return false when passed is not variable def")
240 .that(ScopeUtil
241 .isLocalVariableDef(getNode(TokenTypes.COMMA, TokenTypes.PARAMETER_DEF)))
242 .isFalse();
243 }
244
245 @Test
246 public void testIsLocalVariableDefResource() {
247 final DetailAstImpl node = getNode(TokenTypes.RESOURCE);
248 final DetailAstImpl modifiers = new DetailAstImpl();
249 modifiers.setType(TokenTypes.MODIFIERS);
250 node.addChild(modifiers);
251 final DetailAstImpl ident = new DetailAstImpl();
252 ident.setType(TokenTypes.IDENT);
253 node.addChild(ident);
254 assertWithMessage("invalid result")
255 .that(ScopeUtil.isLocalVariableDef(node))
256 .isTrue();
257 final DetailAstImpl resourceWithIdent = getNode(TokenTypes.RESOURCE);
258 resourceWithIdent.addChild(ident);
259 assertWithMessage("invalid result")
260 .that(ScopeUtil.isLocalVariableDef(resourceWithIdent))
261 .isFalse();
262 assertWithMessage("invalid result")
263 .that(ScopeUtil.isLocalVariableDef(getNode(TokenTypes.RESOURCE)))
264 .isFalse();
265 }
266
267 @Test
268 public void testIsLocalVariableDefVariable() {
269 assertWithMessage("invalid result")
270 .that(ScopeUtil
271 .isLocalVariableDef(getNode(TokenTypes.SLIST, TokenTypes.VARIABLE_DEF)))
272 .isTrue();
273 assertWithMessage("invalid result")
274 .that(ScopeUtil
275 .isLocalVariableDef(getNode(TokenTypes.FOR_INIT, TokenTypes.VARIABLE_DEF)))
276 .isTrue();
277 assertWithMessage("invalid result")
278 .that(ScopeUtil
279 .isLocalVariableDef(getNode(TokenTypes.FOR_EACH_CLAUSE, TokenTypes.VARIABLE_DEF)))
280 .isTrue();
281 assertWithMessage("invalid result")
282 .that(ScopeUtil
283 .isLocalVariableDef(getNode(TokenTypes.CLASS_DEF, TokenTypes.VARIABLE_DEF)))
284 .isFalse();
285 }
286
287 @Test
288 public void testIsClassFieldDef() {
289 assertWithMessage("Should return true when passed is class field def")
290 .that(ScopeUtil.isClassFieldDef(getNode(TokenTypes.CLASS_DEF, TokenTypes.OBJBLOCK,
291 TokenTypes.VARIABLE_DEF)))
292 .isTrue();
293 assertWithMessage("Should return false when passed is unexpected")
294 .that(ScopeUtil.isClassFieldDef(getNode(TokenTypes.CLASS_DEF)))
295 .isFalse();
296 assertWithMessage("Should return false when passed is method variable def")
297 .that(ScopeUtil.isClassFieldDef(
298 getNode(TokenTypes.METHOD_DEF, TokenTypes.SLIST, TokenTypes.VARIABLE_DEF)))
299 .isFalse();
300 }
301
302 @Test
303 public void testSurroundingScope() {
304 final Optional<Scope> publicScope = ScopeUtil.getSurroundingScope(getNodeWithParentScope(
305 TokenTypes.LITERAL_PUBLIC, "public", TokenTypes.ANNOTATION_DEF));
306 assertWithMessage("Invalid surrounding scope")
307 .that(publicScope)
308 .isEqualTo(Optional.of(Scope.PUBLIC));
309 final Optional<Scope> protectedScope = ScopeUtil.getSurroundingScope(getNodeWithParentScope(
310 TokenTypes.LITERAL_PROTECTED, "protected", TokenTypes.INTERFACE_DEF));
311 assertWithMessage("Invalid surrounding scope")
312 .that(protectedScope)
313 .isEqualTo(Optional.of(Scope.PROTECTED));
314 final Optional<Scope> privateScope = ScopeUtil.getSurroundingScope(getNodeWithParentScope(
315 TokenTypes.LITERAL_PRIVATE, "private", TokenTypes.ENUM_DEF));
316 assertWithMessage("Invalid surrounding scope")
317 .that(privateScope)
318 .isEqualTo(Optional.of(Scope.PRIVATE));
319 final Optional<Scope> staticScope = ScopeUtil.getSurroundingScope(getNodeWithParentScope(
320 TokenTypes.LITERAL_STATIC, "static", TokenTypes.CLASS_DEF));
321 assertWithMessage("Invalid surrounding scope")
322 .that(staticScope)
323 .isEqualTo(Optional.of(Scope.PACKAGE));
324 }
325
326 @Test
327 public void testIsInScope() {
328 assertWithMessage("Should return true when node is in valid scope")
329 .that(ScopeUtil.isInScope(getNodeWithParentScope(TokenTypes.LITERAL_PUBLIC,
330 "public", TokenTypes.ANNOTATION_DEF), Scope.PUBLIC))
331 .isTrue();
332 assertWithMessage("Should return false when node is in invalid scope")
333 .that(ScopeUtil.isInScope(getNodeWithParentScope(TokenTypes.LITERAL_PROTECTED,
334 "protected", TokenTypes.INTERFACE_DEF), Scope.PRIVATE))
335 .isFalse();
336 }
337
338 @Test
339 public void testSurroundingScopeOfNodeChildOfLiteralNewIsAnoninner() {
340 final Optional<Scope> scope =
341 ScopeUtil.getSurroundingScope(getNode(TokenTypes.LITERAL_NEW, TokenTypes.IDENT));
342 assertWithMessage("Invalid surrounding scope")
343 .that(scope)
344 .isEqualTo(Optional.of(Scope.ANONINNER));
345 }
346
347 @Test
348 public void testGetScopeOfEnumConstantIsPublic() {
349 final Scope scope = ScopeUtil.getScope(
350 getNode(TokenTypes.ENUM_DEF, TokenTypes.OBJBLOCK, TokenTypes.ENUM_CONSTANT_DEF));
351
352 assertWithMessage("Invalid enum constant scope")
353 .that(scope)
354 .isEqualTo(Scope.PUBLIC);
355 }
356
357 @Test
358 public void testIsInInterfaceBlock() {
359 final DetailAST ast = getNode(TokenTypes.INTERFACE_DEF, TokenTypes.OBJBLOCK,
360 TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS);
361
362 assertWithMessage("Should return true when node is interface block")
363 .that(ScopeUtil.isInInterfaceBlock(ast.getParent()))
364 .isTrue();
365 assertWithMessage("Should return false when node is not interface block")
366 .that(ScopeUtil.isInInterfaceBlock(ast))
367 .isFalse();
368 }
369
370 @Test
371 public void testIsInAnnotationBlock() {
372 final DetailAST ast = getNode(TokenTypes.ANNOTATION_DEF, TokenTypes.OBJBLOCK,
373 TokenTypes.INTERFACE_DEF, TokenTypes.MODIFIERS);
374
375 assertWithMessage("Should return true when node is annotation block")
376 .that(ScopeUtil.isInAnnotationBlock(ast.getParent()))
377 .isTrue();
378 assertWithMessage("Should return false when node is not annotation block")
379 .that(ScopeUtil.isInAnnotationBlock(ast))
380 .isFalse();
381 }
382
383 @Test
384 public void testisInInterfaceOrAnnotationBlock() {
385 assertWithMessage("Should return true when node is in interface or annotation block")
386 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
387 getNode(TokenTypes.ANNOTATION_DEF, TokenTypes.OBJBLOCK)))
388 .isTrue();
389 assertWithMessage("Should return true when node is in interface or annotation block")
390 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
391 getNode(TokenTypes.INTERFACE_DEF, TokenTypes.OBJBLOCK)))
392 .isTrue();
393 assertWithMessage("Should return false when node is not in interface or annotation block")
394 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
395 getNode(TokenTypes.CLASS_DEF, TokenTypes.OBJBLOCK)))
396 .isFalse();
397 assertWithMessage("Should return false when node is not in interface or annotation block")
398 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
399 getNode(TokenTypes.LITERAL_NEW, TokenTypes.IDENT)))
400 .isFalse();
401 assertWithMessage("Should return false when node is not in interface or annotation block")
402 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
403 getNode(TokenTypes.ENUM_DEF, TokenTypes.OBJBLOCK)))
404 .isFalse();
405 }
406
407 private static DetailAstImpl getNode(int... nodeTypes) {
408 DetailAstImpl ast = new DetailAstImpl();
409 ast.setType(nodeTypes[0]);
410 for (int i = 1; i < nodeTypes.length; i++) {
411 final DetailAstImpl astChild = new DetailAstImpl();
412 astChild.setType(nodeTypes[i]);
413 ast.addChild(astChild);
414 ast = astChild;
415 }
416 return ast;
417 }
418
419 private static DetailAST getNodeWithParentScope(int literal, String scope,
420 int parentTokenType) {
421 final DetailAstImpl ast = getNode(parentTokenType, TokenTypes.MODIFIERS, literal);
422 ast.setText(scope);
423 final DetailAstImpl ast2 = getNode(TokenTypes.OBJBLOCK);
424 ((DetailAstImpl) ast.getParent().getParent()).addChild(ast2);
425 return ast;
426 }
427
428 }