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 static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.checks.coding.ModifiedControlVariableCheck.MSG_KEY;
24 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
25
26 import java.io.File;
27 import java.util.Collection;
28 import java.util.Optional;
29 import java.util.Set;
30
31 import org.junit.jupiter.api.Test;
32
33 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
34 import com.puppycrawl.tools.checkstyle.DetailAstImpl;
35 import com.puppycrawl.tools.checkstyle.JavaParser;
36 import com.puppycrawl.tools.checkstyle.api.DetailAST;
37 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
38 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
39 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
40
41 public class ModifiedControlVariableCheckTest
42 extends AbstractModuleTestSupport {
43
44 @Override
45 public String getPackageLocation() {
46 return "com/puppycrawl/tools/checkstyle/checks/coding/modifiedcontrolvariable";
47 }
48
49 @Test
50 public void testModifiedControlVariable() throws Exception {
51 final String[] expected = {
52 "21:14: " + getCheckMessage(MSG_KEY, "i"),
53 "24:15: " + getCheckMessage(MSG_KEY, "i"),
54 "27:37: " + getCheckMessage(MSG_KEY, "i"),
55 "28:17: " + getCheckMessage(MSG_KEY, "i"),
56 "56:15: " + getCheckMessage(MSG_KEY, "s"),
57 "63:14: " + getCheckMessage(MSG_KEY, "m"),
58 "74:15: " + getCheckMessage(MSG_KEY, "i"),
59 "75:15: " + getCheckMessage(MSG_KEY, "k"),
60 "85:15: " + getCheckMessage(MSG_KEY, "v"),
61 };
62 verifyWithInlineConfigParser(
63 getPath("InputModifiedControlVariableBothForLoops.java"), expected);
64 }
65
66 @Test
67 public void testEnhancedForLoopVariableTrue() throws Exception {
68
69 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
70 verifyWithInlineConfigParser(
71 getPath("InputModifiedControlVariableEnhancedForLoopVariable.java"),
72 expected);
73 }
74
75 @Test
76 public void testEnhancedForLoopVariableFalse() throws Exception {
77
78 final String[] expected = {
79 "20:18: " + getCheckMessage(MSG_KEY, "line"),
80 };
81 verifyWithInlineConfigParser(
82 getPath("InputModifiedControlVariableEnhancedForLoopVariable3.java"),
83 expected);
84 }
85
86 @Test
87 public void testEnhancedForLoopVariable2() throws Exception {
88
89 final String[] expected = {
90 "25:18: " + getCheckMessage(MSG_KEY, "i"),
91 };
92 verifyWithInlineConfigParser(
93 getPath("InputModifiedControlVariableEnhancedForLoopVariable2.java"),
94 expected);
95 }
96
97 @Test
98 public void testTokensNotNull() {
99 final ModifiedControlVariableCheck check = new ModifiedControlVariableCheck();
100 assertWithMessage("Acceptable tokens should not be null")
101 .that(check.getAcceptableTokens())
102 .isNotNull();
103 assertWithMessage("Default tokens should not be null")
104 .that(check.getDefaultTokens())
105 .isNotNull();
106 assertWithMessage("Required tokens should not be null")
107 .that(check.getRequiredTokens())
108 .isNotNull();
109 }
110
111 @Test
112 public void testImproperToken() {
113 final ModifiedControlVariableCheck check = new ModifiedControlVariableCheck();
114
115 final DetailAstImpl classDefAst = new DetailAstImpl();
116 classDefAst.setType(TokenTypes.CLASS_DEF);
117 classDefAst.setText("CLASS_DEF");
118
119 final IllegalStateException visitExc =
120 getExpectedThrowable(IllegalStateException.class,
121 () -> check.visitToken(classDefAst));
122 assertWithMessage("Error message must include token name")
123 .that(visitExc.getMessage())
124 .contains("CLASS_DEF");
125
126 final IllegalStateException leaveExc =
127 getExpectedThrowable(IllegalStateException.class,
128 () -> check.leaveToken(classDefAst));
129 assertWithMessage("Error message must include token name")
130 .that(leaveExc.getMessage())
131 .contains("CLASS_DEF");
132 }
133
134 @Test
135 public void testVariousAssignments() throws Exception {
136 final String[] expected = {
137 "18:15: " + getCheckMessage(MSG_KEY, "i"),
138 "19:15: " + getCheckMessage(MSG_KEY, "k"),
139 "25:15: " + getCheckMessage(MSG_KEY, "i"),
140 "26:15: " + getCheckMessage(MSG_KEY, "k"),
141 "32:15: " + getCheckMessage(MSG_KEY, "i"),
142 "33:15: " + getCheckMessage(MSG_KEY, "k"),
143 "39:15: " + getCheckMessage(MSG_KEY, "i"),
144 "40:15: " + getCheckMessage(MSG_KEY, "k"),
145 "46:15: " + getCheckMessage(MSG_KEY, "i"),
146 "47:15: " + getCheckMessage(MSG_KEY, "k"),
147 "52:15: " + getCheckMessage(MSG_KEY, "i"),
148 "53:15: " + getCheckMessage(MSG_KEY, "k"),
149 "59:15: " + getCheckMessage(MSG_KEY, "i"),
150 "60:15: " + getCheckMessage(MSG_KEY, "k"),
151 "66:15: " + getCheckMessage(MSG_KEY, "i"),
152 "67:15: " + getCheckMessage(MSG_KEY, "k"),
153 "73:15: " + getCheckMessage(MSG_KEY, "i"),
154 "74:15: " + getCheckMessage(MSG_KEY, "k"),
155 "80:15: " + getCheckMessage(MSG_KEY, "i"),
156 "81:15: " + getCheckMessage(MSG_KEY, "k"),
157 "87:14: " + getCheckMessage(MSG_KEY, "i"),
158 "88:14: " + getCheckMessage(MSG_KEY, "k"),
159 };
160 verifyWithInlineConfigParser(
161 getPath("InputModifiedControlVariableTestVariousAssignments.java"),
162 expected);
163 }
164
165 @Test
166 public void testRecordDecompositionInEnhancedForLoop() throws Exception {
167 final String[] expected = {
168 "37:15: " + getCheckMessage(MSG_KEY, "p"),
169 };
170 verifyWithInlineConfigParser(
171 getNonCompilablePath("InputModifiedControlVariableRecordDecomposition.java"),
172 expected);
173 }
174
175 @Test
176 public void testCompactSourceFile() throws Exception {
177 final String[] expected = {
178 "11:10: " + getCheckMessage(MSG_KEY, "i"),
179 "19:11: " + getCheckMessage(MSG_KEY, "k"),
180 "24:14: " + getCheckMessage(MSG_KEY, "a"),
181 "31:10: " + getCheckMessage(MSG_KEY, "i"),
182 "36:14: " + getCheckMessage(MSG_KEY, "item"),
183 "43:14: " + getCheckMessage(MSG_KEY, "i"),
184 };
185 verifyWithInlineConfigParser(
186 getNonCompilablePath("InputModifiedControlVariableCompactSourceFile.java"),
187 expected);
188 }
189
190 @Test
191 public void testCompactSourceFileSkipEnhancedForLoop() throws Exception {
192 final String[] expected = {
193 "16:10: " + getCheckMessage(MSG_KEY, "i"),
194 };
195 verifyWithInlineConfigParser(
196 getNonCompilablePath(
197 "InputModifiedControlVariableCompactSourceFileSkipEnhancedForLoop.java"),
198 expected);
199 }
200
201
202
203
204
205
206
207
208 @SuppressWarnings("unchecked")
209 @Test
210 public void testClearState() throws Exception {
211 final ModifiedControlVariableCheck check = new ModifiedControlVariableCheck();
212 final Optional<DetailAST> methodDef = TestUtil.findTokenInAstByPredicate(
213 JavaParser.parseFile(
214 new File(getPath("InputModifiedControlVariableEnhancedForLoopVariable.java")),
215 JavaParser.Options.WITHOUT_COMMENTS),
216 ast -> ast.getType() == TokenTypes.OBJBLOCK);
217
218 assertWithMessage("Ast should contain METHOD_DEF")
219 .that(methodDef.isPresent())
220 .isTrue();
221 assertWithMessage("State is not cleared on beginTree")
222 .that(TestUtil.isStatefulFieldClearedDuringBeginTree(check,
223 methodDef.orElseThrow(), "variableStack",
224 variableStack -> ((Collection<Set<String>>) variableStack).isEmpty()))
225 .isTrue();
226 }
227
228 }