View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 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.javadoc;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  
24  import java.lang.reflect.Method;
25  
26  import org.junit.jupiter.api.Test;
27  
28  import com.puppycrawl.tools.checkstyle.DetailAstImpl;
29  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
30  
31  public class JavadocTagInfoTest {
32  
33      /* Additional test for jacoco, since valueOf()
34       * is generated by javac and jacoco reports that
35       * valueOf() is uncovered.
36       */
37      @Test
38      public void testJavadocTagInfoValueOf() {
39          final JavadocTagInfo tag = JavadocTagInfo.valueOf("AUTHOR");
40          assertWithMessage("Invalid valueOf result")
41              .that(tag)
42              .isEqualTo(JavadocTagInfo.AUTHOR);
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 testTypeValueOf() {
51          final JavadocTagInfo.Type type = JavadocTagInfo.Type.valueOf("BLOCK");
52          assertWithMessage("Invalid valueOf result")
53              .that(type)
54              .isEqualTo(JavadocTagInfo.Type.BLOCK);
55      }
56  
57      /* Additional test for jacoco, since values()
58       * is generated by javac and jacoco reports that
59       * values() is uncovered.
60       */
61      @Test
62      public void testTypeValues() {
63          final JavadocTagInfo.Type[] expected = {
64              JavadocTagInfo.Type.BLOCK,
65              JavadocTagInfo.Type.INLINE,
66          };
67          final JavadocTagInfo.Type[] actual = JavadocTagInfo.Type.values();
68          assertWithMessage("Invalid Type values")
69              .that(actual)
70              .isEqualTo(expected);
71      }
72  
73      @Test
74      public void testAuthor() {
75          final DetailAstImpl ast = new DetailAstImpl();
76  
77          final int[] validTypes = {
78              TokenTypes.PACKAGE_DEF,
79              TokenTypes.CLASS_DEF,
80              TokenTypes.INTERFACE_DEF,
81              TokenTypes.ENUM_DEF,
82              TokenTypes.ANNOTATION_DEF,
83          };
84          for (int type: validTypes) {
85              ast.setType(type);
86              assertWithMessage("Invalid ast type for current tag: " + ast.getType())
87                      .that(JavadocTagInfo.AUTHOR.isValidOn(ast))
88                      .isTrue();
89          }
90  
91          ast.setType(TokenTypes.LAMBDA);
92          assertWithMessage("Should return false when ast type is invalid for current tag")
93                  .that(JavadocTagInfo.AUTHOR.isValidOn(ast))
94                  .isFalse();
95      }
96  
97      @Test
98      public void testOthers() throws ReflectiveOperationException {
99          final JavadocTagInfo[] tags = {
100             JavadocTagInfo.CODE,
101             JavadocTagInfo.DOC_ROOT,
102             JavadocTagInfo.LINK,
103             JavadocTagInfo.LINKPLAIN,
104             JavadocTagInfo.LITERAL,
105             JavadocTagInfo.SEE,
106             JavadocTagInfo.SINCE,
107             JavadocTagInfo.VALUE,
108         };
109         for (JavadocTagInfo tagInfo : tags) {
110             final DetailAstImpl astParent = new DetailAstImpl();
111             astParent.setType(TokenTypes.LITERAL_CATCH);
112 
113             final DetailAstImpl ast = new DetailAstImpl();
114             final Method setParent = ast.getClass().getDeclaredMethod("setParent",
115                     DetailAstImpl.class);
116             setParent.setAccessible(true);
117             setParent.invoke(ast, astParent);
118 
119             final int[] validTypes = {
120                 TokenTypes.PACKAGE_DEF,
121                 TokenTypes.CLASS_DEF,
122                 TokenTypes.INTERFACE_DEF,
123                 TokenTypes.ENUM_DEF,
124                 TokenTypes.ANNOTATION_DEF,
125                 TokenTypes.METHOD_DEF,
126                 TokenTypes.CTOR_DEF,
127                 TokenTypes.VARIABLE_DEF,
128             };
129             for (int type: validTypes) {
130                 ast.setType(type);
131                 assertWithMessage("Invalid ast type for current tag: " + ast.getType())
132                         .that(tagInfo.isValidOn(ast))
133                         .isTrue();
134             }
135 
136             astParent.setType(TokenTypes.SLIST);
137             ast.setType(TokenTypes.VARIABLE_DEF);
138             assertWithMessage("Should return false when ast type is invalid for current tag")
139                     .that(tagInfo.isValidOn(ast))
140                     .isFalse();
141 
142             ast.setType(TokenTypes.PARAMETER_DEF);
143             assertWithMessage("Should return false when ast type is invalid for current tag")
144                     .that(tagInfo.isValidOn(ast))
145                     .isFalse();
146         }
147     }
148 
149     @Test
150     public void testDeprecated() throws ReflectiveOperationException {
151         final DetailAstImpl ast = new DetailAstImpl();
152         final DetailAstImpl astParent = new DetailAstImpl();
153         astParent.setType(TokenTypes.LITERAL_CATCH);
154         final Method setParent = ast.getClass().getDeclaredMethod("setParent", DetailAstImpl.class);
155         setParent.setAccessible(true);
156         setParent.invoke(ast, astParent);
157 
158         final int[] validTypes = {
159             TokenTypes.CLASS_DEF,
160             TokenTypes.INTERFACE_DEF,
161             TokenTypes.ENUM_DEF,
162             TokenTypes.ANNOTATION_DEF,
163             TokenTypes.METHOD_DEF,
164             TokenTypes.CTOR_DEF,
165             TokenTypes.ENUM_CONSTANT_DEF,
166             TokenTypes.ANNOTATION_FIELD_DEF,
167             TokenTypes.VARIABLE_DEF,
168         };
169         for (int type: validTypes) {
170             ast.setType(type);
171             assertWithMessage("Invalid ast type for current tag: " + ast.getType())
172                     .that(JavadocTagInfo.DEPRECATED.isValidOn(ast))
173                     .isTrue();
174         }
175 
176         astParent.setType(TokenTypes.SLIST);
177         ast.setType(TokenTypes.VARIABLE_DEF);
178         assertWithMessage("Should return false when ast type is invalid for current tag")
179                 .that(JavadocTagInfo.DEPRECATED.isValidOn(ast))
180                 .isFalse();
181 
182         ast.setType(TokenTypes.PARAMETER_DEF);
183         assertWithMessage("Should return false when ast type is invalid for current tag")
184                 .that(JavadocTagInfo.DEPRECATED.isValidOn(ast))
185                 .isFalse();
186     }
187 
188     @Test
189     public void testSerial() throws ReflectiveOperationException {
190         final DetailAstImpl ast = new DetailAstImpl();
191         final DetailAstImpl astParent = new DetailAstImpl();
192         astParent.setType(TokenTypes.LITERAL_CATCH);
193         final Method setParent = ast.getClass().getDeclaredMethod("setParent", DetailAstImpl.class);
194         setParent.setAccessible(true);
195         setParent.invoke(ast, astParent);
196 
197         final int[] validTypes = {
198             TokenTypes.VARIABLE_DEF,
199         };
200         for (int type: validTypes) {
201             ast.setType(type);
202             assertWithMessage("Invalid ast type for current tag: " + ast.getType())
203                     .that(JavadocTagInfo.SERIAL.isValidOn(ast))
204                     .isTrue();
205         }
206 
207         astParent.setType(TokenTypes.SLIST);
208         ast.setType(TokenTypes.VARIABLE_DEF);
209         assertWithMessage("Should return false when ast type is invalid for current tag")
210                 .that(JavadocTagInfo.SERIAL.isValidOn(ast))
211                 .isFalse();
212 
213         ast.setType(TokenTypes.PARAMETER_DEF);
214         assertWithMessage("Should return false when ast type is invalid for current tag")
215                 .that(JavadocTagInfo.SERIAL.isValidOn(ast))
216                 .isFalse();
217     }
218 
219     @Test
220     public void testException() {
221         final DetailAstImpl ast = new DetailAstImpl();
222 
223         final int[] validTypes = {
224             TokenTypes.METHOD_DEF,
225             TokenTypes.CTOR_DEF,
226         };
227         for (int type: validTypes) {
228             ast.setType(type);
229             assertWithMessage("Invalid ast type for current tag: " + ast.getType())
230                     .that(JavadocTagInfo.EXCEPTION.isValidOn(ast))
231                     .isTrue();
232         }
233 
234         ast.setType(TokenTypes.LAMBDA);
235         assertWithMessage("Should return false when ast type is invalid for current tag")
236                 .that(JavadocTagInfo.EXCEPTION.isValidOn(ast))
237                 .isFalse();
238     }
239 
240     @Test
241     public void testThrows() {
242         final DetailAstImpl ast = new DetailAstImpl();
243 
244         final int[] validTypes = {
245             TokenTypes.METHOD_DEF,
246             TokenTypes.CTOR_DEF,
247         };
248         for (int type: validTypes) {
249             ast.setType(type);
250             assertWithMessage("Invalid ast type for current tag: " + ast.getType())
251                     .that(JavadocTagInfo.THROWS.isValidOn(ast))
252                     .isTrue();
253         }
254 
255         ast.setType(TokenTypes.LAMBDA);
256         assertWithMessage("Should return false when ast type is invalid for current tag")
257                 .that(JavadocTagInfo.THROWS.isValidOn(ast))
258                 .isFalse();
259     }
260 
261     @Test
262     public void testVersions() {
263         final DetailAstImpl ast = new DetailAstImpl();
264 
265         final int[] validTypes = {
266             TokenTypes.PACKAGE_DEF,
267             TokenTypes.CLASS_DEF,
268             TokenTypes.INTERFACE_DEF,
269             TokenTypes.ENUM_DEF,
270             TokenTypes.ANNOTATION_DEF,
271         };
272         for (int type: validTypes) {
273             ast.setType(type);
274             assertWithMessage("Invalid ast type for current tag: " + ast.getType())
275                     .that(JavadocTagInfo.VERSION.isValidOn(ast))
276                     .isTrue();
277         }
278 
279         ast.setType(TokenTypes.LAMBDA);
280         assertWithMessage("Should return false when ast type is invalid for current tag")
281                 .that(JavadocTagInfo.VERSION.isValidOn(ast))
282                 .isFalse();
283     }
284 
285     @Test
286     public void testParam() {
287         final DetailAstImpl ast = new DetailAstImpl();
288 
289         final int[] validTypes = {
290             TokenTypes.CLASS_DEF,
291             TokenTypes.INTERFACE_DEF,
292             TokenTypes.METHOD_DEF,
293             TokenTypes.CTOR_DEF,
294         };
295         for (int type: validTypes) {
296             ast.setType(type);
297             assertWithMessage("Invalid ast type for current tag: " + ast.getType())
298                     .that(JavadocTagInfo.PARAM.isValidOn(ast))
299                     .isTrue();
300         }
301 
302         ast.setType(TokenTypes.LAMBDA);
303         assertWithMessage("Should return false when ast type is invalid for current tag")
304                 .that(JavadocTagInfo.PARAM.isValidOn(ast))
305                 .isFalse();
306     }
307 
308     @Test
309     public void testReturn() {
310         final DetailAstImpl ast = new DetailAstImpl();
311         final DetailAstImpl astChild = new DetailAstImpl();
312         astChild.setType(TokenTypes.TYPE);
313         ast.setFirstChild(astChild);
314         final DetailAstImpl astChild2 = new DetailAstImpl();
315         astChild2.setType(TokenTypes.LITERAL_INT);
316         astChild.setFirstChild(astChild2);
317 
318         final int[] validTypes = {
319             TokenTypes.METHOD_DEF,
320         };
321         for (int type: validTypes) {
322             ast.setType(type);
323             assertWithMessage("Invalid ast type for current tag: " + ast.getType())
324                     .that(JavadocTagInfo.RETURN.isValidOn(ast))
325                     .isTrue();
326         }
327 
328         astChild2.setType(TokenTypes.LITERAL_VOID);
329         assertWithMessage("Should return false when ast type is invalid for current tag")
330                 .that(JavadocTagInfo.RETURN.isValidOn(ast))
331                 .isFalse();
332 
333         ast.setType(TokenTypes.LAMBDA);
334         assertWithMessage("Should return false when ast type is invalid for current tag")
335                 .that(JavadocTagInfo.RETURN.isValidOn(ast))
336                 .isFalse();
337     }
338 
339     @Test
340     public void testSerialField() {
341         final DetailAstImpl ast = new DetailAstImpl();
342         final DetailAstImpl astChild = new DetailAstImpl();
343         astChild.setType(TokenTypes.TYPE);
344         ast.setFirstChild(astChild);
345         final DetailAstImpl astChild2 = new DetailAstImpl();
346         astChild2.setType(TokenTypes.ARRAY_DECLARATOR);
347         astChild2.setText("ObjectStreamField");
348         astChild.setFirstChild(astChild2);
349 
350         final int[] validTypes = {
351             TokenTypes.VARIABLE_DEF,
352         };
353         for (int type: validTypes) {
354             ast.setType(type);
355             assertWithMessage("Invalid ast type for current tag: " + ast.getType())
356                     .that(JavadocTagInfo.SERIAL_FIELD.isValidOn(ast))
357                     .isTrue();
358         }
359 
360         astChild2.setText("1111");
361         assertWithMessage("Should return false when ast type is invalid for current tag")
362                 .that(JavadocTagInfo.SERIAL_FIELD.isValidOn(ast))
363                 .isFalse();
364 
365         astChild2.setType(TokenTypes.LITERAL_VOID);
366         assertWithMessage("Should return false when ast type is invalid for current tag")
367                 .that(JavadocTagInfo.SERIAL_FIELD.isValidOn(ast))
368                 .isFalse();
369 
370         ast.setType(TokenTypes.LAMBDA);
371         assertWithMessage("Should return false when ast type is invalid for current tag")
372                 .that(JavadocTagInfo.SERIAL_FIELD.isValidOn(ast))
373                 .isFalse();
374     }
375 
376     @Test
377     public void testSerialData() {
378         final DetailAstImpl ast = new DetailAstImpl();
379         ast.setType(TokenTypes.METHOD_DEF);
380         final DetailAstImpl astChild = new DetailAstImpl();
381         astChild.setType(TokenTypes.IDENT);
382         astChild.setText("writeObject");
383         ast.setFirstChild(astChild);
384 
385         final String[] validNames = {
386             "writeObject",
387             "readObject",
388             "writeExternal",
389             "readExternal",
390             "writeReplace",
391             "readResolve",
392         };
393         for (String name: validNames) {
394             astChild.setText(name);
395             assertWithMessage("Invalid ast type for current tag: " + ast.getType())
396                     .that(JavadocTagInfo.SERIAL_DATA.isValidOn(ast))
397                     .isTrue();
398         }
399 
400         astChild.setText("1111");
401         assertWithMessage("Should return false when ast type is invalid for current tag")
402                 .that(JavadocTagInfo.SERIAL_DATA.isValidOn(ast))
403                 .isFalse();
404 
405         ast.setType(TokenTypes.LAMBDA);
406         assertWithMessage("Should return false when ast type is invalid for current tag")
407                 .that(JavadocTagInfo.SERIAL_DATA.isValidOn(ast))
408                 .isFalse();
409     }
410 
411     @Test
412     public void testCoverage() {
413         assertWithMessage("Invalid type")
414             .that(JavadocTagInfo.VERSION.getType())
415             .isEqualTo(JavadocTagInfo.Type.BLOCK);
416 
417         assertWithMessage("Invalid toString result")
418             .that(JavadocTagInfo.VERSION.toString())
419             .isEqualTo("text [@version] name [version] type [BLOCK]");
420 
421         try {
422             JavadocTagInfo.fromName(null);
423             assertWithMessage("IllegalArgumentException is expected").fail();
424         }
425         catch (IllegalArgumentException ex) {
426             assertWithMessage("Invalid exception message")
427                 .that(ex.getMessage())
428                 .isEqualTo("the name is null");
429         }
430 
431         try {
432             JavadocTagInfo.fromName("myname");
433             assertWithMessage("IllegalArgumentException is expected").fail();
434         }
435         catch (IllegalArgumentException ex) {
436             assertWithMessage("Invalid exception message")
437                 .that(ex.getMessage())
438                 .isEqualTo("the name [myname] is not a valid Javadoc tag name");
439         }
440 
441         try {
442             JavadocTagInfo.fromText(null);
443             assertWithMessage("IllegalArgumentException is expected").fail();
444         }
445         catch (IllegalArgumentException ex) {
446             assertWithMessage("Invalid exception message")
447                 .that(ex.getMessage())
448                 .isEqualTo("the text is null");
449         }
450 
451         try {
452             JavadocTagInfo.fromText("myname");
453             assertWithMessage("IllegalArgumentException is expected").fail();
454         }
455         catch (IllegalArgumentException ex) {
456             assertWithMessage("Invalid exception message")
457                 .that(ex.getMessage())
458                 .isEqualTo("the text [myname] is not a valid Javadoc tag text");
459         }
460 
461         assertWithMessage("Invalid fromText result")
462             .that(JavadocTagInfo.fromText("@version"))
463             .isEqualTo(JavadocTagInfo.VERSION);
464     }
465 
466 }