Search in sources :

Example 16 with Token

use of com.google.javascript.rhino.Token in project closure-compiler by google.

the class SemanticReverseAbstractInterpreterTest method testInequalitiesCondition1.

/**
 * Tests reverse interpretation of a COMPARE(NAME, NUMBER) expression, where COMPARE can be LE,
 * LT, GE or GT.
 */
@Test
public void testInequalitiesCondition1() {
    for (Token op : Arrays.asList(Token.LT, Token.GT, Token.LE, Token.GE)) {
        FlowScope[] blind = newScope();
        testBinop(blind, op, createVar(blind, "a", createUnionType(getNativeStringType(), getNativeVoidType())), createNumber(8), ImmutableSet.of(new TypedName("a", getNativeStringType())), ImmutableSet.of(new TypedName("a", createUnionType(getNativeStringType(), getNativeVoidType()))));
    }
}
Also used : Token(com.google.javascript.rhino.Token) FlowScope(com.google.javascript.jscomp.type.FlowScope) Test(org.junit.Test)

Example 17 with Token

use of com.google.javascript.rhino.Token in project closure-compiler by google.

the class TypeInferencePass method inferAllScopes.

/**
 * Execute type inference running over part of the scope tree.
 *
 * @return the top scope, either newly created, or patched by this inference.
 */
TypedScope inferAllScopes(Node inferenceRoot) {
    // order to propagate the type of ns.method in the outer scope.
    try (JSTypeResolver.Closer closer = this.registry.getResolver().openForDefinition()) {
        checkState(inferenceRoot.isRoot());
        checkState(inferenceRoot.getParent() == null);
        checkState(this.topScope == null);
        this.topScope = scopeCreator.createScope(inferenceRoot, null);
        NodeTraversal.builder().setCompiler(compiler).setCallback(new FirstScopeBuildingCallback()).setScopeCreator(scopeCreator).traverseWithScope(inferenceRoot, this.topScope);
        scopeCreator.resolveWeakImportsPreResolution();
    }
    scopeCreator.finishAndFreeze();
    NodeTraversal.builder().setCompiler(compiler).setCallback(new SecondScopeBuildingCallback()).setScopeCreator(scopeCreator).traverseWithScope(inferenceRoot, this.topScope);
    // Normalize TypedVars to have the '?' type instead of null after inference is complete. This
    // currently cannot be done any earlier because it breaks inference of variables assigned in
    // local scopes.
    // TODO(b/149843534): this should be a crash instead.
    final JSType unknownType = this.registry.getNativeType(UNKNOWN_TYPE);
    for (TypedVar var : this.scopeCreator.getAllSymbols()) {
        if (var.getType() == null) {
            var.setType(unknownType);
        }
    }
    if (this.stepCountHistogram != null) {
        try (LogFile histogram = this.compiler.createOrReopenLog(this.getClass(), "step_histogram.log")) {
            histogram.log("step_count token population");
            int[] totals = new int[] { 0, 0 };
            this.stepCountHistogram.keySet().stream().sorted(Comparator.<Integer>naturalOrder().reversed()).forEach((stepCount) -> this.stepCountHistogram.get(stepCount).entrySet().stream().sorted(comparingInt(Multiset.Entry::getCount)).forEach((e) -> {
                totals[0] += stepCount * e.getCount();
                totals[1] += e.getCount();
                histogram.log("%s %s %s", stepCount, e.getElement(), e.getCount());
            }));
            histogram.log("%s TOTAL %s", totals[0], totals[1]);
        }
    }
    return this.topScope;
}
Also used : LogFile(com.google.javascript.jscomp.diagnostic.LogFile) Comparator.comparingInt(java.util.Comparator.comparingInt) LinearFlowState(com.google.javascript.jscomp.DataFlowAnalysis.LinearFlowState) AssertionFunctionLookup(com.google.javascript.jscomp.CodingConvention.AssertionFunctionLookup) AbstractScopedCallback(com.google.javascript.jscomp.NodeTraversal.AbstractScopedCallback) Token(com.google.javascript.rhino.Token) JSType(com.google.javascript.rhino.jstype.JSType) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) ReverseAbstractInterpreter(com.google.javascript.jscomp.type.ReverseAbstractInterpreter) Multiset(com.google.common.collect.Multiset) UNKNOWN_TYPE(com.google.javascript.rhino.jstype.JSTypeNative.UNKNOWN_TYPE) JSTypeResolver(com.google.javascript.rhino.jstype.JSTypeResolver) Preconditions.checkState(com.google.common.base.Preconditions.checkState) LinkedHashMap(java.util.LinkedHashMap) HashMultiset(com.google.common.collect.HashMultiset) JSTypeRegistry(com.google.javascript.rhino.jstype.JSTypeRegistry) LogFile(com.google.javascript.jscomp.diagnostic.LogFile) Comparator(java.util.Comparator) Node(com.google.javascript.rhino.Node) JSType(com.google.javascript.rhino.jstype.JSType) JSTypeResolver(com.google.javascript.rhino.jstype.JSTypeResolver) Multiset(com.google.common.collect.Multiset) HashMultiset(com.google.common.collect.HashMultiset)

