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.AnnotationUseStyleCheck.MSG_KEY_ANNOTATION_INCORRECT_STYLE;
24  import static com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.MSG_KEY_ANNOTATION_PARENS_MISSING;
25  import static com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.MSG_KEY_ANNOTATION_PARENS_PRESENT;
26  import static com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING;
27  import static com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck.MSG_KEY_ANNOTATION_TRAILING_COMMA_PRESENT;
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.api.TokenTypes;
34  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
35  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
36  import de.thetaphi.forbiddenapis.SuppressForbidden;
37  
38  public class AnnotationUseStyleCheckTest extends AbstractModuleTestSupport {
39  
40      @Override
41      public String getPackageLocation() {
42          return "com/puppycrawl/tools/checkstyle/checks/annotation/annotationusestyle";
43      }
44  
45      /* Additional test for jacoco, since valueOf()
46       * is generated by javac and jacoco reports that
47       * valueOf() is uncovered.
48       */
49      @Test
50      public void testElementStyleOptionValueOf() {
51          final AnnotationUseStyleCheck.ElementStyleOption option =
52              AnnotationUseStyleCheck.ElementStyleOption.valueOf("COMPACT");
53          assertWithMessage("Invalid valueOf result")
54              .that(option)
55              .isEqualTo(AnnotationUseStyleCheck.ElementStyleOption.COMPACT);
56      }
57  
58      /* Additional test for jacoco, since valueOf()
59       * is generated by javac and jacoco reports that
60       * valueOf() is uncovered.
61       */
62      @Test
63      public void testTrailingArrayCommaOptionValueOf() {
64          final AnnotationUseStyleCheck.TrailingArrayCommaOption option =
65              AnnotationUseStyleCheck.TrailingArrayCommaOption.valueOf("ALWAYS");
66          assertWithMessage("Invalid valueOf result")
67              .that(option)
68              .isEqualTo(AnnotationUseStyleCheck.TrailingArrayCommaOption.ALWAYS);
69      }
70  
71      /* Additional test for jacoco, since valueOf()
72       * is generated by javac and jacoco reports that
73       * valueOf() is uncovered.
74       */
75      @Test
76      public void testClosingParensOptionValueOf() {
77          final AnnotationUseStyleCheck.ClosingParensOption option =
78              AnnotationUseStyleCheck.ClosingParensOption.valueOf("ALWAYS");
79          assertWithMessage("Invalid valueOf result")
80              .that(option)
81              .isEqualTo(AnnotationUseStyleCheck.ClosingParensOption.ALWAYS);
82      }
83  
84      /**
85       * Additional test for checking whether the properties in the configuration are set correctly
86       * when there is whitespace around them. Not possible to check with the inline config parser
87       * as it trims the whitespace around properties while setting them.
88       *
89       * @throws Exception exception
90       */
91      @SuppressForbidden
92      @Test
93      public void testNonTrimmedInput() throws Exception {
94          final DefaultConfiguration configuration =
95              createModuleConfig(AnnotationUseStyleCheck.class);
96          configuration.addProperty("elementStyle", "ignore");
97          configuration.addProperty("closingParens", " ignore  ");
98          configuration.addProperty("trailingArrayComma", " always");
99          final String filePath = getPath("InputAnnotationUseStyleWithTrailingComma.java");
100         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
101 
102         verify(configuration, filePath, expected);
103     }
104 
105     @Test
106     public void testDefault() throws Exception {
107         final String[] expected = {
108             "13:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
109             "14:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
110             "21:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
111             "23:1: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
112             "29:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
113             "30:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
114             "35:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
115             "42:1: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
116             "45:5: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
117             "53:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
118             "55:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
119             "59:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
120             "88:32: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
121             "91:40: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
122         };
123 
124         verifyWithInlineConfigParser(
125                 getPath("InputAnnotationUseStyleDifferentStyles.java"), expected);
126     }
127 
128     /**
129      * Test that annotation parens are always present.
130      */
131     @Test
132     public void testParensAlways() throws Exception {
133         final String[] expected = {
134             "12:1: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_MISSING),
135             "27:1: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_MISSING),
136             "32:5: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_MISSING),
137             "80:32: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_MISSING),
138             "83:40: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_MISSING),
139             "91:9: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_MISSING),
140             "91:31: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_MISSING),
141         };
142 
143         verifyWithInlineConfigParser(
144                 getPath("InputAnnotationUseStyleWithParens.java"), expected);
145     }
146 
147     /**
148      * Test that annotation parens are never present.
149      */
150     @Test
151     public void testParensNever() throws Exception {
152         final String[] expected = {
153             "22:1: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
154             "40:1: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
155             "43:5: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
156             "86:32: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
157             "89:40: " + getCheckMessage(MSG_KEY_ANNOTATION_PARENS_PRESENT),
158         };
159 
160         verifyWithInlineConfigParser(
161                 getPath("InputAnnotationUseStyleNoParens.java"), expected);
162     }
163 
164     @Test
165     public void testStyleExpanded() throws Exception {
166         final String[] expected = {
167             "14:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
168             "21:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
169             "29:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
170             "35:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
171             "48:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
172             "50:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
173             "67:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
174             "72:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
175             "80:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
176             "84:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "EXPANDED"),
177         };
178 
179         verifyWithInlineConfigParser(
180                 getPath("InputAnnotationUseStyleExpanded.java"), expected);
181     }
182 
183     @Test
184     public void testStyleCompact() throws Exception {
185         final String[] expected = {
186             "52:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT"),
187             "56:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT"),
188             "76:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT"),
189             "83:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT"),
190             "88:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT"),
191         };
192 
193         verifyWithInlineConfigParser(
194                 getPath("InputAnnotationUseStyleCompact.java"), expected);
195     }
196 
197     @Test
198     public void testStyleCompactNoArray() throws Exception {
199         final String[] expected = {
200             "13:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
201             "14:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
202             "21:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
203             "29:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
204             "30:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
205             "35:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
206             "52:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
207             "54:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
208             "58:1: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
209         };
210 
211         verifyWithInlineConfigParser(
212                 getPath("InputAnnotationUseStyleCompactNoArray.java"), expected);
213     }
214 
215     @Test
216     public void testCommaAlwaysViolations() throws Exception {
217         final String[] expected = {
218             "12:20: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
219             "15:30: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
220             "20:40: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
221             "24:45: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
222             "28:55: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
223             "36:22: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
224             "36:36: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
225             "38:21: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
226             "38:30: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
227             "41:39: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
228             "41:49: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
229             "44:21: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
230             "44:41: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
231         };
232 
233         verifyWithInlineConfigParser(
234                 getPath("InputAnnotationUseStyleNoTrailingComma.java"), expected);
235     }
236 
237     @Test
238     public void testCommaAlwaysViolationsNonCompilable() throws Exception {
239         final String[] expected = {
240             "15:37: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
241             "15:65: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_MISSING),
242         };
243 
244         verifyWithInlineConfigParser(
245                 getNonCompilablePath("InputAnnotationUseStyleNoTrailingComma.java"), expected);
246     }
247 
248     @Test
249     public void testCommaAlwaysNoViolations() throws Exception {
250         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
251 
252         verifyWithInlineConfigParser(
253                 getPath("InputAnnotationUseStyleWithTrailingComma.java"), expected);
254     }
255 
256     @Test
257     public void testCommaAlwaysNoViolationsNonCompilable() throws Exception {
258         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
259 
260         verifyWithInlineConfigParser(
261                 getNonCompilablePath("InputAnnotationUseStyleWithTrailingComma.java"), expected);
262     }
263 
264     @Test
265     public void testTrailingArrayIgnore() throws Exception {
266         final String[] expected = {
267             "15:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
268             "23:13: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
269             "35:5: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
270             "42:9: " + getCheckMessage(MSG_KEY_ANNOTATION_INCORRECT_STYLE, "COMPACT_NO_ARRAY"),
271         };
272 
273         verifyWithInlineConfigParser(
274                 getPath("InputAnnotationUseStyleWithTrailingCommaIgnore.java"), expected);
275     }
276 
277     @Test
278     public void testCommaNeverViolations() throws Exception {
279         final String[] expected = {
280             "16:32: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_PRESENT),
281             "21:42: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_PRESENT),
282             "25:46: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_PRESENT),
283             "29:56: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_PRESENT),
284             "37:24: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_PRESENT),
285             "37:39: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_PRESENT),
286             "43:41: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_PRESENT),
287             "43:52: " + getCheckMessage(MSG_KEY_ANNOTATION_TRAILING_COMMA_PRESENT),
288         };
289 
290         verifyWithInlineConfigParser(
291                 getPath("InputAnnotationUseStyleWithTrailingCommaNever.java"), expected);
292     }
293 
294     @Test
295     public void testCommaNeverNoViolations() throws Exception {
296         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
297 
298         verifyWithInlineConfigParser(
299                 getPath("InputAnnotationUseStyleNoTrailingCommaNever.java"), expected);
300     }
301 
302     @Test
303     public void testEverythingMixed() throws Exception {
304         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
305 
306         verifyWithInlineConfigParser(
307                 getPath("InputAnnotationUseStyleEverythingMixed.java"), expected);
308     }
309 
310     @Test
311     public void testAnnotationsWithoutDefaultValues() throws Exception {
312         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
313 
314         verifyWithInlineConfigParser(
315                 getPath("InputAnnotationUseStyleParams.java"), expected);
316     }
317 
318     @Test
319     public void testGetAcceptableTokens() {
320         final AnnotationUseStyleCheck constantNameCheckObj = new AnnotationUseStyleCheck();
321         final int[] actual = constantNameCheckObj.getAcceptableTokens();
322         final int[] expected = {TokenTypes.ANNOTATION };
323         assertWithMessage("Invalid acceptable tokens")
324             .that(actual)
325             .isEqualTo(expected);
326     }
327 
328     @Test
329     public void testGetOption() {
330         final AnnotationUseStyleCheck check = new AnnotationUseStyleCheck();
331         final IllegalArgumentException exc =
332             TestUtil.getExpectedThrowable(
333                 IllegalArgumentException.class, () -> {
334                     check.setElementStyle(
335                         "SHOULD_PRODUCE_ERROR");
336                 });
337         final String messageStart = "unable to parse";
338 
339         assertWithMessage("Invalid exception message, "
340                 + "should start with: " + messageStart)
341                 .that(exc.getMessage())
342                 .startsWith(messageStart);
343     }
344 
345     @Test
346     public void testStyleNotInList() throws Exception {
347         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
348 
349         verifyWithInlineConfigParser(
350                 getPath("InputAnnotationUseStyle.java"), expected);
351     }
352 
353 }