use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.
the class PolymerClassRewriter method rewritePolymerCall.
/**
* Rewrites a given call to Polymer({}) to a set of declarations and assignments which can be
* understood by the compiler.
*
* @param exprRoot The root expression of the call to Polymer({}).
* @param cls The extracted {@link PolymerClassDefinition} for the Polymer element created by this
* call.
*/
void rewritePolymerCall(Node exprRoot, final PolymerClassDefinition cls, boolean isInGlobalScope) {
Node objLit = checkNotNull(cls.descriptor);
// Add {@code @lends} to the object literal.
JSDocInfoBuilder objLitDoc = new JSDocInfoBuilder(true);
objLitDoc.recordLends(cls.target.getQualifiedName() + ".prototype");
objLit.setJSDocInfo(objLitDoc.build());
addTypesToFunctions(objLit, cls.target.getQualifiedName(), cls.defType);
PolymerPassStaticUtils.switchDollarSignPropsToBrackets(objLit, compiler);
PolymerPassStaticUtils.quoteListenerAndHostAttributeKeys(objLit, compiler);
for (MemberDefinition prop : cls.props) {
if (prop.value.isObjectLit()) {
PolymerPassStaticUtils.switchDollarSignPropsToBrackets(prop.value, compiler);
}
}
// For simplicity add everything into a block, before adding it to the AST.
Node block = IR.block();
JSDocInfoBuilder constructorDoc = this.getConstructorDoc(cls);
// Remove the original constructor JS docs from the objlit.
Node ctorKey = cls.constructor.value.getParent();
if (ctorKey != null) {
ctorKey.removeProp(Node.JSDOC_INFO_PROP);
}
if (cls.target.isGetProp()) {
// foo.bar = Polymer({...});
Node assign = IR.assign(cls.target.cloneTree(), cls.constructor.value.cloneTree());
NodeUtil.markNewScopesChanged(assign, compiler);
assign.setJSDocInfo(constructorDoc.build());
Node exprResult = IR.exprResult(assign);
exprResult.useSourceInfoIfMissingFromForTree(cls.target);
block.addChildToBack(exprResult);
} else {
// var foo = Polymer({...}); OR Polymer({...});
Node var = IR.var(cls.target.cloneTree(), cls.constructor.value.cloneTree());
NodeUtil.markNewScopesChanged(var, compiler);
var.useSourceInfoIfMissingFromForTree(exprRoot);
var.setJSDocInfo(constructorDoc.build());
block.addChildToBack(var);
}
appendPropertiesToBlock(cls, block, cls.target.getQualifiedName() + ".prototype.");
appendBehaviorMembersToBlock(cls, block);
ImmutableList<MemberDefinition> readOnlyProps = parseReadOnlyProperties(cls, block);
ImmutableList<MemberDefinition> attributeReflectedProps = parseAttributeReflectedProperties(cls);
addInterfaceExterns(cls, readOnlyProps, attributeReflectedProps);
removePropertyDocs(objLit, PolymerClassDefinition.DefinitionType.ObjectLiteral);
Node statements = block.removeChildren();
Node parent = exprRoot.getParent();
// global.
if (this.polymerVersion == 1 && !isInGlobalScope && !cls.target.isGetProp()) {
Node scriptNode = NodeUtil.getEnclosingScript(parent);
scriptNode.addChildrenToFront(statements);
compiler.reportChangeToChangeScope(scriptNode);
} else {
Node beforeRoot = exprRoot.getPrevious();
if (beforeRoot == null) {
parent.addChildrenToFront(statements);
} else {
parent.addChildrenAfter(statements, beforeRoot);
}
compiler.reportChangeToEnclosingScope(parent);
}
compiler.reportChangeToEnclosingScope(statements);
// we might need to update the FeatureSet.
if (cls.features != null) {
Node scriptNode = NodeUtil.getEnclosingScript(parent);
FeatureSet oldFeatures = (FeatureSet) scriptNode.getProp(Node.FEATURE_SET);
FeatureSet newFeatures = oldFeatures.union(cls.features);
if (!newFeatures.equals(oldFeatures)) {
scriptNode.putProp(Node.FEATURE_SET, newFeatures);
compiler.reportChangeToChangeScope(scriptNode);
}
}
if (NodeUtil.isNameDeclaration(exprRoot)) {
Node assignExpr = varToAssign(exprRoot);
parent.replaceChild(exprRoot, assignExpr);
compiler.reportChangeToEnclosingScope(assignExpr);
}
// with the class members.
if (polymerVersion > 1 && propertyRenamingEnabled && cls.descriptor != null) {
Node props = NodeUtil.getFirstPropMatchingKey(cls.descriptor, "properties");
if (props != null && props.isObjectLit()) {
addObjectReflectionCall(cls, props);
}
}
}
use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.
the class PolymerBehaviorExtractor method extractBehaviors.
/**
* Extracts all Behaviors from an array literal, recursively. Entries in the array can be object
* literals or array literals (of other behaviors). Behavior names must be global, fully qualified
* names. TODO(rishipal): Make this function better handle case where the same behavior
* transitively gets included in the same Polymer element more than once.
*
* @see https://github.com/Polymer/polymer/blob/0.8-preview/PRIMER.md#behaviors
* @param moduleMetadata The module in which these behaviors are being resolved, or null if not in
* a module.
* @return A list of all {@code BehaviorDefinitions} in the array.
*/
ImmutableList<BehaviorDefinition> extractBehaviors(Node behaviorArray, @Nullable ModuleMetadata moduleMetadata) {
if (behaviorArray == null) {
return ImmutableList.of();
}
if (!behaviorArray.isArrayLit()) {
compiler.report(JSError.make(behaviorArray, PolymerPassErrors.POLYMER_INVALID_BEHAVIOR_ARRAY));
return ImmutableList.of();
}
ImmutableList.Builder<BehaviorDefinition> behaviors = ImmutableList.builder();
for (Node behaviorName = behaviorArray.getFirstChild(); behaviorName != null; behaviorName = behaviorName.getNext()) {
if (behaviorName.isObjectLit()) {
PolymerPassStaticUtils.switchDollarSignPropsToBrackets(behaviorName, compiler);
PolymerPassStaticUtils.quoteListenerAndHostAttributeKeys(behaviorName, compiler);
if (NodeUtil.getFirstPropMatchingKey(behaviorName, "is") != null) {
compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_INVALID_BEHAVIOR));
}
Node behaviorModule = NodeUtil.getEnclosingModuleIfPresent(behaviorName);
behaviors.add(new BehaviorDefinition(PolymerPassStaticUtils.extractProperties(behaviorName, PolymerClassDefinition.DefinitionType.ObjectLiteral, compiler, /* constructor= */
null), getBehaviorFunctionsToCopy(behaviorName), getNonPropertyMembersToCopy(behaviorName), /* isGlobalDeclaration= */
NodeUtil.getEnclosingScopeRoot(behaviorName).isRoot(), (FeatureSet) NodeUtil.getEnclosingScript(behaviorName).getProp(Node.FEATURE_SET), behaviorModule));
continue;
}
ResolveBehaviorNameResult resolveResult;
if (isGoogModuleGetCall(behaviorName)) {
resolveResult = resolveGoogModuleGet(behaviorName.getSecondChild().getString());
} else {
resolveResult = resolveBehaviorName(getQualifiedNameThroughCast(behaviorName), moduleMetadata);
}
if (resolveResult.equals(FAILED_RESOLVE_RESULT)) {
compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_UNQUALIFIED_BEHAVIOR));
continue;
}
Node behaviorValue = resolveResult.node;
if (behaviorValue.isArrayLit()) {
// Individual behaviors can also be arrays of behaviors. Parse them recursively.
behaviors.addAll(extractBehaviors(behaviorValue, resolveResult.moduleMetadata));
} else if (behaviorValue.isObjectLit()) {
PolymerPassStaticUtils.switchDollarSignPropsToBrackets(behaviorValue, compiler);
PolymerPassStaticUtils.quoteListenerAndHostAttributeKeys(behaviorValue, compiler);
if (NodeUtil.getFirstPropMatchingKey(behaviorValue, "is") != null) {
compiler.report(JSError.make(behaviorValue, PolymerPassErrors.POLYMER_INVALID_BEHAVIOR));
}
Node behaviorModule = NodeUtil.getEnclosingModuleIfPresent(behaviorValue);
behaviors.add(new BehaviorDefinition(PolymerPassStaticUtils.extractProperties(behaviorValue, PolymerClassDefinition.DefinitionType.ObjectLiteral, compiler, /* constructor= */
null), getBehaviorFunctionsToCopy(behaviorValue), getNonPropertyMembersToCopy(behaviorValue), resolveResult.isGlobalDeclaration, (FeatureSet) NodeUtil.getEnclosingScript(behaviorValue).getProp(Node.FEATURE_SET), behaviorModule));
} else {
compiler.report(JSError.make(behaviorName, PolymerPassErrors.POLYMER_UNQUALIFIED_BEHAVIOR));
}
}
return behaviors.build();
}
use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.
the class InjectTranspilationRuntimeLibraries method process.
@Override
public void process(Node externs, Node root) {
FeatureSet used = FeatureSet.ES3;
for (Node script = root.getFirstChild(); script != null; script = script.getNext()) {
used = used.with(getScriptFeatures(script));
}
FeatureSet outputFeatures = compiler.getOptions().getOutputFeatureSet();
// Check for references to global `Symbol` and getters/setters
if (!outputFeatures.contains(used)) {
NodeTraversal.traverse(compiler, root, this);
}
FeatureSet mustBeCompiledAway = used.without(outputFeatures);
if (mustBeCompiledAway.contains(Feature.TEMPLATE_LITERALS)) {
Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "createtemplatetagfirstarg");
}
if (mustBeCompiledAway.contains(Feature.FOR_OF) || mustBeCompiledAway.contains(Feature.ARRAY_DESTRUCTURING) || mustBeCompiledAway.contains(Feature.OBJECT_PATTERN_REST)) {
// `makeIterator` isn't needed directly for `OBJECT_PATTERN_REST`, but when we transpile
// a destructuring case that contains it, we transpile the entire destructured assignment,
// which may also include `ARRAY_DESTRUCTURING`.
Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "makeIterator");
}
if (mustBeCompiledAway.contains(Feature.ARRAY_PATTERN_REST)) {
Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "arrayFromIterator");
}
if (mustBeCompiledAway.contains(Feature.SPREAD_EXPRESSIONS) || mustBeCompiledAway.contains(Feature.CLASS_EXTENDS)) {
// We must automatically generate the default constructor for descendent classes,
// and those must call super(...arguments), so we end up injecting our own spread
// expressions for such cases.
Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "arrayFromIterable");
}
if ((mustBeCompiledAway.contains(Feature.OBJECT_LITERALS_WITH_SPREAD) || mustBeCompiledAway.contains(Feature.OBJECT_PATTERN_REST)) && !outputFeatures.contains(FeatureSet.ES2015)) {
// We need `Object.assign` to transpile `obj = {a, ...rest};` or `const {a, ...rest} = obj;`,
// but the output language level doesn't indicate that it is guaranteed to be present, so
// we'll include our polyfill.
compiler.ensureLibraryInjected("es6/object/assign", /* force= */
false);
}
if (mustBeCompiledAway.contains(Feature.CLASS_EXTENDS)) {
Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "construct");
Es6ToEs3Util.preloadEs6RuntimeFunction(compiler, "inherits");
}
if (mustBeCompiledAway.contains(Feature.CLASS_GETTER_SETTER)) {
compiler.ensureLibraryInjected("util/global", /* force= */
false);
}
if (mustBeCompiledAway.contains(Feature.GENERATORS)) {
compiler.ensureLibraryInjected("es6/generator_engine", /* force= */
false);
}
if (mustBeCompiledAway.contains(Feature.ASYNC_FUNCTIONS)) {
compiler.ensureLibraryInjected("es6/execute_async_generator", /* force= */
false);
}
if (mustBeCompiledAway.contains(Feature.ASYNC_GENERATORS)) {
compiler.ensureLibraryInjected("es6/async_generator_wrapper", /* force= */
false);
}
if (mustBeCompiledAway.contains(Feature.FOR_AWAIT_OF)) {
compiler.ensureLibraryInjected("es6/util/makeasynciterator", /* force= */
false);
}
if (mustBeCompiledAway.contains(Feature.REST_PARAMETERS)) {
compiler.ensureLibraryInjected("es6/util/restarguments", /* force= */
false);
}
}
use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.
the class NodeUtil method addFeatureToScript.
/**
* Adds the given features to a SCRIPT node's FeatureSet property.
*
* <p>Also updates the compiler's FeatureSet.
*/
static void addFeatureToScript(Node scriptNode, Feature feature, AbstractCompiler compiler) {
checkState(scriptNode.isScript(), scriptNode);
FeatureSet currentFeatures = getFeatureSetOfScript(scriptNode);
FeatureSet newFeatures = currentFeatures != null ? currentFeatures.with(feature) : FeatureSet.BARE_MINIMUM.with(feature);
scriptNode.putProp(Node.FEATURE_SET, newFeatures);
compiler.setFeatureSet(compiler.getFeatureSet().with(feature));
}
use of com.google.javascript.jscomp.parsing.parser.FeatureSet in project closure-compiler by google.
the class RewritePolyfills method removeUnneededPolyfills.
// Remove any $jscomp.polyfill calls whose 3rd parameter (the language version
// that already contains the library) is the same or lower than languageOut.
private void removeUnneededPolyfills(Node parent, Node runtimeEnd) {
Node node = parent.getFirstChild();
// The target environment is assumed to support the features in this set.
final FeatureSet outputFeatureSet = compiler.getOptions().getOutputFeatureSet();
while (node != null && node != runtimeEnd) {
// look up the next node now, because we may be removing this one.
Node next = node.getNext();
FeatureSet polyfillSupportedFeatureSet = getPolyfillSupportedFeatureSet(node);
if (polyfillSupportedFeatureSet != null && outputFeatureSet.contains(polyfillSupportedFeatureSet)) {
NodeUtil.removeChild(parent, node);
NodeUtil.markFunctionsDeleted(node, compiler);
}
node = next;
}
}
Aggregations