1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocContentLocationCheck.MSG_JAVADOC_CONTENT_SECOND_LINE;
24
25 import java.io.File;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.Optional;
30
31 import org.junit.jupiter.api.Test;
32
33 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
34 import com.puppycrawl.tools.checkstyle.api.DetailAST;
35 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
36 import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocContentLocationCheck;
37 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
38
39 public class JavaParserTest extends AbstractModuleTestSupport {
40
41 @Override
42 protected String getPackageLocation() {
43 return "com/puppycrawl/tools/checkstyle/javaparser";
44 }
45
46 @Test
47 public void testIsProperUtilsClass() throws ReflectiveOperationException {
48 assertWithMessage("Constructor is not private")
49 .that(TestUtil.isUtilsClassHasPrivateConstructor(JavaParser.class))
50 .isTrue();
51 }
52
53 @Test
54 public void testNullRootWithComments() {
55 assertWithMessage("Invalid return root")
56 .that(JavaParser.appendHiddenCommentNodes(null))
57 .isNull();
58 }
59
60 @Test
61 public void testAppendHiddenBlockCommentNodes() throws Exception {
62 final DetailAST root =
63 JavaParser.parseFile(new File(getPath("InputJavaParserHiddenComments.java")),
64 JavaParser.Options.WITH_COMMENTS);
65
66 final Optional<DetailAST> blockComment = TestUtil.findTokenInAstByPredicate(root,
67 ast -> ast.getType() == TokenTypes.BLOCK_COMMENT_BEGIN);
68
69 assertWithMessage("Block comment should be present")
70 .that(blockComment.isPresent())
71 .isTrue();
72
73 final DetailAST comment = blockComment.orElseThrow();
74
75 assertWithMessage("Unexpected line number")
76 .that(comment.getLineNo())
77 .isEqualTo(3);
78 assertWithMessage("Unexpected column number")
79 .that(comment.getColumnNo())
80 .isEqualTo(0);
81 assertWithMessage("Unexpected comment content")
82 .that(comment.getText())
83 .isEqualTo("/*");
84
85 final DetailAST commentContent = comment.getFirstChild();
86 final DetailAST commentEnd = comment.getLastChild();
87
88 assertWithMessage("Unexpected line number")
89 .that(commentContent.getLineNo())
90 .isEqualTo(3);
91 assertWithMessage("Unexpected column number")
92 .that(commentContent.getColumnNo())
93 .isEqualTo(2);
94 assertWithMessage("Unexpected line number")
95 .that(commentEnd.getLineNo())
96 .isEqualTo(9);
97 assertWithMessage("Unexpected column number")
98 .that(commentEnd.getColumnNo())
99 .isEqualTo(1);
100 }
101
102 @Test
103 public void testAppendHiddenSingleLineCommentNodes() throws Exception {
104 final DetailAST root =
105 JavaParser.parseFile(new File(getPath("InputJavaParserHiddenComments.java")),
106 JavaParser.Options.WITH_COMMENTS);
107
108 final Optional<DetailAST> singleLineComment = TestUtil.findTokenInAstByPredicate(root,
109 ast -> ast.getType() == TokenTypes.SINGLE_LINE_COMMENT);
110 assertWithMessage("Single line comment should be present")
111 .that(singleLineComment.isPresent())
112 .isTrue();
113
114 final DetailAST comment = singleLineComment.orElseThrow();
115
116 assertWithMessage("Unexpected line number")
117 .that(comment.getLineNo())
118 .isEqualTo(13);
119 assertWithMessage("Unexpected column number")
120 .that(comment.getColumnNo())
121 .isEqualTo(0);
122 assertWithMessage("Unexpected comment content")
123 .that(comment.getText())
124 .isEqualTo("//");
125
126 final DetailAST commentContent = comment.getFirstChild();
127
128 assertWithMessage("Unexpected token type")
129 .that(commentContent.getType())
130 .isEqualTo(TokenTypes.COMMENT_CONTENT);
131 assertWithMessage("Unexpected line number")
132 .that(commentContent.getLineNo())
133 .isEqualTo(13);
134 assertWithMessage("Unexpected column number")
135 .that(commentContent.getColumnNo())
136 .isEqualTo(2);
137 assertWithMessage("Unexpected comment content")
138 .that(commentContent.getText())
139 .startsWith(" inline comment");
140 }
141
142 @Test
143 public void testAppendHiddenSingleLineCommentNodes2() throws Exception {
144 final DetailAST root =
145 JavaParser.parseFile(new File(getPath("InputJavaParserHiddenComments2.java")),
146 JavaParser.Options.WITH_COMMENTS);
147
148 final Optional<DetailAST> singleLineComment = TestUtil.findTokenInAstByPredicate(root,
149 ast -> ast.getType() == TokenTypes.SINGLE_LINE_COMMENT);
150 assertWithMessage("Single line comment should be present")
151 .that(singleLineComment.isPresent())
152 .isTrue();
153
154 final DetailAST comment = singleLineComment.orElseThrow();
155
156 assertWithMessage("Unexpected line number")
157 .that(comment.getLineNo())
158 .isEqualTo(1);
159 assertWithMessage("Unexpected column number")
160 .that(comment.getColumnNo())
161 .isEqualTo(4);
162 assertWithMessage("Unexpected comment content")
163 .that(comment.getText())
164 .isEqualTo("//");
165
166 final DetailAST commentContent = comment.getFirstChild();
167
168 assertWithMessage("Unexpected token type")
169 .that(commentContent.getType())
170 .isEqualTo(TokenTypes.COMMENT_CONTENT);
171 assertWithMessage("Unexpected line number")
172 .that(commentContent.getLineNo())
173 .isEqualTo(1);
174 assertWithMessage("Unexpected column number")
175 .that(commentContent.getColumnNo())
176 .isEqualTo(6);
177 assertWithMessage("Unexpected comment content")
178 .that(commentContent.getText())
179 .startsWith(" indented comment");
180 }
181
182 @Test
183 public void testDontAppendCommentNodes() throws Exception {
184 final DetailAST root =
185 JavaParser.parseFile(new File(getPath("InputJavaParserHiddenComments.java")),
186 JavaParser.Options.WITHOUT_COMMENTS);
187
188 final Optional<DetailAST> singleLineComment = TestUtil.findTokenInAstByPredicate(root,
189 ast -> ast.getType() == TokenTypes.SINGLE_LINE_COMMENT);
190 assertWithMessage("Single line comment should be present")
191 .that(singleLineComment.isPresent())
192 .isFalse();
193 }
194
195 @Test
196 public void testParseException() throws Exception {
197 final File input = new File(getNonCompilablePath("InputJavaParser.java"));
198 try {
199 JavaParser.parseFile(input, JavaParser.Options.WITH_COMMENTS);
200 assertWithMessage("exception expected").fail();
201 }
202 catch (CheckstyleException ex) {
203 assertWithMessage("Invalid exception message")
204 .that(ex.toString())
205 .isEqualTo(CheckstyleException.class.getName()
206 + ": IllegalStateException occurred while parsing file "
207 + input.getAbsolutePath() + ".");
208 assertWithMessage("Invalid class")
209 .that(ex.getCause())
210 .isInstanceOf(IllegalStateException.class);
211 assertWithMessage("Invalid exception message")
212 .that(ex.getCause().toString())
213 .isEqualTo(IllegalStateException.class.getName()
214 + ": 2:0: no viable alternative at input 'classD'");
215 }
216 }
217
218 @Test
219 public void testComments() throws Exception {
220 final DetailAST root =
221 JavaParser.parseFile(new File(getPath("InputJavaParserHiddenComments3.java")),
222 JavaParser.Options.WITH_COMMENTS);
223 final CountComments counter = new CountComments(root);
224
225 assertWithMessage("Invalid line comments")
226 .that(counter.lineComments)
227 .isEqualTo(Arrays.asList("1,4", "6,4", "9,0"));
228 assertWithMessage("Invalid block comments")
229 .that(counter.blockComments)
230 .isEqualTo(Arrays.asList("5,4", "8,0"));
231 }
232
233 @Test
234 public void testJava14TextBlocks() throws Exception {
235 final DetailAST root =
236 JavaParser.parseFile(new File(
237 getNonCompilablePath("InputJavaParserTextBlocks.java")),
238 JavaParser.Options.WITHOUT_COMMENTS);
239
240 final Optional<DetailAST> textBlockContent = TestUtil.findTokenInAstByPredicate(root,
241 ast -> ast.getType() == TokenTypes.TEXT_BLOCK_CONTENT);
242
243 assertWithMessage("Text block content should be present")
244 .that(textBlockContent.isPresent())
245 .isTrue();
246
247 final DetailAST content = textBlockContent.orElseThrow();
248 final String expectedContents = "\n string";
249
250 assertWithMessage("Unexpected line number")
251 .that(content.getLineNo())
252 .isEqualTo(5);
253 assertWithMessage("Unexpected column number")
254 .that(content.getColumnNo())
255 .isEqualTo(32);
256 assertWithMessage("Unexpected text block content")
257 .that(content.getText())
258 .isEqualTo(expectedContents);
259 }
260
261 @Test
262 public void testNoFreezeOnDeeplyNestedLambdas() throws Exception {
263 final File file =
264 new File(getNonCompilablePath("InputJavaParserNoFreezeOnDeeplyNestedLambdas.java"));
265 assertWithMessage("File parsing should complete successfully.")
266 .that(JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS))
267 .isNotNull();
268 }
269
270 @Test
271 public void testFullJavaIdentifierSupport() throws Exception {
272 final File file =
273 new File(getNonCompilablePath("InputJavaParserFullJavaIdentifierSupport.java"));
274 assertWithMessage("File parsing should complete successfully.")
275 .that(JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS))
276 .isNotNull();
277 }
278
279 @Test
280 public void testReturnValueOfAppendHiddenCommentNodes()
281 throws Exception {
282 final String[] expected = {
283 "9:1: " + getCheckMessage(JavadocContentLocationCheck.class,
284 MSG_JAVADOC_CONTENT_SECOND_LINE),
285 };
286 verifyWithInlineConfigParser(
287 getPath("InputJavaParserHiddenComments4.java"), expected);
288 }
289
290 private static final class CountComments {
291 private final List<String> lineComments = new ArrayList<>();
292 private final List<String> blockComments = new ArrayList<>();
293
294 private CountComments(DetailAST root) {
295 forEachChild(root);
296 }
297
298 private void forEachChild(DetailAST root) {
299 for (DetailAST ast = root; ast != null; ast = ast.getNextSibling()) {
300 if (ast.getType() == TokenTypes.SINGLE_LINE_COMMENT) {
301 lineComments.add(ast.getLineNo() + "," + ast.getColumnNo());
302 }
303 else if (ast.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) {
304 blockComments.add(ast.getLineNo() + "," + ast.getColumnNo());
305 }
306
307 forEachChild(ast.getFirstChild());
308 }
309 }
310 }
311 }