Search in sources :

Example 51 with Name

use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.

the class AggressiveInlineAliases method rewriteAllSubclassInheritedAccesses.

/**
 * Inline all references to inherited static superclass properties from the subclass or any
 * descendant of the given subclass. Avoids inlining references to inherited methods when
 * possible, since they may use this or super().
 *
 * @param superclassNameObj The Name of the superclass
 * @param subclassNameObj The Name of the subclass
 * @param prop The property on the superclass to rewrite, if any descendant accesses it.
 * @param namespace The GlobalNamespace containing superclassNameObj
 */
private boolean rewriteAllSubclassInheritedAccesses(Name superclassNameObj, Name subclassNameObj, Name prop, GlobalNamespace namespace) {
    Ref propDeclRef = prop.getDeclaration();
    if (propDeclRef == null || propDeclRef.node == null || !propDeclRef.node.getParent().isAssign()) {
        return false;
    }
    Node propRhs = propDeclRef.node.getParent().getLastChild();
    if (propRhs.isFunction()) {
        return false;
    }
    String subclassQualifiedPropName = subclassNameObj.getFullName() + "." + prop.getBaseName();
    Name subclassPropNameObj = namespace.getOwnSlot(subclassQualifiedPropName);
    // shadows it.
    if (subclassPropNameObj != null && (subclassPropNameObj.localSets > 0 || subclassPropNameObj.globalSets > 0)) {
        return false;
    }
    // Recurse to find potential sub-subclass accesses of the superclass property.
    if (subclassNameObj.subclasses != null) {
        for (Name name : subclassNameObj.subclasses) {
            rewriteAllSubclassInheritedAccesses(superclassNameObj, name, prop, namespace);
        }
    }
    if (subclassPropNameObj != null) {
        Set<AstChange> newNodes = new LinkedHashSet<>();
        // Use this node as a template for rewriteAliasProp.
        Node superclassNameNode = superclassNameObj.getDeclaration().node;
        if (superclassNameNode.isName()) {
            superclassNameNode = superclassNameNode.cloneNode();
        } else if (superclassNameNode.isGetProp()) {
            superclassNameNode = superclassNameNode.cloneTree();
        } else {
            return false;
        }
        rewriteAliasProp(superclassNameNode, 0, newNodes, subclassPropNameObj);
        namespace.scanNewNodes(newNodes);
    }
    return true;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Ref(com.google.javascript.jscomp.GlobalNamespace.Ref) AstChange(com.google.javascript.jscomp.GlobalNamespace.AstChange) Node(com.google.javascript.rhino.Node) Name(com.google.javascript.jscomp.GlobalNamespace.Name)

Example 52 with Name

use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.

the class CollapseProperties method declareVariablesForObjLitValues.

/**
 * Declares global variables to serve as aliases for the values in an object literal, optionally
 * removing all of the object literal's keys and values.
 *
 * @param alias The object literal's flattened name (e.g. "a$b$c")
 * @param objlit The OBJLIT node
 * @param varNode The VAR node to which new global variables should be added as children
 * @param nameToAddAfter The child of {@code varNode} after which new variables should be added
 *     (may be null)
 * @param varParent {@code varNode}'s parent
 */
private void declareVariablesForObjLitValues(Name objlitName, String alias, Node objlit, Node varNode, Node nameToAddAfter, Node varParent) {
    int arbitraryNameCounter = 0;
    boolean discardKeys = !objlitName.shouldKeepKeys();
    for (Node key = objlit.getFirstChild(), nextKey; key != null; key = nextKey) {
        Node value = key.getFirstChild();
        nextKey = key.getNext();
        // A computed property, or a get or a set can not be rewritten as a VAR.
        if (key.isGetterDef() || key.isSetterDef() || key.isComputedProp()) {
            continue;
        }
        // We generate arbitrary names for keys that aren't valid JavaScript
        // identifiers, since those keys are never referenced. (If they were,
        // this object literal's child names wouldn't be collapsible.) The only
        // reason that we don't eliminate them entirely is the off chance that
        // their values are expressions that have side effects.
        boolean isJsIdentifier = !key.isNumber() && TokenStream.isJSIdentifier(key.getString());
        String propName = isJsIdentifier ? key.getString() : String.valueOf(++arbitraryNameCounter);
        // If the name cannot be collapsed, skip it.
        String qName = objlitName.getFullName() + '.' + propName;
        Name p = nameMap.get(qName);
        if (p != null && !canCollapse(p)) {
            continue;
        }
        String propAlias = appendPropForAlias(alias, propName);
        Node refNode = null;
        if (discardKeys) {
            objlit.removeChild(key);
            value.detach();
        // Don't report a change here because the objlit has already been removed from the tree.
        } else {
            // Substitute a reference for the value.
            refNode = IR.name(propAlias);
            if (key.getBooleanProp(Node.IS_CONSTANT_NAME)) {
                refNode.putBooleanProp(Node.IS_CONSTANT_NAME, true);
            }
            key.replaceChild(value, refNode);
            compiler.reportChangeToEnclosingScope(refNode);
        }
        // Declare the collapsed name as a variable with the original value.
        Node nameNode = IR.name(propAlias);
        nameNode.addChildToFront(value);
        if (key.getBooleanProp(Node.IS_CONSTANT_NAME)) {
            nameNode.putBooleanProp(Node.IS_CONSTANT_NAME, true);
        }
        Node newVar = IR.var(nameNode).useSourceInfoIfMissingFromForTree(key);
        if (nameToAddAfter != null) {
            varParent.addChildAfter(newVar, nameToAddAfter);
        } else {
            varParent.addChildBefore(newVar, varNode);
        }
        compiler.reportChangeToEnclosingScope(newVar);
        nameToAddAfter = newVar;
        // for the same global name.)
        if (isJsIdentifier && p != null) {
            if (!discardKeys) {
                Ref newAlias = p.getDeclaration().cloneAndReclassify(Ref.Type.ALIASING_GET);
                newAlias.node = refNode;
                p.addRef(newAlias);
            }
            p.getDeclaration().node = nameNode;
            if (value.isFunction()) {
                checkForHosedThisReferences(value, key.getJSDocInfo(), p);
            }
        }
    }
}
Also used : Ref(com.google.javascript.jscomp.GlobalNamespace.Ref) Node(com.google.javascript.rhino.Node) Name(com.google.javascript.jscomp.GlobalNamespace.Name)

Example 53 with Name

use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.

the class CollapseProperties method process.

@Override
public void process(Node externs, Node root) {
    GlobalNamespace namespace = new GlobalNamespace(compiler, root);
    nameMap = namespace.getNameIndex();
    globalNames = namespace.getNameForest();
    checkNamespaces();
    for (Name name : globalNames) {
        flattenReferencesToCollapsibleDescendantNames(name, name.getBaseName());
    }
    // invalidating the node ancestry stored with each reference.
    for (Name name : globalNames) {
        collapseDeclarationOfNameAndDescendants(name, name.getBaseName());
    }
    // This shouldn't be necessary, this pass should already be setting new constants as constant.
    // TODO(b/64256754): Investigate.
    (new PropagateConstantAnnotationsOverVars(compiler, false)).process(externs, root);
}
Also used : PropagateConstantAnnotationsOverVars(com.google.javascript.jscomp.Normalize.PropagateConstantAnnotationsOverVars) Name(com.google.javascript.jscomp.GlobalNamespace.Name)

Example 54 with Name

use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.

the class CollapseProperties method flattenPrefixes.

/**
 * Flattens all occurrences of a name as a prefix of subnames beginning
 * with a particular subname.
 *
 * @param n A global property name (e.g. "a.b.c.d")
 * @param alias A flattened prefix name (e.g. "a$b")
 * @param depth The difference in depth between the property name and
 *    the prefix name (e.g. 2)
 */
private void flattenPrefixes(String alias, Name n, int depth) {
    // Only flatten the prefix of a name declaration if the name being
    // initialized is fully qualified (i.e. not an object literal key).
    String originalName = n.getFullName();
    Ref decl = n.getDeclaration();
    if (decl != null && decl.node != null && decl.node.isGetProp()) {
        flattenNameRefAtDepth(alias, decl.node, depth, originalName);
    }
    for (Ref r : n.getRefs()) {
        if (r == decl) {
            // Declarations are handled separately.
            continue;
        }
        // have twins. We should only flatten one of the twins.
        if (r.getTwin() == null || r.isSet()) {
            flattenNameRefAtDepth(alias, r.node, depth, originalName);
        }
    }
    if (n.props != null) {
        for (Name p : n.props) {
            flattenPrefixes(alias, p, depth + 1);
        }
    }
}
Also used : Ref(com.google.javascript.jscomp.GlobalNamespace.Ref) Name(com.google.javascript.jscomp.GlobalNamespace.Name)

Example 55 with Name

use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.

the class CollapseProperties method addStubsForUndeclaredProperties.

/**
 * Adds global variable "stubs" for any properties of a global name that are only set in a local
 * scope or read but never set.
 *
 * @param n An object representing a global name (e.g. "a", "a.b.c")
 * @param alias The flattened name of the object whose properties we are adding stubs for (e.g.
 *     "a$b$c")
 * @param parent The node to which new global variables should be added as children
 * @param addAfter The child of after which new variables should be added
 */
private void addStubsForUndeclaredProperties(Name n, String alias, Node parent, Node addAfter) {
    checkState(n.canCollapseUnannotatedChildNames(), n);
    checkArgument(NodeUtil.isStatementBlock(parent), parent);
    checkNotNull(addAfter);
    if (n.props == null) {
        return;
    }
    for (Name p : n.props) {
        if (p.needsToBeStubbed()) {
            String propAlias = appendPropForAlias(alias, p.getBaseName());
            Node nameNode = IR.name(propAlias);
            Node newVar = IR.var(nameNode).useSourceInfoIfMissingFromForTree(addAfter);
            parent.addChildAfter(newVar, addAfter);
            addAfter = newVar;
            compiler.reportChangeToEnclosingScope(newVar);
            // reference to it. Don't check the declaration, as it might be null.
            if (p.getRefs().get(0).node.getLastChild().getBooleanProp(Node.IS_CONSTANT_NAME)) {
                nameNode.putBooleanProp(Node.IS_CONSTANT_NAME, true);
                compiler.reportChangeToEnclosingScope(nameNode);
            }
        }
    }
}
Also used : Node(com.google.javascript.rhino.Node) Name(com.google.javascript.jscomp.GlobalNamespace.Name)

Aggregations

Name (com.google.javascript.jscomp.GlobalNamespace.Name)95 Test (org.junit.Test)72 Ref (com.google.javascript.jscomp.GlobalNamespace.Ref)25 Node (com.google.javascript.rhino.Node)22 ModuleMetadata (com.google.javascript.jscomp.modules.ModuleMetadataMap.ModuleMetadata)12 NodeSubject.assertNode (com.google.javascript.rhino.testing.NodeSubject.assertNode)12 JSDocInfo (com.google.javascript.rhino.JSDocInfo)5 AstChange (com.google.javascript.jscomp.GlobalNamespace.AstChange)2 Inlinability (com.google.javascript.jscomp.GlobalNamespace.Inlinability)2 JSTypeExpression (com.google.javascript.rhino.JSTypeExpression)2 JSType (com.google.javascript.rhino.jstype.JSType)2 LinkedHashSet (java.util.LinkedHashSet)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 PropagateConstantAnnotationsOverVars (com.google.javascript.jscomp.Normalize.PropagateConstantAnnotationsOverVars)1 Module (com.google.javascript.jscomp.modules.Module)1 FeatureSet (com.google.javascript.jscomp.parsing.parser.FeatureSet)1 QualifiedName (com.google.javascript.rhino.QualifiedName)1 ArrayList (java.util.ArrayList)1