• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.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 Júlio 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      */
JavaParser()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      */
JavaParser(ParserConfiguration configuration)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      */
getStaticConfiguration()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      */
setStaticConfiguration(ParserConfiguration staticConfiguration)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      */
getParserConfiguration()96     public ParserConfiguration getParserConfiguration() {
97         return this.configuration;
98     }
99 
getParserForProvider(Provider provider)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      */
parse(ParseStart<N> start, Provider provider)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      */
parse(final InputStream in, Charset encoding)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      */
parse(final InputStream in)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      */
parse(final File file, final Charset encoding)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      */
parse(final File file)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      */
parse(final Path path, final Charset encoding)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      */
parse(final Path path)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      */
parseResource(final String path)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      */
parseResource(final String path, Charset encoding)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      */
parseResource(final ClassLoader classLoader, final String path, Charset encoding)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      */
parse(final Reader reader)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      */
parse(String code)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      */
parseBlock(final String blockStatement)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      */
parseStatement(final String statement)320     public static Statement parseStatement(final String statement) {
321         return simplifiedParse(STATEMENT, provider(statement));
322     }
323 
simplifiedParse(ParseStart<T> context, Provider provider)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      */
parseImport(final String importDeclaration)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")
parseExpression(final String expression)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      */
parseAnnotation(final String annotation)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      */
parseAnnotationBodyDeclaration(final String body)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
parseClassBodyDeclaration(String body)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
parseInterfaceBodyDeclaration(String body)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      */
parseBodyDeclaration(String body)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      */
parseClassOrInterfaceType(String type)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      */
parseType(String type)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      */
parseVariableDeclarationExpr(String declaration)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      */
parseJavadoc(String content)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      */
parseExplicitConstructorInvocationStmt(String statement)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      */
parseName(String qualifiedName)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      */
parseSimpleName(String name)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      */
parseParameter(String parameter)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      */
parsePackageDeclaration(String packageDeclaration)519     public static PackageDeclaration parsePackageDeclaration(String packageDeclaration) {
520         return simplifiedParse(PACKAGE_DECLARATION, provider(packageDeclaration));
521     }
522 }
523