All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.javascript.jscomp.parsing.parser.FeatureSet Maven / Gradle / Ivy

Go to download

Closure Compiler is a JavaScript optimizing compiler. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls. It is used in many of Google's JavaScript apps, including Gmail, Google Web Search, Google Maps, and Google Docs.

There is a newer version: v20240317
Show newest version
/*
 * Copyright 2015 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.javascript.jscomp.parsing.parser;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.errorprone.annotations.Immutable;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

/**
 * Represents various aspects of language version and support.
 *
 * 

This is somewhat redundant with LanguageMode, but is separate * for two reasons: (1) it's used for parsing, which cannot * depend on LanguageMode, and (2) it's concerned with slightly * different nuances: implemented features and modules rather * than strictness. * *

In the long term, it would be good to disentangle all these * concerns and pull out a single LanguageSyntax enum with a * separate strict mode flag, and then these could possibly be * unified. * *

Instances of this class are immutable. */ @Immutable public final class FeatureSet implements Serializable { private final ImmutableSet features; /** The bare minimum set of features. */ public static final FeatureSet BARE_MINIMUM = new FeatureSet(ImmutableSet.of()); /** Features from ES3. */ public static final FeatureSet ES3 = BARE_MINIMUM.with(LangVersion.ES3.features()); /** Features from ES5 only. */ public static final FeatureSet ES5 = ES3.with(LangVersion.ES5.features()); /** All ES6 features, including modules. */ public static final FeatureSet ES6_MODULES = ES5.with(LangVersion.ES6.features()); /** The full set of ES6 features, not including modules. */ public static final FeatureSet ES6 = ES6_MODULES.without(Feature.MODULES); public static final FeatureSet ES7_MODULES = ES6_MODULES.with(LangVersion.ES7.features()); public static final FeatureSet ES7 = ES7_MODULES.without(Feature.MODULES); public static final FeatureSet ES8_MODULES = ES7_MODULES.with(LangVersion.ES8.features()); public static final FeatureSet ES8 = ES8_MODULES.without(Feature.MODULES); public static final FeatureSet TYPESCRIPT = ES8_MODULES.with(LangVersion.TYPESCRIPT.features()); // TODO(b/64536685): Remove this FeatureSet once NTI supports all of ES6. public static final FeatureSet NTI_SUPPORTED = ES5.with( ImmutableSet.of( Feature.COMPUTED_PROPERTIES, Feature.EXPONENT_OP, Feature.EXTENDED_OBJECT_LITERALS, Feature.FOR_OF, Feature.GENERATORS, Feature.MEMBER_DECLARATIONS, Feature.TEMPLATE_LITERALS)); private enum LangVersion { ES3, ES5, ES6, ES7, ES8, TYPESCRIPT; private Set features() { Set set = new HashSet<>(); for (Feature feature : Feature.values()) { if (feature.version == this) { set.add(feature); } } return set; } } /** Specific features that can be included in a FeatureSet. */ public enum Feature { // ES3 features // Functions can be declared in the block scope for all ES versions. However, for ES3 and ES5, // we want to hoist the functions from the block scope by redeclaring them as vars (i.e. // { function f() {} } becomes { var f = function {} }. To prevent this feature from causing // code to run additional transpilation passes beyond rewriting block scoped functions, we mark // block scoped functions as an ES3 feature and then manually determine whether to rewrite // functions inside the processTranspile method of TranspilationPasses.java BLOCK_SCOPED_FUNCTION_DECLARATION("block function", LangVersion.ES3), // ES5 features ES3_KEYWORDS_AS_IDENTIFIERS("ES3 keywords as identifiers", LangVersion.ES5), GETTER("getters", LangVersion.ES5), KEYWORDS_AS_PROPERTIES("reserved words as properties", LangVersion.ES5), SETTER("setters", LangVersion.ES5), STRING_CONTINUATION("string continuation", LangVersion.ES5), TRAILING_COMMA("trailing comma", LangVersion.ES5), // ES6 features (besides modules): all stable browsers are now fully compliant ARROW_FUNCTIONS("arrow function", LangVersion.ES6), BINARY_LITERALS("binary literal", LangVersion.ES6), OCTAL_LITERALS("octal literal", LangVersion.ES6), CLASSES("class", LangVersion.ES6), COMPUTED_PROPERTIES("computed property", LangVersion.ES6), EXTENDED_OBJECT_LITERALS("extended object literal", LangVersion.ES6), FOR_OF("for-of loop", LangVersion.ES6), GENERATORS("generator", LangVersion.ES6), LET_DECLARATIONS("let declaration", LangVersion.ES6), MEMBER_DECLARATIONS("member declaration", LangVersion.ES6), REGEXP_FLAG_Y("RegExp flag 'y'", LangVersion.ES6), ARRAY_PATTERN_REST("array pattern rest", LangVersion.ES6), REST_PARAMETERS("rest parameter", LangVersion.ES6), SPREAD_EXPRESSIONS("spread expression", LangVersion.ES6), SUPER("super", LangVersion.ES6), TEMPLATE_LITERALS("template literal", LangVersion.ES6), CONST_DECLARATIONS("const declaration", LangVersion.ES6), DESTRUCTURING("destructuring", LangVersion.ES6), NEW_TARGET("new.target", LangVersion.ES6), REGEXP_FLAG_U("RegExp flag 'u'", LangVersion.ES6), DEFAULT_PARAMETERS("default parameter", LangVersion.ES6), MODULES("modules", LangVersion.ES6), // ES 2016 only added one new feature: EXPONENT_OP("exponent operator (**)", LangVersion.ES7), // ES 2017 features: ASYNC_FUNCTIONS("async function", LangVersion.ES8), TRAILING_COMMA_IN_PARAM_LIST("trailing comma in param list", LangVersion.ES8), // ES6 typed features that are not at all implemented in browsers ACCESSIBILITY_MODIFIER("accessibility modifier", LangVersion.TYPESCRIPT), AMBIENT_DECLARATION("ambient declaration", LangVersion.TYPESCRIPT), CALL_SIGNATURE("call signature", LangVersion.TYPESCRIPT), CONSTRUCTOR_SIGNATURE("constructor signature", LangVersion.TYPESCRIPT), ENUM("enum", LangVersion.TYPESCRIPT), GENERICS("generics", LangVersion.TYPESCRIPT), IMPLEMENTS("implements", LangVersion.TYPESCRIPT), INDEX_SIGNATURE("index signature", LangVersion.TYPESCRIPT), INTERFACE("interface", LangVersion.TYPESCRIPT), MEMBER_VARIABLE_IN_CLASS("member variable in class", LangVersion.TYPESCRIPT), NAMESPACE_DECLARATION("namespace declaration", LangVersion.TYPESCRIPT), OPTIONAL_PARAMETER("optional parameter", LangVersion.TYPESCRIPT), TYPE_ALIAS("type alias", LangVersion.TYPESCRIPT), TYPE_ANNOTATION("type annotation", LangVersion.TYPESCRIPT); private final String name; private final LangVersion version; private Feature(String name, LangVersion version) { this.name = name; this.version = version; } @Override public String toString() { return name; } } private FeatureSet(Set features) { this.features = ImmutableSet.copyOf(features); } /** Returns a string representation suitable for encoding in depgraph and deps.js files. */ public String version() { if (ES3.contains(this)) { return "es3"; } if (ES5.contains(this)) { return "es5"; } if (ES6_MODULES.contains(this)) { return "es6"; } if (NTI_SUPPORTED.contains(this)) { return "ntiSupported"; } if (ES7_MODULES.contains(this)) { return "es7"; } if (ES8_MODULES.contains(this)) { return "es8"; } if (TYPESCRIPT.contains(this)) { return "ts"; } throw new IllegalStateException(this.toString()); } public FeatureSet without(Feature feature) { return new FeatureSet(Sets.difference(features, ImmutableSet.of(feature))); } public FeatureSet without(FeatureSet other) { return new FeatureSet(Sets.difference(features, other.features)); } public FeatureSet withoutTypes() { return new FeatureSet(Sets.difference(features, LangVersion.TYPESCRIPT.features())); } /** * Returns a new {@link FeatureSet} including all features of both {@code this} and {@code other}. */ public FeatureSet union(FeatureSet other) { return new FeatureSet(Sets.union(features, other.features)); } /** * Does this {@link FeatureSet} contain all of the features of {@code other}? */ public boolean contains(FeatureSet other) { return this.features.containsAll(other.features); } /** Returns a feature set combining all the features from {@code this} and {@code newFeatures}. */ public FeatureSet with(Feature... newFeatures) { return new FeatureSet(Sets.union(features, ImmutableSet.copyOf(newFeatures))); } /** Returns a feature set combining all the features from {@code this} and {@code newFeatures}. */ public FeatureSet with(Set newFeatures) { return new FeatureSet(Sets.union(features, newFeatures)); } /** * Does this {@link FeatureSet} include {@code feature}? */ public boolean has(Feature feature) { return features.contains(feature); } @Override public boolean equals(Object other) { return other instanceof FeatureSet && ((FeatureSet) other).features.equals(features); } @Override public int hashCode() { return features.hashCode(); } @Override public String toString() { return features.toString(); } /** Parses known strings into feature sets. */ public static FeatureSet valueOf(String name) { switch (name) { case "es3": return ES3; case "es5": return ES5; case "es6-impl": case "es6": return ES6; case "es7": return ES7; case "es8": return ES8; case "ts": return TYPESCRIPT; default: throw new IllegalArgumentException("No such FeatureSet: " + name); } } public static FeatureSet latest() { return TYPESCRIPT; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy