1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 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.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertFalse;
25  import static org.junit.Assert.assertTrue;
26  
27  import org.junit.Test;
28  
29  import com.puppycrawl.tools.checkstyle.api.DetailAST;
30  import com.puppycrawl.tools.checkstyle.api.Scope;
31  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
32  
33  public class ScopeUtilTest {
34  
35      @Test
36      public void testIsProperUtilsClass() throws ReflectiveOperationException {
37          assertTrue("Constructor is not private",
38                  isUtilsClassHasPrivateConstructor(ScopeUtil.class, true));
39      }
40  
41      @Test
42      public void testInClassBlock() {
43          assertFalse("Should return false when passed is not class",
44                  ScopeUtil.isInClassBlock(new DetailAST()));
45          assertFalse("Should return false when passed is not class",
46                  ScopeUtil.isInClassBlock(getNode(TokenTypes.LITERAL_NEW,
47                          TokenTypes.MODIFIERS)));
48          assertTrue("Should return true when passed is class",
49                  ScopeUtil.isInClassBlock(getNode(TokenTypes.OBJBLOCK, TokenTypes.CLASS_DEF,
50                          TokenTypes.MODIFIERS)));
51          assertFalse("Should return false when passed is not class",
52                  ScopeUtil.isInClassBlock(getNode(TokenTypes.CLASS_DEF, TokenTypes.INTERFACE_DEF,
53                          TokenTypes.MODIFIERS)));
54          assertFalse("Should return false when passed is not class",
55                  ScopeUtil.isInClassBlock(getNode(TokenTypes.CLASS_DEF, TokenTypes.ANNOTATION_DEF,
56                          TokenTypes.MODIFIERS)));
57          assertFalse("Should return false when passed is not class",
58                  ScopeUtil.isInClassBlock(getNode(TokenTypes.CLASS_DEF, TokenTypes.ENUM_DEF,
59                          TokenTypes.MODIFIERS)));
60          assertFalse("Should return false when passed is not class",
61                  ScopeUtil.isInClassBlock(getNode(TokenTypes.CLASS_DEF, TokenTypes.LITERAL_NEW,
62                          TokenTypes.IDENT)));
63          assertFalse("Should return false when passed is not expected",
64                  ScopeUtil.isInClassBlock(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)));
65      }
66  
67      @Test
68      public void testInEnumBlock() {
69          assertFalse("Should return false when passed is not enum",
70                  ScopeUtil.isInEnumBlock(new DetailAST()));
71          assertFalse("Should return false when passed is not enum",
72                  ScopeUtil.isInEnumBlock(getNode(TokenTypes.LITERAL_NEW,
73                          TokenTypes.MODIFIERS)));
74          assertTrue("Should return true when passed is enum",
75                  ScopeUtil.isInEnumBlock(getNode(TokenTypes.OBJBLOCK, TokenTypes.ENUM_DEF,
76                          TokenTypes.MODIFIERS)));
77          assertFalse("Should return false when passed is not enum",
78                  ScopeUtil.isInEnumBlock(getNode(TokenTypes.ENUM_DEF, TokenTypes.INTERFACE_DEF,
79                          TokenTypes.MODIFIERS)));
80          assertFalse("Should return false when passed is not enum",
81                  ScopeUtil.isInEnumBlock(getNode(TokenTypes.ENUM_DEF, TokenTypes.ANNOTATION_DEF,
82                          TokenTypes.MODIFIERS)));
83          assertFalse("Should return false when passed is not enum",
84                  ScopeUtil.isInEnumBlock(getNode(TokenTypes.ENUM_DEF, TokenTypes.CLASS_DEF,
85                          TokenTypes.MODIFIERS)));
86          assertFalse("Should return false when passed is not enum",
87                  ScopeUtil.isInEnumBlock(getNode(TokenTypes.ENUM_DEF, TokenTypes.LITERAL_NEW,
88                          TokenTypes.IDENT)));
89          assertFalse("Should return false when passed is not expected",
90                  ScopeUtil.isInEnumBlock(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)));
91      }
92  
93      @Test
94      public void testIsInCodeBlock() {
95          assertFalse("invalid result", ScopeUtil.isInCodeBlock(getNode(TokenTypes.CLASS_DEF)));
96          assertFalse("invalid result",
97                  ScopeUtil.isInCodeBlock(getNode(TokenTypes.ASSIGN, TokenTypes.VARIABLE_DEF)));
98          assertTrue("invalid result",
99                  ScopeUtil.isInCodeBlock(getNode(TokenTypes.METHOD_DEF, TokenTypes.OBJBLOCK)));
100         assertTrue("invalid result",
101                 ScopeUtil.isInCodeBlock(getNode(TokenTypes.CTOR_DEF, TokenTypes.OBJBLOCK)));
102         assertTrue("invalid result",
103                 ScopeUtil.isInCodeBlock(getNode(TokenTypes.INSTANCE_INIT, TokenTypes.OBJBLOCK)));
104         assertTrue("invalid result",
105                 ScopeUtil.isInCodeBlock(getNode(TokenTypes.STATIC_INIT, TokenTypes.OBJBLOCK)));
106         assertTrue("invalid result",
107                 ScopeUtil.isInCodeBlock(getNode(TokenTypes.LAMBDA, TokenTypes.ASSIGN)));
108     }
109 
110     @Test
111     public void testIsOuterMostTypeInterface() {
112         assertFalse("Should return false when passed is not outer most type",
113                 ScopeUtil.isOuterMostType(getNode(TokenTypes.INTERFACE_DEF,
114                         TokenTypes.MODIFIERS)));
115     }
116 
117     @Test
118     public void testIsOuterMostTypeAnnotation() {
119         assertFalse("Should return false when passed is not outer most type",
120                 ScopeUtil.isOuterMostType(getNode(TokenTypes.ANNOTATION_DEF,
121                         TokenTypes.MODIFIERS)));
122     }
123 
124     @Test
125     public void testIsOuterMostTypeEnum() {
126         assertFalse("Should return false when passed is not outer most type",
127                 ScopeUtil.isOuterMostType(getNode(TokenTypes.ENUM_DEF, TokenTypes.MODIFIERS)));
128     }
129 
130     @Test
131     public void testIsOuterMostTypeClass() {
132         assertFalse("Should return false when passed is not outer most type",
133                 ScopeUtil.isOuterMostType(getNode(TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS)));
134     }
135 
136     @Test
137     public void testIsOuterMostTypePackageDef() {
138         assertTrue("Should return false when passed is not outer most type",
139                 ScopeUtil.isOuterMostType(getNode(TokenTypes.PACKAGE_DEF, TokenTypes.DOT)));
140     }
141 
142     @Test
143     public void testIsLocalVariableDefCatch() {
144         assertTrue("Should return true when passed is variable def",
145                 ScopeUtil.isLocalVariableDef(getNode(TokenTypes.LITERAL_CATCH,
146                         TokenTypes.PARAMETER_DEF)));
147     }
148 
149     @Test
150     public void testIsLocalVariableDefUnexpected() {
151         assertFalse("Should return false when passed is not variable def",
152                 ScopeUtil.isLocalVariableDef(getNode(TokenTypes.LITERAL_CATCH)));
153         assertFalse("Should return false when passed is not variable def",
154                 ScopeUtil.isLocalVariableDef(getNode(TokenTypes.COMMA, TokenTypes.PARAMETER_DEF)));
155     }
156 
157     @Test
158     public void testIsLocalVariableDefResource() {
159         assertTrue("invalid result",
160                 ScopeUtil.isLocalVariableDef(getNode(TokenTypes.RESOURCE)));
161     }
162 
163     @Test
164     public void testIsLocalVariableDefVariable() {
165         assertTrue("invalid result",
166                 ScopeUtil.isLocalVariableDef(getNode(TokenTypes.SLIST, TokenTypes.VARIABLE_DEF)));
167         assertTrue("invalid result", ScopeUtil.isLocalVariableDef(getNode(TokenTypes.FOR_INIT,
168                 TokenTypes.VARIABLE_DEF)));
169         assertTrue("invalid result", ScopeUtil.isLocalVariableDef(getNode(
170                 TokenTypes.FOR_EACH_CLAUSE, TokenTypes.VARIABLE_DEF)));
171         assertFalse("invalid result", ScopeUtil.isLocalVariableDef(getNode(TokenTypes.CLASS_DEF,
172                 TokenTypes.VARIABLE_DEF)));
173     }
174 
175     @Test
176     public void testIsClassFieldDef() {
177         assertTrue("Should return true when passed is class field def",
178                 ScopeUtil.isClassFieldDef(getNode(TokenTypes.CLASS_DEF,
179                         TokenTypes.OBJBLOCK, TokenTypes.VARIABLE_DEF)));
180         assertFalse("Should return false when passed is unexpected",
181                 ScopeUtil.isClassFieldDef(getNode(TokenTypes.CLASS_DEF)));
182         assertFalse("Should return false when passed is method variable def",
183                 ScopeUtil.isClassFieldDef(getNode(TokenTypes.METHOD_DEF,
184                         TokenTypes.SLIST, TokenTypes.VARIABLE_DEF)));
185     }
186 
187     @Test
188     public void testSurroundingScope() {
189         assertEquals("Invalid surrounding scope",
190                 Scope.PUBLIC, ScopeUtil.getSurroundingScope(getNodeWithParentScope(
191             TokenTypes.LITERAL_PUBLIC, "public", TokenTypes.ANNOTATION_DEF)));
192         assertEquals("Invalid surrounding scope",
193                 Scope.PROTECTED, ScopeUtil.getSurroundingScope(
194             getNodeWithParentScope(TokenTypes.LITERAL_PROTECTED, "protected",
195             TokenTypes.INTERFACE_DEF)));
196         assertEquals("Invalid surrounding scope",
197                 Scope.PRIVATE, ScopeUtil.getSurroundingScope(
198             getNodeWithParentScope(TokenTypes.LITERAL_PRIVATE, "private", TokenTypes.ENUM_DEF)));
199         assertEquals("Invalid surrounding scope",
200                 Scope.PACKAGE, ScopeUtil.getSurroundingScope(
201             getNodeWithParentScope(TokenTypes.LITERAL_STATIC, "static", TokenTypes.CLASS_DEF)));
202     }
203 
204     @Test
205     public void testIsInScope() {
206         assertTrue("Should return true when node is in valid scope",
207                 ScopeUtil.isInScope(getNodeWithParentScope(TokenTypes.LITERAL_PUBLIC,
208                 "public", TokenTypes.ANNOTATION_DEF), Scope.PUBLIC));
209         assertFalse("Should return false when node is in invalid scope",
210                 ScopeUtil.isInScope(getNodeWithParentScope(TokenTypes.LITERAL_PROTECTED,
211                 "protected", TokenTypes.INTERFACE_DEF), Scope.PRIVATE));
212     }
213 
214     @Test
215     public void testSurroundingScopeOfNodeChildOfLiteralNewIsAnoninner() {
216         assertEquals("Invalid surrounding scope",
217                 Scope.ANONINNER, ScopeUtil.getSurroundingScope(
218                 getNode(TokenTypes.LITERAL_NEW, TokenTypes.IDENT)));
219     }
220 
221     @Test
222     public void testIsInInterfaceBlock() {
223         final DetailAST ast = getNode(TokenTypes.INTERFACE_DEF, TokenTypes.OBJBLOCK,
224                 TokenTypes.CLASS_DEF, TokenTypes.MODIFIERS);
225 
226         assertTrue("Should return true when node is interface block",
227                 ScopeUtil.isInInterfaceBlock(ast.getParent()));
228         assertFalse("Should return false when node is not interface block",
229                 ScopeUtil.isInInterfaceBlock(ast));
230     }
231 
232     @Test
233     public void testIsInAnnotationBlock() {
234         final DetailAST ast = getNode(TokenTypes.ANNOTATION_DEF, TokenTypes.OBJBLOCK,
235                 TokenTypes.INTERFACE_DEF, TokenTypes.MODIFIERS);
236 
237         assertTrue("Should return true when node is annotation block",
238                 ScopeUtil.isInAnnotationBlock(ast.getParent()));
239         assertFalse("Should return false when node is not annotation block",
240                 ScopeUtil.isInAnnotationBlock(ast));
241     }
242 
243     @Test
244     public void testisInInterfaceOrAnnotationBlock() {
245         assertTrue("Should return true when node is in interface or annotation block",
246                 ScopeUtil.isInInterfaceOrAnnotationBlock(
247                 getNode(TokenTypes.ANNOTATION_DEF, TokenTypes.OBJBLOCK)));
248         assertTrue("Should return true when node is in interface or annotation block",
249                 ScopeUtil.isInInterfaceOrAnnotationBlock(
250                 getNode(TokenTypes.INTERFACE_DEF, TokenTypes.OBJBLOCK)));
251         assertFalse("Should return false when node is not in interface or annotation block",
252                 ScopeUtil.isInInterfaceOrAnnotationBlock(
253                 getNode(TokenTypes.CLASS_DEF, TokenTypes.OBJBLOCK)));
254         assertFalse("Should return false when node is not in interface or annotation block",
255                 ScopeUtil.isInInterfaceOrAnnotationBlock(
256                 getNode(TokenTypes.LITERAL_NEW, TokenTypes.IDENT)));
257         assertFalse("Should return false when node is not in interface or annotation block",
258                 ScopeUtil.isInInterfaceOrAnnotationBlock(
259                 getNode(TokenTypes.ENUM_DEF, TokenTypes.OBJBLOCK)));
260     }
261 
262     private static DetailAST getNode(int... nodeTypes) {
263         DetailAST ast = new DetailAST();
264         ast.setType(nodeTypes[0]);
265         for (int i = 1; i < nodeTypes.length; i++) {
266             final DetailAST astChild = new DetailAST();
267             astChild.setType(nodeTypes[i]);
268             ast.addChild(astChild);
269             ast = astChild;
270         }
271         return ast;
272     }
273 
274     private static DetailAST getNodeWithParentScope(int literal, String scope,
275                                                     int parentTokenType) {
276         final DetailAST ast = getNode(parentTokenType, TokenTypes.MODIFIERS, literal);
277         ast.setText(scope);
278         final DetailAST ast2 = getNode(TokenTypes.OBJBLOCK);
279         ast.getParent().getParent().addChild(ast2);
280         return ast;
281     }
282 
283 }