1 /* 2 * Copyright (C) 2007-2010 Jlio 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.ImportDeclaration; 26 import com.github.javaparser.ast.Node; 27 import com.github.javaparser.ast.PackageDeclaration; 28 import com.github.javaparser.ast.body.BodyDeclaration; 29 import com.github.javaparser.ast.body.Parameter; 30 import com.github.javaparser.ast.expr.*; 31 import com.github.javaparser.ast.stmt.BlockStmt; 32 import com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt; 33 import com.github.javaparser.ast.stmt.Statement; 34 import com.github.javaparser.ast.type.ClassOrInterfaceType; 35 import com.github.javaparser.ast.type.Type; 36 import com.github.javaparser.javadoc.Javadoc; 37 38 import java.io.*; 39 import java.nio.charset.Charset; 40 import java.nio.file.Path; 41 42 import static com.github.javaparser.ParseStart.*; 43 import static com.github.javaparser.Problem.PROBLEM_BY_BEGIN_POSITION; 44 import static com.github.javaparser.Providers.*; 45 import static com.github.javaparser.utils.Utils.assertNotNull; 46 47 /** 48 * Parse Java source code and creates Abstract Syntax Trees. 49 * 50 * @author Jlio Vilmar Gesser 51 */ 52 public final class JavaParser { 53 private final ParserConfiguration configuration; 54 55 private GeneratedJavaParser astParser = null; 56 private static ParserConfiguration staticConfiguration = new ParserConfiguration(); 57 58 /** 59 * Instantiate the parser with default configuration. Note that parsing can also be done with the static methods on 60 * this class. 61 * Creating an instance will reduce setup time between parsing files. 62 */ 63 public JavaParser() { 64 this(new ParserConfiguration()); 65 } 66 67 /** 68 * Instantiate the parser. Note that parsing can also be done with the static methods on this class. 69 * Creating an instance will reduce setup time between parsing files. 70 */ 71 public JavaParser(ParserConfiguration configuration) { 72 this.configuration = configuration; 73 } 74 75 /** 76 * Get the configuration for the static parse... methods. 77 * This is a STATIC field, so modifying it will directly change how all static parse... methods work! 78 */ 79 public static ParserConfiguration getStaticConfiguration() { 80 return staticConfiguration; 81 } 82 83 /** 84 * Set the configuration for the static parse... methods. 85 * This is a STATIC field, so modifying it will directly change how all static parse... methods work! 86 */ 87 public static void setStaticConfiguration(ParserConfiguration staticConfiguration) { 88 JavaParser.staticConfiguration = staticConfiguration; 89 } 90 91 /** 92 * Get the non-static configuration for this parser. 93 * 94 * @return The non-static configuration for this parser. 95 */ 96 public ParserConfiguration getParserConfiguration() { 97 return this.configuration; 98 } 99 100 private GeneratedJavaParser getParserForProvider(Provider provider) { 101 if (astParser == null) { 102 astParser = new GeneratedJavaParser(provider); 103 } else { 104 astParser.reset(provider); 105 } 106 astParser.setTabSize(configuration.getTabSize()); 107 astParser.setStoreTokens(configuration.isStoreTokens()); 108 return astParser; 109 } 110 111 /** 112 * Parses source code. 113 * It takes the source code from a Provider. 114 * The start indicates what can be found in the source code (compilation unit, block, import...) 115 * 116 * @param start refer to the constants in ParseStart to see what can be parsed. 117 * @param provider refer to Providers to see how you can read source. The provider will be closed after parsing. 118 * @param <N> the subclass of Node that is the result of parsing in the start. 119 * @return the parse result, a collection of encountered problems, and some extra data. 120 */ 121 public <N extends Node> ParseResult<N> parse(ParseStart<N> start, Provider provider) { 122 assertNotNull(start); 123 assertNotNull(provider); 124 final GeneratedJavaParser parser = getParserForProvider(provider); 125 try { 126 N resultNode = start.parse(parser); 127 ParseResult<N> result = new ParseResult<>(resultNode, parser.problems, parser.getTokens(), 128 parser.getCommentsCollection()); 129 130 configuration.getPostProcessors().forEach(postProcessor -> 131 postProcessor.process(result, configuration)); 132 133 result.getProblems().sort(PROBLEM_BY_BEGIN_POSITION); 134 135 return result; 136 } catch (Exception e) { 137 final String message = e.getMessage() == null ? "Unknown error" : e.getMessage(); 138 parser.problems.add(new Problem(message, null, e)); 139 return new ParseResult<>(null, parser.problems, parser.getTokens(), parser.getCommentsCollection()); 140 } finally { 141 try { 142 provider.close(); 143 } catch (IOException e) { 144 // Since we're done parsing and have our result, we don't care about any errors. 145 } 146 } 147 } 148 149 /** 150 * Parses the Java code contained in the {@link InputStream} and returns a 151 * {@link CompilationUnit} that represents it. 152 * 153 * @param in {@link InputStream} containing Java source code. It will be closed after parsing. 154 * @param encoding encoding of the source code 155 * @return CompilationUnit representing the Java source code 156 * @throws ParseProblemException if the source code has parser errors 157 */ 158 public static CompilationUnit parse(final InputStream in, Charset encoding) { 159 return simplifiedParse(COMPILATION_UNIT, provider(in, encoding)); 160 } 161 162 /** 163 * Parses the Java code contained in the {@link InputStream} and returns a 164 * {@link CompilationUnit} that represents it.<br> 165 * Note: Uses UTF-8 encoding 166 * 167 * @param in {@link InputStream} containing Java source code. It will be closed after parsing. 168 * @return CompilationUnit representing the Java source code 169 * @throws ParseProblemException if the source code has parser errors 170 */ 171 public static CompilationUnit parse(final InputStream in) { 172 return parse(in, UTF8); 173 } 174 175 /** 176 * Parses the Java code contained in a {@link File} and returns a 177 * {@link CompilationUnit} that represents it. 178 * 179 * @param file {@link File} containing Java source code. It will be closed after parsing. 180 * @param encoding encoding of the source code 181 * @return CompilationUnit representing the Java source code 182 * @throws ParseProblemException if the source code has parser errors 183 * @throws FileNotFoundException the file was not found 184 */ 185 public static CompilationUnit parse(final File file, final Charset encoding) throws FileNotFoundException { 186 return simplifiedParse(COMPILATION_UNIT, provider(file, encoding)).setStorage(file.toPath()); 187 } 188 189 /** 190 * Parses the Java code contained in a {@link File} and returns a 191 * {@link CompilationUnit} that represents it.<br> 192 * Note: Uses UTF-8 encoding 193 * 194 * @param file {@link File} containing Java source code. It will be closed after parsing. 195 * @return CompilationUnit representing the Java source code 196 * @throws ParseProblemException if the source code has parser errors 197 * @throws FileNotFoundException the file was not found 198 */ 199 public static CompilationUnit parse(final File file) throws FileNotFoundException { 200 return simplifiedParse(COMPILATION_UNIT, provider(file)).setStorage(file.toPath()); 201 } 202 203 /** 204 * Parses the Java code contained in a file and returns a 205 * {@link CompilationUnit} that represents it. 206 * 207 * @param path path to a file containing Java source code 208 * @param encoding encoding of the source code 209 * @return CompilationUnit representing the Java source code 210 * @throws IOException the path could not be accessed 211 * @throws ParseProblemException if the source code has parser errors 212 */ 213 public static CompilationUnit parse(final Path path, final Charset encoding) throws IOException { 214 return simplifiedParse(COMPILATION_UNIT, provider(path, encoding)).setStorage(path); 215 } 216 217 /** 218 * Parses the Java code contained in a file and returns a 219 * {@link CompilationUnit} that represents it.<br> 220 * Note: Uses UTF-8 encoding 221 * 222 * @param path path to a file containing Java source code 223 * @return CompilationUnit representing the Java source code 224 * @throws ParseProblemException if the source code has parser errors 225 * @throws IOException the path could not be accessed 226 */ 227 public static CompilationUnit parse(final Path path) throws IOException { 228 return simplifiedParse(COMPILATION_UNIT, provider(path)).setStorage(path); 229 } 230 231 /** 232 * Parses the Java code contained in a resource and returns a 233 * {@link CompilationUnit} that represents it.<br> 234 * Note: Uses UTF-8 encoding 235 * 236 * @param path path to a resource containing Java source code. As resource is accessed through a class loader, a 237 * leading "/" is not allowed in pathToResource 238 * @return CompilationUnit representing the Java source code 239 * @throws ParseProblemException if the source code has parser errors 240 * @throws IOException the path could not be accessed 241 */ 242 public static CompilationUnit parseResource(final String path) throws IOException { 243 return simplifiedParse(COMPILATION_UNIT, resourceProvider(path)); 244 } 245 246 /** 247 * Parses the Java code contained in a resource and returns a 248 * {@link CompilationUnit} that represents it.<br> 249 * 250 * @param path path to a resource containing Java source code. As resource is accessed through a class loader, a 251 * leading "/" is not allowed in pathToResource 252 * @param encoding encoding of the source code 253 * @return CompilationUnit representing the Java source code 254 * @throws ParseProblemException if the source code has parser errors 255 * @throws IOException the path could not be accessed 256 */ 257 public static CompilationUnit parseResource(final String path, Charset encoding) throws IOException { 258 return simplifiedParse(COMPILATION_UNIT, resourceProvider(path, encoding)); 259 } 260 261 /** 262 * Parses the Java code contained in a resource and returns a 263 * {@link CompilationUnit} that represents it.<br> 264 * 265 * @param classLoader the classLoader that is asked to load the resource 266 * @param path path to a resource containing Java source code. As resource is accessed through a class loader, a 267 * leading "/" is not allowed in pathToResource 268 * @return CompilationUnit representing the Java source code 269 * @throws ParseProblemException if the source code has parser errors 270 * @throws IOException the path could not be accessed 271 */ 272 public static CompilationUnit parseResource(final ClassLoader classLoader, final String path, Charset encoding) throws IOException { 273 return simplifiedParse(COMPILATION_UNIT, resourceProvider(classLoader, path, encoding)); 274 } 275 276 /** 277 * Parses Java code from a Reader and returns a 278 * {@link CompilationUnit} that represents it.<br> 279 * 280 * @param reader the reader containing Java source code. It will be closed after parsing. 281 * @return CompilationUnit representing the Java source code 282 * @throws ParseProblemException if the source code has parser errors 283 */ 284 public static CompilationUnit parse(final Reader reader) { 285 return simplifiedParse(COMPILATION_UNIT, provider(reader)); 286 } 287 288 /** 289 * Parses the Java code contained in code and returns a 290 * {@link CompilationUnit} that represents it. 291 * 292 * @param code Java source code 293 * @return CompilationUnit representing the Java source code 294 * @throws ParseProblemException if the source code has parser errors 295 */ 296 public static CompilationUnit parse(String code) { 297 return simplifiedParse(COMPILATION_UNIT, provider(code)); 298 } 299 300 /** 301 * Parses the Java block contained in a {@link String} and returns a 302 * {@link BlockStmt} that represents it. 303 * 304 * @param blockStatement {@link String} containing Java block code 305 * @return BlockStmt representing the Java block 306 * @throws ParseProblemException if the source code has parser errors 307 */ 308 public static BlockStmt parseBlock(final String blockStatement) { 309 return simplifiedParse(BLOCK, provider(blockStatement)); 310 } 311 312 /** 313 * Parses the Java statement contained in a {@link String} and returns a 314 * {@link Statement} that represents it. 315 * 316 * @param statement {@link String} containing Java statement code 317 * @return Statement representing the Java statement 318 * @throws ParseProblemException if the source code has parser errors 319 */ 320 public static Statement parseStatement(final String statement) { 321 return simplifiedParse(STATEMENT, provider(statement)); 322 } 323 324 private static <T extends Node> T simplifiedParse(ParseStart<T> context, Provider provider) { 325 ParseResult<T> result = new JavaParser(staticConfiguration).parse(context, provider); 326 if (result.isSuccessful()) { 327 return result.getResult().get(); 328 } 329 throw new ParseProblemException(result.getProblems()); 330 } 331 332 /** 333 * Parses the Java import contained in a {@link String} and returns a 334 * {@link ImportDeclaration} that represents it. 335 * 336 * @param importDeclaration {@link String} containing Java import code 337 * @return ImportDeclaration representing the Java import declaration 338 * @throws ParseProblemException if the source code has parser errors 339 */ 340 public static ImportDeclaration parseImport(final String importDeclaration) { 341 return simplifiedParse(IMPORT_DECLARATION, provider(importDeclaration)); 342 } 343 344 /** 345 * Parses the Java expression contained in a {@link String} and returns a 346 * {@link Expression} that represents it. 347 * 348 * @param expression {@link String} containing Java expression 349 * @return Expression representing the Java expression 350 * @throws ParseProblemException if the source code has parser errors 351 */ 352 @SuppressWarnings("unchecked") 353 public static <T extends Expression> T parseExpression(final String expression) { 354 return (T) simplifiedParse(EXPRESSION, provider(expression)); 355 } 356 357 /** 358 * Parses the Java annotation contained in a {@link String} and returns a 359 * {@link AnnotationExpr} that represents it. 360 * 361 * @param annotation {@link String} containing Java annotation 362 * @return AnnotationExpr representing the Java annotation 363 * @throws ParseProblemException if the source code has parser errors 364 */ 365 public static AnnotationExpr parseAnnotation(final String annotation) { 366 return simplifiedParse(ANNOTATION, provider(annotation)); 367 } 368 369 /** 370 * Parses the Java annotation body declaration(e.g fields or methods) contained in a 371 * {@link String} and returns a {@link BodyDeclaration} that represents it. 372 * 373 * @param body {@link String} containing Java body declaration 374 * @return BodyDeclaration representing the Java annotation 375 * @throws ParseProblemException if the source code has parser errors 376 */ 377 public static BodyDeclaration<?> parseAnnotationBodyDeclaration(final String body) { 378 return simplifiedParse(ANNOTATION_BODY, provider(body)); 379 } 380 381 /** 382 * Parses a Java class body declaration(e.g fields or methods) and returns a 383 * {@link BodyDeclaration} that represents it. 384 * 385 * @param body the body of a class 386 * @return BodyDeclaration representing the Java class body 387 * @throws ParseProblemException if the source code has parser errors 388 * @deprecated just use parseBodyDeclaration now. 389 */ 390 @Deprecated 391 public static BodyDeclaration<?> parseClassBodyDeclaration(String body) { 392 return parseBodyDeclaration(body); 393 } 394 395 /** 396 * Parses a Java interface body declaration(e.g fields or methods) and returns a 397 * {@link BodyDeclaration} that represents it. 398 * 399 * @param body the body of an interface 400 * @return BodyDeclaration representing the Java interface body 401 * @throws ParseProblemException if the source code has parser errors 402 * @deprecated just use parseBodyDeclaration now. 403 */ 404 @Deprecated 405 public static BodyDeclaration<?> parseInterfaceBodyDeclaration(String body) { 406 return parseBodyDeclaration(body); 407 } 408 409 /** 410 * Parses a Java class or interface body declaration(e.g fields or methods) and returns a 411 * {@link BodyDeclaration} that represents it. 412 * 413 * @param body the body of a class or interface 414 * @return BodyDeclaration representing the Java interface body 415 * @throws ParseProblemException if the source code has parser errors 416 */ 417 public static BodyDeclaration<?> parseBodyDeclaration(String body) { 418 return simplifiedParse(CLASS_BODY, provider(body)); 419 } 420 421 /** 422 * Parses a Java class or interface type name and returns a {@link ClassOrInterfaceType} that represents it. 423 * 424 * @param type the type name like a.b.c.X or Y 425 * @return ClassOrInterfaceType representing the type 426 * @throws ParseProblemException if the source code has parser errors 427 */ 428 public static ClassOrInterfaceType parseClassOrInterfaceType(String type) { 429 return simplifiedParse(CLASS_OR_INTERFACE_TYPE, provider(type)); 430 } 431 432 /** 433 * Parses a Java type name and returns a {@link Type} that represents it. 434 * 435 * @param type the type name like a.b.c.X, Y, or int 436 * @return ClassOrInterfaceType representing the type 437 * @throws ParseProblemException if the source code has parser errors 438 */ 439 public static Type parseType(String type) { 440 return simplifiedParse(TYPE, provider(type)); 441 } 442 443 /** 444 * Parses a variable declaration expression and returns a {@link com.github.javaparser.ast.expr.VariableDeclarationExpr} 445 * that represents it. 446 * 447 * @param declaration a variable declaration like <code>int x=2;</code> 448 * @return VariableDeclarationExpr representing the type 449 * @throws ParseProblemException if the source code has parser errors 450 */ 451 public static VariableDeclarationExpr parseVariableDeclarationExpr(String declaration) { 452 return simplifiedParse(VARIABLE_DECLARATION_EXPR, provider(declaration)); 453 } 454 455 /** 456 * Parses the content of a JavadocComment and returns a {@link com.github.javaparser.javadoc.Javadoc} that 457 * represents it. 458 * 459 * @param content a variable declaration like <code>content of my javadoc\n * second line\n * third line</code> 460 * @return Javadoc representing the content of the comment 461 * @throws ParseProblemException if the source code has parser errors 462 */ 463 public static Javadoc parseJavadoc(String content) { 464 return JavadocParser.parse(content); 465 } 466 467 /** 468 * Parses the this(...) and super(...) statements that may occur at the start of a constructor. 469 * 470 * @param statement a statement like super("hello"); 471 * @return the AST for the statement. 472 * @throws ParseProblemException if the source code has parser errors 473 */ 474 public static ExplicitConstructorInvocationStmt parseExplicitConstructorInvocationStmt(String statement) { 475 return simplifiedParse(EXPLICIT_CONSTRUCTOR_INVOCATION_STMT, provider(statement)); 476 } 477 478 /** 479 * Parses a qualified name (one that can have "."s in it) and returns it as a Name. 480 * 481 * @param qualifiedName a name like "com.laamella.parameter_source" 482 * @return the AST for the name 483 * @throws ParseProblemException if the source code has parser errors 484 */ 485 public static Name parseName(String qualifiedName) { 486 return simplifiedParse(NAME, provider(qualifiedName)); 487 } 488 489 /** 490 * Parses a simple name (one that can NOT have "."s in it) and returns it as a SimpleName. 491 * 492 * @param name a name like "parameter_source" 493 * @return the AST for the name 494 * @throws ParseProblemException if the source code has parser errors 495 */ 496 public static SimpleName parseSimpleName(String name) { 497 return simplifiedParse(SIMPLE_NAME, provider(name)); 498 } 499 500 /** 501 * Parses a single parameter (a type and a name) and returns it as a Parameter. 502 * 503 * @param parameter a parameter like "int[] x" 504 * @return the AST for the parameter 505 * @throws ParseProblemException if the source code has parser errors 506 */ 507 public static Parameter parseParameter(String parameter) { 508 return simplifiedParse(PARAMETER, provider(parameter)); 509 } 510 511 512 /** 513 * Parses a package declaration and returns it as a PackageDeclaration. 514 * 515 * @param packageDeclaration a declaration like "package com.microsoft.java;" 516 * @return the AST for the parameter 517 * @throws ParseProblemException if the source code has parser errors 518 */ 519 public static PackageDeclaration parsePackageDeclaration(String packageDeclaration) { 520 return simplifiedParse(PACKAGE_DECLARATION, provider(packageDeclaration)); 521 } 522 } 523