|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package com.github.javaparser; |
|
|
|
import com.github.javaparser.ParseResult.PostProcessor; |
|
import com.github.javaparser.Providers.PreProcessor; |
|
import com.github.javaparser.UnicodeEscapeProcessingProvider.PositionMapping; |
|
import com.github.javaparser.ast.CompilationUnit; |
|
import com.github.javaparser.ast.Node; |
|
import com.github.javaparser.ast.validator.*; |
|
import com.github.javaparser.ast.validator.language_level_validations.*; |
|
import com.github.javaparser.ast.validator.postprocessors.*; |
|
import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter; |
|
import com.github.javaparser.resolution.SymbolResolver; |
|
import com.github.javaparser.utils.LineSeparator; |
|
|
|
import java.nio.charset.Charset; |
|
import java.util.ArrayList; |
|
import java.util.Arrays; |
|
import java.util.List; |
|
import java.util.Optional; |
|
|
|
import static com.github.javaparser.ParserConfiguration.LanguageLevel.POPULAR; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class ParserConfiguration { |
|
|
|
public enum LanguageLevel { |
|
|
|
|
|
*/ |
|
JAVA_1_0(new Java1_0Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_1_1(new Java1_1Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_1_2(new Java1_2Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_1_3(new Java1_3Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_1_4(new Java1_4Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_5(new Java5Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_6(new Java6Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_7(new Java7Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_8(new Java8Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_9(new Java9Validator(), null), |
|
|
|
|
|
*/ |
|
JAVA_10(new Java10Validator(), new Java10PostProcessor()), |
|
|
|
|
|
|
|
*/ |
|
JAVA_10_PREVIEW(new Java10PreviewValidator(), new Java10PostProcessor()), |
|
|
|
|
|
*/ |
|
JAVA_11(new Java11Validator(), new Java11PostProcessor()), |
|
|
|
|
|
|
|
*/ |
|
JAVA_11_PREVIEW(new Java11PreviewValidator(), new Java11PostProcessor()), |
|
|
|
|
|
*/ |
|
JAVA_12(new Java12Validator(), new Java12PostProcessor()), |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
JAVA_12_PREVIEW(new Java12PreviewValidator(), new Java12PostProcessor()), |
|
|
|
|
|
*/ |
|
JAVA_13(new Java13Validator(), new Java13PostProcessor()), |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
JAVA_13_PREVIEW(new Java13PreviewValidator(), new Java13PostProcessor()), |
|
|
|
|
|
*/ |
|
JAVA_14(new Java14Validator(), new Java14PostProcessor()), |
|
|
|
|
|
|
|
*/ |
|
JAVA_14_PREVIEW(new Java14PreviewValidator(), new Java14PostProcessor()), |
|
|
|
|
|
*/ |
|
JAVA_15(new Java15Validator(), new Java15PostProcessor()), |
|
|
|
|
|
|
|
*/ |
|
JAVA_15_PREVIEW(new Java15PreviewValidator(), new Java15PostProcessor()), |
|
|
|
|
|
*/ |
|
JAVA_16(new Java16Validator(), new Java16PostProcessor()), |
|
|
|
|
|
|
|
*/ |
|
JAVA_16_PREVIEW(new Java16PreviewValidator(), new Java16PostProcessor()), |
|
|
|
|
|
*/ |
|
JAVA_17(new Java17Validator(), new Java17PostProcessor()), |
|
|
|
|
|
|
|
*/ |
|
JAVA_17_PREVIEW(new Java17PreviewValidator(), new Java17PostProcessor()); |
|
|
|
|
|
|
|
*/ |
|
public static LanguageLevel RAW = null; |
|
|
|
|
|
*/ |
|
public static LanguageLevel POPULAR = JAVA_11; |
|
|
|
|
|
*/ |
|
public static LanguageLevel CURRENT = JAVA_16; |
|
|
|
|
|
*/ |
|
public static LanguageLevel BLEEDING_EDGE = JAVA_17_PREVIEW; |
|
|
|
final Validator validator; |
|
final ParseResult.PostProcessor postProcessor; |
|
|
|
private static final LanguageLevel[] yieldSupport = new LanguageLevel[]{ |
|
JAVA_13, JAVA_13_PREVIEW, |
|
JAVA_14, JAVA_14_PREVIEW, |
|
JAVA_15, JAVA_15_PREVIEW, |
|
JAVA_16, JAVA_16_PREVIEW, |
|
JAVA_17, JAVA_17_PREVIEW |
|
}; |
|
|
|
LanguageLevel(Validator validator, ParseResult.PostProcessor postProcessor) { |
|
this.validator = validator; |
|
this.postProcessor = postProcessor; |
|
} |
|
|
|
public boolean isYieldSupported() { |
|
return Arrays.stream(yieldSupport).anyMatch(level -> level == this); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
private boolean detectOriginalLineSeparator = true; |
|
private boolean storeTokens = true; |
|
private boolean attributeComments = true; |
|
private boolean doNotAssignCommentsPrecedingEmptyLines = true; |
|
private boolean ignoreAnnotationsWhenAttributingComments = false; |
|
private boolean lexicalPreservationEnabled = false; |
|
private boolean preprocessUnicodeEscapes = false; |
|
private SymbolResolver symbolResolver = null; |
|
private int tabSize = 1; |
|
private LanguageLevel languageLevel = POPULAR; |
|
private Charset characterEncoding = Providers.UTF8; |
|
|
|
private final List<Providers.PreProcessor> preProcessors = new ArrayList<>(); |
|
private final List<ParseResult.PostProcessor> postProcessors = new ArrayList<>(); |
|
|
|
public ParserConfiguration() { |
|
|
|
class UnicodeEscapeProcessor implements PreProcessor, PostProcessor { |
|
private UnicodeEscapeProcessingProvider _unicodeDecoder; |
|
|
|
@Override |
|
public Provider process(Provider innerProvider) { |
|
if (isPreprocessUnicodeEscapes()) { |
|
_unicodeDecoder = new UnicodeEscapeProcessingProvider(innerProvider); |
|
return _unicodeDecoder; |
|
} |
|
return innerProvider; |
|
} |
|
|
|
@Override |
|
public void process(ParseResult<? extends Node> result, |
|
ParserConfiguration configuration) { |
|
if (isPreprocessUnicodeEscapes()) { |
|
result.getResult().ifPresent( |
|
root -> { |
|
PositionMapping mapping = _unicodeDecoder.getPositionMapping(); |
|
if (!mapping.isEmpty()) { |
|
root.walk( |
|
node -> node.getRange().ifPresent( |
|
range -> node.setRange(mapping.transform(range)))); |
|
} |
|
} |
|
); |
|
} |
|
} |
|
} |
|
|
|
class LineEndingProcessor implements PreProcessor, PostProcessor { |
|
private LineEndingProcessingProvider _lineEndingProcessingProvider; |
|
|
|
@Override |
|
public Provider process(Provider innerProvider) { |
|
if (isDetectOriginalLineSeparator()) { |
|
_lineEndingProcessingProvider = new LineEndingProcessingProvider(innerProvider); |
|
return _lineEndingProcessingProvider; |
|
} |
|
return innerProvider; |
|
} |
|
|
|
@Override |
|
public void process(ParseResult<? extends Node> result, ParserConfiguration configuration) { |
|
if (isDetectOriginalLineSeparator()) { |
|
result.getResult().ifPresent( |
|
rootNode -> { |
|
LineSeparator detectedLineSeparator = _lineEndingProcessingProvider.getDetectedLineEnding(); |
|
|
|
|
|
rootNode.setData(Node.LINE_SEPARATOR_KEY, detectedLineSeparator); |
|
|
|
// // Set the line ending on all children of the root node -- FIXME: Should ignore """textblocks""" |
|
// rootNode.findAll(Node.class) |
|
// .forEach(node -> node.setData(Node.LINE_SEPARATOR_KEY, detectedLineSeparator)); |
|
} |
|
); |
|
} |
|
} |
|
} |
|
|
|
UnicodeEscapeProcessor unicodeProcessor = new UnicodeEscapeProcessor(); |
|
preProcessors.add(unicodeProcessor); |
|
postProcessors.add(unicodeProcessor); |
|
|
|
LineEndingProcessor lineEndingProcessor = new LineEndingProcessor(); |
|
preProcessors.add(lineEndingProcessor); |
|
postProcessors.add(lineEndingProcessor); |
|
|
|
|
|
postProcessors.add((result, configuration) -> { |
|
if (configuration.isAttributeComments()) { |
|
result.ifSuccessful(resultNode -> result |
|
.getCommentsCollection().ifPresent(comments -> |
|
new CommentsInserter(configuration).insertComments(resultNode, comments.copy().getComments()))); |
|
} |
|
}); |
|
postProcessors.add((result, configuration) -> { |
|
LanguageLevel languageLevel = getLanguageLevel(); |
|
if (languageLevel != null) { |
|
if (languageLevel.postProcessor != null) { |
|
languageLevel.postProcessor.process(result, configuration); |
|
} |
|
if (languageLevel.validator != null) { |
|
languageLevel.validator.accept(result.getResult().get(), new ProblemReporter(newProblem -> result.getProblems().add(newProblem))); |
|
} |
|
} |
|
}); |
|
postProcessors.add((result, configuration) -> configuration.getSymbolResolver().ifPresent(symbolResolver -> |
|
result.ifSuccessful(resultNode -> { |
|
if (resultNode instanceof CompilationUnit) { |
|
resultNode.setData(Node.SYMBOL_RESOLVER_KEY, symbolResolver); |
|
} |
|
}) |
|
)); |
|
postProcessors.add((result, configuration) -> { |
|
if (configuration.isLexicalPreservationEnabled()) { |
|
result.ifSuccessful(LexicalPreservingPrinter::setup); |
|
} |
|
}); |
|
} |
|
|
|
public boolean isAttributeComments() { |
|
return attributeComments; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public ParserConfiguration setAttributeComments(boolean attributeComments) { |
|
this.attributeComments = attributeComments; |
|
return this; |
|
} |
|
|
|
public boolean isDoNotAssignCommentsPrecedingEmptyLines() { |
|
return doNotAssignCommentsPrecedingEmptyLines; |
|
} |
|
|
|
public ParserConfiguration setDoNotAssignCommentsPrecedingEmptyLines(boolean doNotAssignCommentsPrecedingEmptyLines) { |
|
this.doNotAssignCommentsPrecedingEmptyLines = doNotAssignCommentsPrecedingEmptyLines; |
|
return this; |
|
} |
|
|
|
public boolean isIgnoreAnnotationsWhenAttributingComments() { |
|
return ignoreAnnotationsWhenAttributingComments; |
|
} |
|
|
|
public ParserConfiguration setIgnoreAnnotationsWhenAttributingComments(boolean ignoreAnnotationsWhenAttributingComments) { |
|
this.ignoreAnnotationsWhenAttributingComments = ignoreAnnotationsWhenAttributingComments; |
|
return this; |
|
} |
|
|
|
public ParserConfiguration setStoreTokens(boolean storeTokens) { |
|
this.storeTokens = storeTokens; |
|
if (!storeTokens) { |
|
setAttributeComments(false); |
|
} |
|
return this; |
|
} |
|
|
|
public boolean isStoreTokens() { |
|
return storeTokens; |
|
} |
|
|
|
public int getTabSize() { |
|
return tabSize; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public ParserConfiguration setTabSize(int tabSize) { |
|
this.tabSize = tabSize; |
|
return this; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public ParserConfiguration setLexicalPreservationEnabled(boolean lexicalPreservationEnabled) { |
|
this.lexicalPreservationEnabled = lexicalPreservationEnabled; |
|
return this; |
|
} |
|
|
|
public boolean isLexicalPreservationEnabled() { |
|
return lexicalPreservationEnabled; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public Optional<SymbolResolver> getSymbolResolver() { |
|
return Optional.ofNullable(symbolResolver); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public ParserConfiguration setSymbolResolver(SymbolResolver symbolResolver) { |
|
this.symbolResolver = symbolResolver; |
|
return this; |
|
} |
|
|
|
public List<Providers.PreProcessor> getPreProcessors() { |
|
return preProcessors; |
|
} |
|
|
|
public List<ParseResult.PostProcessor> getPostProcessors() { |
|
return postProcessors; |
|
} |
|
|
|
public ParserConfiguration setLanguageLevel(LanguageLevel languageLevel) { |
|
this.languageLevel = languageLevel; |
|
return this; |
|
} |
|
|
|
public LanguageLevel getLanguageLevel() { |
|
return languageLevel; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public ParserConfiguration setPreprocessUnicodeEscapes(boolean preprocessUnicodeEscapes) { |
|
this.preprocessUnicodeEscapes = preprocessUnicodeEscapes; |
|
return this; |
|
} |
|
|
|
public boolean isPreprocessUnicodeEscapes() { |
|
return preprocessUnicodeEscapes; |
|
} |
|
|
|
public ParserConfiguration setDetectOriginalLineSeparator(boolean detectOriginalLineSeparator) { |
|
this.detectOriginalLineSeparator = detectOriginalLineSeparator; |
|
return this; |
|
} |
|
|
|
public boolean isDetectOriginalLineSeparator() { |
|
return detectOriginalLineSeparator; |
|
} |
|
|
|
public Charset getCharacterEncoding() { |
|
return characterEncoding; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public ParserConfiguration setCharacterEncoding(Charset characterEncoding) { |
|
this.characterEncoding = characterEncoding; |
|
return this; |
|
} |
|
|
|
} |