Example 18 with Token

use of com.google.javascript.rhino.Token in project closure-compiler by google.

the class CollectFunctionNames method collectObjectLiteralMethodsNames.

/**
 * Sets names in the functionNames map for unnamed functions inside object literals,
 * and recursively visits nested object literals.
 * @param objectLiteral The object literal node to visit.
 * @param context Represents the qualified name "so far"
 */
private void collectObjectLiteralMethodsNames(Node objectLiteral, String context) {
    for (Node keyNode = objectLiteral.getFirstChild(); keyNode != null; keyNode = keyNode.getNext()) {
        Node valueNode = keyNode.getFirstChild();
        // TODO(lharker): Find a way to name Get, Set, and CompProp keys.
        if (keyNode.isStringKey() || keyNode.isMemberFunctionDef()) {
            // concatenate the context and key name to get a new qualified name.
            String name = combineNames(context, extractor.getName(keyNode));
            Token type = valueNode.getToken();
            if (type == Token.FUNCTION) {
                Node functionNameNode = valueNode.getFirstChild();
                String functionName = functionNameNode.getString();
                if (functionName.isEmpty()) {
                    functionNames.setFunctionName(name, valueNode);
                }
            } else if (type == Token.OBJECTLIT) {
                // process nested object literal
                collectObjectLiteralMethodsNames(valueNode, name);
            }
        }
    }
}
Also used : Node(com.google.javascript.rhino.Node) Token(com.google.javascript.rhino.Token)

Example 19 with Token

use of com.google.javascript.rhino.Token in project closure-compiler by google.

the class NewTypeInference method analyzeNonStrictComparisonFwd.

