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.Node;
     26 import com.github.javaparser.ast.validator.*;
     27 import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
     28 import com.github.javaparser.resolution.SymbolResolver;
     29 import com.github.javaparser.version.Java10PostProcessor;
     30 import com.github.javaparser.version.Java11PostProcessor;
     31 
     32 import java.util.ArrayList;
     33 import java.util.List;
     34 import java.util.Optional;
     35 
     36 import static com.github.javaparser.ParserConfiguration.LanguageLevel.*;
     37 import static com.github.javaparser.utils.Utils.assertNotNull;
     38 
     39 /**
     40  * The configuration that is used by the parser.
     41  * Note that this can be changed even when reusing the same JavaParser instance.
     42  * It will pick up the changes.
     43  */
     44 public class ParserConfiguration {
     45     public enum LanguageLevel {
     46         /** Does no post processing or validation. Only for people wanting the fastest parsing. */
     47         RAW(null, null),
     48         /** The most used Java version. */
     49         POPULAR(new Java8Validator(), null),
     50         /** The latest Java version that is available. */
     51         CURRENT(new Java8Validator(), null),
     52         /** The newest Java features supported. */
     53         BLEEDING_EDGE(new Java11Validator(), new Java11PostProcessor()),
     54         /** Java 1.0 */
     55         JAVA_1_0(new Java1_0Validator(), null),
     56         /** Java 1.1 */
     57         JAVA_1_1(new Java1_1Validator(), null),
     58         /** Java 1.2 */
     59         JAVA_1_2(new Java1_2Validator(), null),
     60         /** Java 1.3 */
     61         JAVA_1_3(new Java1_3Validator(), null),
     62         /** Java 1.4 */
     63         JAVA_1_4(new Java1_4Validator(), null),
     64         /** Java 5 */
     65         JAVA_5(new Java5Validator(), null),
     66         /** Java 6 */
     67         JAVA_6(new Java6Validator(), null),
     68         /** Java 7 */
     69         JAVA_7(new Java7Validator(), null),
     70         /** Java 8 */
     71         JAVA_8(new Java8Validator(), null),
     72         /** Java 9 */
     73         JAVA_9(new Java9Validator(), null),
     74         /** Java 10 */
     75         JAVA_10(new Java10Validator(), new Java10PostProcessor()),
     76         /** Java 11 (work in progress) */
     77         JAVA_11_PREVIEW(new Java11Validator(), new Java11PostProcessor());
     78 
     79         final Validator validator;
     80         final ParseResult.PostProcessor postProcessor;
     81 
     82         LanguageLevel(Validator validator, ParseResult.PostProcessor postProcessor) {
     83             this.validator = validator;
     84             this.postProcessor = postProcessor;
     85         }
     86     }
     87 
     88     private boolean storeTokens = true;
     89     private boolean attributeComments = true;
     90     private boolean doNotAssignCommentsPrecedingEmptyLines = true;
     91     private boolean doNotConsiderAnnotationsAsNodeStartForCodeAttribution = false;
     92     private boolean lexicalPreservationEnabled = false;
     93     private SymbolResolver symbolResolver = null;
     94     private int tabSize = 1;
     95     private LanguageLevel languageLevel = CURRENT;
     96 
     97     private final List<ParseResult.PostProcessor> postProcessors = new ArrayList<>();
     98 
     99     public ParserConfiguration() {
    100         postProcessors.add((result, configuration) -> {
    101             if (configuration.isLexicalPreservationEnabled()) {
    102                 if (configuration.isLexicalPreservationEnabled()) {
    103                     result.ifSuccessful(LexicalPreservingPrinter::setup);
    104                 }
    105             }
    106         });
    107         postProcessors.add((result, configuration) -> {
    108             if (configuration.isAttributeComments()) {
    109                 result.ifSuccessful(resultNode -> result
    110                         .getCommentsCollection().ifPresent(comments ->
    111                                 new CommentsInserter(configuration).insertComments(resultNode, comments.copy().getComments())));
    112             }
    113         });
    114         postProcessors.add((result, configuration) -> {
    115             LanguageLevel languageLevel = getLanguageLevel();
    116             if (languageLevel.postProcessor != null) {
    117                 languageLevel.postProcessor.process(result, configuration);
    118             }
    119             if (languageLevel.validator != null) {
    120                 languageLevel.validator.accept(result.getResult().get(), new ProblemReporter(newProblem -> result.getProblems().add(newProblem)));
    121             }
    122         });
    123         postProcessors.add((result, configuration) -> configuration.getSymbolResolver().ifPresent(symbolResolver ->
    124                 result.ifSuccessful(resultNode -> {
    125                     if (resultNode instanceof CompilationUnit) {
    126                         resultNode.setData(Node.SYMBOL_RESOLVER_KEY, symbolResolver);
    127                     }
    128                 })
    129         ));
    130     }
    131 
    132     public boolean isAttributeComments() {
    133         return attributeComments;
    134     }
    135 
    136     /**
    137      * Whether to run CommentsInserter, which will put the comments that were found in the source code into the comment
    138      * and javadoc fields of the nodes it thinks they refer to.
    139      */
    140     public ParserConfiguration setAttributeComments(boolean attributeComments) {
    141         this.attributeComments = attributeComments;
    142         return this;
    143     }
    144 
    145     public boolean isDoNotAssignCommentsPrecedingEmptyLines() {
    146         return doNotAssignCommentsPrecedingEmptyLines;
    147     }
    148 
    149     public ParserConfiguration setDoNotAssignCommentsPrecedingEmptyLines(boolean doNotAssignCommentsPrecedingEmptyLines) {
    150         this.doNotAssignCommentsPrecedingEmptyLines = doNotAssignCommentsPrecedingEmptyLines;
    151         return this;
    152     }
    153 
    154     public boolean isDoNotConsiderAnnotationsAsNodeStartForCodeAttribution() {
    155         return doNotConsiderAnnotationsAsNodeStartForCodeAttribution;
    156     }
    157 
    158     public ParserConfiguration setDoNotConsiderAnnotationsAsNodeStartForCodeAttribution(boolean doNotConsiderAnnotationsAsNodeStartForCodeAttribution) {
    159         this.doNotConsiderAnnotationsAsNodeStartForCodeAttribution = doNotConsiderAnnotationsAsNodeStartForCodeAttribution;
    160         return this;
    161     }
    162 
    163     public ParserConfiguration setStoreTokens(boolean storeTokens) {
    164         this.storeTokens = storeTokens;
    165         if (!storeTokens) {
    166             setAttributeComments(false);
    167         }
    168         return this;
    169     }
    170 
    171     public boolean isStoreTokens() {
    172         return storeTokens;
    173     }
    174 
    175     public int getTabSize() {
    176         return tabSize;
    177     }
    178 
    179     /**
    180      * When a TAB character is encountered during parsing, the column position will be increased by this value.
    181      * By default it is 1.
    182      */
    183     public ParserConfiguration setTabSize(int tabSize) {
    184         this.tabSize = tabSize;
    185         return this;
    186     }
    187 
    188     /**
    189      * @deprecated use getLanguageLevel
    190      */
    191     @Deprecated
    192     public Optional<Validator> getValidator() {
    193         throw new IllegalStateException("method is deprecated");
    194     }
    195 
    196     /**
    197      * @deprecated use setLanguageLevel, or getPostProcessors if you use a custom validator.
    198      */
    199     @Deprecated
    200     public ParserConfiguration setValidator(Validator validator) {
    201         // This whole method is a backwards compatability hack.
    202         if (validator instanceof Java10Validator) {
    203             setLanguageLevel(JAVA_10);
    204         } else if (validator instanceof Java9Validator) {
    205             setLanguageLevel(JAVA_9);
    206         } else if (validator instanceof Java8Validator) {
    207             setLanguageLevel(JAVA_8);
    208         } else if (validator instanceof Java7Validator) {
    209             setLanguageLevel(JAVA_7);
    210         } else if (validator instanceof Java6Validator) {
    211             setLanguageLevel(JAVA_6);
    212         } else if (validator instanceof Java5Validator) {
    213             setLanguageLevel(JAVA_5);
    214         } else if (validator instanceof Java1_4Validator) {
    215             setLanguageLevel(JAVA_1_4);
    216         } else if (validator instanceof Java1_3Validator) {
    217             setLanguageLevel(JAVA_1_3);
    218         } else if (validator instanceof Java1_2Validator) {
    219             setLanguageLevel(JAVA_1_2);
    220         } else if (validator instanceof Java1_1Validator) {
    221             setLanguageLevel(JAVA_1_1);
    222         } else if (validator instanceof Java1_0Validator) {
    223             setLanguageLevel(JAVA_1_0);
    224         } else if (validator instanceof NoProblemsValidator) {
    225             setLanguageLevel(RAW);
    226         }
    227         return this;
    228     }
    229 
    230     /**
    231      * Disabled by default.
    232      * When this is enabled, LexicalPreservingPrinter.print can be used to reproduce
    233      * the original formatting of the file.
    234      */
    235     public ParserConfiguration setLexicalPreservationEnabled(boolean lexicalPreservationEnabled) {
    236         this.lexicalPreservationEnabled = lexicalPreservationEnabled;
    237         return this;
    238     }
    239 
    240     public boolean isLexicalPreservationEnabled() {
    241         return lexicalPreservationEnabled;
    242     }
    243 
    244     /**
    245      * Retrieve the SymbolResolver to be used while parsing, if any.
    246      */
    247     public Optional<SymbolResolver> getSymbolResolver() {
    248         return Optional.ofNullable(symbolResolver);
    249     }
    250 
    251     /**
    252      * Set the SymbolResolver to be injected while parsing.
    253      */
    254     public ParserConfiguration setSymbolResolver(SymbolResolver symbolResolver) {
    255         this.symbolResolver = symbolResolver;
    256         return this;
    257     }
    258 
    259     public List<ParseResult.PostProcessor> getPostProcessors() {
    260         return postProcessors;
    261     }
    262 
    263     public ParserConfiguration setLanguageLevel(LanguageLevel languageLevel) {
    264         this.languageLevel = assertNotNull(languageLevel);
    265         return this;
    266     }
    267 
    268     public LanguageLevel getLanguageLevel() {
    269         return languageLevel;
    270     }
    271 }
    272