Home | History | Annotate | Download | only in javaparser
      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