private EnvTypePair analyzeNonStrictComparisonFwd(Node expr, TypeEnv inEnv, JSType specializedType) {
    Token tokenType = expr.getToken();
    Node lhs = expr.getFirstChild();
    Node rhs = expr.getLastChild();
    if (specializedType.isTrueOrTruthy() || specializedType.isFalseOrFalsy()) {
        if (lhs.isTypeOf()) {
            return analyzeSpecializedTypeof(lhs, rhs, tokenType, inEnv, specializedType);
        } else if (rhs.isTypeOf()) {
            return analyzeSpecializedTypeof(rhs, lhs, tokenType, inEnv, specializedType);
        } else if (isGoogTypeof(lhs)) {
            return analyzeGoogTypeof(lhs, rhs, inEnv, specializedType);
        } else if (isGoogTypeof(rhs)) {
            return analyzeGoogTypeof(rhs, lhs, inEnv, specializedType);
        }
    }
    EnvTypePair lhsPair = analyzeExprFwd(lhs, inEnv);
    EnvTypePair rhsPair = analyzeExprFwd(rhs, lhsPair.env);
    // This env may contain types that have been tightened after nullable deref.
    TypeEnv preciseEnv = rhsPair.env;
    JSType lhsType = lhsPair.type;
    JSType rhsType = rhsPair.type;
    if ((tokenType == Token.EQ && specializedType.isTrueOrTruthy()) || (tokenType == Token.NE && specializedType.isFalseOrFalsy())) {
        if (lhsType.isNullOrUndef()) {
            rhsPair = analyzeExprFwd(rhs, preciseEnv, UNKNOWN, NULL_OR_UNDEFINED);
        } else if (rhsType.isNullOrUndef()) {
            lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, NULL_OR_UNDEFINED);
            rhsPair = analyzeExprFwd(rhs, lhsPair.env);
        } else if (!NULL.isSubtypeOf(lhsType) && !UNDEFINED.isSubtypeOf(lhsType)) {
            rhsType = rhsType.removeType(NULL_OR_UNDEFINED);
            rhsPair = analyzeExprFwd(rhs, preciseEnv, UNKNOWN, rhsType);
        } else if (!NULL.isSubtypeOf(rhsType) && !UNDEFINED.isSubtypeOf(rhsType)) {
            lhsType = lhsType.removeType(NULL_OR_UNDEFINED);
            lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, lhsType);
            rhsPair = analyzeExprFwd(rhs, lhsPair.env);
        }
    } else if ((tokenType == Token.EQ && specializedType.isFalseOrFalsy()) || (tokenType == Token.NE && specializedType.isTrueOrTruthy())) {
        if (lhsType.isNullOrUndef()) {
            rhsType = rhsType.removeType(NULL_OR_UNDEFINED);
            rhsPair = analyzeExprFwd(rhs, preciseEnv, UNKNOWN, rhsType);
        } else if (rhsType.isNullOrUndef()) {
            lhsType = lhsType.removeType(NULL_OR_UNDEFINED);
            lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, lhsType);
            rhsPair = analyzeExprFwd(rhs, lhsPair.env);
        }
    }
    rhsPair.type = BOOLEAN;
    return rhsPair;
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) Token(com.google.javascript.rhino.Token) TypeEnv(com.google.javascript.jscomp.newtypes.TypeEnv)

Example 20 with Token

use of com.google.javascript.rhino.Token in project closure-compiler by google.

the class SemanticReverseAbstractInterpreter method getPreciserScopeKnowingConditionOutcome.

