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.annotation;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationLocationCheck.MSG_KEY_ANNOTATION_LOCATION;
24  import static com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationLocationCheck.MSG_KEY_ANNOTATION_LOCATION_ALONE;
25  
26  import org.junit.jupiter.api.Test;
27  
28  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
29  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
30  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
31  
32  public class AnnotationLocationCheckTest extends AbstractModuleTestSupport {
33  
34      @Override
35      public String getPackageLocation() {
36          return "com/puppycrawl/tools/checkstyle/checks/annotation/annotationlocation";
37      }
38  
39      @Test
40      public void testGetRequiredTokens() {
41          final AnnotationLocationCheck checkObj = new AnnotationLocationCheck();
42          assertWithMessage(
43                  "AnnotationLocationCheck#getRequiredTokens should return empty array by default")
44                          .that(checkObj.getRequiredTokens())
45                          .isEqualTo(CommonUtil.EMPTY_INT_ARRAY);
46      }
47  
48      @Test
49      public void testCorrect() throws Exception {
50          final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
51  
52          verifyWithInlineConfigParser(
53                  getPath("InputAnnotationLocationCorrect.java"), expected);
54      }
55  
56      @Test
57      public void testIncorrectOne() throws Exception {
58          final String[] expected = {
59              "16:11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnn"),
60              "21:15: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
61              "24:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
62              "27:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation1", 8, 4),
63              "33:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation1", 8, 4),
64              "36:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
65              "36:27: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnn_21"),
66              "42:8: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_21", 7, 4),
67              "46:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_21", 8, 4),
68              "47:7: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation3", 6, 4),
69              "48:11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation4", 10, 4),
70              "51:19: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
71              "55:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
72              "58:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation1", 12, 8),
73              "66:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
74              "71:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_21", 12, 8),
75              "75:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_21", 12, 8),
76              "80:8: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_21", 7, 4),
77              "83:19: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
78              "85:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
79              "95:12: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_21", 11, 8),
80              "98:11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_21", 10, 8),
81              "100:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation1"),
82          };
83          verifyWithInlineConfigParser(
84                  getPath("InputAnnotationLocationIncorrectOne.java"), expected);
85      }
86  
87      @Test
88      public void testIncorrectTwo() throws Exception {
89          final String[] expected = {
90              "18:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_21", 0, 3),
91          };
92          verifyWithInlineConfigParser(
93                  getPath("InputAnnotationLocationIncorrectTwo.java"), expected);
94      }
95  
96      @Test
97      public void testIncorrectAllTokensOne() throws Exception {
98          final String[] expected = {
99              "15:11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnn3"),
100             "20:15: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation_13"),
101             "23:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation_13"),
102             "26:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_13", 8, 4),
103             "32:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_13", 8, 4),
104             "36:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation_13"),
105             "36:29: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnn_23"),
106             "41:8: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_23", 7, 4),
107             "45:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_23", 8, 4),
108             "46:7: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_33", 6, 4),
109             "47:11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_43", 10, 4),
110             "50:19: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation_13"),
111             "54:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation_13"),
112             "57:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_13", 12, 8),
113             "65:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation_13"),
114             "70:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_23", 12, 8),
115             "74:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_23", 12, 8),
116             "79:8: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_23", 7, 4),
117             "83:19: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation_13"),
118             "85:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation_13"),
119             "95:12: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_23", 11, 8),
120             "98:11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_23", 10, 8),
121             "101:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation_13"),
122         };
123         verifyWithInlineConfigParser(
124                 getPath("InputAnnotationLocationIncorrect3One.java"), expected);
125     }
126 
127     @Test
128     public void testIncorrectAllTokensTwo() throws Exception {
129         final String[] expected = {
130             "17:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_23", 0, 3),
131         };
132         verifyWithInlineConfigParser(
133                 getPath("InputAnnotationLocationIncorrect3Two.java"), expected);
134     }
135 
136     @Test
137     public void testGetAcceptableTokens() {
138         final AnnotationLocationCheck constantNameCheckObj = new AnnotationLocationCheck();
139         final int[] actual = constantNameCheckObj.getAcceptableTokens();
140         final int[] expected = {
141             TokenTypes.CLASS_DEF,
142             TokenTypes.INTERFACE_DEF,
143             TokenTypes.PACKAGE_DEF,
144             TokenTypes.ENUM_CONSTANT_DEF,
145             TokenTypes.ENUM_DEF,
146             TokenTypes.METHOD_DEF,
147             TokenTypes.CTOR_DEF,
148             TokenTypes.VARIABLE_DEF,
149             TokenTypes.ANNOTATION_DEF,
150             TokenTypes.ANNOTATION_FIELD_DEF,
151             TokenTypes.RECORD_DEF,
152             TokenTypes.COMPACT_CTOR_DEF,
153             TokenTypes.MODULE_DEF,
154         };
155         assertWithMessage("Default acceptable tokens are invalid")
156                 .that(actual)
157                 .isEqualTo(expected);
158     }
159 
160     @Test
161     public void testWithoutAnnotations() throws Exception {
162         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
163         verifyWithInlineConfigParser(
164                 getPath("InputAnnotationLocationEmpty.java"), expected);
165     }
166 
167     @Test
168     public void testWithParametersOne() throws Exception {
169         final String[] expected = {
170             "26:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_12", 8, 4),
171             "34:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_12", 8, 4),
172             "41:8: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_22", 7, 4),
173             "45:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_22", 8, 4),
174             "46:7: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_32", 6, 4),
175             "47:11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_42", 10, 4),
176             "57:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnnotation_12", 12, 8),
177             "70:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_22", 12, 8),
178             "74:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_22", 12, 8),
179             "79:8: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_22", 7, 4),
180             "94:12: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_22", 11, 8),
181             "97:11: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_22", 10, 8),
182         };
183         verifyWithInlineConfigParser(
184                 getPath("InputAnnotationLocationIncorrect2One.java"), expected);
185     }
186 
187     @Test
188     public void testWithParametersTwo() throws Exception {
189         final String[] expected = {
190             "18:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "MyAnn_22", 0, 3),
191         };
192         verifyWithInlineConfigParser(
193                 getPath("InputAnnotationLocationIncorrect2Two.java"), expected);
194     }
195 
196     @Test
197     public void testWithMultipleAnnotations() throws Exception {
198         final String[] expected = {
199             "18:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation11"),
200             "18:17: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation12"),
201             "18:33: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "MyAnnotation13"),
202         };
203         verifyWithInlineConfigParser(
204                 getPath("InputAnnotationLocationCustomAnnotationsDeclared.java"),
205                 expected);
206     }
207 
208     @Test
209     public void testAllTokens() throws Exception {
210         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
211         verifyWithInlineConfigParser(
212                 getPath("InputAnnotationLocationWithoutAnnotations.java"), expected);
213     }
214 
215     @Test
216     public void testAnnotation() throws Exception {
217         final String[] expected = {
218             "20:3: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "AnnotationAnnotation", 2, 0),
219             "21:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "AnnotationAnnotation"),
220             "24:7: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "AnnotationAnnotation", 6, 4),
221             "25:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "AnnotationAnnotation"),
222         };
223         verifyWithInlineConfigParser(
224                 getPath("InputAnnotationLocationAnnotation.java"), expected);
225     }
226 
227     @Test
228     public void testClass() throws Exception {
229         final String[] expected = {
230             "20:3: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "ClassAnnotation", 2, 0),
231             "21:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "ClassAnnotation"),
232             "24:7: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "ClassAnnotation", 6, 4),
233             "25:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "ClassAnnotation"),
234             "30:7: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "ClassAnnotation", 6, 4),
235             "31:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "ClassAnnotation"),
236         };
237         verifyWithInlineConfigParser(
238                 getPath("InputAnnotationLocationClass.java"), expected);
239     }
240 
241     @Test
242     public void testEnum() throws Exception {
243         final String[] expected = {
244             "18:3: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "EnumAnnotation", 2, 0),
245             "19:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "EnumAnnotation"),
246             "22:7: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "EnumAnnotation", 6, 4),
247             "23:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "EnumAnnotation"),
248         };
249         verifyWithInlineConfigParser(
250                 getPath("InputAnnotationLocationEnum.java"), expected);
251     }
252 
253     @Test
254     public void testInterface() throws Exception {
255         final String[] expected = {
256             "20:3: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "InterfaceAnnotation", 2, 0),
257             "21:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "InterfaceAnnotation"),
258             "26:7: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "InterfaceAnnotation", 6, 4),
259             "27:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "InterfaceAnnotation"),
260         };
261         verifyWithInlineConfigParser(
262                 getPath("InputAnnotationLocationInterface.java"), expected);
263     }
264 
265     @Test
266     public void testPackage() throws Exception {
267         final String[] expected = {
268             "14:3: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "PackageAnnotation", 2, 0),
269             "15:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "PackageAnnotation"),
270         };
271         verifyWithInlineConfigParser(
272                 getPath("inputs/package-info.java"), expected);
273     }
274 
275     @Test
276     public void testAnnotationInForEachLoopParameterAndVariableDef() throws Exception {
277         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
278         verifyWithInlineConfigParser(
279                 getPath("InputAnnotationLocationDeprecatedAndCustom.java"), expected);
280     }
281 
282     @Test
283     public void testAnnotationMultiple() throws Exception {
284         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
285         verifyWithInlineConfigParser(
286                 getPath("InputAnnotationLocationMultiple.java"), expected);
287     }
288 
289     @Test
290     public void testAnnotationParameterized() throws Exception {
291         final String[] expected = {
292             "19:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
293             "21:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
294             "21:17: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
295             "30:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
296             "30:17: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
297             "30:33: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
298             "37:21: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
299         };
300         verifyWithInlineConfigParser(
301                 getPath("InputAnnotationLocationParameterized.java"), expected);
302     }
303 
304     @Test
305     public void testAnnotationSingleParameterless() throws Exception {
306         final String[] expected = {
307             "24:17: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
308             "26:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
309             "28:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
310             "30:17: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
311             "30:33: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
312             "35:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
313             "35:21: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Annotation"),
314         };
315         verifyWithInlineConfigParser(
316                 getPath("InputAnnotationLocationSingleParameterless.java"), expected);
317     }
318 
319     @Test
320     public void testAnnotationLocationRecordsAndCompactCtors() throws Exception {
321         final String[] expected = {
322             "21:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
323             "25:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
324             "29:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
325             "31:9: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
326             "38:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
327             "50:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
328             "61:34: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
329         };
330         verifyWithInlineConfigParser(
331                 getPath("InputAnnotationLocationRecordsAndCompactCtors.java"),
332             expected);
333     }
334 
335     @Test
336     public void testAnnotationLocationOnLocalAndPatternVariables() throws Exception {
337         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
338         verifyWithInlineConfigParser(
339                 getNonCompilablePath("InputAnnotationLocationLocalAndPatternVariables.java"),
340             expected);
341     }
342 
343     @Test
344     public void testAnnotationLocationCompactSourceFile() throws Exception {
345         final String[] expected = {
346             "16:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
347             "29:1: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
348             "29:29: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "Deprecated"),
349             "32:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION, "Deprecated", 4, 0),
350             "43:5: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
351         };
352         verifyWithInlineConfigParser(
353                 getNonCompilablePath("InputAnnotationLocationCompactSourceFile.java"),
354             expected);
355     }
356 
357     @Test
358     public void testModuleAnnotationValid() throws Exception {
359         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
360         verifyWithInlineConfigParser(
361                 getNonCompilablePath("module-info/valid/module-info.java"), expected);
362     }
363 
364     @Test
365     public void testModuleAnnotationViolation() throws Exception {
366         final String[] expected = {
367             "14:13: " + getCheckMessage(MSG_KEY_ANNOTATION_LOCATION_ALONE, "SuppressWarnings"),
368         };
369         verifyWithInlineConfigParser(
370                 getNonCompilablePath("module-info/violation/module-info.java"), expected);
371     }
372 
373 }