1 /*
2  * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
3  * Copyright (C) 2011, 2013-2016 The JavaParser Team.
4  *
5  * This file is part of JavaParser.
6  *
7  * JavaParser can be used either under the terms of
8  * a) the GNU Lesser General Public License as published by
9  *     the Free Software Foundation, either version 3 of the License, or
10  *     (at your option) any later version.
11  * b) the terms of the Apache License
12  *
13  * You should have received a copy of both licenses in LICENCE.LGPL and
14  * LICENCE.APACHE. Please refer to those files for details.
15  *
16  * JavaParser is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Lesser General Public License for more details.
20  */
21 
22 package com.github.javaparser;
23 
24 import com.github.javaparser.ast.CompilationUnit;
25 import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
26 import com.github.javaparser.ast.body.MethodDeclaration;
27 import com.github.javaparser.ast.expr.ArrayCreationExpr;
28 import com.github.javaparser.ast.expr.CastExpr;
29 import com.github.javaparser.ast.expr.Expression;
30 import com.github.javaparser.ast.expr.LambdaExpr;
31 import com.github.javaparser.ast.stmt.*;
32 import com.github.javaparser.ast.type.ClassOrInterfaceType;
33 import com.github.javaparser.ast.type.IntersectionType;
34 import com.github.javaparser.ast.type.Type;
35 import org.junit.Test;
36 
37 import java.io.IOException;
38 import java.nio.file.Path;
39 import java.util.Optional;
40 
41 import static com.github.javaparser.ParseStart.COMPILATION_UNIT;
42 import static com.github.javaparser.Providers.provider;
43 import static com.github.javaparser.Range.range;
44 import static com.github.javaparser.utils.CodeGenerationUtils.mavenModuleRoot;
45 import static com.github.javaparser.utils.TestUtils.assertInstanceOf;
46 import static com.github.javaparser.utils.Utils.EOL;
47 import static org.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertTrue;
49 
50 public class JavaParserTest {
51 
52     @Test
rangeOfAnnotationMemberDeclarationIsCorrect()53     public void rangeOfAnnotationMemberDeclarationIsCorrect() {
54         String code = "@interface AD { String foo(); }";
55         CompilationUnit cu = JavaParser.parse(code);
56         AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
57         assertEquals(true, memberDeclaration.getRange().isPresent());
58         assertEquals(new Range(new Position(1, 17), new Position(1, 29)), memberDeclaration.getRange().get());
59     }
60 
61     @Test
rangeOfAnnotationMemberDeclarationWithArrayTypeIsCorrect()62     public void rangeOfAnnotationMemberDeclarationWithArrayTypeIsCorrect() {
63         String code = "@interface AD { String[] foo(); }";
64         CompilationUnit cu = JavaParser.parse(code);
65         AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
66         assertEquals(true, memberDeclaration.getRange().isPresent());
67         assertEquals(new Range(new Position(1, 17), new Position(1, 31)), memberDeclaration.getRange().get());
68     }
69 
70     @Test
rangeOfArrayCreationLevelWithExpressionIsCorrect()71     public void rangeOfArrayCreationLevelWithExpressionIsCorrect() {
72         String code = "new int[123][456]";
73         ArrayCreationExpr expression = JavaParser.parseExpression(code);
74         Optional<Range> range;
75 
76         range = expression.getLevels().get(0).getRange();
77         assertEquals(true, range.isPresent());
78         assertEquals(new Range(new Position(1, 8), new Position(1, 12)), range.get());
79 
80         range = expression.getLevels().get(1).getRange();
81         assertEquals(true, range.isPresent());
82         assertEquals(new Range(new Position(1, 13), new Position(1, 17)), range.get());
83     }
84 
85     @Test
rangeOfArrayCreationLevelWithoutExpressionIsCorrect()86     public void rangeOfArrayCreationLevelWithoutExpressionIsCorrect() {
87         String code = "new int[][]";
88         ArrayCreationExpr expression = JavaParser.parseExpression(code);
89         Optional<Range> range;
90 
91         range = expression.getLevels().get(0).getRange();
92         assertEquals(true, range.isPresent());
93         assertEquals(new Range(new Position(1, 8), new Position(1, 9)), range.get());
94 
95         range = expression.getLevels().get(1).getRange();
96         assertEquals(true, range.isPresent());
97         assertEquals(new Range(new Position(1, 10), new Position(1, 11)), range.get());
98     }
99 
100     @Test
parseErrorContainsLocation()101     public void parseErrorContainsLocation() {
102         ParseResult<CompilationUnit> result = new JavaParser().parse(COMPILATION_UNIT, provider("class X { // blah"));
103 
104         Problem problem = result.getProblem(0);
105         assertEquals(range(1, 9, 1, 17), problem.getLocation().get().toRange().get());
106         assertEquals("Parse error. Found <EOF>, expected one of  \";\" \"<\" \"@\" \"abstract\" \"boolean\" \"byte\" \"char\" \"class\" \"default\" \"double\" \"enum\" \"exports\" \"final\" \"float\" \"int\" \"interface\" \"long\" \"module\" \"native\" \"open\" \"opens\" \"private\" \"protected\" \"provides\" \"public\" \"requires\" \"short\" \"static\" \"strictfp\" \"synchronized\" \"to\" \"transient\" \"transitive\" \"uses\" \"void\" \"volatile\" \"with\" \"{\" \"}\" <IDENTIFIER>", problem.getMessage());
107         assertInstanceOf(ParseException.class, problem.getCause().get());
108     }
109 
110     @Test
parseIntersectionType()111     public void parseIntersectionType() {
112         String code = "(Runnable & Serializable) (() -> {})";
113         Expression expression = JavaParser.parseExpression(code);
114         Type type = expression.asCastExpr().getType();
115 
116         assertTrue(type instanceof IntersectionType);
117         IntersectionType intersectionType = type.asIntersectionType();
118         assertEquals(2, intersectionType.getElements().size());
119         assertTrue(intersectionType.getElements().get(0) instanceof ClassOrInterfaceType);
120         assertEquals("Runnable", intersectionType.getElements().get(0).asClassOrInterfaceType().getNameAsString());
121         assertTrue(intersectionType.getElements().get(1) instanceof ClassOrInterfaceType);
122         assertEquals("Serializable", intersectionType.getElements().get(1).asClassOrInterfaceType().getNameAsString());
123     }
124 
125     @Test
rangeOfIntersectionType()126     public void rangeOfIntersectionType() {
127         String code = "class A {" + EOL
128                 + "  Object f() {" + EOL
129                 + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
130                 + "}}";
131         CompilationUnit cu = JavaParser.parse(code);
132         MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
133         ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
134         CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
135         Type type = castExpr.getType();
136         assertEquals(range(3, 13, 3, 54), type.getRange().get());
137     }
138 
139     @Test
rangeOfCast()140     public void rangeOfCast() {
141         String code = "class A {" + EOL
142                 + "  Object f() {" + EOL
143                 + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
144                 + "}}";
145         CompilationUnit cu = JavaParser.parse(code);
146         MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
147         ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
148         CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
149         assertEquals(range(3, 12, 3, 101), castExpr.getRange().get());
150     }
151 
152     @Test
rangeOfCastNonIntersection()153     public void rangeOfCastNonIntersection() {
154         String code = "class A {" + EOL
155                 + "  Object f() {" + EOL
156                 + "    return (Comparator<Map.Entry<K, V>>               )(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
157                 + "}}";
158         CompilationUnit cu = JavaParser.parse(code);
159         MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
160         ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
161         CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
162         assertEquals(range(3, 12, 3, 101), castExpr.getRange().get());
163     }
164 
165     @Test
rangeOfLambda()166     public void rangeOfLambda() {
167         String code = "class A {" + EOL
168                 + "  Object f() {" + EOL
169                 + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
170                 + "}}";
171         CompilationUnit cu = JavaParser.parse(code);
172         MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
173         ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
174         CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
175         LambdaExpr lambdaExpr = castExpr.getExpression().asLambdaExpr();
176         assertEquals(range(3, 56, 3, 101), lambdaExpr.getRange().get());
177         assertEquals(GeneratedJavaParserConstants.LPAREN, lambdaExpr.getTokenRange().get().getBegin().getKind());
178         assertEquals(GeneratedJavaParserConstants.RPAREN, lambdaExpr.getTokenRange().get().getEnd().getKind());
179     }
180 
181     @Test
rangeOfLambdaBody()182     public void rangeOfLambdaBody() {
183         String code = "class A {" + EOL
184                 + "  Object f() {" + EOL
185                 + "    return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey()); " + EOL
186                 + "}}";
187         CompilationUnit cu = JavaParser.parse(code);
188         MethodDeclaration methodDeclaration = cu.getClassByName("A").get().getMember(0).asMethodDeclaration();
189         ReturnStmt returnStmt = methodDeclaration.getBody().get().getStatement(0).asReturnStmt();
190         CastExpr castExpr = returnStmt.getExpression().get().asCastExpr();
191         LambdaExpr lambdaExpr = castExpr.getExpression().asLambdaExpr();
192         Statement lambdaBody = lambdaExpr.getBody();
193         assertEquals(range(3, 68, 3, 101), lambdaBody.getRange().get());
194     }
195 
196     @Test
testNotStoringTokens()197     public void testNotStoringTokens() {
198         JavaParser javaParser = new JavaParser(new ParserConfiguration().setStoreTokens(false));
199         ParseResult<CompilationUnit> result = javaParser.parse(ParseStart.COMPILATION_UNIT, provider("class X{}"));
200         assertEquals(false, result.getTokens().isPresent());
201     }
202 
203     @Test(expected = ParseProblemException.class)
trailingCodeIsAnError()204     public void trailingCodeIsAnError() {
205         JavaParser.parseBlock("{} efijqoifjqefj");
206     }
207 
208     @Test
trailingWhitespaceIsIgnored()209     public void trailingWhitespaceIsIgnored() {
210         BlockStmt blockStmt = JavaParser.parseBlock("{} // hello");
211         assertEquals("{}", blockStmt.getTokenRange().get().toString());
212     }
213 
214     @Test
everyTokenHasACategory()215     public void everyTokenHasACategory() throws IOException {
216         final int tokenCount = GeneratedJavaParserConstants.tokenImage.length;
217         Path tokenTypesPath = mavenModuleRoot(JavaParserTest.class).resolve("../javaparser-core/src/main/java/com/github/javaparser/TokenTypes.java");
218         CompilationUnit tokenTypesCu = JavaParser.parse(tokenTypesPath);
219         // -1 to take off the default: case.
220         int switchEntries = tokenTypesCu.findAll(SwitchEntryStmt.class).size()-1;
221         // The amount of "case XXX:" in TokenTypes.java should be equal to the amount of tokens JavaCC knows about:
222         assertEquals(tokenCount, switchEntries);
223     }
224 
225     @Test
parsingInitializedAndUnitializedVarsInForStmt()226     public void parsingInitializedAndUnitializedVarsInForStmt() {
227         ForStmt forStmt = JavaParser.parseStatement("for(int a,b=0;;){}").asForStmt();
228         assertEquals(1, forStmt.getInitialization().size());
229         assertEquals(true, forStmt.getInitialization().get(0).isVariableDeclarationExpr());
230         assertEquals(2, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().size());
231         assertEquals("a", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getNameAsString());
232         assertEquals("b", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getNameAsString());
233         assertEquals(false, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getInitializer().isPresent());
234         assertEquals(true, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getInitializer().isPresent());
235     }
236 
237     @Test
parsingInitializedAndUnitializedVarsInForStmtComplexCase()238     public void parsingInitializedAndUnitializedVarsInForStmtComplexCase() {
239         // See issue 1281
240         ForStmt forStmt = JavaParser.parseStatement("for(int i, j = array2.length - 1;;){}").asForStmt();
241         assertEquals(1, forStmt.getInitialization().size());
242         assertEquals(true, forStmt.getInitialization().get(0).isVariableDeclarationExpr());
243         assertEquals(2, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().size());
244         assertEquals("i", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getNameAsString());
245         assertEquals("j", forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getNameAsString());
246         assertEquals(false, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(0).getInitializer().isPresent());
247         assertEquals(true, forStmt.getInitialization().get(0).asVariableDeclarationExpr().getVariables().get(1).getInitializer().isPresent());
248     }
249 }
250