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.javadoc;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocTypeCheck.MSG_JAVADOC_MISSING;
24  
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import org.junit.jupiter.api.Test;
29  
30  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
31  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
32  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
33  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
34  
35  public class MissingJavadocTypeCheckTest extends AbstractModuleTestSupport {
36  
37      @Override
38      public String getPackageLocation() {
39          return "com/puppycrawl/tools/checkstyle/checks/javadoc/missingjavadoctype";
40      }
41  
42      @Test
43      public void testGetRequiredTokens() {
44          final MissingJavadocTypeCheck missingJavadocTypeCheck = new MissingJavadocTypeCheck();
45          missingJavadocTypeCheck.visitJavadocToken(null);
46          assertWithMessage(
47                  "MissingJavadocTypeCheck#getRequiredTokens should return empty array by default")
48                          .that(missingJavadocTypeCheck.getRequiredTokens())
49                          .isEmpty();
50      }
51  
52      @Test
53      public void testGetAcceptableTokens() {
54          final MissingJavadocTypeCheck missingJavadocTypeCheck = new MissingJavadocTypeCheck();
55  
56          final int[] actual = missingJavadocTypeCheck.getAcceptableTokens();
57          final int[] expected = {
58              TokenTypes.INTERFACE_DEF,
59              TokenTypes.CLASS_DEF,
60              TokenTypes.ENUM_DEF,
61              TokenTypes.ANNOTATION_DEF,
62              TokenTypes.RECORD_DEF,
63          };
64  
65          assertWithMessage("Default acceptable tokens are invalid")
66                  .that(actual)
67                  .isEqualTo(expected);
68      }
69  
70      @Test
71      public void testTagsOne() throws Exception {
72          final String[] expected = {
73              "16:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeTags1One"),
74              "47:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputJavadocTypeTagsEnum"),
75              "73:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputJavadocTypeTagsAnnotation"),
76          };
77          verifyWithInlineConfigParser(
78                  getPath("InputMissingJavadocTypeTagsOne.java"), expected);
79      }
80  
81      @Test
82      public void testTagsTwo() throws Exception {
83          final String[] expected = {
84              "22:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeTags1Two"),
85          };
86          verifyWithInlineConfigParser(
87                  getPath("InputMissingJavadocTypeTagsTwo.java"), expected);
88      }
89  
90      @Test
91      public void testTagsThree() throws Exception {
92          final String[] expected = {
93              "22:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeTags1Three"),
94          };
95          verifyWithInlineConfigParser(
96                  getPath("InputMissingJavadocTypeTagsThree.java"), expected);
97      }
98  
99      @Test
100     public void testTagsFour() throws Exception {
101         final String[] expected = {
102             "22:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeTags1Four"),
103         };
104         verifyWithInlineConfigParser(
105                 getPath("InputMissingJavadocTypeTagsFour.java"), expected);
106     }
107 
108     @Test
109     public void testInner() throws Exception {
110         final String[] expected = {
111             "21:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerInner2"),
112             "29:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerInterface2"),
113             "36:9: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerInterfaceInnerClass"),
114         };
115         verifyWithInlineConfigParser(
116                 getPath("InputMissingJavadocTypeInner.java"), expected);
117     }
118 
119     @Test
120     public void testMissingJavadocTypePublicOnly1One() throws Exception {
121         final String[] expected = {
122             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
123                     "InputMissingJavadocTypePublicOnly1One"),
124             "18:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerInterface"),
125             "24:9: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerInnerClass"),
126             "45:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerClass"),
127         };
128         verifyWithInlineConfigParser(
129                 getPath("InputMissingJavadocTypePublicOnly1One.java"), expected);
130     }
131 
132     @Test
133     public void testMissingJavadocTypePublicOnly1Two() throws Exception {
134         final String[] expected = {
135             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
136                     "InputMissingJavadocTypePublicOnly1Two"),
137         };
138         verifyWithInlineConfigParser(
139                 getPath("InputMissingJavadocTypePublicOnly1Two.java"), expected);
140     }
141 
142     @Test
143     public void testMissingJavadocTypePublicOnly2One() throws Exception {
144         final String[] expected = {
145             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
146                     "InputMissingJavadocTypePublicOnly2One"),
147         };
148         verifyWithInlineConfigParser(
149                 getPath("InputMissingJavadocTypePublicOnly2One.java"), expected);
150     }
151 
152     @Test
153     public void testMissingJavadocTypePublicOnly2Two() throws Exception {
154         final String[] expected = {
155             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
156                     "InputMissingJavadocTypePublicOnly2Two"),
157         };
158         verifyWithInlineConfigParser(
159                 getPath("InputMissingJavadocTypePublicOnly2Two.java"), expected);
160     }
161 
162     @Test
163     public void testPublic() throws Exception {
164         final String[] expected = {
165             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
166                     "InputMissingJavadocTypeScopeInnerInterfaces1"),
167             "47:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PublicInnerInterface"),
168         };
169         verifyWithInlineConfigParser(
170                 getPath("InputMissingJavadocTypeScopeInnerInterfaces1.java"),
171                expected);
172     }
173 
174     @Test
175     public void testProtest() throws Exception {
176         final String[] expected = {
177             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
178                     "InputMissingJavadocTypeScopeInnerInterfaces2"),
179             "38:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "ProtectedInnerInterface"),
180             "48:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PublicInnerInterface"),
181             "76:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "MyEnum"),
182         };
183         verifyWithInlineConfigParser(
184                 getPath("InputMissingJavadocTypeScopeInnerInterfaces2.java"),
185                expected);
186     }
187 
188     @Test
189     public void testPkg() throws Exception {
190         final String[] expected = {
191             "24:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerPublic"),
192             "27:9: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerProtected"),
193             "30:13: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerPackage"),
194         };
195         verifyWithInlineConfigParser(
196                 getPath("InputMissingJavadocTypeScopeInnerClasses1.java"), expected);
197     }
198 
199     @Test
200     public void testEclipse() throws Exception {
201         final String[] expected = {
202             "24:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerPublic"),
203         };
204         verifyWithInlineConfigParser(
205                 getPath("InputMissingJavadocTypeScopeInnerClasses2.java"), expected);
206     }
207 
208     @Test
209     public void testScopesOne() throws Exception {
210         final String[] expected = {
211             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeNoJavadoc1One"),
212             "28:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "ProtectedInner"),
213             "41:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PackageInner"),
214             "54:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PrivateInner"),
215         };
216         verifyWithInlineConfigParser(
217                 getPath("InputMissingJavadocTypeNoJavadoc1One.java"),
218                expected);
219     }
220 
221     @Test
222     public void testScopesTwo() throws Exception {
223         final String[] expected = {
224             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeNoJavadoc1Two"),
225             "18:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "PackageClass1"),
226             "30:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PublicInner"),
227             "43:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "ProtectedInner"),
228             "56:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PackageInner"),
229             "69:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PrivateInner"),
230             "82:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "IgnoredName"),
231         };
232         verifyWithInlineConfigParser(
233                 getPath("InputMissingJavadocTypeNoJavadoc1Two.java"),
234                expected);
235     }
236 
237     @Test
238     public void testLimitViolationsBySpecifyingTokens() throws Exception {
239         final String[] expected = {
240             "17:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "NoJavadoc"),
241         };
242         verifyWithInlineConfigParser(
243                 getPath("InputMissingJavadocTypeNoJavadocOnInterface.java"),
244                expected);
245     }
246 
247     @Test
248     public void testMissingJavadocTypeNoJavadoc2One() throws Exception {
249         final String[] expected = {
250             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeNoJavadoc2One"),
251             "28:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "ProtectedInner"),
252         };
253         verifyWithInlineConfigParser(
254                 getPath("InputMissingJavadocTypeNoJavadoc2One.java"),
255                expected);
256     }
257 
258     @Test
259     public void testMissingJavadocTypeNoJavadoc2Two() throws Exception {
260         final String[] expected = {
261             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeNoJavadoc2Two"),
262         };
263         verifyWithInlineConfigParser(
264                 getPath("InputMissingJavadocTypeNoJavadoc2Two.java"),
265                expected);
266     }
267 
268     @Test
269     public void testMissingJavadocTypeNoJavadoc3One() throws Exception {
270         final String[] expected = {
271             "39:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PackageInner"),
272             "52:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PrivateInner"),
273         };
274         verifyWithInlineConfigParser(
275                 getPath("InputMissingJavadocTypeNoJavadoc3One.java"),
276                expected);
277     }
278 
279     @Test
280     public void testMissingJavadocTypeNoJavadoc3Two() throws Exception {
281         final String[] expected = {
282             "17:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "PackageClass3"),
283             "29:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PublicInner"),
284             "42:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "ProtectedInner"),
285             "55:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PackageInner"),
286             "68:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "PrivateInner"),
287             "81:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "IgnoredName"),
288         };
289         verifyWithInlineConfigParser(
290                 getPath("InputMissingJavadocTypeNoJavadoc3Two.java"),
291                expected);
292     }
293 
294     @Test
295     public void testSkipAnnotationsDefault() throws Exception {
296 
297         final String[] expected = {
298             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
299                     "InputMissingJavadocTypeSkipAnnotations1"),
300             "20:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
301                     "InputJavadocTypeSkipAnnotationsFullyQualifiedName1"),
302             "25:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
303                     "InputJavadocTypeAllowedAnnotationByDefault1"),
304         };
305         verifyWithInlineConfigParser(
306                 getPath("InputMissingJavadocTypeSkipAnnotations1.java"),
307             expected);
308     }
309 
310     @Test
311     public void testSkipAnnotationsWithFullyQualifiedName() throws Exception {
312         final String[] expected = {
313             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
314                     "InputMissingJavadocTypeSkipAnnotations2"),
315             "20:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
316                     "InputJavadocTypeSkipAnnotationsFullyQualifiedName2"),
317             "25:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
318                     "InputJavadocTypeAllowedAnnotationByDefault2"),
319         };
320         verifyWithInlineConfigParser(
321                 getPath("InputMissingJavadocTypeSkipAnnotations2.java"),
322                 expected);
323     }
324 
325     @Test
326     public void testSkipAnnotationsAllowed() throws Exception {
327 
328         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
329         verifyWithInlineConfigParser(
330                 getPath("InputMissingJavadocTypeSkipAnnotations3.java"),
331             expected);
332     }
333 
334     @Test
335     public void testSkipAnnotationsNotAllowed() throws Exception {
336 
337         final String[] expected = {
338             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
339                     "InputMissingJavadocTypeSkipAnnotations4"),
340             "20:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
341                     "InputJavadocTypeSkipAnnotationsFullyQualifiedName4"),
342             "25:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
343                     "InputJavadocTypeAllowedAnnotationByDefault4"),
344         };
345         verifyWithInlineConfigParser(
346                 getPath("InputMissingJavadocTypeSkipAnnotations4.java"),
347             expected);
348     }
349 
350     @Test
351     public void testMissingJavadocTypeCheckRecords() throws Exception {
352 
353         final String[] expected = {
354             "16:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeRecords"),
355             "18:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "TestClass"),
356             "23:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "MyRecord1"),
357             "28:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "MyRecord2"),
358             "37:9: " + getCheckMessage(MSG_JAVADOC_MISSING, "MyRecord4"),
359             "39:13: " + getCheckMessage(MSG_JAVADOC_MISSING, "MyRecord5"),
360             "49:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "NonNull1"),
361         };
362         verifyWithInlineConfigParser(
363                 getPath("InputMissingJavadocTypeRecords.java"),
364             expected);
365     }
366 
367     @Test
368     public void testInterfaceMemberScopeIsPublic() throws Exception {
369 
370         final String[] expected = {
371             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
372                     "InputMissingJavadocTypeInterfaceMemberScopeIsPublic"),
373             "18:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "Enum"),
374             "23:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "Class"),
375         };
376         verifyWithInlineConfigParser(
377                 getPath("InputMissingJavadocTypeInterfaceMemberScopeIsPublic.java"),
378             expected);
379     }
380 
381     @Test
382     public void testQualifiedAnnotation1() throws Exception {
383         final String[] expected = {
384             "18:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "A"),
385             "22:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "B"),
386             "26:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "C"),
387         };
388         verifyWithInlineConfigParser(
389             getPath("InputMissingJavadocTypeQualifiedAnnotation1.java"), expected);
390     }
391 
392     @Test
393     public void testQualifiedAnnotation2() throws Exception {
394         final String[] expected = {
395             "21:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "B"),
396             "25:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "C"),
397         };
398         verifyWithInlineConfigParser(
399             getPath("InputMissingJavadocTypeQualifiedAnnotation2.java"), expected);
400     }
401 
402     @Test
403     public void testQualifiedAnnotation3() throws Exception {
404         final String[] expected = {
405             "18:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "A"),
406             "25:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "C"),
407         };
408         verifyWithInlineConfigParser(
409             getPath("InputMissingJavadocTypeQualifiedAnnotation3.java"), expected);
410     }
411 
412     @Test
413     public void testQualifiedAnnotation4() throws Exception {
414         final String[] expected = {
415             "19:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "A"),
416             "23:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "B"),
417         };
418         verifyWithInlineConfigParser(
419             getPath("InputMissingJavadocTypeQualifiedAnnotation4.java"), expected);
420     }
421 
422     @Test
423     public void testQualifiedAnnotation5() throws Exception {
424         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
425         verifyWithInlineConfigParser(
426             getPath("InputMissingJavadocTypeQualifiedAnnotation5.java"), expected);
427     }
428 
429     @Test
430     public void testMultipleQualifiedAnnotation() throws Exception {
431         final String[] expected = {
432             "31:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "B"),
433             "41:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "D"),
434         };
435         verifyWithInlineConfigParser(
436             getPath("InputMissingJavadocTypeMultipleQualifiedAnnotation.java"), expected);
437     }
438 
439     @Test
440     public void testQualifiedAnnotationWithParameters() throws Exception {
441         final String[] expected = {
442             "34:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "D"),
443             "38:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "E"),
444             "43:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "F"),
445             "51:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "G"),
446         };
447         verifyWithInlineConfigParser(
448             getPath("InputMissingJavadocTypeQualifiedAnnotationWithParameters.java"),
449             expected);
450     }
451 
452     @Test
453     public void testMissingJavadocTypeAboveComments() throws Exception {
454         final String[] expected = {
455             "15:1: " + getCheckMessage(MSG_JAVADOC_MISSING, "InputMissingJavadocTypeAboveComments"),
456             "30:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "MyClass2"),
457         };
458         verifyWithInlineConfigParser(
459             getPath("InputMissingJavadocTypeAboveComments.java"),
460             expected);
461     }
462 
463     @Test
464     public void testNonJavadocBlockCommentDoesNotSatisfyJavadoc() throws Exception {
465         final String[] expected = {
466             "14:1: " + getCheckMessage(MSG_JAVADOC_MISSING,
467                     "InputMissingJavadocTypeNonJavadocOnly"),
468             "17:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerClass"),
469             "24:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerClass2"),
470             "29:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "InnerClass3"),
471         };
472         verifyWithInlineConfigParser(
473                 getPath("InputMissingJavadocTypeNonJavadocOnly.java"),
474                 expected);
475     }
476 
477     @Test
478     public void testMissingJavadocTypeEnum() throws Exception {
479         final String[] expected = {
480             "37:6: " + getCheckMessage(MSG_JAVADOC_MISSING, "Test2"),
481             "51:5: " + getCheckMessage(MSG_JAVADOC_MISSING, "A"),
482         };
483         verifyWithInlineConfigParser(
484             getPath("InputMissingJavadocTypeEnum.java"),
485             expected);
486     }
487 
488     @Test
489     public void testClearJavadocComments() {
490         final MissingJavadocTypeCheck check = new MissingJavadocTypeCheck();
491         final List<Object> mockList = new ArrayList<>();
492         mockList.add(new Object());
493         TestUtil.setInternalState(check, "javadocComments", mockList);
494         check.beginTree(null);
495         final List<?> javadocComments =
496                 (List<?>) TestUtil.getInternalState(check, "javadocComments", List.class);
497         assertWithMessage("javadocComments state is not cleared on beginTree")
498                 .that(javadocComments)
499                 .isEmpty();
500     }
501 
502 }