Search in sources :

Example 1 with MemberDefinition

use of com.google.javascript.jscomp.PolymerPass.MemberDefinition in project closure-compiler by google.

the class PolymerClassRewriter method appendPropertiesToBlock.

/**
 * Appends all properties in the ClassDefinition to the prototype of the custom element.
 */
private void appendPropertiesToBlock(final PolymerClassDefinition cls, Node block, String basePath) {
    for (MemberDefinition prop : cls.props) {
        Node propertyNode = IR.exprResult(NodeUtil.newQName(compiler, basePath + prop.name.getString()));
        // If a property string is quoted, make sure the added prototype properties are also quoted
        if (prop.name.isQuotedString()) {
            continue;
        }
        propertyNode.useSourceInfoIfMissingFromForTree(prop.name);
        JSDocInfoBuilder info = JSDocInfoBuilder.maybeCopyFrom(prop.info);
        JSTypeExpression propType = PolymerPassStaticUtils.getTypeFromProperty(prop, compiler);
        if (propType == null) {
            return;
        }
        info.recordType(propType);
        propertyNode.getFirstChild().setJSDocInfo(info.build());
        block.addChildToBack(propertyNode);
    }
}
Also used : Node(com.google.javascript.rhino.Node) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) JSDocInfoBuilder(com.google.javascript.rhino.JSDocInfoBuilder) MemberDefinition(com.google.javascript.jscomp.PolymerPass.MemberDefinition)

Example 2 with MemberDefinition

use of com.google.javascript.jscomp.PolymerPass.MemberDefinition in project closure-compiler by google.

the class PolymerClassRewriter method addTypesToFunctions.

/**
 * Adds an @this annotation to all functions in the objLit.
 */
private void addTypesToFunctions(Node objLit, String thisType, PolymerClassDefinition.DefinitionType defType) {
    checkState(objLit.isObjectLit());
    for (Node keyNode = objLit.getFirstChild(); keyNode != null; keyNode = keyNode.getNext()) {
        Node value = keyNode.getLastChild();
        if (value != null && value.isFunction()) {
            JSDocInfo.Builder fnDoc = JSDocInfo.Builder.maybeCopyFrom(keyNode.getJSDocInfo());
            fnDoc.recordThisType(new JSTypeExpression(new Node(Token.BANG, IR.string(thisType)).srcrefTree(keyNode), VIRTUAL_FILE));
            keyNode.setJSDocInfo(fnDoc.build());
        }
    }
    // Add @this and @return to default property values.
    for (MemberDefinition property : PolymerPassStaticUtils.extractProperties(objLit, defType, compiler, /**
     * constructor=
     */
    null)) {
        if (!property.value.isObjectLit()) {
            continue;
        }
        Node defaultValue = NodeUtil.getFirstPropMatchingKey(property.value, "value");
        if (defaultValue == null || !defaultValue.isFunction()) {
            continue;
        }
        Node defaultValueKey = defaultValue.getParent();
        JSDocInfo.Builder fnDoc = JSDocInfo.Builder.maybeCopyFrom(defaultValueKey.getJSDocInfo());
        fnDoc.recordThisType(new JSTypeExpression(new Node(Token.BANG, IR.string(thisType)).srcrefTree(defaultValueKey), VIRTUAL_FILE));
        fnDoc.recordReturnType(PolymerPassStaticUtils.getTypeFromProperty(property, compiler));
        defaultValueKey.setJSDocInfo(fnDoc.build());
    }
}
Also used : Node(com.google.javascript.rhino.Node) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) JSDocInfo(com.google.javascript.rhino.JSDocInfo) MemberDefinition(com.google.javascript.jscomp.PolymerPass.MemberDefinition)

Example 3 with MemberDefinition

use of com.google.javascript.jscomp.PolymerPass.MemberDefinition in project closure-compiler by google.

the class PolymerClassRewriter method convertSimpleObserverStringsToReferences.

/**
 * Converts property observer strings to direct function references.
 *
 * <p>From: <code>observer: '_observerName'</code> To: <code>
 * observer: ClassName.prototype._observerName</code>
 */
private void convertSimpleObserverStringsToReferences(final PolymerClassDefinition cls) {
    for (MemberDefinition prop : cls.props) {
        if (prop.value.isObjectLit()) {
            Node observer = NodeUtil.getFirstPropMatchingKey(prop.value, "observer");
            if (observer != null && observer.isStringLit()) {
                Node observerDirectReference = IR.getprop(cls.target.cloneTree(), "prototype", observer.getString()).srcref(observer);
                observer.replaceWith(observerDirectReference);
                compiler.reportChangeToEnclosingScope(observerDirectReference);
            }
        }
    }
}
Also used : Node(com.google.javascript.rhino.Node) MemberDefinition(com.google.javascript.jscomp.PolymerPass.MemberDefinition)

