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  import static com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser.MSG_JAVADOC_PARSE_RULE_ERROR;
24  import static com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser.MSG_UNCLOSED_HTML_TAG;
25  import static com.puppycrawl.tools.checkstyle.checks.javadoc.AbstractJavadocCheck.MSG_JAVADOC_MISSED_HTML_CLOSE;
26  import static com.puppycrawl.tools.checkstyle.checks.javadoc.AbstractJavadocCheck.MSG_JAVADOC_WRONG_SINGLETON_TAG;
27  import static com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTypeCheck.MSG_TAG_FORMAT;
28  import static com.puppycrawl.tools.checkstyle.checks.javadoc.SummaryJavadocCheck.MSG_SUMMARY_FIRST_SENTENCE;
29  import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
30  
31  import java.io.File;
32  import java.util.UUID;
33  
34  import org.itsallcode.io.Capturable;
35  import org.itsallcode.junit.sysextensions.SystemErrGuard;
36  import org.itsallcode.junit.sysextensions.SystemErrGuard.SysErr;
37  import org.junit.jupiter.api.BeforeEach;
38  import org.junit.jupiter.api.Test;
39  import org.junit.jupiter.api.extension.ExtendWith;
40  import org.junit.jupiter.api.io.TempDir;
41  
42  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
43  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
44  import com.puppycrawl.tools.checkstyle.api.DetailNode;
45  import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes;
46  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
47  import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
48  
49  @ExtendWith(SystemErrGuard.class)
50  public class AbstractJavadocCheckTest extends AbstractModuleTestSupport {
51  
52      @TempDir
53      public File temporaryFolder;
54  
55      @Override
56      protected String getPackageLocation() {
57          return "com/puppycrawl/tools/checkstyle/checks/javadoc/abstractjavadoc";
58      }
59  
60      /**
61       * <p>Configures the environment for each test.</p>
62       * <ul>
63       * <li>Start output capture for {@link System#err}</li>
64       * </ul>
65       *
66       * @param systemErr wrapper for {@code System.err}
67       */
68      @BeforeEach
69      public void setUp(@SysErr Capturable systemErr) {
70          systemErr.captureMuted();
71      }
72  
73      @Test
74      public void testJavadocTagsWithoutArgs() throws Exception {
75          final String[] expected = {
76              "16: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 4,
77                      "no viable alternative at input '<EOF>'", "JAVADOC_TAG"),
78              "29: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 10,
79                      "no viable alternative at input '<EOF>'", "JAVADOC_TAG"),
80              "35: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 7,
81                      "no viable alternative at input '<EOF>'", "JAVADOC_TAG"),
82              "46: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 6,
83                      "no viable alternative at input '<EOF>'", "JAVADOC_TAG"),
84              "68: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 13,
85                      "mismatched input '}' expecting {LEADING_ASTERISK, WS, NEWLINE}",
86                      "JAVADOC_INLINE_TAG"),
87              "78: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 19,
88                      "no viable alternative at input '}'", "REFERENCE"),
89          };
90          verifyWithInlineConfigParser(
91                  getPath("InputAbstractJavadocJavadocTagsWithoutArgs.java"), expected);
92      }
93  
94      @Test
95      public void testNumberFormatException() throws Exception {
96          final String[] expected = {
97              "8: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 52,
98                      "mismatched input ';' expecting MEMBER", "REFERENCE"),
99          };
100         verifyWithInlineConfigParser(
101                 getPath("InputAbstractJavadocNumberFormatException.java"), expected);
102     }
103 
104     @Test
105     public void testCustomTag() throws Exception {
106         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
107         verifyWithInlineConfigParser(getPath("InputAbstractJavadocCustomTag.java"), expected);
108     }
109 
110     @Test
111     public void testParsingErrors(@SysErr Capturable systemErr) throws Exception {
112         final String[] expected = {
113             "9: " + getCheckMessage(MSG_JAVADOC_MISSED_HTML_CLOSE, 4, "unclosedTag"),
114             "16: " + getCheckMessage(MSG_JAVADOC_WRONG_SINGLETON_TAG, 35, "img"),
115         };
116         verifyWithInlineConfigParser(getPath("InputAbstractJavadocParsingErrors.java"), expected);
117         assertWithMessage("Error is unexpected")
118             .that(systemErr.getCapturedData())
119             .isEqualTo("");
120     }
121 
122     @Test
123     public void testWithMultipleChecksOne() throws Exception {
124         verifyWithInlineConfigParser(
125                 getPath("InputAbstractJavadocCorrectParagraphOne.java"),
126                 CommonUtil.EMPTY_STRING_ARRAY);
127     }
128 
129     @Test
130     public void testWithMultipleChecksTwo() throws Exception {
131         verifyWithInlineConfigParser(
132                 getPath("InputAbstractJavadocCorrectParagraphTwo.java"),
133                 CommonUtil.EMPTY_STRING_ARRAY);
134     }
135 
136     @Test
137     public void testAntlrError(@SysErr Capturable systemErr) throws Exception {
138         final String[] expected = {
139             "9: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 78,
140                     "mismatched input '(' expecting <EOF>", "JAVADOC"),
141         };
142         verifyWithInlineConfigParser(
143                 getPath("InputAbstractJavadocInvalidAtSeeReference.java"), expected);
144         assertWithMessage("Error is unexpected")
145             .that(systemErr.getCapturedData())
146             .isEqualTo("");
147     }
148 
149     @Test
150     public void testCheckReuseAfterParseErrorWithFollowingAntlrErrorInTwoFiles(
151             @SysErr Capturable systemErr) throws Exception {
152         final String[] expectedMessagesForFile1 = {
153             "9: " + getCheckMessage(MSG_JAVADOC_MISSED_HTML_CLOSE, 4, "unclosedTag"),
154             "16: " + getCheckMessage(MSG_JAVADOC_WRONG_SINGLETON_TAG, 35, "img"),
155         };
156         verifyWithInlineConfigParser(getPath(
157                 "InputAbstractJavadocParsingErrors2.java"), expectedMessagesForFile1);
158 
159         final String[] expectedMessagesForFile2 = {
160             "9: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 78,
161                     "mismatched input '(' expecting <EOF>", "JAVADOC"),
162         };
163         verifyWithInlineConfigParser(getPath(
164                 "InputAbstractJavadocInvalidAtSeeReference2.java"), expectedMessagesForFile2);
165 
166         assertWithMessage("Error is unexpected")
167                 .that(systemErr.getCapturedData())
168                 .isEqualTo("");
169     }
170 
171     @Test
172     public void testCheckReuseAfterParseErrorWithFollowingAntlrErrorInSingleFile()
173             throws Exception {
174         final String[] expected = {
175             "9: " + getCheckMessage(MSG_JAVADOC_MISSED_HTML_CLOSE, 4, "unclosedTag"),
176             "16: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR, 82,
177                     "mismatched input '(' expecting <EOF>", "JAVADOC"),
178         };
179         verifyWithInlineConfigParser(
180             getPath("InputAbstractJavadocUnclosedTagAndInvalidAtSeeReference.java"), expected);
181     }
182 
183     @Test
184     public void testCache() throws Exception {
185         final String[] expected = {
186             "12: " + getCheckMessage(SummaryJavadocCheck.class, MSG_SUMMARY_FIRST_SENTENCE),
187         };
188         verifyWithInlineConfigParser(getPath("InputAbstractJavadocCache1.java"),
189             getPath("InputAbstractJavadocCache2.java"), expected);
190     }
191 
192     @Test
193     public void testPositionOne() throws Exception {
194         JavadocCatchCheck.clearCounter();
195         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
196         verifyWithInlineConfigParser(getPath("InputAbstractJavadocPositionOne.java"), expected);
197         assertWithMessage("Invalid number of javadocs")
198             .that(JavadocCatchCheck.javadocsNumber)
199             // until https://github.com/checkstyle/checkstyle/issues/12586
200             // actual javadoc count is 21, but verifyWithInlineConfigParser verify file twice
201             .isEqualTo(42);
202     }
203 
204     @Test
205     public void testPositionTwo() throws Exception {
206         JavadocCatchCheck.clearCounter();
207         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
208         verifyWithInlineConfigParser(getPath("InputAbstractJavadocPositionTwo.java"), expected);
209         assertWithMessage("Invalid number of javadocs")
210             .that(JavadocCatchCheck.javadocsNumber)
211             // until https://github.com/checkstyle/checkstyle/issues/12586
212             // actual javadoc count is 29, but verifyWithInlineConfigParser verify file twice
213             .isEqualTo(58);
214     }
215 
216     @Test
217     public void testPositionThree() throws Exception {
218         JavadocCatchCheck.clearCounter();
219         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
220         verifyWithInlineConfigParser(getPath("InputAbstractJavadocPositionThree.java"), expected);
221         assertWithMessage("Invalid number of javadocs")
222             .that(JavadocCatchCheck.javadocsNumber)
223             // until https://github.com/checkstyle/checkstyle/issues/12586
224             // actual javadoc count is 15, but verifyWithInlineConfigParser verify file twice
225             .isEqualTo(30);
226     }
227 
228     @Test
229     public void testPositionWithSinglelineCommentsOne() throws Exception {
230         JavadocCatchCheck.clearCounter();
231         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
232         verifyWithInlineConfigParser(
233                 getPath("InputAbstractJavadocPositionWithSinglelineCommentsOne.java"), expected);
234         assertWithMessage("Invalid number of javadocs")
235             .that(JavadocCatchCheck.javadocsNumber)
236             // until https://github.com/checkstyle/checkstyle/issues/12586
237             // actual javadoc count is 21, but verifyWithInlineConfigParser verify file twice
238             .isEqualTo(42);
239     }
240 
241     @Test
242     public void testPositionWithSinglelineCommentsTwo() throws Exception {
243         JavadocCatchCheck.clearCounter();
244         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
245         verifyWithInlineConfigParser(
246                 getPath("InputAbstractJavadocPositionWithSinglelineCommentsTwo.java"), expected);
247         assertWithMessage("Invalid number of javadocs")
248             .that(JavadocCatchCheck.javadocsNumber)
249             // until https://github.com/checkstyle/checkstyle/issues/12586
250             // actual javadoc count is 29, but verifyWithInlineConfigParser verify file twice
251             .isEqualTo(58);
252     }
253 
254     @Test
255     public void testPositionWithSinglelineCommentsThree() throws Exception {
256         JavadocCatchCheck.clearCounter();
257         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
258         verifyWithInlineConfigParser(
259                 getPath("InputAbstractJavadocPositionWithSinglelineCommentsThree.java"), expected);
260         assertWithMessage("Invalid number of javadocs")
261             .that(JavadocCatchCheck.javadocsNumber)
262             // until https://github.com/checkstyle/checkstyle/issues/12586
263             // actual javadoc count is 15, but verifyWithInlineConfigParser verify file twice
264             .isEqualTo(30);
265     }
266 
267     @Test
268     public void testPositionOnlyComments() throws Exception {
269         JavadocCatchCheck.clearCounter();
270         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
271         verifyWithInlineConfigParser(
272                 getPath("InputAbstractJavadocPositionOnlyComments.java"), expected);
273         assertWithMessage("Invalid number of javadocs")
274             .that(JavadocCatchCheck.javadocsNumber)
275             .isEqualTo(0);
276     }
277 
278     @Test
279     public void testTokens() {
280         final int[] defaultJavadocTokens = {JavadocTokenTypes.JAVADOC};
281         final AbstractJavadocCheck check = new AbstractJavadocCheck() {
282             @Override
283             public void visitJavadocToken(DetailNode ast) {
284                 // no code necessary
285             }
286 
287             @Override
288             public int[] getDefaultJavadocTokens() {
289                 return defaultJavadocTokens;
290             }
291         };
292 
293         assertWithMessage("Default tokens should not be null")
294             .that(check.getDefaultTokens())
295             .isNotNull();
296         assertWithMessage("Acceptable tokens should be equal to default")
297             .that(check.getAcceptableTokens())
298             .isEqualTo(check.getDefaultTokens());
299         assertWithMessage("Required tokens should be equal to default")
300             .that(check.getRequiredTokens())
301             .isEqualTo(check.getDefaultTokens());
302         assertWithMessage("Invalid default javadoc tokens")
303             .that(check.getDefaultJavadocTokens())
304             .isEqualTo(defaultJavadocTokens);
305         assertWithMessage("Invalid acceptable javadoc tokens")
306             .that(check.getAcceptableJavadocTokens())
307             .isEqualTo(defaultJavadocTokens);
308         assertWithMessage("Invalid required javadoc tokens")
309             .that(check.getRequiredJavadocTokens())
310             .isNotEqualTo(defaultJavadocTokens);
311     }
312 
313     @Test
314     public void testTokensFail() {
315         final int[] defaultJavadocTokens = {JavadocTokenTypes.JAVADOC,
316             JavadocTokenTypes.AREA_HTML_TAG_NAME,
317             JavadocTokenTypes.PARAGRAPH,
318             JavadocTokenTypes.HR_TAG,
319             JavadocTokenTypes.RETURN_LITERAL,
320             JavadocTokenTypes.BR_TAG};
321         final AbstractJavadocCheck check = new AbstractJavadocCheck() {
322             @Override
323             public void visitJavadocToken(DetailNode ast) {
324                 // no code necessary
325             }
326 
327             @Override
328             public int[] getDefaultJavadocTokens() {
329                 return defaultJavadocTokens;
330             }
331         };
332         check.setJavadocTokens("RETURN_LITERAL");
333         assertDoesNotThrow(check::init);
334     }
335 
336     @Test
337     public void testAcceptableTokensFail() throws Exception {
338         final String path = getPath("InputAbstractJavadocTokensFail.java");
339         try {
340             final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
341             verifyWithInlineConfigParser(path, expected);
342             assertWithMessage("CheckstyleException is expected").fail();
343         }
344         catch (IllegalStateException ex) {
345             final String expected = "Javadoc Token "
346                     + "\"RETURN_LITERAL\" was not found in "
347                     + "Acceptable javadoc tokens list in check "
348                     + TokenIsNotInAcceptablesCheck.class.getName();
349             assertWithMessage("Invalid exception, should start with: " + expected)
350                     .that(ex.getMessage())
351                     .startsWith(expected);
352         }
353     }
354 
355     @Test
356     public void testAcceptableTokensPass() throws Exception {
357         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
358         verifyWithInlineConfigParser(getPath("InputAbstractJavadocTokensPass.java"), expected);
359     }
360 
361     @Test
362     public void testRequiredTokenIsNotInDefaultTokens() throws Exception {
363         final DefaultConfiguration checkConfig =
364             createModuleConfig(RequiredTokenIsNotInDefaultsJavadocCheck.class);
365         final String uniqueFileName = "empty_" + UUID.randomUUID() + ".java";
366         final File pathToEmptyFile = new File(temporaryFolder, uniqueFileName);
367 
368         try {
369             execute(checkConfig, pathToEmptyFile.toString());
370             assertWithMessage("CheckstyleException is expected").fail();
371         }
372         catch (IllegalStateException ex) {
373             final String expected = "Javadoc Token \""
374                     + JavadocTokenTypes.RETURN_LITERAL + "\" from required"
375                     + " javadoc tokens was not found in default javadoc tokens list in check "
376                     + RequiredTokenIsNotInDefaultsJavadocCheck.class.getName();
377             assertWithMessage("Invalid exception, should start with: " + expected)
378                     .that(ex.getMessage())
379                     .startsWith(expected);
380         }
381     }
382 
383     @Test
384     public void testVisitLeaveTokenOne() throws Exception {
385         JavadocVisitLeaveCheck.clearCounter();
386         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
387         verifyWithInlineConfigParser(getPath("InputAbstractJavadocLeaveTokenOne.java"), expected);
388         assertWithMessage("Javadoc visit count should be greater than zero")
389                 .that(JavadocVisitLeaveCheck.visitCount)
390                 .isGreaterThan(0);
391         assertWithMessage("Javadoc visit and leave count should be equal")
392             .that(JavadocVisitLeaveCheck.leaveCount)
393             .isEqualTo(JavadocVisitLeaveCheck.visitCount);
394     }
395 
396     @Test
397     public void testVisitLeaveTokenTwo() throws Exception {
398         JavadocVisitLeaveCheck.clearCounter();
399         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
400         verifyWithInlineConfigParser(getPath("InputAbstractJavadocLeaveTokenTwo.java"), expected);
401         assertWithMessage("Javadoc visit count should be greater than zero")
402                 .that(JavadocVisitLeaveCheck.visitCount)
403                 .isGreaterThan(0);
404         assertWithMessage("Javadoc visit and leave count should be equal")
405             .that(JavadocVisitLeaveCheck.leaveCount)
406             .isEqualTo(JavadocVisitLeaveCheck.visitCount);
407     }
408 
409     @Test
410     public void testVisitLeaveTokenThree() throws Exception {
411         JavadocVisitLeaveCheck.clearCounter();
412         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
413         verifyWithInlineConfigParser(getPath("InputAbstractJavadocLeaveTokenThree.java"), expected);
414         assertWithMessage("Javadoc visit count should be greater than zero")
415                 .that(JavadocVisitLeaveCheck.visitCount)
416                 .isGreaterThan(0);
417         assertWithMessage("Javadoc visit and leave count should be equal")
418             .that(JavadocVisitLeaveCheck.leaveCount)
419             .isEqualTo(JavadocVisitLeaveCheck.visitCount);
420     }
421 
422     @Test
423     public void testNoWsBeforeDescriptionInJavadocTags() throws Exception {
424         final String[] expected = {
425             "18: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
426                     23, "mismatched input 'd' expecting <EOF>", "JAVADOC"),
427             "29: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
428                     30, "mismatched input '-' expecting <EOF>", "JAVADOC"),
429             "37: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
430                     39, "mismatched input '-' expecting <EOF>", "JAVADOC"),
431             "51: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
432                     34, "mismatched input '-' expecting <EOF>", "JAVADOC"),
433             "61: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
434                     31, "mismatched input '-' expecting <EOF>", "JAVADOC"),
435             "72: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
436                     15, "mismatched input '-' expecting <EOF>", "JAVADOC"),
437             "81: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
438                     32, "mismatched input '-' expecting <EOF>", "JAVADOC"),
439             "92: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
440                     17, "mismatched input '<' expecting <EOF>", "JAVADOC"),
441             "99: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
442                     34, "no viable alternative at input '-'", "JAVADOC_INLINE_TAG"),
443             "106: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
444                     39, "no viable alternative at input '-'", "JAVADOC_INLINE_TAG"),
445             "114: " + getCheckMessage(MSG_JAVADOC_PARSE_RULE_ERROR,
446                     19, "no viable alternative at input '<'", "JAVADOC_INLINE_TAG"),
447         };
448         verifyWithInlineConfigParser(
449                 getPath("InputAbstractJavadocNoWsBeforeDescriptionInJavadocTags.java"),
450                 expected);
451     }
452 
453     @Test
454     public void testWrongSingletonTagInJavadoc() throws Exception {
455         final String[] expected = {
456             "10: " + getCheckMessage(MSG_JAVADOC_WRONG_SINGLETON_TAG, 9, "embed"),
457             "17: " + getCheckMessage(MSG_JAVADOC_WRONG_SINGLETON_TAG, 9, "keygen"),
458             "24: " + getCheckMessage(MSG_JAVADOC_WRONG_SINGLETON_TAG, 9, "SOURCE"),
459             "31: " + getCheckMessage(MSG_JAVADOC_WRONG_SINGLETON_TAG, 9, "TRACK"),
460             "38: " + getCheckMessage(MSG_JAVADOC_WRONG_SINGLETON_TAG, 9, "WBR"),
461         };
462         verifyWithInlineConfigParser(getPath("InputAbstractJavadocWrongSingletonTagInJavadoc.java"),
463                 expected);
464     }
465 
466     @Test
467     public void testNonTightHtmlTagIntolerantCheckOne() throws Exception {
468         final String[] expected = {
469             "12: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
470             "19: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
471             "22: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"),
472             "28: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
473             "35: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"),
474             "54: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
475             "64: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"),
476         };
477         verifyWithInlineConfigParser(
478                 getPath("InputAbstractJavadocNonTightHtmlTagsOne.java"), expected);
479     }
480 
481     @Test
482     public void testNonTightHtmlTagIntolerantCheckTwo() throws Exception {
483         final String[] expected = {
484             "12: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
485             "19: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
486             "25: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"),
487             "46: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"),
488             "80: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
489         };
490         verifyWithInlineConfigParser(
491                 getPath("InputAbstractJavadocNonTightHtmlTagsTwo.java"), expected);
492     }
493 
494     @Test
495     public void testNonTightHtmlTagIntolerantCheckReportingNoViolationOne() throws Exception {
496         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
497         verifyWithInlineConfigParser(
498                 getPath("InputAbstractJavadocNonTightHtmlTagsNoViolationOne.java"), expected);
499     }
500 
501     @Test
502     public void testNonTightHtmlTagIntolerantCheckReportingNoViolationTwo() throws Exception {
503         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
504         verifyWithInlineConfigParser(
505                 getPath("InputAbstractJavadocNonTightHtmlTagsNoViolationTwo.java"), expected);
506     }
507 
508     @Test
509     public void testNonTightHtmlTagIntolerantCheckVisitCountOne() throws Exception {
510         final String[] expected = {
511             "13: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
512             "20: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
513             "23: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"),
514             "29: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
515             "36: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"),
516             "46:13: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
517             "56: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
518             "66: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"),
519         };
520         verifyWithInlineConfigParser(
521                 getPath("InputAbstractJavadocNonTightHtmlTagsVisitCountOne.java"),
522                 expected);
523     }
524 
525     @Test
526     public void testNonTightHtmlTagIntolerantCheckVisitCountTwo() throws Exception {
527         final String[] expected = {
528             "13: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
529             "20: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
530             "27: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"),
531             "35:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "BODY_TAG_START"),
532             "49: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"),
533             "58:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
534             "65:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
535             "69:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "BODY_TAG_START"),
536             "86: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
537         };
538         verifyWithInlineConfigParser(
539                 getPath("InputAbstractJavadocNonTightHtmlTagsVisitCountTwo.java"),
540                 expected);
541     }
542 
543     @Test
544     public void testVisitCountForCheckAcceptingJavadocWithNonTightHtml() throws Exception {
545         final String[] expected = {
546             "11:4: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "BODY_TAG_START"),
547             "12:4: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
548             "14: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
549             "14:4: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
550             "15:4: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
551             "15:39: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
552             "30: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
553             "30:9: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
554             "30:13: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
555             "37: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"),
556             "37:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
557             "44:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
558             "45: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
559             "45:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
560             "45:25: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
561             "55:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
562             "55:22: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
563             "56: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"),
564             "65:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
565             "66:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
566             "67: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"),
567             "67:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
568             "67:23: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
569             "78:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "BODY_TAG_START"),
570             "78:20: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
571             "78:34: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
572             "80: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"),
573             "80:16: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
574             "80:21: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
575             "96:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
576             "98: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
577             "98:22: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
578             "107:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
579             "108:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
580             "111: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"),
581         };
582         verifyWithInlineConfigParser(
583                 getPath("InputAbstractJavadocNonTightHtmlTags2.java"), expected);
584     }
585 
586     @Test
587     public void testVisitCountForCheckAcceptingJavadocWithNonTightHtml3() throws Exception {
588         final String[] expected = {
589             "29:8: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
590             "36: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"),
591             "36:9: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "P_TAG_START"),
592             "36:13: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "LI_TAG_START"),
593             "36:33: " + getCheckMessage(NonTightHtmlTagCheck.MSG_KEY, "BODY_TAG_START"),
594         };
595         verifyWithInlineConfigParser(
596                 getPath("InputAbstractJavadocNonTightHtmlTags3.java"), expected);
597     }
598 
599     public static class ParseJavadocOnlyCheck extends AbstractJavadocCheck {
600 
601         @Override
602         public int[] getDefaultJavadocTokens() {
603             return CommonUtil.EMPTY_INT_ARRAY;
604         }
605 
606         @Override
607         public void visitJavadocToken(DetailNode ast) {
608             // do nothing
609         }
610 
611     }
612 
613     public static class JavadocCatchCheck extends AbstractJavadocCheck {
614         private static int javadocsNumber;
615 
616         public static void clearCounter() {
617             javadocsNumber = 0;
618         }
619 
620         @Override
621         public int[] getDefaultJavadocTokens() {
622             return new int[] {JavadocTokenTypes.JAVADOC};
623         }
624 
625         @Override
626         public void visitJavadocToken(DetailNode ast) {
627             assertWithMessage(ast.toString())
628                 .that(ast.getText())
629                 .isEqualTo("JAVADOC");
630             final DetailNode text = JavadocUtil.findFirstToken(ast, JavadocTokenTypes.TEXT);
631             assertWithMessage("Empty javadoc text at " + ast)
632                 .that(text)
633                 .isNotNull();
634             assertWithMessage(ast.toString())
635                 .that(text.getText())
636                 .isEqualTo("Javadoc");
637             javadocsNumber++;
638         }
639 
640     }
641 
642     public static class RequiredTokenIsNotInDefaultsJavadocCheck extends AbstractJavadocCheck {
643 
644         @Override
645         public int[] getRequiredJavadocTokens() {
646             return new int[] {JavadocTokenTypes.RETURN_LITERAL};
647         }
648 
649         @Override
650         public int[] getDefaultJavadocTokens() {
651             return new int[] {JavadocTokenTypes.DEPRECATED_LITERAL};
652         }
653 
654         @Override
655         public int[] getAcceptableJavadocTokens() {
656             return CommonUtil.EMPTY_INT_ARRAY;
657         }
658 
659         @Override
660         public void visitJavadocToken(DetailNode ast) {
661             // not used
662         }
663 
664     }
665 
666     public static class TokenIsNotInAcceptablesCheck extends AbstractJavadocCheck {
667 
668         @Override
669         public int[] getRequiredJavadocTokens() {
670             return new int[] {JavadocTokenTypes.DEPRECATED_LITERAL};
671         }
672 
673         @Override
674         public int[] getDefaultJavadocTokens() {
675             return new int[] {JavadocTokenTypes.DEPRECATED_LITERAL};
676         }
677 
678         @Override
679         public int[] getAcceptableJavadocTokens() {
680             return new int[] {JavadocTokenTypes.DEPRECATED_LITERAL};
681         }
682 
683         @Override
684         public void visitJavadocToken(DetailNode ast) {
685             // not used
686         }
687 
688     }
689 
690     public static class JavadocVisitLeaveCheck extends AbstractJavadocCheck {
691 
692         private static int visitCount;
693         private static int leaveCount;
694 
695         public static void clearCounter() {
696             visitCount = 0;
697             leaveCount = 0;
698         }
699 
700         @Override
701         public int[] getRequiredJavadocTokens() {
702             return new int[] {JavadocTokenTypes.TEXT};
703         }
704 
705         @Override
706         public int[] getDefaultJavadocTokens() {
707             return getRequiredJavadocTokens();
708         }
709 
710         @Override
711         public int[] getAcceptableJavadocTokens() {
712             return getRequiredJavadocTokens();
713         }
714 
715         @Override
716         public void visitJavadocToken(DetailNode ast) {
717             visitCount++;
718         }
719 
720         @Override
721         public void leaveJavadocToken(DetailNode ast) {
722             leaveCount++;
723         }
724 
725     }
726 
727     public static class NonTightHtmlTagCheck extends AbstractJavadocCheck {
728         // extra variable to make it explicit in test expected array
729         // that message is from NonTightHtmlTagCheck
730         public static final String MSG_KEY = MSG_TAG_FORMAT;
731 
732         private boolean reportVisitJavadocToken;
733 
734         public final void setReportVisitJavadocToken(boolean reportVisitJavadocToken) {
735             this.reportVisitJavadocToken = reportVisitJavadocToken;
736         }
737 
738         @Override
739         public int[] getDefaultJavadocTokens() {
740             return new int[] {
741                 JavadocTokenTypes.P_TAG_START,
742                 JavadocTokenTypes.LI_TAG_START,
743                 JavadocTokenTypes.BODY_TAG_START,
744             };
745         }
746 
747         @Override
748         public void visitJavadocToken(DetailNode ast) {
749             if (reportVisitJavadocToken) {
750                 // We reusing messages from JavadocTypeCheck
751                 // it is not possible to use test specific bundle of messages
752                 log(ast.getLineNumber(), ast.getColumnNumber(), MSG_TAG_FORMAT, ast.getText());
753             }
754         }
755 
756         @Override
757         public boolean acceptJavadocWithNonTightHtml() {
758             return false;
759         }
760     }
761 
762     public static class NonTightHtmlTagTolerantCheck extends AbstractJavadocCheck {
763         // extra variable to make it explicit in test expected array
764         // that message is from NonTightHtmlTagCheck
765         public static final String MSG_KEY = MSG_TAG_FORMAT;
766 
767         private boolean reportVisitJavadocToken;
768 
769         public final void setReportVisitJavadocToken(boolean reportVisitJavadocToken) {
770             this.reportVisitJavadocToken = reportVisitJavadocToken;
771         }
772 
773         @Override
774         public int[] getDefaultJavadocTokens() {
775             return new int[] {
776                 JavadocTokenTypes.P_TAG_START,
777                 JavadocTokenTypes.LI_TAG_START,
778                 JavadocTokenTypes.BODY_TAG_START,
779             };
780         }
781 
782         @Override
783         public void visitJavadocToken(DetailNode ast) {
784             if (reportVisitJavadocToken) {
785                 // We reusing messages from JavadocTypeCheck
786                 // it is not possible to use test specific bundle of messages
787                 log(ast.getLineNumber(), ast.getColumnNumber(), MSG_TAG_FORMAT, ast.getText());
788             }
789         }
790 
791     }
792 }