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.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 
LanguageLevel(Validator validator, ParseResult.PostProcessor postProcessor)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 
ParserConfiguration()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 
isAttributeComments()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      */
setAttributeComments(boolean attributeComments)140     public ParserConfiguration setAttributeComments(boolean attributeComments) {
141         this.attributeComments = attributeComments;
142         return this;
143     }
144 
isDoNotAssignCommentsPrecedingEmptyLines()145     public boolean isDoNotAssignCommentsPrecedingEmptyLines() {
146         return doNotAssignCommentsPrecedingEmptyLines;
147     }
148 
setDoNotAssignCommentsPrecedingEmptyLines(boolean doNotAssignCommentsPrecedingEmptyLines)149     public ParserConfiguration setDoNotAssignCommentsPrecedingEmptyLines(boolean doNotAssignCommentsPrecedingEmptyLines) {
150         this.doNotAssignCommentsPrecedingEmptyLines = doNotAssignCommentsPrecedingEmptyLines;
151         return this;
152     }
153 
isDoNotConsiderAnnotationsAsNodeStartForCodeAttribution()154     public boolean isDoNotConsiderAnnotationsAsNodeStartForCodeAttribution() {
155         return doNotConsiderAnnotationsAsNodeStartForCodeAttribution;
156     }
157 
setDoNotConsiderAnnotationsAsNodeStartForCodeAttribution(boolean doNotConsiderAnnotationsAsNodeStartForCodeAttribution)158     public ParserConfiguration setDoNotConsiderAnnotationsAsNodeStartForCodeAttribution(boolean doNotConsiderAnnotationsAsNodeStartForCodeAttribution) {
159         this.doNotConsiderAnnotationsAsNodeStartForCodeAttribution = doNotConsiderAnnotationsAsNodeStartForCodeAttribution;
160         return this;
161     }
162 
setStoreTokens(boolean storeTokens)163     public ParserConfiguration setStoreTokens(boolean storeTokens) {
164         this.storeTokens = storeTokens;
165         if (!storeTokens) {
166             setAttributeComments(false);
167         }
168         return this;
169     }
170 
isStoreTokens()171     public boolean isStoreTokens() {
172         return storeTokens;
173     }
174 
getTabSize()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      */
setTabSize(int tabSize)183     public ParserConfiguration setTabSize(int tabSize) {
184         this.tabSize = tabSize;
185         return this;
186     }
187 
188     /**
189      * @deprecated use getLanguageLevel
190      */
191     @Deprecated
getValidator()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
setValidator(Validator validator)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      */
setLexicalPreservationEnabled(boolean lexicalPreservationEnabled)235     public ParserConfiguration setLexicalPreservationEnabled(boolean lexicalPreservationEnabled) {
236         this.lexicalPreservationEnabled = lexicalPreservationEnabled;
237         return this;
238     }
239 
isLexicalPreservationEnabled()240     public boolean isLexicalPreservationEnabled() {
241         return lexicalPreservationEnabled;
242     }
243 
244     /**
245      * Retrieve the SymbolResolver to be used while parsing, if any.
246      */
getSymbolResolver()247     public Optional<SymbolResolver> getSymbolResolver() {
248         return Optional.ofNullable(symbolResolver);
249     }
250 
251     /**
252      * Set the SymbolResolver to be injected while parsing.
253      */
setSymbolResolver(SymbolResolver symbolResolver)254     public ParserConfiguration setSymbolResolver(SymbolResolver symbolResolver) {
255         this.symbolResolver = symbolResolver;
256         return this;
257     }
258 
getPostProcessors()259     public List<ParseResult.PostProcessor> getPostProcessors() {
260         return postProcessors;
261     }
262 
setLanguageLevel(LanguageLevel languageLevel)263     public ParserConfiguration setLanguageLevel(LanguageLevel languageLevel) {
264         this.languageLevel = assertNotNull(languageLevel);
265         return this;
266     }
267 
getLanguageLevel()268     public LanguageLevel getLanguageLevel() {
269         return languageLevel;
270     }
271 }
272