Search in sources :

Example 21 with Ref

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

the class CollapseProperties method updateGlobalNameDeclarationAtClassNode.

/**
 * Updates the first initialization (a.k.a "declaration") of a global name that occurs at a CLASS
 * node. See comment for {@link #updateGlobalNameDeclaration}.
 *
 * @param n An object representing a global name (e.g. "a")
 */
private void updateGlobalNameDeclarationAtClassNode(Name n, boolean canCollapseChildNames) {
    if (!canCollapseChildNames || !canCollapse(n)) {
        return;
    }
    Ref ref = n.getDeclaration();
    String className = ref.node.getString();
    addStubsForUndeclaredProperties(n, className, ref.node.getAncestor(2), ref.node.getParent());
}
Also used : Ref(com.google.javascript.jscomp.GlobalNamespace.Ref)

Example 22 with Ref

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

the class AggressiveInlineAliases method inlineGlobalAliasIfPossible.

/**
 * Attempt to inline an global alias of a global name. This requires that the name is well
 * defined: assigned unconditionally, assigned exactly once. It is assumed that, the name for
 * which it is an alias must already meet these same requirements.
 *
 * @param alias The alias to inline
 * @return Whether the alias was inlined.
 */
private boolean inlineGlobalAliasIfPossible(Name name, Ref alias, GlobalNamespace namespace) {
    // Ensure that the alias is assigned to global name at that the
    // declaration.
    Node aliasParent = alias.node.getParent();
    if (((aliasParent.isAssign() || aliasParent.isName()) && NodeUtil.isExecutedExactlyOnce(aliasParent)) || // TODO(tbreisacher): Do we still need this special case?
    (aliasParent.isName() && name.isConstructor())) {
        Node lvalue = aliasParent.isName() ? aliasParent : aliasParent.getFirstChild();
        if (!lvalue.isQualifiedName()) {
            return false;
        }
        if (lvalue.isName() && compiler.getCodingConvention().isExported(lvalue.getString(), /* local */
        false)) {
            return false;
        }
        name = namespace.getSlot(lvalue.getQualifiedName());
        if (name != null && name.isInlinableGlobalAlias()) {
            Set<AstChange> newNodes = new LinkedHashSet<>();
            List<Ref> refs = new ArrayList<>(name.getRefs());
            for (Ref ref : refs) {
                switch(ref.type) {
                    case SET_FROM_GLOBAL:
                        continue;
                    case DIRECT_GET:
                    case ALIASING_GET:
                    case PROTOTYPE_GET:
                    case CALL_GET:
                        Node newNode = alias.node.cloneTree();
                        Node node = ref.node;
                        node.getParent().replaceChild(node, newNode);
                        compiler.reportChangeToEnclosingScope(newNode);
                        newNodes.add(new AstChange(ref.module, ref.scope, newNode));
                        name.removeRef(ref);
                        break;
                    default:
                        throw new IllegalStateException();
                }
            }
            rewriteAliasProps(name, alias.node, 0, newNodes);
            // just set the original alias to null.
            aliasParent.replaceChild(alias.node, IR.nullNode());
            codeChanged = true;
            compiler.reportChangeToEnclosingScope(aliasParent);
            // Inlining the variable may have introduced new references
            // to descendants of {@code name}. So those need to be collected now.
            namespace.scanNewNodes(newNodes);
            return true;
        }
    }
    return false;
}
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) ArrayList(java.util.ArrayList)

Example 23 with Ref

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

the class AggressiveInlineAliases method rewriteAliasProp.

/**
 * @param value The value to use when rewriting.
 * @param depth The chain depth.
 * @param newNodes Expression nodes that have been updated.
 * @param prop The property to rewrite with value.
 */
