View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 org.junit.jupiter.api.Test;
26  
27  import com.puppycrawl.tools.checkstyle.DetailAstImpl;
28  import com.puppycrawl.tools.checkstyle.api.DetailAST;
29  import com.puppycrawl.tools.checkstyle.api.Scope;
30  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
31  
32  public class ScopeUtilTest {
33  
34      @Test
35      public void testIsProperUtilsClass() throws ReflectiveOperationException {
36          assertWithMessage("Constructor is not private")
37                  .that(isUtilsClassHasPrivateConstructor(ScopeUtil.class))
38                  .isTrue();
39      }
40  
41      @Test
42      public void testInClassBlock() {
43          assertWithMessage("Should return false when passed is not class")
44                  .that(ScopeUtil.isInClassBlock(new DetailAstImpl()))
45                  .isFalse();
46          assertWithMessage("Should return false when passed is not class")
47                  .that(ScopeUtil
48                          .isInClassBlock(getNode(TokenTypes.LITERAL_NEW, TokenTypes.MODIFIERS)))
49                  .isFalse();
50          assertWithMessage("Should return true when passed is class")
51                  .that(ScopeUtil.isInClassBlock(
52                          getNode(TokenTypes.OBJBLOCK, TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS)))
53                  .isTrue();
54          assertWithMessage("Should return false when passed is not class")
55                  .that(ScopeUtil.isInClassBlock(getNode(TokenTypes.CLASS_DEF,
56                          TokenTypes.INTERFACE_DEF, TokenTypes.MODIFIERS)))
57                  .isFalse();
58          assertWithMessage("Should return false when passed is not class")
59                  .that(ScopeUtil.isInClassBlock(getNode(TokenTypes.CLASS_DEF,
60                          TokenTypes.ANNOTATION_DEF, TokenTypes.MODIFIERS)))
61                  .isFalse();
62          assertWithMessage("Should return false when passed is not class")
63                  .that(ScopeUtil.isInClassBlock(
64                          getNode(TokenTypes.CLASS_DEF, TokenTypes.ENUM_DEF, TokenTypes.MODIFIERS)))
65                  .isFalse();
66          assertWithMessage("Should return false when passed is not class")
67                  .that(ScopeUtil.isInClassBlock(
68                          getNode(TokenTypes.CLASS_DEF, TokenTypes.LITERAL_NEW, TokenTypes.IDENT)))
69                  .isFalse();
70          assertWithMessage("Should return false when passed is not expected")
71                  .that(ScopeUtil.isInClassBlock(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)))
72                  .isFalse();
73      }
74  
75      @Test
76      public void testInEnumBlock() {
77          assertWithMessage("Should return false when passed is not enum")
78                  .that(ScopeUtil.isInEnumBlock(new DetailAstImpl()))
79                  .isFalse();
80          assertWithMessage("Should return false when passed is not enum")
81                  .that(ScopeUtil
82                          .isInEnumBlock(getNode(TokenTypes.LITERAL_NEW, TokenTypes.MODIFIERS)))
83                  .isFalse();
84          assertWithMessage("Should return true when passed is enum")
85                  .that(ScopeUtil.isInEnumBlock(
86                          getNode(TokenTypes.OBJBLOCK, TokenTypes.ENUM_DEF, TokenTypes.MODIFIERS)))
87                  .isTrue();
88          assertWithMessage("Should return false when passed is not enum")
89                  .that(ScopeUtil.isInEnumBlock(getNode(TokenTypes.ENUM_DEF, TokenTypes.INTERFACE_DEF,
90                          TokenTypes.MODIFIERS)))
91                  .isFalse();
92          assertWithMessage("Should return false when passed is not enum")
93                  .that(ScopeUtil.isInEnumBlock(getNode(TokenTypes.ENUM_DEF,
94                          TokenTypes.ANNOTATION_DEF, TokenTypes.MODIFIERS)))
95                  .isFalse();
96          assertWithMessage("Should return false when passed is not enum")
97                  .that(ScopeUtil.isInEnumBlock(
98                          getNode(TokenTypes.ENUM_DEF, TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS)))
99                  .isFalse();
100         assertWithMessage("Should return false when passed is not enum")
101                 .that(ScopeUtil.isInEnumBlock(
102                         getNode(TokenTypes.ENUM_DEF, TokenTypes.LITERAL_NEW, TokenTypes.IDENT)))
103                 .isFalse();
104         assertWithMessage("Should return false when passed is not expected")
105                 .that(ScopeUtil.isInEnumBlock(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)))
106                 .isFalse();
107     }
108 
109     @Test
110     public void testIsInCodeBlock() {
111         assertWithMessage("invalid result")
112                 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.CLASS_DEF)))
113                 .isFalse();
114         assertWithMessage("invalid result")
115                 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.ASSIGN, TokenTypes.VARIABLE_DEF)))
116                 .isFalse();
117         assertWithMessage("invalid result")
118                 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.METHOD_DEF, TokenTypes.OBJBLOCK)))
119                 .isTrue();
120         assertWithMessage("invalid result")
121                 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.CTOR_DEF, TokenTypes.OBJBLOCK)))
122                 .isTrue();
123         assertWithMessage("invalid result")
124                 .that(ScopeUtil
125                         .isInCodeBlock(getNode(TokenTypes.INSTANCE_INIT, TokenTypes.OBJBLOCK)))
126                 .isTrue();
127         assertWithMessage("invalid result")
128                 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.STATIC_INIT, TokenTypes.OBJBLOCK)))
129                 .isTrue();
130         assertWithMessage("invalid result")
131                 .that(ScopeUtil.isInCodeBlock(getNode(TokenTypes.LAMBDA, TokenTypes.ASSIGN)))
132                 .isTrue();
133     }
134 
135     @Test
136     public void testInRecordBlock() {
137         assertWithMessage("Should return false when passed is not record")
138                 .that(ScopeUtil.isInRecordBlock(new DetailAstImpl()))
139                 .isFalse();
140         assertWithMessage("Should return false when passed is not record")
141                 .that(ScopeUtil
142                         .isInRecordBlock(getNode(TokenTypes.LITERAL_NEW, TokenTypes.MODIFIERS)))
143                 .isFalse();
144         assertWithMessage("Should return true when passed is record")
145                 .that(ScopeUtil.isInRecordBlock(
146                         getNode(TokenTypes.OBJBLOCK, TokenTypes.RECORD_DEF, TokenTypes.MODIFIERS)))
147                 .isTrue();
148         assertWithMessage("Should return false when passed is not record")
149                 .that(ScopeUtil.isInRecordBlock(getNode(TokenTypes.RECORD_DEF,
150                         TokenTypes.INTERFACE_DEF, TokenTypes.MODIFIERS)))
151                 .isFalse();
152         assertWithMessage("Should return false when passed is not record")
153                 .that(ScopeUtil.isInRecordBlock(getNode(TokenTypes.RECORD_DEF,
154                         TokenTypes.ANNOTATION_DEF, TokenTypes.MODIFIERS)))
155                 .isFalse();
156         assertWithMessage("Should return false when passed is not record")
157                 .that(ScopeUtil.isInRecordBlock(
158                         getNode(TokenTypes.RECORD_DEF, TokenTypes.ENUM_DEF, TokenTypes.MODIFIERS)))
159                 .isFalse();
160         assertWithMessage("Should return false when passed is not record")
161                 .that(ScopeUtil.isInRecordBlock(
162                         getNode(TokenTypes.RECORD_DEF, TokenTypes.LITERAL_NEW, TokenTypes.IDENT)))
163                 .isFalse();
164         assertWithMessage("Should return false when passed is not expected")
165                 .that(ScopeUtil.isInRecordBlock(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)))
166                 .isFalse();
167     }
168 
169     @Test
170     public void testIsOuterMostTypeInterface() {
171         assertWithMessage("Should return false when passed is not outer most type")
172                 .that(ScopeUtil
173                         .isOuterMostType(getNode(TokenTypes.INTERFACE_DEF, TokenTypes.MODIFIERS)))
174                 .isFalse();
175     }
176 
177     @Test
178     public void testIsOuterMostTypeAnnotation() {
179         assertWithMessage("Should return false when passed is not outer most type")
180                 .that(ScopeUtil
181                         .isOuterMostType(getNode(TokenTypes.ANNOTATION_DEF, TokenTypes.MODIFIERS)))
182                 .isFalse();
183     }
184 
185     @Test
186     public void testIsOuterMostTypeEnum() {
187         assertWithMessage("Should return false when passed is not outer most type")
188                 .that(ScopeUtil.isOuterMostType(getNode(TokenTypes.ENUM_DEF, TokenTypes.MODIFIERS)))
189                 .isFalse();
190     }
191 
192     @Test
193     public void testIsOuterMostTypeClass() {
194         assertWithMessage("Should return false when passed is not outer most type")
195                 .that(ScopeUtil
196                         .isOuterMostType(getNode(TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS)))
197                 .isFalse();
198     }
199 
200     @Test
201     public void testIsOuterMostTypePackageDef() {
202         assertWithMessage("Should return false when passed is not outer most type")
203                 .that(ScopeUtil.isOuterMostType(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)))
204                 .isTrue();
205     }
206 
207     @Test
208     public void testIsLocalVariableDefCatch() {
209         assertWithMessage("Should return true when passed is variable def")
210             .that(ScopeUtil
211                 .isLocalVariableDef(getNode(TokenTypes.LITERAL_CATCH, TokenTypes.PARAMETER_DEF)))
212                 .isTrue();
213     }
214 
215     @Test
216     public void testIsLocalVariableDefUnexpected() {
217         assertWithMessage("Should return false when passed is not variable def")
218                 .that(ScopeUtil.isLocalVariableDef(getNode(TokenTypes.LITERAL_CATCH)))
219                 .isFalse();
220         assertWithMessage("Should return false when passed is not variable def")
221                 .that(ScopeUtil
222                         .isLocalVariableDef(getNode(TokenTypes.COMMA, TokenTypes.PARAMETER_DEF)))
223                 .isFalse();
224     }
225 
226     @Test
227     public void testIsLocalVariableDefResource() {
228         final DetailAstImpl node = getNode(TokenTypes.RESOURCE);
229         final DetailAstImpl modifiers = new DetailAstImpl();
230         modifiers.setType(TokenTypes.MODIFIERS);
231         node.addChild(modifiers);
232         final DetailAstImpl ident = new DetailAstImpl();
233         ident.setType(TokenTypes.IDENT);
234         node.addChild(ident);
235         assertWithMessage("invalid result")
236                 .that(ScopeUtil.isLocalVariableDef(node))
237                 .isTrue();
238         final DetailAstImpl resourceWithIdent = getNode(TokenTypes.RESOURCE);
239         resourceWithIdent.addChild(ident);
240         assertWithMessage("invalid result")
241                 .that(ScopeUtil.isLocalVariableDef(resourceWithIdent))
242                 .isFalse();
243         assertWithMessage("invalid result")
244                 .that(ScopeUtil.isLocalVariableDef(getNode(TokenTypes.RESOURCE)))
245                 .isFalse();
246     }
247 
248     @Test
249     public void testIsLocalVariableDefVariable() {
250         assertWithMessage("invalid result")
251                 .that(ScopeUtil
252                         .isLocalVariableDef(getNode(TokenTypes.SLIST, TokenTypes.VARIABLE_DEF)))
253                 .isTrue();
254         assertWithMessage("invalid result")
255                 .that(ScopeUtil
256                         .isLocalVariableDef(getNode(TokenTypes.FOR_INIT, TokenTypes.VARIABLE_DEF)))
257                 .isTrue();
258         assertWithMessage("invalid result")
259             .that(ScopeUtil
260                 .isLocalVariableDef(getNode(TokenTypes.FOR_EACH_CLAUSE, TokenTypes.VARIABLE_DEF)))
261                 .isTrue();
262         assertWithMessage("invalid result")
263                 .that(ScopeUtil
264                         .isLocalVariableDef(getNode(TokenTypes.CLASS_DEF, TokenTypes.VARIABLE_DEF)))
265                 .isFalse();
266     }
267 
268     @Test
269     public void testIsClassFieldDef() {
270         assertWithMessage("Should return true when passed is class field def")
271                 .that(ScopeUtil.isClassFieldDef(getNode(TokenTypes.CLASS_DEF, TokenTypes.OBJBLOCK,
272                         TokenTypes.VARIABLE_DEF)))
273                 .isTrue();
274         assertWithMessage("Should return false when passed is unexpected")
275                 .that(ScopeUtil.isClassFieldDef(getNode(TokenTypes.CLASS_DEF)))
276                 .isFalse();
277         assertWithMessage("Should return false when passed is method variable def")
278                 .that(ScopeUtil.isClassFieldDef(
279                         getNode(TokenTypes.METHOD_DEF, TokenTypes.SLIST, TokenTypes.VARIABLE_DEF)))
280                 .isFalse();
281     }
282 
283     @Test
284     public void testSurroundingScope() {
285         final Scope publicScope = ScopeUtil.getSurroundingScope(getNodeWithParentScope(
286                 TokenTypes.LITERAL_PUBLIC, "public", TokenTypes.ANNOTATION_DEF));
287         assertWithMessage("Invalid surrounding scope")
288             .that(publicScope)
289             .isEqualTo(Scope.PUBLIC);
290         final Scope protectedScope = ScopeUtil.getSurroundingScope(getNodeWithParentScope(
291                 TokenTypes.LITERAL_PROTECTED, "protected", TokenTypes.INTERFACE_DEF));
292         assertWithMessage("Invalid surrounding scope")
293             .that(protectedScope)
294             .isEqualTo(Scope.PROTECTED);
295         final Scope privateScope = ScopeUtil.getSurroundingScope(getNodeWithParentScope(
296                 TokenTypes.LITERAL_PRIVATE, "private", TokenTypes.ENUM_DEF));
297         assertWithMessage("Invalid surrounding scope")
298             .that(privateScope)
299             .isEqualTo(Scope.PRIVATE);
300         final Scope staticScope = ScopeUtil.getSurroundingScope(getNodeWithParentScope(
301                 TokenTypes.LITERAL_STATIC, "static", TokenTypes.CLASS_DEF));
302         assertWithMessage("Invalid surrounding scope")
303             .that(staticScope)
304             .isEqualTo(Scope.PACKAGE);
305     }
306 
307     @Test
308     public void testIsInScope() {
309         assertWithMessage("Should return true when node is in valid scope")
310                 .that(ScopeUtil.isInScope(getNodeWithParentScope(TokenTypes.LITERAL_PUBLIC,
311                         "public", TokenTypes.ANNOTATION_DEF), Scope.PUBLIC))
312                 .isTrue();
313         assertWithMessage("Should return false when node is in invalid scope")
314                 .that(ScopeUtil.isInScope(getNodeWithParentScope(TokenTypes.LITERAL_PROTECTED,
315                         "protected", TokenTypes.INTERFACE_DEF), Scope.PRIVATE))
316                 .isFalse();
317     }
318 
319     @Test
320     public void testSurroundingScopeOfNodeChildOfLiteralNewIsAnoninner() {
321         final Scope scope =
322                 ScopeUtil.getSurroundingScope(getNode(TokenTypes.LITERAL_NEW, TokenTypes.IDENT));
323         assertWithMessage("Invalid surrounding scope")
324             .that(scope)
325             .isEqualTo(Scope.ANONINNER);
326     }
327 
328     @Test
329     public void testIsInInterfaceBlock() {
330         final DetailAST ast = getNode(TokenTypes.INTERFACE_DEF, TokenTypes.OBJBLOCK,
331                 TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS);
332 
333         assertWithMessage("Should return true when node is interface block")
334                 .that(ScopeUtil.isInInterfaceBlock(ast.getParent()))
335                 .isTrue();
336         assertWithMessage("Should return false when node is not interface block")
337                 .that(ScopeUtil.isInInterfaceBlock(ast))
338                 .isFalse();
339     }
340 
341     @Test
342     public void testIsInAnnotationBlock() {
343         final DetailAST ast = getNode(TokenTypes.ANNOTATION_DEF, TokenTypes.OBJBLOCK,
344                 TokenTypes.INTERFACE_DEF, TokenTypes.MODIFIERS);
345 
346         assertWithMessage("Should return true when node is annotation block")
347                 .that(ScopeUtil.isInAnnotationBlock(ast.getParent()))
348                 .isTrue();
349         assertWithMessage("Should return false when node is not annotation block")
350                 .that(ScopeUtil.isInAnnotationBlock(ast))
351                 .isFalse();
352     }
353 
354     @Test
355     public void testisInInterfaceOrAnnotationBlock() {
356         assertWithMessage("Should return true when node is in interface or annotation block")
357                 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
358                         getNode(TokenTypes.ANNOTATION_DEF, TokenTypes.OBJBLOCK)))
359                 .isTrue();
360         assertWithMessage("Should return true when node is in interface or annotation block")
361                 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
362                         getNode(TokenTypes.INTERFACE_DEF, TokenTypes.OBJBLOCK)))
363                 .isTrue();
364         assertWithMessage("Should return false when node is not in interface or annotation block")
365                 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
366                         getNode(TokenTypes.CLASS_DEF, TokenTypes.OBJBLOCK)))
367                 .isFalse();
368         assertWithMessage("Should return false when node is not in interface or annotation block")
369                 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
370                         getNode(TokenTypes.LITERAL_NEW, TokenTypes.IDENT)))
371                 .isFalse();
372         assertWithMessage("Should return false when node is not in interface or annotation block")
373                 .that(ScopeUtil.isInInterfaceOrAnnotationBlock(
374                         getNode(TokenTypes.ENUM_DEF, TokenTypes.OBJBLOCK)))
375                 .isFalse();
376     }
377 
378     private static DetailAstImpl getNode(int... nodeTypes) {
379         DetailAstImpl ast = new DetailAstImpl();
380         ast.setType(nodeTypes[0]);
381         for (int i = 1; i < nodeTypes.length; i++) {
382             final DetailAstImpl astChild = new DetailAstImpl();
383             astChild.setType(nodeTypes[i]);
384             ast.addChild(astChild);
385             ast = astChild;
386         }
387         return ast;
388     }
389 
390     private static DetailAST getNodeWithParentScope(int literal, String scope,
391                                                     int parentTokenType) {
392         final DetailAstImpl ast = getNode(parentTokenType, TokenTypes.MODIFIERS, literal);
393         ast.setText(scope);
394         final DetailAstImpl ast2 = getNode(TokenTypes.OBJBLOCK);
395         ((DetailAstImpl) ast.getParent().getParent()).addChild(ast2);
396         return ast;
397     }
398 
399 }