JavaParser Source Viewer

Home|JavaParser/com/github/javaparser/ParserConfiguration.java
1/*
2 * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser.
3 * Copyright (C) 2011, 2013-2020 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
22package com.github.javaparser;
23
24import com.github.javaparser.ParseResult.PostProcessor;
25import com.github.javaparser.Providers.PreProcessor;
26import com.github.javaparser.UnicodeEscapeProcessingProvider.PositionMapping;
27import com.github.javaparser.ast.CompilationUnit;
28import com.github.javaparser.ast.Node;
29import com.github.javaparser.ast.validator.*;
30import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
31import com.github.javaparser.resolution.SymbolResolver;
32import com.github.javaparser.utils.LineSeparator;
33import com.github.javaparser.version.Java10PostProcessor;
34import com.github.javaparser.version.Java11PostProcessor;
35import com.github.javaparser.version.Java12PostProcessor;
36import com.github.javaparser.version.Java13PostProcessor;
37import com.github.javaparser.version.Java14PostProcessor;
38
39import java.nio.charset.Charset;
40import java.util.ArrayList;
41import java.util.List;
42import java.util.Optional;
43
44import static com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_8;
45
46/**
47 * The configuration that is used by the parser.
48 * Note that this can be changed even when reusing the same JavaParser instance.
49 * It will pick up the changes.
50 */
51public class ParserConfiguration {
52
53    public enum LanguageLevel {
54        /**
55         * Java 1.0
56         */
57        JAVA_1_0(new Java1_0Validator(), null),
58        /**
59         * Java 1.1
60         */
61        JAVA_1_1(new Java1_1Validator(), null),
62        /**
63         * Java 1.2
64         */
65        JAVA_1_2(new Java1_2Validator(), null),
66        /**
67         * Java 1.3
68         */
69        JAVA_1_3(new Java1_3Validator(), null),
70        /**
71         * Java 1.4
72         */
73        JAVA_1_4(new Java1_4Validator(), null),
74        /**
75         * Java 5
76         */
77        JAVA_5(new Java5Validator(), null),
78        /**
79         * Java 6
80         */
81        JAVA_6(new Java6Validator(), null),
82        /**
83         * Java 7
84         */
85        JAVA_7(new Java7Validator(), null),
86        /**
87         * Java 8
88         */
89        JAVA_8(new Java8Validator(), null),
90        /**
91         * Java 9
92         */
93        JAVA_9(new Java9Validator(), null),
94        /**
95         * Java 10
96         */
97        JAVA_10(new Java10Validator(), new Java10PostProcessor()),
98        /**
99         * Java 11
100         */
101        JAVA_11(new Java11Validator(), new Java11PostProcessor()),
102        /**
103         * Java 12
104         */
105        JAVA_12(new Java12Validator(), new Java12PostProcessor()),
106        /**
107         * Java 13
108         */
109        JAVA_13(new Java13Validator(), new Java13PostProcessor()),
110        /**
111         * Java 14
112         */
113        JAVA_14(new Java14Validator(), new Java14PostProcessor());
114
115        /**
116         * Does no post processing or validation. Only for people wanting the fastest parsing.
117         */
118        public static LanguageLevel RAW = null;
119        /**
120         * The most used Java version.
121         */
122        public static LanguageLevel POPULAR = JAVA_8;
123        /**
124         * The latest Java version that is available.
125         */
126        public static LanguageLevel CURRENT = JAVA_13;
127        /**
128         * The newest Java features supported.
129         */
130        public static LanguageLevel BLEEDING_EDGE = JAVA_14;
131
132        final Validator validator;
133        final ParseResult.PostProcessor postProcessor;
134
135        LanguageLevel(Validator validatorParseResult.PostProcessor postProcessor) {
136            this.validator = validator;
137            this.postProcessor = postProcessor;
138        }
139    }
140
141
142
143    // TODO: Add a configurable option e.g. setDesiredLineEnding(...) to replace/swap out existing line endings
144    private boolean detectOriginalLineSeparator = true;
145    private boolean storeTokens = true;
146    private boolean attributeComments = true;
147    private boolean doNotAssignCommentsPrecedingEmptyLines = true;
148    private boolean ignoreAnnotationsWhenAttributingComments = false;
149    private boolean lexicalPreservationEnabled = false;
150    private boolean preprocessUnicodeEscapes = false;
151    private SymbolResolver symbolResolver = null;
152    private int tabSize = 1;
153    private LanguageLevel languageLevel = JAVA_8;
154    private Charset characterEncoding = Providers.UTF8;
155
156    private final List<Providers.PreProcessorpreProcessors = new ArrayList<>();
157    private final List<ParseResult.PostProcessorpostProcessors = new ArrayList<>();
158
159    public ParserConfiguration() {
160
161        class UnicodeEscapeProcessor implements PreProcessorPostProcessor {
162            private UnicodeEscapeProcessingProvider _unicodeDecoder;
163
164            @Override
165            public Provider process(Provider innerProvider) {
166                if (isPreprocessUnicodeEscapes()) {
167                    _unicodeDecoder = new UnicodeEscapeProcessingProvider(innerProvider);
168                    return _unicodeDecoder;
169                }
170                return innerProvider;
171            }
172
173            @Override
174            public void process(ParseResult<? extends Noderesult,
175                                ParserConfiguration configuration) {
176                if (isPreprocessUnicodeEscapes()) {
177                    result.getResult().ifPresent(
178                            root -> {
179                                PositionMapping mapping = _unicodeDecoder.getPositionMapping();
180                                if (!mapping.isEmpty()) {
181                                    root.walk(
182                                            node -> node.getRange().ifPresent(
183                                                    range -> node.setRange(mapping.transform(range))));
184                                }
185                            }
186                    );
187                }
188            }
189        }
190        
191        class LineEndingProcessor implements PreProcessorPostProcessor {
192            private LineEndingProcessingProvider _lineEndingProcessingProvider;
193
194            @Override
195            public Provider process(Provider innerProvider) {
196                if (isDetectOriginalLineSeparator()) {
197                    _lineEndingProcessingProvider = new LineEndingProcessingProvider(innerProvider);
198                    return _lineEndingProcessingProvider;
199                }
200                return innerProvider;
201            }
202
203            @Override
204            public void process(ParseResult<? extends NoderesultParserConfiguration configuration) {
205                if (isDetectOriginalLineSeparator()) {
206                    result.getResult().ifPresent(
207                            rootNode -> {
208                                LineSeparator detectedLineSeparator = _lineEndingProcessingProvider.getDetectedLineEnding();
209
210                                // Set the line ending on the root node
211                                rootNode.setData(Node.LINE_SEPARATOR_KEYdetectedLineSeparator);
212
213//                                // Set the line ending on all children of the root node -- FIXME: Should ignore """textblocks"""
214//                                rootNode.findAll(Node.class)
215//                                        .forEach(node -> node.setData(Node.LINE_SEPARATOR_KEY, detectedLineSeparator));
216                            }
217                    );
218                }
219            }
220        }
221        
222        UnicodeEscapeProcessor unicodeProcessor = new UnicodeEscapeProcessor();
223        preProcessors.add(unicodeProcessor);
224        postProcessors.add(unicodeProcessor);
225        
226        LineEndingProcessor lineEndingProcessor = new LineEndingProcessor();
227        preProcessors.add(lineEndingProcessor);
228        postProcessors.add(lineEndingProcessor);
229        
230        
231        postProcessors.add((resultconfiguration) -> {
232            if (configuration.isAttributeComments()) {
233                result.ifSuccessful(resultNode -> result
234                        .getCommentsCollection().ifPresent(comments ->
235                                new CommentsInserter(configuration).insertComments(resultNodecomments.copy().getComments())));
236            }
237        });
238        postProcessors.add((resultconfiguration) -> {
239            LanguageLevel languageLevel = getLanguageLevel();
240            if (languageLevel != null) {
241                if (languageLevel.postProcessor != null) {
242                    languageLevel.postProcessor.process(resultconfiguration);
243                }
244                if (languageLevel.validator != null) {
245                    languageLevel.validator.accept(result.getResult().get(), new ProblemReporter(newProblem -> result.getProblems().add(newProblem)));
246                }
247            }
248        });
249        postProcessors.add((resultconfiguration) -> configuration.getSymbolResolver().ifPresent(symbolResolver ->
250                result.ifSuccessful(resultNode -> {
251                    if (resultNode instanceof CompilationUnit) {
252                        resultNode.setData(Node.SYMBOL_RESOLVER_KEYsymbolResolver);
253                    }
254                })
255        ));
256        postProcessors.add((resultconfiguration) -> {
257            if (configuration.isLexicalPreservationEnabled()) {
258                result.ifSuccessful(LexicalPreservingPrinter::setup);
259            }
260        });
261    }
262
263    public boolean isAttributeComments() {
264        return attributeComments;
265    }
266
267    /**
268     * Whether to run CommentsInserter, which will put the comments that were found in the source code into the comment
269     * and javadoc fields of the nodes it thinks they refer to.
270     */
271    public ParserConfiguration setAttributeComments(boolean attributeComments) {
272        this.attributeComments = attributeComments;
273        return this;
274    }
275
276    public boolean isDoNotAssignCommentsPrecedingEmptyLines() {
277        return doNotAssignCommentsPrecedingEmptyLines;
278    }
279
280    public ParserConfiguration setDoNotAssignCommentsPrecedingEmptyLines(boolean doNotAssignCommentsPrecedingEmptyLines) {
281        this.doNotAssignCommentsPrecedingEmptyLines = doNotAssignCommentsPrecedingEmptyLines;
282        return this;
283    }
284
285    public boolean isIgnoreAnnotationsWhenAttributingComments() {
286        return ignoreAnnotationsWhenAttributingComments;
287    }
288
289    public ParserConfiguration setIgnoreAnnotationsWhenAttributingComments(boolean ignoreAnnotationsWhenAttributingComments) {
290        this.ignoreAnnotationsWhenAttributingComments = ignoreAnnotationsWhenAttributingComments;
291        return this;
292    }
293
294    public ParserConfiguration setStoreTokens(boolean storeTokens) {
295        this.storeTokens = storeTokens;
296        if (!storeTokens) {
297            setAttributeComments(false);
298        }
299        return this;
300    }
301
302    public boolean isStoreTokens() {
303        return storeTokens;
304    }
305
306    public int getTabSize() {
307        return tabSize;
308    }
309
310    /**
311     * When a TAB character is encountered during parsing, the column position will be increased by this value.
312     * By default it is 1.
313     */
314    public ParserConfiguration setTabSize(int tabSize) {
315        this.tabSize = tabSize;
316        return this;
317    }
318
319    /**
320     * Disabled by default.
321     * When this is enabled, LexicalPreservingPrinter.print can be used to reproduce
322     * the original formatting of the file.
323     */
324    public ParserConfiguration setLexicalPreservationEnabled(boolean lexicalPreservationEnabled) {
325        this.lexicalPreservationEnabled = lexicalPreservationEnabled;
326        return this;
327    }
328
329    public boolean isLexicalPreservationEnabled() {
330        return lexicalPreservationEnabled;
331    }
332
333    /**
334     * Retrieve the SymbolResolver to be used while parsing, if any.
335     */
336    public Optional<SymbolResolvergetSymbolResolver() {
337        return Optional.ofNullable(symbolResolver);
338    }
339
340    /**
341     * Set the SymbolResolver to be injected while parsing.
342     */
343    public ParserConfiguration setSymbolResolver(SymbolResolver symbolResolver) {
344        this.symbolResolver = symbolResolver;
345        return this;
346    }
347
348    public List<Providers.PreProcessorgetPreProcessors() {
349        return preProcessors;
350    }
351
352    public List<ParseResult.PostProcessorgetPostProcessors() {
353        return postProcessors;
354    }
355
356    public ParserConfiguration setLanguageLevel(LanguageLevel languageLevel) {
357        this.languageLevel = languageLevel;
358        return this;
359    }
360
361    public LanguageLevel getLanguageLevel() {
362        return languageLevel;
363    }
364
365    /**
366     * When set to true, unicode escape handling is done by preprocessing the whole input,
367     * meaning that all unicode escapes are turned into unicode characters before parsing.
368     * That means the AST will never contain literal unicode escapes. However,
369     * positions in the AST will point to the original input, which is exactly the same as without this option.
370     * Without this option enabled, the unicode escapes will not be processed and are transfered intact to the AST.
371     */
372    public ParserConfiguration setPreprocessUnicodeEscapes(boolean preprocessUnicodeEscapes) {
373        this.preprocessUnicodeEscapes = preprocessUnicodeEscapes;
374        return this;
375    }
376
377    public boolean isPreprocessUnicodeEscapes() {
378        return preprocessUnicodeEscapes;
379    }
380    
381    public ParserConfiguration setDetectOriginalLineSeparator(boolean detectOriginalLineSeparator) {
382        this.detectOriginalLineSeparator = detectOriginalLineSeparator;
383        return this;
384    }
385
386    public boolean isDetectOriginalLineSeparator() {
387        return detectOriginalLineSeparator;
388    }
389
390    public Charset getCharacterEncoding() {
391        return characterEncoding;
392    }
393
394    /**
395     * The character encoding used for reading input from files and streams. By default UTF8 is used.
396     */
397    public ParserConfiguration setCharacterEncoding(Charset characterEncoding) {
398        this.characterEncoding = characterEncoding;
399        return this;
400    }
401
402}
403
MembersX
ParserConfiguration:ParserConfiguration:Block:UnicodeEscapeProcessor:process
ParserConfiguration:getPreProcessors
ParserConfiguration:ParserConfiguration:Block:UnicodeEscapeProcessor:process:Block:Block:Block:mapping
ParserConfiguration:isLexicalPreservationEnabled
ParserConfiguration:setDetectOriginalLineSeparator
ParserConfiguration:isStoreTokens
ParserConfiguration:getTabSize
ParserConfiguration:LanguageLevel:postProcessor
ParserConfiguration:setDoNotAssignCommentsPrecedingEmptyLines
ParserConfiguration:getPostProcessors
ParserConfiguration:LanguageLevel:BLEEDING_EDGE
ParserConfiguration:setStoreTokens
ParserConfiguration:detectOriginalLineSeparator
ParserConfiguration:ParserConfiguration
ParserConfiguration:tabSize
ParserConfiguration:getCharacterEncoding
ParserConfiguration:preprocessUnicodeEscapes
ParserConfiguration:setCharacterEncoding
ParserConfiguration:ignoreAnnotationsWhenAttributingComments
ParserConfiguration:LanguageLevel:RAW
ParserConfiguration:symbolResolver
ParserConfiguration:isDetectOriginalLineSeparator
ParserConfiguration:setIgnoreAnnotationsWhenAttributingComments
ParserConfiguration:ParserConfiguration:Block:Block:languageLevel
ParserConfiguration:setAttributeComments
ParserConfiguration:isIgnoreAnnotationsWhenAttributingComments
ParserConfiguration:setPreprocessUnicodeEscapes
ParserConfiguration:lexicalPreservationEnabled
ParserConfiguration:getSymbolResolver
ParserConfiguration:getLanguageLevel
ParserConfiguration:postProcessors
ParserConfiguration:ParserConfiguration:Block:unicodeProcessor
ParserConfiguration:LanguageLevel:POPULAR
ParserConfiguration:ParserConfiguration:Block:LineEndingProcessor:process:Block:Block:Block:detectedLineSeparator
ParserConfiguration:doNotAssignCommentsPrecedingEmptyLines
ParserConfiguration:isPreprocessUnicodeEscapes
ParserConfiguration:LanguageLevel:CURRENT
ParserConfiguration:ParserConfiguration:Block:UnicodeEscapeProcessor:_unicodeDecoder
ParserConfiguration:characterEncoding
ParserConfiguration:isAttributeComments
ParserConfiguration:ParserConfiguration:Block:lineEndingProcessor
ParserConfiguration:LanguageLevel:LanguageLevel
ParserConfiguration:languageLevel
ParserConfiguration:isDoNotAssignCommentsPrecedingEmptyLines
ParserConfiguration:LanguageLevel:JAVA_1_1
ParserConfiguration:ParserConfiguration:Block:LineEndingProcessor:process
ParserConfiguration:LanguageLevel:JAVA_1_2
ParserConfiguration:preProcessors
ParserConfiguration:LanguageLevel:JAVA_1_0
ParserConfiguration:setSymbolResolver
ParserConfiguration:LanguageLevel:JAVA_14
ParserConfiguration:attributeComments
ParserConfiguration:setTabSize
ParserConfiguration:setLanguageLevel
ParserConfiguration:LanguageLevel:JAVA_9
ParserConfiguration:LanguageLevel:JAVA_1_3
ParserConfiguration:storeTokens
ParserConfiguration:LanguageLevel:JAVA_1_4
ParserConfiguration:LanguageLevel:validator
ParserConfiguration:LanguageLevel:JAVA_6
ParserConfiguration:LanguageLevel:JAVA_5
ParserConfiguration:LanguageLevel:JAVA_8
ParserConfiguration:LanguageLevel:JAVA_7
ParserConfiguration:ParserConfiguration:Block:LineEndingProcessor:_lineEndingProcessingProvider
ParserConfiguration:LanguageLevel:JAVA_10
ParserConfiguration:LanguageLevel:JAVA_11
ParserConfiguration:setLexicalPreservationEnabled
ParserConfiguration:LanguageLevel:JAVA_12
ParserConfiguration:LanguageLevel:JAVA_13
Members
X