private void rewriteAliasProp(Node value, int depth, Set<AstChange> newNodes, Name prop) {
    rewriteAliasProps(prop, value, depth + 1, newNodes);
    List<Ref> refs = new ArrayList<>(prop.getRefs());
    for (Ref ref : refs) {
        Node target = ref.node;
        for (int i = 0; i <= depth; i++) {
            if (target.isGetProp()) {
                target = target.getFirstChild();
            } else if (NodeUtil.isObjectLitKey(target)) {
                // Object literal key definitions are a little trickier, as we
                // need to find the assignment target
                Node gparent = target.getGrandparent();
                if (gparent.isAssign()) {
                    target = gparent.getFirstChild();
                } else {
                    checkState(NodeUtil.isObjectLitKey(gparent));
                    target = gparent;
                }
            } else {
                throw new IllegalStateException("unexpected: " + target);
            }
        }
        checkState(target.isGetProp() || target.isName());
        Node newValue = value.cloneTree();
        target.replaceWith(newValue);
        compiler.reportChangeToEnclosingScope(newValue);
        prop.removeRef(ref);
        // Rescan the expression root.
        newNodes.add(new AstChange(ref.module, ref.scope, ref.node));
        codeChanged = true;
    }
}
Also used : Ref(com.google.javascript.jscomp.GlobalNamespace.Ref) AstChange(com.google.javascript.jscomp.GlobalNamespace.AstChange) Node(com.google.javascript.rhino.Node) ArrayList(java.util.ArrayList)

Example 24 with Ref

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

the class CheckGlobalNames method propertyMustBeInitializedByFullName.

/**
 * The input name is a property. Check whether this property
 * must be initialized with its full qualified name.
 */
private boolean propertyMustBeInitializedByFullName(Name name) {
    // chain of functions and objects.
    if (name.parent == null) {
        return false;
    }
    boolean parentIsAliased = false;
    if (name.parent.aliasingGets > 0) {
        for (Ref ref : name.parent.getRefs()) {
            if (ref.type == Ref.Type.ALIASING_GET) {
                Node aliaser = ref.getNode().getParent();
                // We don't need to worry about known aliased, because
                // they're already covered by the getIndirectlyDeclaredProperties
                // call at the top.
                boolean isKnownAlias = aliaser.isCall() && (convention.getClassesDefinedByCall(aliaser) != null || convention.getSingletonGetterClassName(aliaser) != null);
                if (!isKnownAlias) {
                    parentIsAliased = true;
                }
            }
        }
    }
    if (parentIsAliased) {
        return false;
    }
    if (objectPrototypeProps.contains(name.getBaseName())) {
        return false;
    }
    if (name.parent.type == Name.Type.OBJECTLIT || name.parent.type == Name.Type.CLASS) {
        return true;
    }
    return name.parent.type == Name.Type.FUNCTION && name.parent.isDeclaredType() && !functionPrototypeProps.contains(name.getBaseName());
}
Also used : Ref(com.google.javascript.jscomp.GlobalNamespace.Ref) Node(com.google.javascript.rhino.Node)

Example 25 with Ref

use of com.google.javascript.jscomp.GlobalNamespace.Ref 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)

Aggregations

Ref (com.google.javascript.jscomp.GlobalNamespace.Ref)34 Name (com.google.javascript.jscomp.GlobalNamespace.Name)25 Node (com.google.javascript.rhino.Node)24 Test (org.junit.Test)13 NodeSubject.assertNode (com.google.javascript.rhino.testing.NodeSubject.assertNode)9 JSDocInfo (com.google.javascript.rhino.JSDocInfo)7 AstChange (com.google.javascript.jscomp.GlobalNamespace.AstChange)4 ArrayList (java.util.ArrayList)3 LinkedHashSet (java.util.LinkedHashSet)3 JSTypeExpression (com.google.javascript.rhino.JSTypeExpression)2 JSType (com.google.javascript.rhino.jstype.JSType)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableSet (com.google.common.collect.ImmutableSet)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 Nullable (javax.annotation.Nullable)1