@Override
public FlowScope getPreciserScopeKnowingConditionOutcome(Node condition, FlowScope blindScope, boolean outcome) {
    // Check for the typeof operator.
    Token operatorToken = condition.getToken();
    switch(operatorToken) {
        case EQ:
        case NE:
        case SHEQ:
        case SHNE:
        case CASE:
            Node left;
            Node right;
            if (operatorToken == Token.CASE) {
                // the switch condition
                left = condition.getParent().getFirstChild();
                right = condition.getFirstChild();
            } else {
                left = condition.getFirstChild();
                right = condition.getLastChild();
            }
            Node typeOfNode = null;
            Node stringNode = null;
            if (left.isTypeOf() && right.isString()) {
                typeOfNode = left;
                stringNode = right;
            } else if (right.isTypeOf() && left.isString()) {
                typeOfNode = right;
                stringNode = left;
            }
            if (typeOfNode != null && stringNode != null) {
                Node operandNode = typeOfNode.getFirstChild();
                JSType operandType = getTypeIfRefinable(operandNode, blindScope);
                if (operandType != null) {
                    boolean resultEqualsValue = operatorToken == Token.EQ || operatorToken == Token.SHEQ || operatorToken == Token.CASE;
                    if (!outcome) {
                        resultEqualsValue = !resultEqualsValue;
                    }
                    return caseTypeOf(operandNode, operandType, stringNode.getString(), resultEqualsValue, blindScope);
                }
            }
            break;
        default:
            break;
    }
    switch(operatorToken) {
        case AND:
            if (outcome) {
                return caseAndOrNotShortCircuiting(condition.getFirstChild(), condition.getLastChild(), blindScope, true);
            } else {
                return caseAndOrMaybeShortCircuiting(condition.getFirstChild(), condition.getLastChild(), blindScope, true);
            }
        case OR:
            if (!outcome) {
                return caseAndOrNotShortCircuiting(condition.getFirstChild(), condition.getLastChild(), blindScope, false);
            } else {
                return caseAndOrMaybeShortCircuiting(condition.getFirstChild(), condition.getLastChild(), blindScope, false);
            }
        case EQ:
            if (outcome) {
                return caseEquality(condition, blindScope, EQ);
            } else {
                return caseEquality(condition, blindScope, NE);
            }
        case NE:
            if (outcome) {
                return caseEquality(condition, blindScope, NE);
            } else {
                return caseEquality(condition, blindScope, EQ);
            }
        case SHEQ:
            if (outcome) {
                return caseEquality(condition, blindScope, SHEQ);
            } else {
                return caseEquality(condition, blindScope, SHNE);
            }
        case SHNE:
            if (outcome) {
                return caseEquality(condition, blindScope, SHNE);
            } else {
                return caseEquality(condition, blindScope, SHEQ);
            }
        case NAME:
        case GETPROP:
            return caseNameOrGetProp(condition, blindScope, outcome);
        case ASSIGN:
            return firstPreciserScopeKnowingConditionOutcome(condition.getFirstChild(), firstPreciserScopeKnowingConditionOutcome(condition.getSecondChild(), blindScope, outcome), outcome);
        case NOT:
            return firstPreciserScopeKnowingConditionOutcome(condition.getFirstChild(), blindScope, !outcome);
        case LE:
        case LT:
        case GE:
        case GT:
            if (outcome) {
                return caseEquality(condition, blindScope, ineq);
            }
            break;
        case INSTANCEOF:
            return caseInstanceOf(condition.getFirstChild(), condition.getLastChild(), blindScope, outcome);
        case IN:
            if (outcome && condition.getFirstChild().isString()) {
                return caseIn(condition.getLastChild(), condition.getFirstChild().getString(), blindScope);
            }
            break;
        case CASE:
            {
                Node left = // the switch condition
                condition.getParent().getFirstChild();
                Node right = condition.getFirstChild();
                if (outcome) {
                    return caseEquality(left, right, blindScope, SHEQ);
                } else {
                    return caseEquality(left, right, blindScope, SHNE);
                }
            }
        case CALL:
            {
                Node left = condition.getFirstChild();
                String leftName = left.getQualifiedName();
                if ("Array.isArray".equals(leftName) && left.getNext() != null) {
                    return caseIsArray(left.getNext(), blindScope, outcome);
                }
                break;
            }
        default:
            break;
    }
    return nextPreciserScopeKnowingConditionOutcome(condition, blindScope, outcome);
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) Token(com.google.javascript.rhino.Token)

Aggregations

Token (com.google.javascript.rhino.Token)35 Node (com.google.javascript.rhino.Node)29 JSType (com.google.javascript.rhino.jstype.JSType)4 Tri (com.google.javascript.jscomp.base.Tri)3 DiGraphNode (com.google.javascript.jscomp.graph.DiGraph.DiGraphNode)3 FlowScope (com.google.javascript.jscomp.type.FlowScope)3 JSDocInfo (com.google.javascript.rhino.JSDocInfo)3 Test (org.junit.Test)3 MeasuredNode (com.google.javascript.jscomp.MinimizedCondition.MeasuredNode)2 JSType (com.google.javascript.jscomp.newtypes.JSType)2 Preconditions.checkState (com.google.common.base.Preconditions.checkState)1 Predicate (com.google.common.base.Predicate)1 HashMultiset (com.google.common.collect.HashMultiset)1 Multiset (com.google.common.collect.Multiset)1 CheckReturnValue (com.google.errorprone.annotations.CheckReturnValue)1 AssertionFunctionLookup (com.google.javascript.jscomp.CodingConvention.AssertionFunctionLookup)1 LinearFlowState (com.google.javascript.jscomp.DataFlowAnalysis.LinearFlowState)1 FunctionlessLocalScope (com.google.javascript.jscomp.NodeIterators.FunctionlessLocalScope)1 AbstractScopedCallback (com.google.javascript.jscomp.NodeTraversal.AbstractScopedCallback)1 LogFile (com.google.javascript.jscomp.diagnostic.LogFile)1