From 0265efa303ec010b8079c74df18ffcc3ca825770 Mon Sep 17 00:00:00 2001 From: sdh Date: Fri, 8 Dec 2017 21:54:23 -0800 Subject: [PATCH] Change parsing.Config to use @AutoValue.Builder. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=178463919 --- .../javascript/jscomp/parsing/Config.java | 145 ++++++++++-------- .../javascript/jscomp/parsing/IRFactory.java | 34 ++-- .../jscomp/parsing/JsDocInfoParser.java | 22 ++- .../jscomp/parsing/ParserRunner.java | 25 +-- .../parsing/TypeTransformationParser.java | 11 +- .../jscomp/parsing/JsDocInfoParserTest.java | 38 ++--- 6 files changed, 137 insertions(+), 138 deletions(-) diff --git a/src/com/google/javascript/jscomp/parsing/Config.java b/src/com/google/javascript/jscomp/parsing/Config.java index 08cb4b63f94..8c36b6066df 100644 --- a/src/com/google/javascript/jscomp/parsing/Config.java +++ b/src/com/google/javascript/jscomp/parsing/Config.java @@ -16,24 +16,29 @@ package com.google.javascript.jscomp.parsing; +import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.javascript.jscomp.parsing.parser.FeatureSet; -import java.util.Set; /** - * Configuration for the AST factory. Should be shared across AST creation - * for all files of a compilation process. + * Configuration for the AST factory. Should be shared across AST creation for all files of a + * compilation process. * * @author nicksantos@google.com (Nick Santos) */ -public final class Config { +@AutoValue +public abstract class Config { /** * Level of language strictness required for the input source code. */ public enum StrictMode { STRICT, SLOPPY; + + public boolean isStrict() { + return this == STRICT; + } } /** JavaScript mode */ @@ -95,8 +100,11 @@ public enum JsDocParsing { boolean shouldParseDescriptions() { return this != TYPES_ONLY; } + + boolean shouldPreserveWhitespace() { + return this == INCLUDE_DESCRIPTIONS_WITH_WHITESPACE; + } } - final JsDocParsing parseJsDocDocumentation; /** * Whether to keep going after encountering a parse error. @@ -105,80 +113,81 @@ public enum RunMode { STOP_AFTER_ERROR, KEEP_GOING, } - final RunMode keepGoing; - /** - * Recognized JSDoc annotations, mapped from their name to their internal - * representation. - */ - final ImmutableMap annotationNames; + /** Language level to accept. */ + abstract LanguageMode languageMode(); - /** - * Recognized names in a {@code @suppress} tag. - */ - final ImmutableSet suppressionNames; + /** Whether to assume input is strict mode compliant. */ + abstract StrictMode strictMode(); - /** - * Accept ECMAScript5 syntax, such as getter/setter. - */ - final LanguageMode languageMode; + /** How to parse the descriptions of JsDoc comments. */ + abstract JsDocParsing jsDocParsingMode(); - final StrictMode strictMode; + /** Whether to keep going after encountering a parse error. */ + abstract RunMode runMode(); - /** - * Parse inline source maps (//# sourceMappingURL=data:...). - */ - final boolean parseInlineSourceMaps; - - Config( - Set annotationWhitelist, - Set suppressionNames, - LanguageMode languageMode, - StrictMode strictMode) { - this( - annotationWhitelist, - JsDocParsing.TYPES_ONLY, - RunMode.STOP_AFTER_ERROR, - suppressionNames, - languageMode, - false, - strictMode); + /** Recognized JSDoc annotations, mapped from their name to their internal representation. */ + abstract ImmutableMap annotations(); + + /** Set of recognized names in a {@code @suppress} tag. */ + abstract ImmutableSet suppressionNames(); + + /** Whether to parse inline source maps (//# sourceMappingURL=data:...). */ + abstract boolean parseInlineSourceMaps(); + + final ImmutableSet annotationNames() { + return annotations().keySet(); } - Config( - Set annotationWhitelist, - JsDocParsing parseJsDocDocumentation, - RunMode keepGoing, - Set suppressionNames, - LanguageMode languageMode, - boolean parseInlineSourceMaps, - StrictMode strictMode) { - this.parseInlineSourceMaps = parseInlineSourceMaps; - this.annotationNames = buildAnnotationNames(annotationWhitelist); - this.parseJsDocDocumentation = parseJsDocDocumentation; - this.keepGoing = keepGoing; - this.suppressionNames = ImmutableSet.copyOf(suppressionNames); - this.languageMode = languageMode; - this.strictMode = strictMode; + static Builder builder() { + return new AutoValue_Config.Builder() + .setLanguageMode(LanguageMode.TYPESCRIPT) + .setStrictMode(StrictMode.STRICT) + .setJsDocParsingMode(JsDocParsing.TYPES_ONLY) + .setRunMode(RunMode.STOP_AFTER_ERROR) + .setExtraAnnotationNames(ImmutableSet.of()) + .setSuppressionNames(ImmutableSet.of()) + .setParseInlineSourceMaps(false); } - /** - * Create the annotation names from the user-specified - * annotation whitelist. - */ - private static ImmutableMap buildAnnotationNames( - Set annotationWhitelist) { - ImmutableMap.Builder annotationBuilder = - ImmutableMap.builder(); - annotationBuilder.putAll(Annotation.recognizedAnnotations); - for (String unrecognizedAnnotation : annotationWhitelist) { + @AutoValue.Builder + abstract static class Builder { + abstract Builder setLanguageMode(LanguageMode mode); + + abstract Builder setStrictMode(StrictMode mode); + + abstract Builder setJsDocParsingMode(JsDocParsing mode); + + abstract Builder setRunMode(RunMode mode); + + abstract Builder setParseInlineSourceMaps(boolean parseInlineSourceMaps); + + final Builder setSuppressionNames(Iterable names) { + return setSuppressionNames(ImmutableSet.copyOf(names)); + } + + final Builder setExtraAnnotationNames(Iterable names) { + return setAnnotations(buildAnnotations(names)); + } + + abstract Config build(); + + // The following are intended to be used internally only (but aren't private due to AutoValue). + abstract Builder setSuppressionNames(ImmutableSet names); + + abstract Builder setAnnotations(ImmutableMap names); + } + + /** Create the annotation names from the user-specified annotation whitelist. */ + private static ImmutableMap buildAnnotations(Iterable whitelist) { + ImmutableMap.Builder annotationsBuilder = ImmutableMap.builder(); + annotationsBuilder.putAll(Annotation.recognizedAnnotations); + for (String unrecognizedAnnotation : whitelist) { if (!unrecognizedAnnotation.isEmpty() - && !Annotation.recognizedAnnotations.containsKey( - unrecognizedAnnotation)) { - annotationBuilder.put( - unrecognizedAnnotation, Annotation.NOT_IMPLEMENTED); + && !Annotation.recognizedAnnotations.containsKey(unrecognizedAnnotation)) { + annotationsBuilder.put(unrecognizedAnnotation, Annotation.NOT_IMPLEMENTED); } } - return annotationBuilder.build(); + return annotationsBuilder.build(); } } diff --git a/src/com/google/javascript/jscomp/parsing/IRFactory.java b/src/com/google/javascript/jscomp/parsing/IRFactory.java index fc56e295ae2..876fc9e269c 100644 --- a/src/com/google/javascript/jscomp/parsing/IRFactory.java +++ b/src/com/google/javascript/jscomp/parsing/IRFactory.java @@ -36,7 +36,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.UnmodifiableIterator; import com.google.javascript.jscomp.parsing.Config.LanguageMode; -import com.google.javascript.jscomp.parsing.Config.StrictMode; import com.google.javascript.jscomp.parsing.parser.FeatureSet; import com.google.javascript.jscomp.parsing.parser.FeatureSet.Feature; import com.google.javascript.jscomp.parsing.parser.IdentifierToken; @@ -287,7 +286,7 @@ private IRFactory(String sourceString, this.templateNode = createTemplateNode(); this.fileLevelJsDocBuilder = - new JSDocInfoBuilder(config.parseJsDocDocumentation.shouldParseDescriptions()); + new JSDocInfoBuilder(config.jsDocParsingMode().shouldParseDescriptions()); // Pre-generate all the newlines in the file. for (int charNo = 0; true; charNo++) { @@ -305,9 +304,9 @@ private IRFactory(String sourceString, this.errorReporter = errorReporter; this.transformDispatcher = new TransformDispatcher(); - if (config.strictMode == StrictMode.STRICT) { + if (config.strictMode().isStrict()) { reservedKeywords = ES5_STRICT_RESERVED_KEYWORDS; - } else if (config.languageMode == LanguageMode.ECMASCRIPT3) { + } else if (config.languageMode() == LanguageMode.ECMASCRIPT3) { reservedKeywords = null; // use TokenStream.isKeyword instead } else { reservedKeywords = ES5_RESERVED_KEYWORDS; @@ -375,12 +374,7 @@ static FeatureSet detectFeatures( return irFactory.features; } - static final Config NULL_CONFIG = - new Config( - ImmutableSet.of(), - ImmutableSet.of(), - LanguageMode.TYPESCRIPT, - Config.StrictMode.STRICT); + static final Config NULL_CONFIG = Config.builder().build(); static final ErrorReporter NULL_REPORTER = new ErrorReporter() { @Override @@ -1337,7 +1331,7 @@ Node processFunction(FunctionDeclarationTree functionTree) { if (!isArrow && !isSignature && !bodyNode.isNormalBlock()) { // When in "keep going" mode the parser tries to parse some constructs the // compiler doesn't support, repair it here. - checkState(config.keepGoing == Config.RunMode.KEEP_GOING); + checkState(config.runMode() == Config.RunMode.KEEP_GOING); bodyNode = IR.block(); } parseDirectives(bodyNode); @@ -1555,7 +1549,7 @@ Node processNameWithInlineJSDoc(IdentifierToken identifierToken) { private void maybeWarnKeywordProperty(Node node) { if (TokenStream.isKeyword(node.getString())) { features = features.with(Feature.KEYWORDS_AS_PROPERTIES); - if (config.languageMode == LanguageMode.ECMASCRIPT3) { + if (config.languageMode() == LanguageMode.ECMASCRIPT3) { errorReporter.warning(INVALID_ES3_PROP_NAME, sourceName, node.getLineno(), node.getCharno()); } @@ -1567,11 +1561,11 @@ private void maybeWarnReservedKeyword(IdentifierToken token) { boolean isIdentifier = false; if (TokenStream.isKeyword(identifier)) { features = features.with(Feature.ES3_KEYWORDS_AS_IDENTIFIERS); - isIdentifier = config.languageMode == LanguageMode.ECMASCRIPT3; + isIdentifier = config.languageMode() == LanguageMode.ECMASCRIPT3; } if (reservedKeywords != null && reservedKeywords.contains(identifier)) { features = features.with(Feature.KEYWORDS_AS_PROPERTIES); - isIdentifier = config.languageMode == LanguageMode.ECMASCRIPT3; + isIdentifier = config.languageMode() == LanguageMode.ECMASCRIPT3; } if (isIdentifier) { errorReporter.error( @@ -2089,7 +2083,7 @@ Node processIllegalToken(ParseTree node) { /** Reports an illegal getter and returns true if the language mode is too low. */ boolean maybeReportGetter(ParseTree node) { features = features.with(Feature.GETTER); - if (config.languageMode == LanguageMode.ECMASCRIPT3) { + if (config.languageMode() == LanguageMode.ECMASCRIPT3) { errorReporter.error( GETTER_ERROR_MESSAGE, sourceName, @@ -2102,7 +2096,7 @@ boolean maybeReportGetter(ParseTree node) { /** Reports an illegal setter and returns true if the language mode is too low. */ boolean maybeReportSetter(ParseTree node) { features = features.with(Feature.SETTER); - if (config.languageMode == LanguageMode.ECMASCRIPT3) { + if (config.languageMode() == LanguageMode.ECMASCRIPT3) { errorReporter.error( SETTER_ERROR_MESSAGE, sourceName, @@ -2635,7 +2629,7 @@ void maybeProcessAccessibilityModifier(ParseTree parseTree, Node n, @Nullable To } void maybeWarnTypeSyntax(ParseTree node, Feature feature) { - if (config.languageMode != LanguageMode.TYPESCRIPT) { + if (config.languageMode() != LanguageMode.TYPESCRIPT) { errorReporter.warning( "type syntax is only supported in ES6 typed mode: " + feature, sourceName, @@ -3070,17 +3064,17 @@ String normalizeString(LiteralToken token, boolean templateLiteral) { } boolean isSupportedForInputLanguageMode(Feature feature) { - return config.languageMode.featureSet.has(feature); + return config.languageMode().featureSet.has(feature); } boolean isEs5OrBetterMode() { - return config.languageMode.featureSet.contains(FeatureSet.ES5); + return config.languageMode().featureSet.contains(FeatureSet.ES5); } private boolean inStrictContext() { // TODO(johnlenz): in ECMASCRIPT5/6 is a "mixed" mode and we should track the context // that we are in, if we want to support it. - return config.strictMode == StrictMode.STRICT; + return config.strictMode().isStrict(); } double normalizeNumber(LiteralToken token) { diff --git a/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java b/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java index 98c5436ea26..913272198b8 100644 --- a/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java +++ b/src/com/google/javascript/jscomp/parsing/JsDocInfoParser.java @@ -117,7 +117,7 @@ private void addMissingTypeWarning(int lineno, int charno) { private JSDocInfo fileOverviewJSDocInfo = null; private State state; - private final Map annotationNames; + private final Map annotations; private final Set suppressionNames; private final boolean preserveWhitespace; private static final Set modifiesAnnotationKeywords = @@ -166,16 +166,15 @@ private enum State { ErrorReporter errorReporter) { this.stream = stream; - boolean parseDocumentation = config.parseJsDocDocumentation.shouldParseDescriptions(); + boolean parseDocumentation = config.jsDocParsingMode().shouldParseDescriptions(); this.jsdocBuilder = new JSDocInfoBuilder(parseDocumentation); if (comment != null) { this.jsdocBuilder.recordOriginalCommentString(comment); this.jsdocBuilder.recordOriginalCommentPosition(commentPosition); } - this.annotationNames = config.annotationNames; - this.suppressionNames = config.suppressionNames; - this.preserveWhitespace = - config.parseJsDocDocumentation == Config.JsDocParsing.INCLUDE_DESCRIPTIONS_WITH_WHITESPACE; + this.annotations = config.annotations(); + this.suppressionNames = config.suppressionNames(); + this.preserveWhitespace = config.jsDocParsingMode().shouldPreserveWhitespace(); this.errorReporter = errorReporter; this.templateNode = templateNode == null ? IR.script() : templateNode; @@ -238,11 +237,10 @@ public static JSDocInfo parseJsdoc(String toParse) { private static JsDocInfoParser getParser(String toParse) { Config config = - new Config( - new HashSet(), - new HashSet(), - LanguageMode.ECMASCRIPT3, - Config.StrictMode.SLOPPY); + Config.builder() + .setLanguageMode(LanguageMode.ECMASCRIPT3) + .setStrictMode(Config.StrictMode.SLOPPY) + .build(); JsDocInfoParser parser = new JsDocInfoParser( new JsDocTokenStream(toParse), toParse, @@ -384,7 +382,7 @@ private JsDocToken parseAnnotation(JsDocToken token, int charno = stream.getCharno(); String annotationName = stream.getString(); - Annotation annotation = annotationNames.get(annotationName); + Annotation annotation = annotations.get(annotationName); if (annotation == null || annotationName.isEmpty()) { addParserWarning("msg.bad.jsdoc.tag", annotationName); } else { diff --git a/src/com/google/javascript/jscomp/parsing/ParserRunner.java b/src/com/google/javascript/jscomp/parsing/ParserRunner.java index 386cd725f1d..96da0ca01f0 100644 --- a/src/com/google/javascript/jscomp/parsing/ParserRunner.java +++ b/src/com/google/javascript/jscomp/parsing/ParserRunner.java @@ -81,14 +81,15 @@ public static Config createConfig( effectiveAnnotationNames = new HashSet<>(annotationNames); effectiveAnnotationNames.addAll(extraAnnotationNames); } - return new Config( - effectiveAnnotationNames, - jsdocParsingMode, - runMode, - suppressionNames, - languageMode, - parseInlineSourceMaps, - strictMode); + return Config.builder() + .setExtraAnnotationNames(effectiveAnnotationNames) + .setJsDocParsingMode(jsdocParsingMode) + .setRunMode(runMode) + .setSuppressionNames(suppressionNames) + .setLanguageMode(languageMode) + .setParseInlineSourceMaps(parseInlineSourceMaps) + .setStrictMode(strictMode) + .build(); } public static Set getReservedVars() { @@ -121,7 +122,7 @@ public static ParseResult parse( String sourceName = sourceFile.getName(); try { SourceFile file = new SourceFile(sourceName, sourceString); - boolean keepGoing = config.keepGoing == Config.RunMode.KEEP_GOING; + boolean keepGoing = config.runMode() == Config.RunMode.KEEP_GOING; Es6ErrorReporter es6ErrorReporter = new Es6ErrorReporter(errorReporter, keepGoing); com.google.javascript.jscomp.parsing.parser.Parser.Config es6config = newParserConfig(config); Parser p = new Parser(es6config, es6ErrorReporter, file); @@ -136,7 +137,7 @@ public static ParseResult parse( features = features.union(factory.getFeatures()); root.putProp(Node.FEATURE_SET, features); - if (config.parseJsDocDocumentation.shouldParseDescriptions()) { + if (config.jsDocParsingMode().shouldParseDescriptions()) { comments = p.getComments(); } } @@ -148,8 +149,8 @@ public static ParseResult parse( private static com.google.javascript.jscomp.parsing.parser.Parser.Config newParserConfig( Config config) { - LanguageMode languageMode = config.languageMode; - boolean isStrictMode = config.strictMode == StrictMode.STRICT; + LanguageMode languageMode = config.languageMode(); + boolean isStrictMode = config.strictMode().isStrict(); Mode parserConfigLanguageMode; switch (languageMode) { case TYPESCRIPT: diff --git a/src/com/google/javascript/jscomp/parsing/TypeTransformationParser.java b/src/com/google/javascript/jscomp/parsing/TypeTransformationParser.java index 8f5bb07ed35..2b37d8e0e57 100644 --- a/src/com/google/javascript/jscomp/parsing/TypeTransformationParser.java +++ b/src/com/google/javascript/jscomp/parsing/TypeTransformationParser.java @@ -18,13 +18,11 @@ import com.google.common.base.Ascii; import com.google.common.base.Preconditions; -import com.google.javascript.jscomp.parsing.Config.LanguageMode; import com.google.javascript.jscomp.parsing.ParserRunner.ParseResult; import com.google.javascript.rhino.ErrorReporter; import com.google.javascript.rhino.Node; import com.google.javascript.rhino.SimpleErrorReporter; import com.google.javascript.rhino.StaticSourceFile; -import java.util.HashSet; /** * A parser for the type transformation expressions (TTL-Exp) as in @@ -251,11 +249,10 @@ private boolean checkParameterCount(Node expr, Keywords keyword) { */ public boolean parseTypeTransformation() { Config config = - new Config( - new HashSet(), - new HashSet(), - LanguageMode.ECMASCRIPT6, - Config.StrictMode.SLOPPY); + Config.builder() + .setLanguageMode(Config.LanguageMode.ECMASCRIPT6) + .setStrictMode(Config.StrictMode.SLOPPY) + .build(); // TODO(lpino): ParserRunner reports errors if the expression is not // ES6 valid. We need to abort the validation of the type transformation // whenever an error is reported. diff --git a/test/com/google/javascript/jscomp/parsing/JsDocInfoParserTest.java b/test/com/google/javascript/jscomp/parsing/JsDocInfoParserTest.java index 10dfcff7364..3b922707037 100644 --- a/test/com/google/javascript/jscomp/parsing/JsDocInfoParserTest.java +++ b/test/com/google/javascript/jscomp/parsing/JsDocInfoParserTest.java @@ -66,12 +66,11 @@ public void setUp() throws Exception { extraAnnotations = new HashSet<>( ParserRunner.createConfig(LanguageMode.ECMASCRIPT3, null, StrictMode.SLOPPY) - .annotationNames - .keySet()); + .annotationNames()); extraSuppressions = new HashSet<>( ParserRunner.createConfig(LanguageMode.ECMASCRIPT3, null, StrictMode.SLOPPY) - .suppressionNames); + .suppressionNames()); extraSuppressions.add("x"); extraSuppressions.add("y"); @@ -4728,14 +4727,15 @@ private static void assertContains(Collection collection, T item) { private Node parseFull(String code, String... warnings) { TestErrorReporter testErrorReporter = new TestErrorReporter(null, warnings); Config config = - new Config( - extraAnnotations, - JsDocParsing.INCLUDE_DESCRIPTIONS_NO_WHITESPACE, - RunMode.KEEP_GOING, - extraSuppressions, - LanguageMode.ECMASCRIPT3, - true, - StrictMode.SLOPPY); + Config.builder() + .setExtraAnnotationNames(extraAnnotations) + .setJsDocParsingMode(JsDocParsing.INCLUDE_DESCRIPTIONS_NO_WHITESPACE) + .setRunMode(RunMode.KEEP_GOING) + .setSuppressionNames(extraSuppressions) + .setLanguageMode(LanguageMode.ECMASCRIPT3) + .setParseInlineSourceMaps(true) + .setStrictMode(StrictMode.SLOPPY) + .build(); ParseResult result = ParserRunner.parse( new SimpleSourceFile("source", false), code, config, testErrorReporter); @@ -4780,14 +4780,14 @@ private JSDocInfo parse(String comment, JsDocParsing parseDocumentation, TestErrorReporter errorReporter = new TestErrorReporter(null, warnings); Config config = - new Config( - extraAnnotations, - parseDocumentation, - RunMode.STOP_AFTER_ERROR, - extraSuppressions, - LanguageMode.ECMASCRIPT3, - true, - Config.StrictMode.SLOPPY); + Config.builder() + .setExtraAnnotationNames(extraAnnotations) + .setJsDocParsingMode(parseDocumentation) + .setSuppressionNames(extraSuppressions) + .setLanguageMode(LanguageMode.ECMASCRIPT3) + .setParseInlineSourceMaps(true) + .setStrictMode(Config.StrictMode.SLOPPY) + .build(); StaticSourceFile file = new SimpleSourceFile("testcode", false); Node templateNode = IR.script();