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