private static JSType scalarValueToType(int token) { switch (token) { case Token.NUMBER: return JSType.NUMBER; case Token.STRING: return JSType.STRING; case Token.TRUE: return JSType.TRUE_TYPE; case Token.FALSE: return JSType.FALSE_TYPE; case Token.NULL: return JSType.NULL; default: throw new RuntimeException("The token isn't a scalar value " + Token.name(token)); } }
/** * Returns human-readable name of the given node's type. */ private static String getReadableTokenName(Node node) { return Token.name(node.getType()); }
private static String name(Node n) { int type = n.getType(); switch (type) { case Token.VOID: return "VOID"; default: return Token.name(type); } }
/** * Converts an operator's token value (see {@link Token}) to a string * representation or fails. * * @param operator the operator's token value to convert * @return the string representation * @throws Error if the token value is not an operator */ static String opToStrNoFail(int operator) { String res = opToStr(operator); if (res == null) { throw new Error("Unknown op " + operator + ": " + Token.name(operator)); } return res; }
IncompleteDefinition(Node lValue, boolean inExterns) { super(inExterns); Preconditions.checkNotNull(lValue); Preconditions.checkArgument(ALLOWED_TYPES.contains(lValue.getType()), "Unexpected lValue type %s", Token.name(lValue.getType())); this.lValue = lValue; }
private void warnInvalidOperand( Node expr, int operatorType, Object expected, Object actual) { Preconditions.checkArgument( (expected instanceof String) || (expected instanceof JSType)); Preconditions.checkArgument( (actual instanceof String) || (actual instanceof JSType)); if (expected instanceof JSType && actual instanceof JSType) { warnings.add(JSError.make( expr, INVALID_OPERAND_TYPE, Token.name(operatorType), errorMsgWithTypeDiff((JSType) expected, (JSType) actual))); } else { warnings.add(JSError.make( expr, INVALID_OPERAND_TYPE, Token.name(operatorType), "Expected : " + expected.toString() + "\n" + "Found : " + actual.toString() + "\n")); } }
/** * Marks this function or constructor call's side effect flags. * This property is only meaningful for {@link Token#CALL} and * {@link Token#NEW} nodes. */ public void setSideEffectFlags(int flags) { Preconditions.checkArgument( getType() == Token.CALL || getType() == Token.NEW, "setIsNoSideEffectsCall only supports CALL and NEW nodes, got %s", Token.name(getType())); putIntProp(SIDE_EFFECT_FLAGS, flags); }
private void validateAssignmentTarget(Node n) { if (!n.isValidAssignmentTarget()) { violation("Expected assignment target expression but was " + Token.name(n.getType()), n); } }
/** * Processes a NEW expression. * * @return true to continue traversal, false otherwise */ boolean processConstructorCall(Node node) { Preconditions.checkArgument(node.isNew(), "Expected: NEW, Got: %s", Token.name(node.getType())); // Calls to constructors that are known to be "pure" have no // side effects. if (!NodeUtil.constructorCallHasSideEffects(node)) { return true; } accumulator.keepSubTree(node); return false; }
@Override public Node reduce(Node node) { if (!isReduceableFunctionExpression(node)) { return node; } Node propName = getGetPropertyName(node); if (propName != null) { if (!propName.isString()) { throw new IllegalStateException( "Expected STRING, got " + Token.name(propName.getType())); } return buildCallNode(FACTORY_METHOD_NAME, propName, node); } else { return node; } }
@Override public Node reduce(Node node) { if (!isReduceableFunctionExpression(node)) { return node; } Node propName = getSetPropertyName(node); if (propName != null) { if (!propName.isString()) { throw new IllegalStateException( "Expected STRING, got " + Token.name(propName.getType())); } return buildCallNode(FACTORY_METHOD_NAME, propName, node); } else { return node; } }
private void validateObjectLiteralKeyName(Node n) { if (n.isQuotedString()) { try { // Validate that getString doesn't throw n.getString(); } catch (UnsupportedOperationException e) { violation("getString failed for" + Token.name(n.getType()), n); } } else { validateNonEmptyString(n); } }
private static Node fromDefsiteToName(Node defSite) { if (defSite.isGetProp()) { return defSite.getLastChild(); } if (defSite.isName() || defSite.isStringKey() || defSite.isGetterDef() || defSite.isSetterDef()) { return defSite; } throw new RuntimeException("Unknown defsite: " + Token.name(defSite.getType())); }
private void validateSwitchMember(Node n) { switch (n.getType()) { case Token.CASE: validateCase(n); return; case Token.DEFAULT_CASE: validateDefaultCase(n); return; default: violation("Expected switch member but was " + Token.name(n.getType()), n); } }
/** * Do calls to this constructor have side effects? * * @param callNode - constructor call node */ static boolean constructorCallHasSideEffects(Node callNode) { if (!callNode.isNew()) { throw new IllegalStateException( "Expected NEW node, got " + Token.name(callNode.getType())); } if (callNode.isNoSideEffectsCall()) { return false; } if (callNode.isOnlyModifiesArgumentsCall() && allArgsUnescapedLocal(callNode)) { return false; } Node nameNode = callNode.getFirstChild(); return !nameNode.isName() || !CONSTRUCTORS_WITHOUT_SIDE_EFFECTS.contains(nameNode.getString()); }
private void validateNameDeclarationChild(int type, Node n) { if (n.isName()) { validateLHS(type, n); } else if (n.isDestructuringLhs()) { validateLHS(type, n.getFirstChild()); } else { violation("Invalid child for " + Token.name(type) + " node", n); } }
@Override public void keepSimplifiedShortCircuitExpression(Node original) { Preconditions.checkArgument( (original.isAnd()) || (original.isOr()), "Expected: AND or OR, Got: %s", Token.name(original.getType())); Node left = original.getFirstChild(); Node right = left.getNext(); Node simplifiedRight = simplifyShortCircuitBranch(right); original.detachChildren(); original.addChildToBack(left); original.addChildToBack(simplifiedRight); keepSubTree(original); }
private void validateSpread(Node n) { validateNodeType(Token.SPREAD, n); validateChildCount(n); Node parent = n.getParent(); switch (parent.getType()) { case Token.CALL: case Token.NEW: if (n == parent.getFirstChild()) { violation("SPREAD node is not callable.", n); } break; case Token.ARRAYLIT: break; default: violation("SPREAD node should not be the child of a " + Token.name(parent.getType()) + " node.", n); } }
private void mayWarnAboutUnknownType(Node expr, JSType t) { boolean isKnownGetElem = expr.isGetElem() && expr.getLastChild().isString(); if (t.isUnknown() && this.reportUnknownTypes // Don't warn for expressions whose value isn't used && !expr.getParent().isExprResult() // The old type checker doesn't warn about unknown getelems. // Maybe because we can't do anything about them, so why warn? // We mimic that behavior here. && (!expr.isGetElem() || isKnownGetElem)) { warnings.add(JSError.make(expr, UNKNOWN_EXPR_TYPE, Token.name(expr.getType()))); } }