View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2026 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.RequireThisCheck.MSG_METHOD;
24  import static com.puppycrawl.tools.checkstyle.checks.coding.RequireThisCheck.MSG_VARIABLE;
25  
26  import java.io.File;
27  import java.util.Collection;
28  import java.util.Optional;
29  import java.util.SortedSet;
30  
31  import org.antlr.v4.runtime.CommonToken;
32  import org.junit.jupiter.api.Test;
33  
34  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
35  import com.puppycrawl.tools.checkstyle.DetailAstImpl;
36  import com.puppycrawl.tools.checkstyle.JavaParser;
37  import com.puppycrawl.tools.checkstyle.api.DetailAST;
38  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
39  import com.puppycrawl.tools.checkstyle.api.Violation;
40  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
41  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
42  
43  public class RequireThisCheckTest extends AbstractModuleTestSupport {
44  
45      @Override
46      public String getPackageLocation() {
47          return "com/puppycrawl/tools/checkstyle/checks/coding/requirethis";
48      }
49  
50      @Test
51      public void testIt() throws Exception {
52          final String[] expected = {
53              "20:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
54              "26:9: " + getCheckMessage(MSG_METHOD, "method1", ""),
55              "40:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
56              "58:13: " + getCheckMessage(MSG_VARIABLE, "z", ""),
57              "65:9: " + getCheckMessage(MSG_VARIABLE, "z", ""),
58              "122:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
59              "123:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
60              "124:9: " + getCheckMessage(MSG_METHOD, "instanceMethod", ""),
61              "130:13: " + getCheckMessage(MSG_METHOD, "instanceMethod", "Issue2240."),
62              "131:13: " + getCheckMessage(MSG_VARIABLE, "i", "Issue2240."),
63              "143:9: " + getCheckMessage(MSG_METHOD, "foo", ""),
64              "151:9: " + getCheckMessage(MSG_VARIABLE, "s", ""),
65              "177:16: " + getCheckMessage(MSG_VARIABLE, "a", ""),
66              "177:20: " + getCheckMessage(MSG_VARIABLE, "a", ""),
67              "177:24: " + getCheckMessage(MSG_VARIABLE, "a", ""),
68              "183:16: " + getCheckMessage(MSG_VARIABLE, "b", ""),
69              "183:20: " + getCheckMessage(MSG_VARIABLE, "b", ""),
70              "183:24: " + getCheckMessage(MSG_VARIABLE, "b", ""),
71              "211:25: " + getCheckMessage(MSG_VARIABLE, "field", ""),
72          };
73          verifyWithInlineConfigParser(
74                  getPath("InputRequireThisEnumInnerClassesAndBugs.java"),
75                 expected);
76      }
77  
78      @Test
79      public void testMethodsOnly() throws Exception {
80          final String[] expected = {
81              "25:9: " + getCheckMessage(MSG_METHOD, "method1", ""),
82              "124:9: " + getCheckMessage(MSG_METHOD, "instanceMethod", ""),
83              "130:13: " + getCheckMessage(MSG_METHOD, "instanceMethod", "Issue22402."),
84              "143:9: " + getCheckMessage(MSG_METHOD, "foo", ""),
85          };
86          verifyWithInlineConfigParser(
87                  getPath("InputRequireThisEnumInnerClassesAndBugs2.java"),
88                 expected);
89      }
90  
91      @Test
92      public void testFieldsOnly() throws Exception {
93          final String[] expected = {
94              "19:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
95              "39:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
96              "58:13: " + getCheckMessage(MSG_VARIABLE, "z", ""),
97              "65:9: " + getCheckMessage(MSG_VARIABLE, "z", ""),
98              "122:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
99              "123:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
100             "131:13: " + getCheckMessage(MSG_VARIABLE, "i", "Issue22403."),
101             "152:9: " + getCheckMessage(MSG_VARIABLE, "s", ""),
102             "179:16: " + getCheckMessage(MSG_VARIABLE, "a", ""),
103             "179:20: " + getCheckMessage(MSG_VARIABLE, "a", ""),
104             "179:24: " + getCheckMessage(MSG_VARIABLE, "a", ""),
105             "185:16: " + getCheckMessage(MSG_VARIABLE, "b", ""),
106             "185:20: " + getCheckMessage(MSG_VARIABLE, "b", ""),
107             "185:24: " + getCheckMessage(MSG_VARIABLE, "b", ""),
108         };
109         verifyWithInlineConfigParser(
110                 getPath("InputRequireThisEnumInnerClassesAndBugs3.java"),
111                expected);
112     }
113 
114     @Test
115     public void testFieldsInExpressions() throws Exception {
116         final String[] expected = {
117             "18:28: " + getCheckMessage(MSG_VARIABLE, "id", ""),
118             "19:28: " + getCheckMessage(MSG_VARIABLE, "length", ""),
119             "20:28: " + getCheckMessage(MSG_VARIABLE, "length", ""),
120             "21:26: " + getCheckMessage(MSG_VARIABLE, "length", ""),
121             "22:26: " + getCheckMessage(MSG_VARIABLE, "length", ""),
122             "23:25: " + getCheckMessage(MSG_VARIABLE, "length", ""),
123             "24:25: " + getCheckMessage(MSG_VARIABLE, "length", ""),
124             "25:26: " + getCheckMessage(MSG_VARIABLE, "length", ""),
125             "26:26: " + getCheckMessage(MSG_VARIABLE, "length", ""),
126             "27:33: " + getCheckMessage(MSG_VARIABLE, "b", ""),
127             "28:36: " + getCheckMessage(MSG_VARIABLE, "b", ""),
128             "29:26: " + getCheckMessage(MSG_VARIABLE, "length", ""),
129             "30:26: " + getCheckMessage(MSG_VARIABLE, "length", ""),
130             "31:28: " + getCheckMessage(MSG_VARIABLE, "length", ""),
131             "32:26: " + getCheckMessage(MSG_VARIABLE, "length", ""),
132             "33:26: " + getCheckMessage(MSG_VARIABLE, "length", ""),
133             "34:26: " + getCheckMessage(MSG_VARIABLE, "length", ""),
134             "35:31: " + getCheckMessage(MSG_VARIABLE, "b", ""),
135             "36:32: " + getCheckMessage(MSG_VARIABLE, "b", ""),
136         };
137         verifyWithInlineConfigParser(
138                 getPath("InputRequireThisExpressions.java"),
139                expected);
140     }
141 
142     @Test
143     public void testGenerics() throws Exception {
144         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
145         verifyWithInlineConfigParser(
146                 getPath("InputRequireThis15Extensions.java"), expected);
147     }
148 
149     @Test
150     public void testGithubIssue41() throws Exception {
151         final String[] expected = {
152             "16:19: " + getCheckMessage(MSG_VARIABLE, "number", ""),
153             "17:16: " + getCheckMessage(MSG_METHOD, "other", ""),
154         };
155         verifyWithInlineConfigParser(
156                 getPath("InputRequireThisSimple.java"),
157                 expected);
158     }
159 
160     @Test
161     public void testTokensNotNull() {
162         final RequireThisCheck check = new RequireThisCheck();
163         assertWithMessage("Acceptable tokens should not be null")
164             .that(check.getAcceptableTokens())
165             .isNotNull();
166         assertWithMessage("Default tokens should not be null")
167             .that(check.getDefaultTokens())
168             .isNotNull();
169         assertWithMessage("Required tokens should not be null")
170             .that(check.getRequiredTokens())
171             .isNotNull();
172     }
173 
174     @Test
175     public void testWithAnonymousClass() throws Exception {
176         final String[] expected = {
177             "29:25: " + getCheckMessage(MSG_METHOD, "doSideEffect", ""),
178             "33:24: " + getCheckMessage(MSG_VARIABLE, "bar", "InputRequireThisAnonymousEmpty."),
179             "56:17: " + getCheckMessage(MSG_VARIABLE, "foobar", ""),
180         };
181         verifyWithInlineConfigParser(
182                 getPath("InputRequireThisAnonymousEmpty.java"),
183                 expected);
184     }
185 
186     @Test
187     public void testCompactSourceFile() throws Exception {
188         final String[] expected = {
189             "15:15: " + getCheckMessage(MSG_VARIABLE, "field", ""),
190             "20:5: " + getCheckMessage(MSG_VARIABLE, "field", ""),
191             "20:13: " + getCheckMessage(MSG_VARIABLE, "field", ""),
192             "28:5: " + getCheckMessage(MSG_METHOD, "increment", ""),
193             "35:9: " + getCheckMessage(MSG_VARIABLE, "innerField", ""),
194             "35:22: " + getCheckMessage(MSG_VARIABLE, "innerField", ""),
195         };
196         verifyWithInlineConfigParser(
197                 getNonCompilablePath("InputRequireThisCompactSourceFile.java"),
198                 expected);
199     }
200 
201     @Test
202     public void testCompactSourceFileDefault() throws Exception {
203         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
204         verifyWithInlineConfigParser(
205                 getNonCompilablePath("InputRequireThisCompactSourceFileDefault.java"),
206                 expected);
207     }
208 
209     @Test
210     public void testCompactSourceFileNestedReference() throws Exception {
211         final String[] expected = {
212             "22:9: " + getCheckMessage(MSG_VARIABLE, "innerField", ""),
213         };
214         verifyWithInlineConfigParser(
215                 getNonCompilablePath("InputRequireThisCompactSourceFileNestedReference.java"),
216                 expected);
217     }
218 
219     @Test
220     public void testCompactSourceFileImport() throws Exception {
221         final String[] expected = {
222             "18:5: " + getCheckMessage(MSG_VARIABLE, "java", ""),
223             "18:12: " + getCheckMessage(MSG_VARIABLE, "java", ""),
224         };
225         verifyWithInlineConfigParser(
226                 getNonCompilablePath("InputRequireThisCompactSourceFileImport.java"),
227                 expected);
228     }
229 
230     @Test
231     public void testCompactSourceFileModuleImport() throws Exception {
232         final String[] expected = {
233             "18:5: " + getCheckMessage(MSG_VARIABLE, "java", ""),
234             "18:12: " + getCheckMessage(MSG_VARIABLE, "java", ""),
235         };
236         verifyWithInlineConfigParser(
237                 getNonCompilablePath("InputRequireThisCompactSourceFileModuleImport.java"),
238                 expected);
239     }
240 
241     @Test
242     public void testDefaultSwitch() {
243         final RequireThisCheck check = new RequireThisCheck();
244 
245         final DetailAstImpl ast = new DetailAstImpl();
246         ast.initialize(new CommonToken(TokenTypes.ENUM, "ENUM"));
247 
248         check.visitToken(ast);
249         final SortedSet<Violation> violations = check.getViolations();
250 
251         assertWithMessage("No exception violations expected")
252             .that(violations)
253             .isEmpty();
254     }
255 
256     @Test
257     public void testValidateOnlyOverlappingFalse() throws Exception {
258         final String[] expected = {
259             "29:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
260             "30:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal1", ""),
261             "31:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal2", ""),
262             "32:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal3", ""),
263             "36:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal1", ""),
264             "37:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal2", ""),
265             "38:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal3", ""),
266             "42:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal1", ""),
267             "46:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal3", ""),
268             "50:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal1", ""),
269             "52:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
270             "54:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal3", ""),
271             "58:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal2", ""),
272             "59:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal3", ""),
273             "69:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal1", ""),
274             "70:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal2", ""),
275             "89:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
276             "128:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
277             "137:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
278             "141:9: " + getCheckMessage(MSG_METHOD, "method1", ""),
279             "177:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal1", ""),
280             "178:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal2", ""),
281             "179:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal3", ""),
282             "181:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
283             "185:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal1", ""),
284             "186:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal2", ""),
285             "187:9: " + getCheckMessage(MSG_VARIABLE, "fieldFinal3", ""),
286             "189:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
287             "194:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
288             "198:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
289             "219:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
290             "226:29: " + getCheckMessage(MSG_VARIABLE, "booleanField", ""),
291             "237:21: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
292             "247:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
293             "262:9: " + getCheckMessage(MSG_VARIABLE, "booleanField", ""),
294             "271:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
295             "279:18: " + getCheckMessage(MSG_METHOD, "addSuf2F", ""),
296             "284:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
297             "284:18: " + getCheckMessage(MSG_METHOD, "addSuf2F", ""),
298             "310:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
299             "349:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
300             "383:25: " + getCheckMessage(MSG_METHOD, "getAction", ""),
301             "385:20: " + getCheckMessage(MSG_METHOD, "processAction", ""),
302             "393:16: " + getCheckMessage(MSG_METHOD, "processAction", ""),
303             "499:22: " + getCheckMessage(MSG_VARIABLE, "add", ""),
304         };
305         verifyWithInlineConfigParser(
306                 getPath("InputRequireThisValidateOnlyOverlappingFalse.java"), expected);
307     }
308 
309     @Test
310     public void testValidateOnlyOverlappingFalseLeaves() throws Exception {
311         final String[] expected = {
312             "26:31: " + getCheckMessage(MSG_METHOD, "id", ""),
313             "36:16: " + getCheckMessage(MSG_VARIABLE, "_a", ""),
314         };
315         verifyWithInlineConfigParser(
316                 getPath("InputRequireThisValidateOnlyOverlappingFalseLeaves.java"),
317                 expected);
318     }
319 
320     @Test
321     public void testValidateOnlyOverlappingTrue() throws Exception {
322         final String[] expected = {
323             "29:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
324             "52:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
325             "89:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
326             "128:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
327             "181:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
328             "189:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
329             "247:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
330             "262:9: " + getCheckMessage(MSG_VARIABLE, "booleanField", ""),
331             "271:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
332             "284:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
333             "310:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
334             "348:9: " + getCheckMessage(MSG_VARIABLE, "field1", ""),
335         };
336         verifyWithInlineConfigParser(
337                 getPath("InputRequireThisValidateOnlyOverlappingTrue.java"), expected);
338     }
339 
340     @Test
341     public void testValidateOnlyOverlappingTrue2() throws Exception {
342         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
343         verifyWithInlineConfigParser(
344                 getPath("InputRequireThisValidateOnlyOverlappingTrue2.java"), expected);
345     }
346 
347     @Test
348     public void testReceiverParameter() throws Exception {
349         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
350         verifyWithInlineConfigParser(
351                 getPath("InputRequireThisReceiver.java"), expected);
352     }
353 
354     @Test
355     public void testBraceAlone() throws Exception {
356         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
357         verifyWithInlineConfigParser(
358                 getPath("InputRequireThisBraceAlone.java"), expected);
359     }
360 
361     @Test
362     public void testStatic() throws Exception {
363         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
364         verifyWithInlineConfigParser(
365                 getPath("InputRequireThisStatic.java"), expected);
366     }
367 
368     @Test
369     public void testMethodReferences() throws Exception {
370         final String[] expected = {
371             "24:9: " + getCheckMessage(MSG_VARIABLE, "tags", ""),
372         };
373         verifyWithInlineConfigParser(
374                 getPath("InputRequireThisMethodReferences.java"), expected);
375     }
376 
377     @Test
378     public void testAllowLocalVars() throws Exception {
379         final String[] expected = {
380             "18:9: " + getCheckMessage(MSG_VARIABLE, "s1", ""),
381             "26:9: " + getCheckMessage(MSG_VARIABLE, "s1", ""),
382             "39:9: " + getCheckMessage(MSG_VARIABLE, "s2", ""),
383             "44:9: " + getCheckMessage(MSG_VARIABLE, "s2", ""),
384             "50:9: " + getCheckMessage(MSG_VARIABLE, "s2", ""),
385             "51:16: " + getCheckMessage(MSG_VARIABLE, "s1", ""),
386         };
387         verifyWithInlineConfigParser(
388                 getPath("InputRequireThisAllowLocalVars.java"), expected);
389     }
390 
391     @Test
392     public void testAllowLambdaParameters() throws Exception {
393         final String[] expected = {
394             "24:9: " + getCheckMessage(MSG_VARIABLE, "s1", ""),
395             "46:21: " + getCheckMessage(MSG_VARIABLE, "z", ""),
396             "71:29: " + getCheckMessage(MSG_VARIABLE, "a", ""),
397             "71:34: " + getCheckMessage(MSG_VARIABLE, "b", ""),
398             "81:17: " + getCheckMessage(MSG_VARIABLE, "thread", ""),
399         };
400         verifyWithInlineConfigParser(
401                 getPath("InputRequireThisAllowLambdaParameters.java"), expected);
402     }
403 
404     @Test
405     public void testTryWithResources() throws Exception {
406         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
407         verifyWithInlineConfigParser(
408                 getPath("InputRequireThisTryWithResources.java"), expected);
409     }
410 
411     @Test
412     public void testTryWithResourcesOnlyOverlappingFalse() throws Exception {
413         final String[] expected = {
414             "44:23: " + getCheckMessage(MSG_VARIABLE, "fldCharset", ""),
415             "57:13: " + getCheckMessage(MSG_VARIABLE, "fldCharset", ""),
416             "69:45: " + getCheckMessage(MSG_METHOD, "methodToInvoke", ""),
417             "77:24: " + getCheckMessage(MSG_METHOD, "methodToInvoke", ""),
418             "103:51: " + getCheckMessage(MSG_VARIABLE, "fldBufferedReader", ""),
419             "107:23: " + getCheckMessage(MSG_VARIABLE, "fldBufferedReader", ""),
420             "107:54: " + getCheckMessage(MSG_VARIABLE, "fldScanner", ""),
421             "110:24: " + getCheckMessage(MSG_VARIABLE, "fldStreamReader", ""),
422             "111:23: " + getCheckMessage(MSG_VARIABLE, "fldBufferedReader", ""),
423             "111:54: " + getCheckMessage(MSG_VARIABLE, "fldScanner", ""),
424         };
425         verifyWithInlineConfigParser(
426                 getPath("InputRequireThisTryWithResourcesOnlyOverlappingFalse.java"), expected);
427     }
428 
429     @Test
430     public void testCatchVariables() throws Exception {
431         final String[] expected = {
432             "38:21: " + getCheckMessage(MSG_VARIABLE, "ex", ""),
433         };
434         verifyWithInlineConfigParser(
435                 getPath("InputRequireThisCatchVariables.java"), expected);
436     }
437 
438     @Test
439     public void testEnumConstant() throws Exception {
440         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
441         verifyWithInlineConfigParser(
442                 getPath("InputRequireThisEnumConstant.java"), expected);
443     }
444 
445     @Test
446     public void testAnnotationInterface() throws Exception {
447         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
448         verifyWithInlineConfigParser(
449                 getPath("InputRequireThisAnnotationInterface.java"), expected);
450     }
451 
452     @Test
453     public void testFor() throws Exception {
454         final String[] expected = {
455             "22:13: " + getCheckMessage(MSG_VARIABLE, "bottom", ""),
456             "30:32: " + getCheckMessage(MSG_VARIABLE, "name", ""),
457         };
458         verifyWithInlineConfigParser(
459                 getPath("InputRequireThisFor.java"), expected);
460     }
461 
462     @Test
463     public void testFinalInstanceVariable() throws Exception {
464         final String[] expected = {
465             "18:9: " + getCheckMessage(MSG_VARIABLE, "y", ""),
466             "19:9: " + getCheckMessage(MSG_VARIABLE, "z", ""),
467         };
468         verifyWithInlineConfigParser(
469                 getPath("InputRequireThisFinalInstanceVariable.java"), expected);
470     }
471 
472     @Test
473     public void test() throws Exception {
474         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
475         verifyWithInlineConfigParser(
476                 getPath("InputRequireThisCaseGroup.java"), expected);
477     }
478 
479     @Test
480     public void testExtendedMethod() throws Exception {
481         final String[] expected = {
482             "31:9: " + getCheckMessage(MSG_VARIABLE, "EXPR", ""),
483         };
484         verifyWithInlineConfigParser(
485                 getPath("InputRequireThisExtendedMethod.java"), expected);
486     }
487 
488     @Test
489     public void testRecordsAndCompactCtors() throws Exception {
490         final String[] expected = {
491             "18:13: " + getCheckMessage(MSG_METHOD, "method1", ""),
492             "19:13: " + getCheckMessage(MSG_METHOD, "method2", ""),
493             "20:13: " + getCheckMessage(MSG_METHOD, "method3", ""),
494             "30:13: " + getCheckMessage(MSG_METHOD, "method1", ""),
495             "56:13: " + getCheckMessage(MSG_METHOD, "method1", ""),
496             "57:13: " + getCheckMessage(MSG_METHOD, "method2", ""),
497             "58:13: " + getCheckMessage(MSG_METHOD, "method3", ""),
498             "68:13: " + getCheckMessage(MSG_METHOD, "method1", ""),
499         };
500         verifyWithInlineConfigParser(
501                 getPath("InputRequireThisRecordsAndCompactCtors.java"),
502                 expected);
503     }
504 
505     @Test
506     public void testRecordCompactCtors() throws Exception {
507         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
508         verifyWithInlineConfigParser(
509                 getPath("InputRequireThisRecordCompactCtors.java"),
510                 expected);
511     }
512 
513     @Test
514     public void testRecordsAsTopLevel() throws Exception {
515         final String[] expected = {
516             "17:9: " + getCheckMessage(MSG_METHOD, "method1", ""),
517             "18:9: " + getCheckMessage(MSG_METHOD, "method2", ""),
518             "19:9: " + getCheckMessage(MSG_METHOD, "method3", ""),
519             "26:9: " + getCheckMessage(MSG_METHOD, "method1", ""),
520             "30:21: " + getCheckMessage(MSG_VARIABLE, "x", ""),
521             "38:17: " + getCheckMessage(MSG_VARIABLE, "y", ""),
522             "45:9: " + getCheckMessage(MSG_METHOD, "method1", ""),
523         };
524         verifyWithInlineConfigParser(
525                 getPath("InputRequireThisRecordAsTopLevel.java"),
526                 expected);
527     }
528 
529     @Test
530     public void testRecordsDefault() throws Exception {
531         final String[] expected = {
532             "26:9: " + getCheckMessage(MSG_VARIABLE, "x", ""),
533         };
534         verifyWithInlineConfigParser(
535                 getPath("InputRequireThisRecordDefault.java"),
536                 expected);
537     }
538 
539     @Test
540     public void testRecordsWithCheckFields() throws Exception {
541         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
542         verifyWithInlineConfigParser(
543                 getPath("InputRequireThisRecordsWithCheckFields.java"),
544                 expected);
545     }
546 
547     @Test
548     public void testRecordsWithCheckFieldsOverlap() throws Exception {
549         final String[] expected = {
550             "20:20: " + getCheckMessage(MSG_VARIABLE, "a", ""),
551             "39:20: " + getCheckMessage(MSG_VARIABLE, "a", ""),
552             "46:16: " + getCheckMessage(MSG_VARIABLE, "a", ""),
553         };
554         verifyWithInlineConfigParser(
555                 getPath("InputRequireThisRecordsWithCheckFieldsOverlap.java"),
556                 expected);
557     }
558 
559     @Test
560     public void testLocalClassesInsideLambdas() throws Exception {
561         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
562         verifyWithInlineConfigParser(
563             getPath("InputRequireThisLocalClassesInsideLambdas.java"),
564             expected);
565     }
566 
567     /**
568      * We cannot confirm the type of the private class unless using reflection.
569      * Until <a href="https://github.com/checkstyle/checkstyle/issues/12666">#12666</a>.
570      *
571      * @throws Exception when code tested throws an exception.
572      */
573     @Test
574     public void testUnusedMethodCatch() throws Exception {
575         final DetailAstImpl ident = new DetailAstImpl();
576         ident.setText("testName");
577 
578         final Class<?> cls = Class.forName(RequireThisCheck.class.getName() + "$CatchFrame");
579         final Object o = TestUtil.instantiate(cls, null, ident);
580 
581         final DetailAstImpl actual = TestUtil.invokeMethod(o,
582                 "getFrameNameIdent", DetailAstImpl.class);
583         assertWithMessage("expected ident token")
584             .that(actual)
585             .isSameInstanceAs(ident);
586         assertWithMessage("expected catch frame type")
587             .that(TestUtil.invokeMethod(o, "getType", Object.class).toString())
588             .isEqualTo("CATCH_FRAME");
589     }
590 
591     /**
592      * We cannot confirm the type of the private class unless using reflection.
593      * Until <a href="https://github.com/checkstyle/checkstyle/issues/12666">#12666</a>.
594      *
595      * @throws Exception when code tested throws an exception.
596      */
597     @Test
598     public void testUnusedMethodFor() throws Exception {
599         final DetailAstImpl ident = new DetailAstImpl();
600         ident.setText("testName");
601 
602         final Class<?> cls = Class.forName(RequireThisCheck.class.getName() + "$ForFrame");
603         final Object o = TestUtil.instantiate(cls, null, ident);
604 
605         assertWithMessage("expected for frame type")
606             .that(TestUtil.invokeMethod(o, "getType", Object.class).toString())
607             .isEqualTo("FOR_FRAME");
608     }
609 
610     /**
611      * We cannot reproduce situation when visitToken is called and leaveToken is not.
612      * So, we have to use reflection to be sure that even in such situation
613      * state of the field will be cleared.
614      *
615      * @throws Exception when code tested throws exception
616      */
617     @Test
618     public void testClearState() throws Exception {
619         final RequireThisCheck check = new RequireThisCheck();
620         final DetailAST root = JavaParser.parseFile(
621                 new File(getPath("InputRequireThisSimple.java")),
622                 JavaParser.Options.WITHOUT_COMMENTS);
623         final Optional<DetailAST> classDef = TestUtil.findTokenInAstByPredicate(root,
624             ast -> ast.getType() == TokenTypes.CLASS_DEF);
625 
626         assertWithMessage("Ast should contain CLASS_DEF")
627                 .that(classDef.isPresent())
628                 .isTrue();
629         assertWithMessage("State is not cleared on beginTree")
630                 .that(TestUtil.isStatefulFieldClearedDuringBeginTree(check, classDef.orElseThrow(),
631                         "current", current -> ((Collection<?>) current).isEmpty()))
632                 .isTrue();
633     }
634 
635     @Test
636     public void testLocalTypeDefsInsideLambdasTwo() throws Exception {
637         final String[] expected = {
638             "89:9: " + getCheckMessage(MSG_VARIABLE, "index", ""),
639             "98:21: " + getCheckMessage(MSG_VARIABLE, "index", ""),
640             "112:29: " + getCheckMessage(MSG_VARIABLE, "index", ""),
641         };
642         verifyWithInlineConfigParser(
643             getPath("InputRequireThisLocalTypeDefsInsideLambdas.java"), expected);
644     }
645 
646     @Test
647     public void testAnnotationFieldDoesNotRequireThis() throws Exception {
648         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
649 
650         verifyWithInlineConfigParser(
651                 getPath("InputRequireThisAnnotationField.java"), expected);
652     }
653 
654     @Test
655     public void testAnnotationDefaultValueIsIgnored() throws Exception {
656         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
657 
658         verifyWithInlineConfigParser(
659                 getPath("InputRequireThisAnnotationDefault.java"), expected);
660     }
661 
662     @Test
663     public void testAnnotationUsageIsIgnored() throws Exception {
664         final String[] expected = {
665             "45:9: " + getCheckMessage(MSG_VARIABLE, "value", ""),
666             "46:9: " + getCheckMessage(MSG_VARIABLE, "name", ""),
667             "47:9: " + getCheckMessage(MSG_VARIABLE, "outer", ""),
668         };
669 
670         verifyWithInlineConfigParser(
671                 getPath("InputRequireThisAnnotationMutation.java"), expected);
672     }
673 
674     @Test
675     public void testAnnotationConstantOverlappingTrue() throws Exception {
676         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
677 
678         verifyWithInlineConfigParser(
679                 getPath("InputRequireThisAnnotationConstantOverlappingTrue.java"), expected);
680     }
681 
682     @Test
683     public void testAnnotationConstantOverlappingFalse() throws Exception {
684         final String[] expected = {
685             "19:18: " + getCheckMessage(MSG_VARIABLE, "CONTAINER", ""),
686             "26:31: " + getCheckMessage(MSG_VARIABLE, "warningsType", ""),
687         };
688 
689         verifyWithInlineConfigParser(
690                 getPath("InputRequireThisAnnotationConstantOverlappingFalse.java"), expected);
691     }
692 
693     @Test
694     public void testAnnotationQualified() throws Exception {
695         final String[] expected = {
696             "19:19: " + getCheckMessage(MSG_VARIABLE, "CONTAINER", ""),
697         };
698 
699         verifyWithInlineConfigParser(
700                 getPath("InputRequireThisAnnotationQualified.java"), expected);
701     }
702 
703     @Test
704     public void testAnnotationQualifiedDot() throws Exception {
705         final String[] expected = {
706             "31:22: " + getCheckMessage(MSG_VARIABLE, "value", ""),
707         };
708 
709         verifyWithInlineConfigParser(
710                 getPath("InputRequireThisAnnotationQualifiedDot.java"), expected);
711     }
712 
713     @Test
714     public void testAnnotationOverlappingTrue() throws Exception {
715         final String[] expected = {
716             "31:9: " + getCheckMessage(MSG_VARIABLE, "value", ""),
717             "39:9: " + getCheckMessage(MSG_VARIABLE, "Outer", ""),
718         };
719 
720         verifyWithInlineConfigParser(
721                 getPath("InputRequireThisAnnotationOverlappingTrue.java"), expected);
722     }
723 
724 }