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.utils;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
24  import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
25  
26  import java.util.List;
27  
28  import org.junit.jupiter.api.Test;
29  
30  import com.puppycrawl.tools.checkstyle.DetailAstImpl;
31  import com.puppycrawl.tools.checkstyle.api.Comment;
32  import com.puppycrawl.tools.checkstyle.api.JavadocCommentsTokenTypes;
33  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
34  import com.puppycrawl.tools.checkstyle.checks.javadoc.InvalidJavadocTag;
35  import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTag;
36  import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTagInfo;
37  import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTags;
38  
39  public class JavadocUtilTest {
40  
41      @Test
42      public void testTags() {
43          final String[] text = {
44              "/** @see elsewhere ",
45              " * {@link List }, {@link List link text }",
46              "   {@link List#add(Object) link text}",
47              " * {@link Class link text}",
48          };
49          final Comment comment = new Comment(text, 1, 4, text[3].length());
50          final JavadocTags allTags =
51              JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.ALL);
52          assertWithMessage("Invalid valid tags size")
53              .that(allTags.validTags())
54              .hasSize(5);
55      }
56  
57      @Test
58      public void testBlockTag() {
59          final String[] text = {
60              "/** @see elsewhere ",
61              " */",
62          };
63          final Comment comment = new Comment(text, 1, 4, text[1].length());
64          final JavadocTags allTags =
65              JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.ALL);
66          assertWithMessage("Invalid valid tags size")
67              .that(allTags.validTags())
68              .hasSize(1);
69      }
70  
71      @Test
72      public void testTagType() {
73          final String[] text = {
74              "/** @see block",
75              " * {@link List inline}, {@link List#add(Object)}",
76          };
77          final Comment comment = new Comment(text, 1, 2, text[1].length());
78          final JavadocTags blockTags =
79              JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.BLOCK);
80          final JavadocTags inlineTags =
81              JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.INLINE);
82          assertWithMessage("Invalid valid tags size")
83              .that(blockTags.validTags())
84              .hasSize(1);
85          assertWithMessage("Invalid valid tags size")
86              .that(inlineTags.validTags())
87              .hasSize(2);
88      }
89  
90      @Test
91      public void testInlineTagLinkText() {
92          final String[] text = {
93              "/** {@link List link text }",
94          };
95          final Comment comment = new Comment(text, 1, 1, text[0].length());
96          final List<JavadocTag> tags = JavadocUtil.getJavadocTags(
97              comment, JavadocUtil.JavadocTagType.ALL).validTags();
98          assertWithMessage("Invalid first arg")
99              .that(tags.getFirst().getFirstArg())
100             .isEqualTo("List link text");
101     }
102 
103     @Test
104     public void testInlineTagMethodRef() {
105         final String[] text = {
106             "/** {@link List#add(Object)}",
107         };
108         final Comment comment = new Comment(text, 1, 1, text[0].length());
109         final List<JavadocTag> tags = JavadocUtil.getJavadocTags(
110             comment, JavadocUtil.JavadocTagType.ALL).validTags();
111         assertWithMessage("Invalid first arg")
112             .that(tags.getFirst().getFirstArg())
113             .isEqualTo("List#add(Object)");
114     }
115 
116     @Test
117     public void testTagPositions() {
118         final String[] text = {
119             "/** @see elsewhere",
120             "    also {@link Name value} */",
121         };
122         final Comment comment = new Comment(text, 1, 2, text[1].length());
123 
124         final List<JavadocTag> tags = JavadocUtil.getJavadocTags(
125             comment, JavadocUtil.JavadocTagType.ALL).validTags();
126 
127         assertWithMessage("Invalid tags size")
128             .that(tags)
129             .hasSize(2);
130 
131         final JavadocTag seeTag = tags.getFirst();
132         assertWithMessage("Invalid tag name")
133             .that(seeTag.getTagName())
134             .isEqualTo(JavadocTagInfo.SEE.getName());
135         assertWithMessage("Invalid line number")
136             .that(seeTag.getLineNo())
137             .isEqualTo(1);
138         assertWithMessage("Invalid column number")
139             .that(seeTag.getColumnNo())
140             .isEqualTo(4);
141 
142         final JavadocTag linkTag = tags.get(1);
143         assertWithMessage("Invalid tag name")
144             .that(linkTag.getTagName())
145             .isEqualTo(JavadocTagInfo.LINK.getName());
146         assertWithMessage("Invalid line number")
147             .that(linkTag.getLineNo())
148             .isEqualTo(2);
149         assertWithMessage("Invalid column number")
150             .that(linkTag.getColumnNo())
151             .isEqualTo(10);
152     }
153 
154     @Test
155     public void testInlineTagPositions() {
156         final String[] text = {"/** Also {@link Name value} */"};
157         final Comment comment = new Comment(text, 1, 0, text[0].length());
158 
159         final List<JavadocTag> tags = JavadocUtil.getJavadocTags(
160             comment, JavadocUtil.JavadocTagType.INLINE).validTags();
161 
162         assertWithMessage("Invalid tags size")
163             .that(tags)
164             .hasSize(1);
165         final int lineNo = tags.getFirst().getLineNo();
166         assertWithMessage("Unexpected line number")
167             .that(lineNo)
168             .isEqualTo(0);
169         final int columnNo = tags.getFirst().getColumnNo();
170         assertWithMessage("Unexpected column number")
171             .that(columnNo)
172             .isEqualTo(10);
173     }
174 
175     @Test
176     public void testInvalidTags() {
177         final String[] text = {
178             "/** @fake block",
179             " * {@bogus inline}",
180             " * {@link List valid}",
181         };
182         final Comment comment = new Comment(text, 1, 3, text[2].length());
183         final JavadocTags allTags =
184             JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.ALL);
185         assertWithMessage("Unexpected invalid tags size")
186             .that(allTags.invalidTags())
187             .hasSize(2);
188         assertTag("Unexpected invalid tag", new InvalidJavadocTag(1, 4, "fake"),
189                 allTags.invalidTags().getFirst());
190         assertTag("Unexpected invalid tag", new InvalidJavadocTag(2, 4, "bogus"),
191                 allTags.invalidTags().get(1));
192         assertWithMessage("Unexpected valid tags size")
193             .that(allTags.validTags())
194             .hasSize(1);
195         assertTag("Unexpected valid tag", new JavadocTag(3, 4, "link", "List valid"),
196                 allTags.validTags().getFirst());
197     }
198 
199     @Test
200     public void testEmptyBlockComment() {
201         final String emptyComment = "";
202         assertWithMessage("Should return false when empty string is passed")
203                 .that(JavadocUtil.isJavadocComment(emptyComment))
204                 .isFalse();
205     }
206 
207     @Test
208     public void testEmptyBlockCommentAst() {
209         final DetailAstImpl commentBegin = new DetailAstImpl();
210         commentBegin.setType(TokenTypes.BLOCK_COMMENT_BEGIN);
211         commentBegin.setText("/*");
212 
213         final DetailAstImpl commentContent = new DetailAstImpl();
214         commentContent.setType(TokenTypes.COMMENT_CONTENT);
215         commentContent.setText("");
216 
217         final DetailAstImpl commentEnd = new DetailAstImpl();
218         commentEnd.setType(TokenTypes.BLOCK_COMMENT_END);
219         commentEnd.setText("*/");
220 
221         commentBegin.setFirstChild(commentContent);
222         commentContent.setNextSibling(commentEnd);
223 
224         assertWithMessage("Should return false when empty block comment is passed")
225                 .that(JavadocUtil.isJavadocComment(commentBegin))
226                 .isFalse();
227     }
228 
229     @Test
230     public void testEmptyJavadocComment() {
231         final String emptyJavadocComment = "*";
232         assertWithMessage("Should return true when empty javadoc comment is passed")
233                 .that(JavadocUtil.isJavadocComment(emptyJavadocComment))
234                 .isTrue();
235     }
236 
237     @Test
238     public void testEmptyJavadocCommentAst() {
239         final DetailAstImpl commentBegin = new DetailAstImpl();
240         commentBegin.setType(TokenTypes.BLOCK_COMMENT_BEGIN);
241         commentBegin.setText("/*");
242 
243         final DetailAstImpl javadocCommentContent = new DetailAstImpl();
244         javadocCommentContent.setType(TokenTypes.COMMENT_CONTENT);
245         javadocCommentContent.setText("*");
246 
247         final DetailAstImpl commentEnd = new DetailAstImpl();
248         commentEnd.setType(TokenTypes.BLOCK_COMMENT_END);
249         commentEnd.setText("*/");
250 
251         commentBegin.setFirstChild(javadocCommentContent);
252         javadocCommentContent.setNextSibling(commentEnd);
253 
254         final DetailAstImpl commentBeginParent = new DetailAstImpl();
255         commentBeginParent.setType(TokenTypes.MODIFIERS);
256         commentBeginParent.setFirstChild(commentBegin);
257 
258         final DetailAstImpl aJavadocPosition = new DetailAstImpl();
259         aJavadocPosition.setType(TokenTypes.METHOD_DEF);
260         aJavadocPosition.setFirstChild(commentBeginParent);
261         assertWithMessage("Should return true when empty javadoc comment ast is passed")
262                 .that(JavadocUtil.isJavadocComment(commentBegin))
263                 .isTrue();
264     }
265 
266     @Test
267     public void testIsProperUtilsClass() throws ReflectiveOperationException {
268         assertWithMessage("Constructor is not private")
269                 .that(isUtilsClassHasPrivateConstructor(JavadocUtil.class))
270                 .isTrue();
271     }
272 
273     @Test
274     public void testGetTokenNameForId() {
275         assertWithMessage("Invalid token name")
276             .that(JavadocUtil.getTokenName(JavadocCommentsTokenTypes.JAVADOC_CONTENT))
277             .isEqualTo("JAVADOC_CONTENT");
278     }
279 
280     @Test
281     public void testGetTokenNameForLargeId() {
282         final IllegalArgumentException exc =
283                 getExpectedThrowable(IllegalArgumentException.class, () -> {
284                     JavadocUtil.getTokenName(30073);
285                 });
286         assertWithMessage("Invalid exception message")
287             .that(exc.getMessage())
288             .isEqualTo("Unknown javadoc token id. Given id: 30073");
289     }
290 
291     @Test
292     public void testGetTokenNameForInvalidId() {
293         final IllegalArgumentException exc =
294                 getExpectedThrowable(IllegalArgumentException.class, () -> {
295                     JavadocUtil.getTokenName(110);
296                 });
297         assertWithMessage("Invalid exception message")
298             .that(exc.getMessage())
299             .isEqualTo("Unknown javadoc token id. Given id: 110");
300     }
301 
302     @Test
303     public void testGetTokenNameForLowerBoundInvalidId() {
304         final IllegalArgumentException exc =
305                 getExpectedThrowable(IllegalArgumentException.class, () -> {
306                     JavadocUtil.getTokenName(10095);
307                 });
308         assertWithMessage("Invalid exception message")
309             .that(exc.getMessage())
310             .isEqualTo("Unknown javadoc token id. Given id: 10095");
311     }
312 
313     @Test
314     public void testGetTokenIdThatIsUnknown() {
315         final IllegalArgumentException exc =
316                 getExpectedThrowable(IllegalArgumentException.class, () -> {
317                     JavadocUtil.getTokenId("");
318                 });
319         assertWithMessage("Invalid exception message")
320             .that(exc.getMessage())
321             .isEqualTo("Unknown javadoc token name. Given name ");
322     }
323 
324     @Test
325     public void testGetTokenId() {
326         final int tokenId = JavadocUtil.getTokenId("JAVADOC_CONTENT");
327 
328         assertWithMessage("Invalid token id")
329             .that(tokenId)
330             .isEqualTo(JavadocCommentsTokenTypes.JAVADOC_CONTENT);
331     }
332 
333     @Test
334     public void testGetJavadocCommentContent() {
335         final DetailAstImpl detailAST = new DetailAstImpl();
336         final DetailAstImpl javadoc = new DetailAstImpl();
337 
338         javadoc.setText("1javadoc");
339         detailAST.setFirstChild(javadoc);
340         final String commentContent = JavadocUtil.getJavadocCommentContent(detailAST);
341 
342         assertWithMessage("Invalid comment content")
343             .that(commentContent)
344             .isEqualTo("javadoc");
345     }
346 
347     @Test
348     public void testGetLastTokenName() {
349         assertWithMessage("Unexpected token name")
350             .that(JavadocUtil.getTokenName(103))
351             .isEqualTo("CUSTOM_BLOCK_TAG");
352     }
353 
354     @Test
355     public void testEscapeAllControlChars() {
356         assertWithMessage("invalid result")
357             .that(JavadocUtil.escapeAllControlChars("abc"))
358             .isEqualTo("abc");
359         assertWithMessage("invalid result")
360             .that(JavadocUtil.escapeAllControlChars("1\\r2\\n3\\t"))
361             .isEqualTo("1\\r2\\n3\\t");
362     }
363 
364     private static void assertTag(String message, InvalidJavadocTag expected,
365             InvalidJavadocTag actual) {
366         assertWithMessage("%s line", message)
367             .that(actual.getLine())
368             .isEqualTo(expected.getLine());
369         assertWithMessage("%s column", message)
370             .that(actual.getCol())
371             .isEqualTo(expected.getCol());
372         assertWithMessage("%s name", message)
373             .that(actual.getName())
374             .isEqualTo(expected.getName());
375     }
376 
377     private static void assertTag(String message, JavadocTag expected,
378             JavadocTag actual) {
379         assertWithMessage("%s line", message)
380             .that(actual.getLineNo())
381             .isEqualTo(expected.getLineNo());
382         assertWithMessage("%s column", message)
383             .that(actual.getColumnNo())
384             .isEqualTo(expected.getColumnNo());
385         assertWithMessage("%s first arg", message)
386             .that(actual.getFirstArg())
387             .isEqualTo(expected.getFirstArg());
388         assertWithMessage("%s tag name", message)
389             .that(actual.getTagName())
390             .isEqualTo(expected.getTagName());
391     }
392 
393 }