Example 4 with MemberDefinition

use of com.google.javascript.jscomp.PolymerPass.MemberDefinition 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 cls The extracted {@link PolymerClassDefinition} for the Polymer element created by this
 *     call.
 * @param traversal Nodetraversal used here to identify the scope in which Polymer exists
 */
void rewritePolymerCall(final PolymerClassDefinition cls, NodeTraversal traversal) {
    Node callParent = cls.definition.getParent();
    // Determine whether we are in a Polymer({}) call at the top level versus in an assignment.
    Node exprRoot = callParent.isExprResult() ? callParent : callParent.getParent();
    checkState(NodeUtil.isStatementParent(exprRoot.getParent()), exprRoot.getParent());
    Node objLit = checkNotNull(cls.descriptor);
    // Add {@code @lends} to the object literal.
    JSDocInfo.Builder objLitDoc = JSDocInfo.builder().parseDocumentation();
    JSTypeExpression jsTypeExpression = new JSTypeExpression(IR.string(cls.target.getQualifiedName() + ".prototype").srcref(exprRoot), exprRoot.getSourceFileName());
    objLitDoc.recordLends(jsTypeExpression);
    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);
        }
    }
    // The propsAndBehaviorBlock holds code generated for the  Polymer's properties and behaviors
    Node propsAndBehaviorBlock = IR.block();
    JSDocInfo.Builder constructorDoc = this.getConstructorDoc(cls);
    // Remove the original constructor JS docs from the objlit.
    Node ctorKey = cls.constructor.value.getParent();
    if (ctorKey != null) {
        ctorKey.setJSDocInfo(null);
    }
    // Check for a conflicting definition of PolymerElement
    if (!traversal.inGlobalScope()) {
        Var polymerElement = traversal.getScope().getVar("PolymerElement");
        if (polymerElement != null && !polymerElement.getScope().isGlobal()) {
            Node nameNode = polymerElement.getNameNode();
            compiler.report(JSError.make(cls.constructor.value, POLYMER_ELEMENT_CONFLICT, nameNode.getSourceFileName(), Integer.toString(nameNode.getLineno()), Integer.toString(nameNode.getCharno())));
        }
    }
    Node declarationCode = generateDeclarationCode(exprRoot, cls, constructorDoc, traversal);
    String basePath = cls.target.getQualifiedName() + ".prototype.";
    appendBehaviorPropertiesToBlock(cls, propsAndBehaviorBlock, basePath, /*isExternsBlock*/
    false);
    appendPropertiesToBlock(cls.props, propsAndBehaviorBlock, basePath, /* isExternsBlock= */
    false);
    appendBehaviorMembersToBlock(cls, propsAndBehaviorBlock);
    ImmutableList<MemberDefinition> readOnlyPropsAll = parseReadOnlyProperties(cls, propsAndBehaviorBlock);
    ImmutableList<MemberDefinition> attributeReflectedPropsAll = parseAttributeReflectedProperties(cls);
    createExportsAndExterns(cls, readOnlyPropsAll, attributeReflectedPropsAll);
    removePropertyDocs(objLit, cls.defType);
    Node propsAndBehaviorCode = propsAndBehaviorBlock.removeChildren();
    Node parent = exprRoot.getParent();
    // exported.
    if (!traversal.inGlobalScope() && cls.hasGeneratedLhs && !cls.target.isGetProp()) {
        Node enclosingNode = NodeUtil.getEnclosingNode(parent, node -> node.isScript() || node.isModuleBody() || isIIFE(node) || isFunctionArgInGoogLoadModule(node));
        // For module, IIFE and goog.LoadModule enclosed Polymer calls, the declaration code and the
        // code generated from properties and behavior have to be hoisted in different places within
        // the AST. We want to insert the generated declarations to global scope, and insert the
        // propsAndbehaviorCode in the same scope. Hence, dealing with them separately.
        insertGeneratedDeclarationCodeToGlobalScope(enclosingNode, declarationCode);
        if (propsAndBehaviorCode != null) {
            insertGeneratedPropsAndBehaviorCode(enclosingNode, propsAndBehaviorCode);
        }
    } else {
        Node beforeRoot = exprRoot.getPrevious();
        if (beforeRoot == null) {
            if (propsAndBehaviorCode != null) {
                parent.addChildrenToFront(propsAndBehaviorCode);
            }
            parent.addChildToFront(declarationCode);
        } else {
            if (propsAndBehaviorCode != null) {
                parent.addChildrenAfter(propsAndBehaviorCode, beforeRoot);
            }
            declarationCode.insertAfter(beforeRoot);
        }
        compiler.reportChangeToEnclosingScope(parent);
    }
    if (propsAndBehaviorCode != null) {
        compiler.reportChangeToEnclosingScope(propsAndBehaviorCode);
    }
    // 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);
        exprRoot.replaceWith(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()) {
            addPropertiesConfigObjectReflection(cls, props);
        }
    }
}
Also used : Node(com.google.javascript.rhino.Node) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) FeatureSet(com.google.javascript.jscomp.parsing.parser.FeatureSet) JSDocInfo(com.google.javascript.rhino.JSDocInfo) MemberDefinition(com.google.javascript.jscomp.PolymerPass.MemberDefinition)

