View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 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.checks.coding;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.coding.HiddenFieldCheck.MSG_KEY;
24  
25  import java.io.File;
26  import java.util.Optional;
27  import java.util.function.Predicate;
28  
29  import org.junit.jupiter.api.Test;
30  
31  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
32  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
33  import com.puppycrawl.tools.checkstyle.JavaParser;
34  import com.puppycrawl.tools.checkstyle.api.DetailAST;
35  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
36  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
37  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
38  
39  public class HiddenFieldCheckTest
40      extends AbstractModuleTestSupport {
41  
42      @Override
43      protected String getPackageLocation() {
44          return "com/puppycrawl/tools/checkstyle/checks/coding/hiddenfield";
45      }
46  
47      @Test
48      public void testStaticVisibilityFromLambdas() throws Exception {
49          final String[] expected = {
50              "31:34: " + getCheckMessage(MSG_KEY, "value"),
51              "64:31: " + getCheckMessage(MSG_KEY, "languageCode"),
52              "74:35: " + getCheckMessage(MSG_KEY, "number"),
53              "87:35: " + getCheckMessage(MSG_KEY, "id"),
54              "115:33: " + getCheckMessage(MSG_KEY, "note"),
55              "141:48: " + getCheckMessage(MSG_KEY, "stringValue"),
56              "141:69: " + getCheckMessage(MSG_KEY, "intValue"),
57              "155:69: " + getCheckMessage(MSG_KEY, "doubleValue"),
58              "168:51: " + getCheckMessage(MSG_KEY, "firstString"),
59              "168:64: " + getCheckMessage(MSG_KEY, "secondString"),
60              "187:49: " + getCheckMessage(MSG_KEY, "first"),
61              "214:62: " + getCheckMessage(MSG_KEY, "mPi"),
62              "231:27: " + getCheckMessage(MSG_KEY, "justSomeList"),
63              "231:61: " + getCheckMessage(MSG_KEY, "justSomeMap"),
64              "246:55: " + getCheckMessage(MSG_KEY, "someObject"),
65              "255:52: " + getCheckMessage(MSG_KEY, "someObject"),
66          };
67          verifyWithInlineConfigParser(
68                  getPath("InputHiddenFieldLambdas.java"), expected);
69      }
70  
71      @Test
72      public void testStaticVisibilityFromAnonymousClasses() throws Exception {
73          final String[] expected = {
74              "22:45: " + getCheckMessage(MSG_KEY, "other"),
75              "28:42: " + getCheckMessage(MSG_KEY, "other"),
76              "36:49: " + getCheckMessage(MSG_KEY, "other"),
77              "46:53: " + getCheckMessage(MSG_KEY, "other"),
78              "58:26: " + getCheckMessage(MSG_KEY, "someField"),
79          };
80          verifyWithInlineConfigParser(
81                  getPath("InputHiddenFieldStaticVisibility.java"), expected);
82      }
83  
84      @Test
85      public void testNoParameters()
86              throws Exception {
87          final String[] expected = {
88              "30:13: " + getCheckMessage(MSG_KEY, "hidden"),
89              "39:13: " + getCheckMessage(MSG_KEY, "hidden"),
90              "44:18: " + getCheckMessage(MSG_KEY, "hidden"),
91              "59:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
92              "68:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
93              "69:17: " + getCheckMessage(MSG_KEY, "hidden"),
94              "74:22: " + getCheckMessage(MSG_KEY, "innerHidden"),
95              "78:22: " + getCheckMessage(MSG_KEY, "hidden"),
96              "90:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
97              "91:17: " + getCheckMessage(MSG_KEY, "hidden"),
98              "96:13: " + getCheckMessage(MSG_KEY, "hidden"),
99              "152:13: " + getCheckMessage(MSG_KEY, "hidden"),
100             "157:13: " + getCheckMessage(MSG_KEY, "hidden"),
101             "162:13: " + getCheckMessage(MSG_KEY, "hidden"),
102             "166:13: " + getCheckMessage(MSG_KEY, "hidden"),
103             "214:17: " + getCheckMessage(MSG_KEY, "hidden"),
104             "231:13: " + getCheckMessage(MSG_KEY, "hidden"),
105             "237:13: " + getCheckMessage(MSG_KEY, "hiddenStatic"),
106         };
107         verifyWithInlineConfigParser(
108                 getPath("InputHiddenField1.java"), expected);
109     }
110 
111     @Test
112     public void testDefault()
113             throws Exception {
114         final String[] expected = {
115             "30:13: " + getCheckMessage(MSG_KEY, "hidden"),
116             "33:34: " + getCheckMessage(MSG_KEY, "hidden"),
117             "40:13: " + getCheckMessage(MSG_KEY, "hidden"),
118             "45:18: " + getCheckMessage(MSG_KEY, "hidden"),
119             "50:33: " + getCheckMessage(MSG_KEY, "hidden"),
120             "61:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
121             "64:26: " + getCheckMessage(MSG_KEY, "innerHidden"),
122             "70:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
123             "71:17: " + getCheckMessage(MSG_KEY, "hidden"),
124             "76:22: " + getCheckMessage(MSG_KEY, "innerHidden"),
125             "80:22: " + getCheckMessage(MSG_KEY, "hidden"),
126             "85:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
127             "87:17: " + getCheckMessage(MSG_KEY, "hidden"),
128             "93:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
129             "94:17: " + getCheckMessage(MSG_KEY, "hidden"),
130             "99:13: " + getCheckMessage(MSG_KEY, "hidden"),
131             "117:29: " + getCheckMessage(MSG_KEY, "prop"),
132             "123:29: " + getCheckMessage(MSG_KEY, "prop"),
133             "129:29: " + getCheckMessage(MSG_KEY, "prop"),
134             "141:28: " + getCheckMessage(MSG_KEY, "prop"),
135             "155:13: " + getCheckMessage(MSG_KEY, "hidden"),
136             "160:13: " + getCheckMessage(MSG_KEY, "hidden"),
137             "165:13: " + getCheckMessage(MSG_KEY, "hidden"),
138             "169:13: " + getCheckMessage(MSG_KEY, "hidden"),
139             "196:23: " + getCheckMessage(MSG_KEY, "y"),
140             "217:17: " + getCheckMessage(MSG_KEY, "hidden"),
141             "227:22: " + getCheckMessage(MSG_KEY, "hidden"),
142             "234:13: " + getCheckMessage(MSG_KEY, "hidden"),
143             "240:13: " + getCheckMessage(MSG_KEY, "hiddenStatic"),
144             "247:41: " + getCheckMessage(MSG_KEY, "x"),
145             "253:30: " + getCheckMessage(MSG_KEY, "xAxis"),
146             "270:41: " + getCheckMessage(MSG_KEY, "prop"),
147             "284:29: " + getCheckMessage(MSG_KEY, "prop"),
148             "295:42: " + getCheckMessage(MSG_KEY, "prop2"),
149             "307:19: " + getCheckMessage(MSG_KEY, "i"),
150         };
151         verifyWithInlineConfigParser(
152                 getPath("InputHiddenField2.java"), expected);
153     }
154 
155     /** Tests ignoreFormat property. */
156     @Test
157     public void testIgnoreFormat()
158             throws Exception {
159         final DefaultConfiguration checkConfig =
160             createModuleConfig(HiddenFieldCheck.class);
161         checkConfig.addProperty("ignoreFormat", "^i.*$");
162         assertWithMessage("Ignore format should not be null")
163             .that(checkConfig.getProperty("ignoreFormat"))
164             .isNotNull();
165         final String[] expected = {
166             "30:13: " + getCheckMessage(MSG_KEY, "hidden"),
167             "33:34: " + getCheckMessage(MSG_KEY, "hidden"),
168             "40:13: " + getCheckMessage(MSG_KEY, "hidden"),
169             "45:18: " + getCheckMessage(MSG_KEY, "hidden"),
170             "50:33: " + getCheckMessage(MSG_KEY, "hidden"),
171             "71:17: " + getCheckMessage(MSG_KEY, "hidden"),
172             "79:22: " + getCheckMessage(MSG_KEY, "hidden"),
173             "85:17: " + getCheckMessage(MSG_KEY, "hidden"),
174             "92:17: " + getCheckMessage(MSG_KEY, "hidden"),
175             "97:13: " + getCheckMessage(MSG_KEY, "hidden"),
176             "115:29: " + getCheckMessage(MSG_KEY, "prop"),
177             "121:29: " + getCheckMessage(MSG_KEY, "prop"),
178             "127:29: " + getCheckMessage(MSG_KEY, "prop"),
179             "139:28: " + getCheckMessage(MSG_KEY, "prop"),
180             "153:13: " + getCheckMessage(MSG_KEY, "hidden"),
181             "158:13: " + getCheckMessage(MSG_KEY, "hidden"),
182             "163:13: " + getCheckMessage(MSG_KEY, "hidden"),
183             "167:13: " + getCheckMessage(MSG_KEY, "hidden"),
184             "194:23: " + getCheckMessage(MSG_KEY, "y"),
185             "215:17: " + getCheckMessage(MSG_KEY, "hidden"),
186             "225:22: " + getCheckMessage(MSG_KEY, "hidden"),
187             "232:13: " + getCheckMessage(MSG_KEY, "hidden"),
188             "238:13: " + getCheckMessage(MSG_KEY, "hiddenStatic"),
189             "245:41: " + getCheckMessage(MSG_KEY, "x"),
190             "251:30: " + getCheckMessage(MSG_KEY, "xAxis"),
191             "268:41: " + getCheckMessage(MSG_KEY, "prop"),
192             "282:29: " + getCheckMessage(MSG_KEY, "prop"),
193             "293:42: " + getCheckMessage(MSG_KEY, "prop2"),
194         };
195         verifyWithInlineConfigParser(
196                 getPath("InputHiddenField3.java"), expected);
197     }
198 
199     /** Tests ignoreSetter property. */
200     @Test
201     public void testIgnoreSetter()
202             throws Exception {
203         final String[] expected = {
204             "30:13: " + getCheckMessage(MSG_KEY, "hidden"),
205             "33:34: " + getCheckMessage(MSG_KEY, "hidden"),
206             "40:13: " + getCheckMessage(MSG_KEY, "hidden"),
207             "45:18: " + getCheckMessage(MSG_KEY, "hidden"),
208             "50:33: " + getCheckMessage(MSG_KEY, "hidden"),
209             "61:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
210             "64:26: " + getCheckMessage(MSG_KEY, "innerHidden"),
211             "70:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
212             "71:17: " + getCheckMessage(MSG_KEY, "hidden"),
213             "76:22: " + getCheckMessage(MSG_KEY, "innerHidden"),
214             "80:22: " + getCheckMessage(MSG_KEY, "hidden"),
215             "85:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
216             "87:17: " + getCheckMessage(MSG_KEY, "hidden"),
217             "93:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
218             "94:17: " + getCheckMessage(MSG_KEY, "hidden"),
219             "99:13: " + getCheckMessage(MSG_KEY, "hidden"),
220             "123:29: " + getCheckMessage(MSG_KEY, "prop"),
221             "129:29: " + getCheckMessage(MSG_KEY, "prop"),
222             "141:28: " + getCheckMessage(MSG_KEY, "prop"),
223             "155:13: " + getCheckMessage(MSG_KEY, "hidden"),
224             "160:13: " + getCheckMessage(MSG_KEY, "hidden"),
225             "165:13: " + getCheckMessage(MSG_KEY, "hidden"),
226             "169:13: " + getCheckMessage(MSG_KEY, "hidden"),
227             "196:23: " + getCheckMessage(MSG_KEY, "y"),
228             "217:17: " + getCheckMessage(MSG_KEY, "hidden"),
229             "227:22: " + getCheckMessage(MSG_KEY, "hidden"),
230             "234:13: " + getCheckMessage(MSG_KEY, "hidden"),
231             "240:13: " + getCheckMessage(MSG_KEY, "hiddenStatic"),
232             "247:41: " + getCheckMessage(MSG_KEY, "x"),
233             "270:41: " + getCheckMessage(MSG_KEY, "prop"),
234             "295:42: " + getCheckMessage(MSG_KEY, "prop2"),
235         };
236         verifyWithInlineConfigParser(
237                 getPath("InputHiddenField4.java"), expected);
238     }
239 
240     /** Tests ignoreSetter and setterCanReturnItsClass properties. */
241     @Test
242     public void testIgnoreChainSetter()
243             throws Exception {
244         final String[] expected = {
245             "30:13: " + getCheckMessage(MSG_KEY, "hidden"),
246             "33:34: " + getCheckMessage(MSG_KEY, "hidden"),
247             "40:13: " + getCheckMessage(MSG_KEY, "hidden"),
248             "45:18: " + getCheckMessage(MSG_KEY, "hidden"),
249             "50:33: " + getCheckMessage(MSG_KEY, "hidden"),
250             "61:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
251             "64:26: " + getCheckMessage(MSG_KEY, "innerHidden"),
252             "70:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
253             "71:17: " + getCheckMessage(MSG_KEY, "hidden"),
254             "76:22: " + getCheckMessage(MSG_KEY, "innerHidden"),
255             "80:22: " + getCheckMessage(MSG_KEY, "hidden"),
256             "85:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
257             "87:17: " + getCheckMessage(MSG_KEY, "hidden"),
258             "93:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
259             "94:17: " + getCheckMessage(MSG_KEY, "hidden"),
260             "99:13: " + getCheckMessage(MSG_KEY, "hidden"),
261             "123:29: " + getCheckMessage(MSG_KEY, "prop"),
262             "129:29: " + getCheckMessage(MSG_KEY, "prop"),
263             "141:28: " + getCheckMessage(MSG_KEY, "prop"),
264             "155:13: " + getCheckMessage(MSG_KEY, "hidden"),
265             "160:13: " + getCheckMessage(MSG_KEY, "hidden"),
266             "165:13: " + getCheckMessage(MSG_KEY, "hidden"),
267             "169:13: " + getCheckMessage(MSG_KEY, "hidden"),
268             "196:23: " + getCheckMessage(MSG_KEY, "y"),
269             "217:17: " + getCheckMessage(MSG_KEY, "hidden"),
270             "227:22: " + getCheckMessage(MSG_KEY, "hidden"),
271             "234:13: " + getCheckMessage(MSG_KEY, "hidden"),
272             "240:13: " + getCheckMessage(MSG_KEY, "hiddenStatic"),
273             "247:41: " + getCheckMessage(MSG_KEY, "x"),
274         };
275         verifyWithInlineConfigParser(
276                 getPath("InputHiddenField5.java"), expected);
277     }
278 
279     /** Tests ignoreConstructorParameter property. */
280     @Test
281     public void testIgnoreConstructorParameter()
282             throws Exception {
283         final String[] expected = {
284             "29:13: " + getCheckMessage(MSG_KEY, "hidden"),
285             "38:13: " + getCheckMessage(MSG_KEY, "hidden"),
286             "43:18: " + getCheckMessage(MSG_KEY, "hidden"),
287             "48:33: " + getCheckMessage(MSG_KEY, "hidden"),
288             "59:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
289             "68:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
290             "69:17: " + getCheckMessage(MSG_KEY, "hidden"),
291             "74:22: " + getCheckMessage(MSG_KEY, "innerHidden"),
292             "78:22: " + getCheckMessage(MSG_KEY, "hidden"),
293             "83:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
294             "85:17: " + getCheckMessage(MSG_KEY, "hidden"),
295             "91:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
296             "92:17: " + getCheckMessage(MSG_KEY, "hidden"),
297             "97:13: " + getCheckMessage(MSG_KEY, "hidden"),
298             "115:29: " + getCheckMessage(MSG_KEY, "prop"),
299             "121:29: " + getCheckMessage(MSG_KEY, "prop"),
300             "127:29: " + getCheckMessage(MSG_KEY, "prop"),
301             "139:28: " + getCheckMessage(MSG_KEY, "prop"),
302             "153:13: " + getCheckMessage(MSG_KEY, "hidden"),
303             "158:13: " + getCheckMessage(MSG_KEY, "hidden"),
304             "163:13: " + getCheckMessage(MSG_KEY, "hidden"),
305             "167:13: " + getCheckMessage(MSG_KEY, "hidden"),
306             "194:23: " + getCheckMessage(MSG_KEY, "y"),
307             "215:17: " + getCheckMessage(MSG_KEY, "hidden"),
308             "232:13: " + getCheckMessage(MSG_KEY, "hidden"),
309             "238:13: " + getCheckMessage(MSG_KEY, "hiddenStatic"),
310             "245:41: " + getCheckMessage(MSG_KEY, "x"),
311             "251:30: " + getCheckMessage(MSG_KEY, "xAxis"),
312             "268:41: " + getCheckMessage(MSG_KEY, "prop"),
313             "282:29: " + getCheckMessage(MSG_KEY, "prop"),
314             "293:42: " + getCheckMessage(MSG_KEY, "prop2"),
315             "305:19: " + getCheckMessage(MSG_KEY, "i"),
316         };
317         verifyWithInlineConfigParser(
318                 getPath("InputHiddenField6.java"), expected);
319     }
320 
321     /** Test against a class with field declarations in different order. */
322     @Test
323     public void testReordered()
324             throws Exception {
325         final String[] expected = {
326             "30:13: " + getCheckMessage(MSG_KEY, "hidden"),
327             "33:40: " + getCheckMessage(MSG_KEY, "hidden"),
328             "40:13: " + getCheckMessage(MSG_KEY, "hidden"),
329             "45:18: " + getCheckMessage(MSG_KEY, "hidden"),
330             "50:33: " + getCheckMessage(MSG_KEY, "hidden"),
331             "61:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
332             "64:26: " + getCheckMessage(MSG_KEY, "innerHidden"),
333             "70:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
334             "71:17: " + getCheckMessage(MSG_KEY, "hidden"),
335             "76:22: " + getCheckMessage(MSG_KEY, "innerHidden"),
336             "80:22: " + getCheckMessage(MSG_KEY, "hidden"),
337             "85:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
338             "87:17: " + getCheckMessage(MSG_KEY, "hidden"),
339             "93:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
340             "94:17: " + getCheckMessage(MSG_KEY, "hidden"),
341             "100:13: " + getCheckMessage(MSG_KEY, "hidden"),
342             "122:17: " + getCheckMessage(MSG_KEY, "hidden"),
343             "135:21: " + getCheckMessage(MSG_KEY, "hidden"),
344             "142:13: " + getCheckMessage(MSG_KEY, "hidden"),
345             "148:13: " + getCheckMessage(MSG_KEY, "hiddenStatic"),
346         };
347         verifyWithInlineConfigParser(
348                 getPath("InputHiddenFieldReorder.java"), expected);
349     }
350 
351     @Test
352     public void testIgnoreAbstractMethods() throws Exception {
353 
354         final String[] expected = {
355             "30:13: " + getCheckMessage(MSG_KEY, "hidden"),
356             "33:34: " + getCheckMessage(MSG_KEY, "hidden"),
357             "40:13: " + getCheckMessage(MSG_KEY, "hidden"),
358             "45:18: " + getCheckMessage(MSG_KEY, "hidden"),
359             "50:33: " + getCheckMessage(MSG_KEY, "hidden"),
360             "61:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
361             "64:26: " + getCheckMessage(MSG_KEY, "innerHidden"),
362             "70:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
363             "71:17: " + getCheckMessage(MSG_KEY, "hidden"),
364             "76:22: " + getCheckMessage(MSG_KEY, "innerHidden"),
365             "80:22: " + getCheckMessage(MSG_KEY, "hidden"),
366             "85:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
367             "87:17: " + getCheckMessage(MSG_KEY, "hidden"),
368             "93:17: " + getCheckMessage(MSG_KEY, "innerHidden"),
369             "94:17: " + getCheckMessage(MSG_KEY, "hidden"),
370             "99:13: " + getCheckMessage(MSG_KEY, "hidden"),
371             "117:29: " + getCheckMessage(MSG_KEY, "prop"),
372             "123:29: " + getCheckMessage(MSG_KEY, "prop"),
373             "129:29: " + getCheckMessage(MSG_KEY, "prop"),
374             "141:28: " + getCheckMessage(MSG_KEY, "prop"),
375             "155:13: " + getCheckMessage(MSG_KEY, "hidden"),
376             "160:13: " + getCheckMessage(MSG_KEY, "hidden"),
377             "165:13: " + getCheckMessage(MSG_KEY, "hidden"),
378             "169:13: " + getCheckMessage(MSG_KEY, "hidden"),
379             "196:23: " + getCheckMessage(MSG_KEY, "y"),
380             "217:17: " + getCheckMessage(MSG_KEY, "hidden"),
381             "227:22: " + getCheckMessage(MSG_KEY, "hidden"),
382             "234:13: " + getCheckMessage(MSG_KEY, "hidden"),
383             "240:13: " + getCheckMessage(MSG_KEY, "hiddenStatic"),
384             "253:30: " + getCheckMessage(MSG_KEY, "xAxis"),
385             "270:41: " + getCheckMessage(MSG_KEY, "prop"),
386             "284:29: " + getCheckMessage(MSG_KEY, "prop"),
387             "295:42: " + getCheckMessage(MSG_KEY, "prop2"),
388             "307:19: " + getCheckMessage(MSG_KEY, "i"),
389         };
390         verifyWithInlineConfigParser(
391                 getPath("InputHiddenField7.java"), expected);
392     }
393 
394     @Test
395     public void testReceiverParameter() throws Exception {
396         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
397         verifyWithInlineConfigParser(
398                 getPath("InputHiddenFieldReceiver.java"), expected);
399     }
400 
401     @Test
402     public void testHiddenFieldEnhancedInstanceof() throws Exception {
403 
404         final String[] expected = {
405             "26:39: " + getCheckMessage(MSG_KEY, "price"),
406             "37:35: " + getCheckMessage(MSG_KEY, "hiddenStaticField"),
407         };
408         verifyWithInlineConfigParser(
409                 getNonCompilablePath("InputHiddenFieldEnhancedInstanceof.java"), expected);
410     }
411 
412     @Test
413     public void testHiddenFieldSwitchExpression() throws Exception {
414 
415         final String[] expected = {
416             "28:13: " + getCheckMessage(MSG_KEY, "x"),
417             "32:30: " + getCheckMessage(MSG_KEY, "word"),
418             "33:35: " + getCheckMessage(MSG_KEY, "otherWord"),
419             "35:21: " + getCheckMessage(MSG_KEY, "y"),
420             "39:21: " + getCheckMessage(MSG_KEY, "z"),
421             "43:21: " + getCheckMessage(MSG_KEY, "a"),
422             "47:21: " + getCheckMessage(MSG_KEY, "b"),
423             "54:13: " + getCheckMessage(MSG_KEY, "x"),
424             "58:30: " + getCheckMessage(MSG_KEY, "word"),
425             "59:35: " + getCheckMessage(MSG_KEY, "otherWord"),
426             "61:21: " + getCheckMessage(MSG_KEY, "y"),
427             "65:21: " + getCheckMessage(MSG_KEY, "z"),
428             "69:21: " + getCheckMessage(MSG_KEY, "a"),
429             "73:21: " + getCheckMessage(MSG_KEY, "b"),
430         };
431         verifyWithInlineConfigParser(
432                 getNonCompilablePath("InputHiddenFieldSwitchExpression.java"), expected);
433     }
434 
435     @Test
436     public void testHiddenFieldRecords() throws Exception {
437 
438         final String[] expected = {
439             "23:17: " + getCheckMessage(MSG_KEY, "myHiddenInt"),
440             "28:17: " + getCheckMessage(MSG_KEY, "myHiddenInt"),
441             "36:17: " + getCheckMessage(MSG_KEY, "hiddenField"),
442             "44:39: " + getCheckMessage(MSG_KEY, "hiddenStaticField"),
443             "59:39: " + getCheckMessage(MSG_KEY, "price"),
444             "68:21: " + getCheckMessage(MSG_KEY, "x"),
445             "72:20: " + getCheckMessage(MSG_KEY, "string"),
446             "82:21: " + getCheckMessage(MSG_KEY, "x"),
447             "86:20: " + getCheckMessage(MSG_KEY, "string"),
448         };
449         verifyWithInlineConfigParser(
450                 getNonCompilablePath("InputHiddenFieldRecords.java"), expected);
451     }
452 
453     @Test
454     public void testHiddenFieldLambdasInNestedScope() throws Exception {
455         final String[] expected = {
456             "21:34: " + getCheckMessage(MSG_KEY, "value"),
457         };
458         verifyWithInlineConfigParser(
459             getPath("InputHiddenFieldLambdas2.java"), expected);
460     }
461 
462     @Test
463     public void testClassNestedInRecord() throws Exception {
464 
465         final String[] expected = {
466             "23:26: " + getCheckMessage(MSG_KEY, "a"),
467         };
468         verifyWithInlineConfigParser(
469             getNonCompilablePath("InputHiddenFieldClassNestedInRecord.java"),
470             expected);
471     }
472 
473     @Test
474     public void testHiddenFieldInnerRecordsImplicitlyStatic() throws Exception {
475 
476         final String[] expected = {
477             "35:30: " + getCheckMessage(MSG_KEY, "pointer"),
478         };
479 
480         verifyWithInlineConfigParser(
481                 getNonCompilablePath("InputHiddenFieldInnerRecordsImplicitlyStatic.java"),
482                 expected);
483     }
484 
485     @Test
486     public void testHiddenFieldRecordsImplicitlyStaticClassComparison() throws Exception {
487 
488         final String[] expected = {
489             "49:27: " + getCheckMessage(MSG_KEY, "x"),
490         };
491 
492         verifyWithInlineConfigParser(
493                 getNonCompilablePath("InputHiddenFieldRecordsImplicitlyStaticClassComparison.java"),
494                 expected);
495     }
496 
497     @Test
498     public void testHiddenFieldRecordPattern() throws Exception {
499 
500         final String[] expected = {
501             "18:46: " + getCheckMessage(MSG_KEY, "s"),
502             "18:53: " + getCheckMessage(MSG_KEY, "x"),
503             "26:39: " + getCheckMessage(MSG_KEY, "s"),
504             "26:46: " + getCheckMessage(MSG_KEY, "x"),
505             "35:45: " + getCheckMessage(MSG_KEY, "s"),
506             "35:52: " + getCheckMessage(MSG_KEY, "x"),
507             "35:63: " + getCheckMessage(MSG_KEY, "z"),
508             "43:37: " + getCheckMessage(MSG_KEY, "s"),
509             "43:44: " + getCheckMessage(MSG_KEY, "x"),
510         };
511         verifyWithInlineConfigParser(
512                 getNonCompilablePath("InputHiddenFieldRecordPattern.java"), expected);
513     }
514 
515     /**
516      * We cannot reproduce situation when visitToken is called and leaveToken is not.
517      * So, we have to use reflection to be sure that even in such situation
518      * state of the field will be cleared.
519      *
520      * @throws Exception when code tested throws exception
521      */
522     @Test
523     public void testClearState() throws Exception {
524         final HiddenFieldCheck check = new HiddenFieldCheck();
525         final DetailAST root = JavaParser.parseFile(new File(getPath("InputHiddenField8.java")),
526                 JavaParser.Options.WITHOUT_COMMENTS);
527         final Optional<DetailAST> classDef = TestUtil.findTokenInAstByPredicate(root,
528             ast -> ast.getType() == TokenTypes.CLASS_DEF);
529 
530         assertWithMessage("Ast should contain CLASS_DEF")
531                 .that(classDef.isPresent())
532                 .isTrue();
533         assertWithMessage("State is not cleared on beginTree")
534                 .that(
535                     TestUtil.isStatefulFieldClearedDuringBeginTree(check, classDef.orElseThrow(),
536                         "frame", new CheckIfStatefulFieldCleared()))
537                 .isTrue();
538     }
539 
540     private static final class CheckIfStatefulFieldCleared implements Predicate<Object> {
541 
542         @Override
543         public boolean test(Object frame) {
544             boolean result = frame != null;
545 
546             // verify object is cleared
547             if (result
548                     && (TestUtil.getInternalState(frame, "parent") != null
549                         || !TestUtil.<Boolean>getInternalState(frame, "staticType")
550                         || TestUtil.getInternalState(frame, "frameName") != null)) {
551                 result = false;
552             }
553 
554             return result;
555         }
556 
557     }
558 
559 }