Example 5 with MemberDefinition

use of com.google.javascript.jscomp.PolymerPass.MemberDefinition in project closure-compiler by google.

the class PolymerClassRewriter method parseReadOnlyProperties.

/**
 * Generates the _set* setters for readonly properties and appends them to the given block.
 *
 * @return A List of all readonly properties.
 */
private ImmutableList<MemberDefinition> parseReadOnlyProperties(final PolymerClassDefinition cls, Node block) {
    String qualifiedPath = cls.target.getQualifiedName() + ".prototype.";
    ImmutableList.Builder<MemberDefinition> readOnlyProps = ImmutableList.builder();
    for (MemberDefinition prop : cls.props) {
        // Generate the setter for readOnly properties.
        if (prop.value.isObjectLit()) {
            Node readOnlyValue = NodeUtil.getFirstPropMatchingKey(prop.value, "readOnly");
            if (readOnlyValue != null && readOnlyValue.isTrue()) {
                Node setter = makeReadOnlySetter(prop, qualifiedPath);
                setter.srcrefTreeIfMissing(prop.name);
                block.addChildToBack(setter);
                readOnlyProps.add(prop);
            }
        }
    }
    if (cls.behaviorProps != null) {
        for (Map.Entry<MemberDefinition, BehaviorDefinition> itr : cls.behaviorProps.entrySet()) {
            // Generate the setter for readOnly properties.
            MemberDefinition prop = itr.getKey();
            if (prop.value.isObjectLit()) {
                Node readOnlyValue = NodeUtil.getFirstPropMatchingKey(prop.value, "readOnly");
                if (readOnlyValue != null && readOnlyValue.isTrue()) {
                    Node setter = makeReadOnlySetter(prop, qualifiedPath);
                    setter.srcrefTreeIfMissing(prop.name);
                    block.addChildToBack(setter);
                    readOnlyProps.add(prop);
                }
            }
        }
    }
    return readOnlyProps.build();
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) Node(com.google.javascript.rhino.Node) MemberDefinition(com.google.javascript.jscomp.PolymerPass.MemberDefinition) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) BehaviorDefinition(com.google.javascript.jscomp.PolymerBehaviorExtractor.BehaviorDefinition)

Aggregations

MemberDefinition (com.google.javascript.jscomp.PolymerPass.MemberDefinition)22 Node (com.google.javascript.rhino.Node)21 JSDocInfo (com.google.javascript.rhino.JSDocInfo)13 JSTypeExpression (com.google.javascript.rhino.JSTypeExpression)9 BehaviorDefinition (com.google.javascript.jscomp.PolymerBehaviorExtractor.BehaviorDefinition)7 ArrayList (java.util.ArrayList)7 ImmutableList (com.google.common.collect.ImmutableList)6 LinkedHashMap (java.util.LinkedHashMap)6 FeatureSet (com.google.javascript.jscomp.parsing.parser.FeatureSet)5 JSDocInfoBuilder (com.google.javascript.rhino.JSDocInfoBuilder)4 HashMap (java.util.HashMap)4 Nullable (javax.annotation.Nullable)4 Map (java.util.Map)3 HashSet (java.util.HashSet)2 List (java.util.List)2 CaseFormat (com.google.common.base.CaseFormat)1 MoreObjects.toStringHelper (com.google.common.base.MoreObjects.toStringHelper)1 Preconditions.checkState (com.google.common.base.Preconditions.checkState)1 Supplier (com.google.common.base.Supplier)1 ModuleMetadata (com.google.javascript.jscomp.modules.ModuleMetadataMap.ModuleMetadata)1