/** * Pops the loop information off of our stack if we reach the marker cooresponding * to the end of the current loop. */ private void visitGeneratorMarker() { if (!currentLoopContext.isEmpty() && currentLoopContext.get(0).breakCase == currentStatement.getFirstChild().getDouble()) { currentLoopContext.remove(0); } if (!currentExceptionContext.isEmpty() && currentExceptionContext.get(0).catchStartCase == currentStatement.getFirstChild().getDouble()) { currentExceptionContext.remove(0); } }
private void validateNumber(Node n) { validateNodeType(Token.NUMBER, n); validateChildCount(n); try { // Validate that getDouble doesn't throw n.getDouble(); } catch (UnsupportedOperationException e) { violation("Invalid NUMBER node.", n); } }
private void validateNumber(Node n) { validateNodeType(Token.NUMBER, n); validateChildCount(n); try { // Validate that getDouble doesn't throw n.getDouble(); } catch (UnsupportedOperationException e) { violation("Invalid NUMBER node.", n); } }
private JSType evalTemplateTypeOf(Node ttlAst, NameResolver nameResolver) { ImmutableList<Node> params = getCallParams(ttlAst); JSType type = evalInternal(params.get(0), nameResolver); if (!type.isGenericObjectType()) { reportWarning(ttlAst, TEMPTYPE_INVALID, "templateTypeOf", type.toString()); return getUnknownType(); } int index = (int) params.get(1).getDouble(); ImmutableList<? extends JSType> templateTypes = type.toMaybeObjectType().getTemplateTypes(); if (index >= templateTypes.size()) { reportWarning(ttlAst, INDEX_OUTOFBOUNDS, Integer.toString(templateTypes.size()), Integer.toString(index)); return getUnknownType(); } return templateTypes.get(index); }
private JSType evalTemplateTypeOf(Node ttlAst, NameResolver nameResolver) { ImmutableList<Node> params = getCallParams(ttlAst); JSType type = evalInternal(params.get(0), nameResolver); if (!type.isTemplatizedType()) { reportWarning(ttlAst, TEMPTYPE_INVALID, "templateTypeOf", type.toString()); return getUnknownType(); } int index = (int) params.get(1).getDouble(); ImmutableList<JSType> templateTypes = ((TemplatizedType) type).getTemplateTypes(); if (index > templateTypes.size()) { reportWarning(ttlAst, INDEX_OUTOFBOUNDS, Integer.toString(index), Integer.toString(templateTypes.size())); return getUnknownType(); } return templateTypes.get(index); }
private void checkDuplicateEnumValues(NodeTraversal t, Node n) { Set<String> values = new HashSet<>(); for (Node child : n.children()) { Node valueNode = child.getLastChild(); String value; if (valueNode == null) { return; } else if (valueNode.isString()) { value = valueNode.getString(); } else if (valueNode.isNumber()) { value = Double.toString(valueNode.getDouble()); } else { return; } if (!values.add(value)) { t.report(valueNode, DUPLICATE_ENUM_VALUE, value); } } } }
private void checkDuplicateEnumValues(NodeTraversal t, Node n) { Set<String> values = new HashSet<String>(); for (Node child : n.children()) { Node valueNode = child.getLastChild(); String value; if (valueNode == null) { return; } else if (valueNode.isString()) { value = valueNode.getString(); } else if (valueNode.isNumber()) { value = Double.toString(valueNode.getDouble()); } else { return; } if (!values.add(value)) { t.report(valueNode, DUPLICATE_ENUM_VALUE, value); } } } }
public static String getCommonJsImportPath( Node requireCall, ModuleLoader.ResolutionMode resolutionMode) { if (resolutionMode == ModuleLoader.ResolutionMode.WEBPACK) { Node pathArgument = requireCall.getChildCount() >= 3 ? requireCall.getChildAtIndex(2) : requireCall.getSecondChild(); if (pathArgument.isNumber()) { return String.valueOf((int) pathArgument.getDouble()); } else { return pathArgument.getString(); } } return requireCall.getSecondChild().getString(); }
/** * Try to fold .charCodeAt() calls on strings */ private Node tryFoldStringCharCodeAt(Node n, Node stringNode, Node arg1) { checkArgument(n.isCall()); checkArgument(stringNode.isString()); int index; String stringAsString = stringNode.getString(); if (arg1 != null && arg1.isNumber() && arg1.getNext() == null) { index = (int) arg1.getDouble(); } else { return n; } if (index < 0 || stringAsString.length() <= index) { // http://es5.github.com/#x15.5.4.5 says NaN is returned when index is // out of bounds but we bail. return n; } Node resultNode = IR.number(stringAsString.charAt(index)); Node parent = n.getParent(); parent.replaceChild(n, resultNode); reportChangeToEnclosingScope(parent); return resultNode; }
private Node reduceSubstractionAssignment(Node n) { Node right = n.getLastChild(); if (right.isNumber()) { if (right.getDouble() == 1) { Node newNode = IR.dec(n.removeFirstChild(), false); n.replaceWith(newNode); reportChangeToEnclosingScope(newNode); return newNode; } else if (right.getDouble() == -1) { Node newNode = IR.inc(n.removeFirstChild(), false); n.replaceWith(newNode); reportChangeToEnclosingScope(newNode); return newNode; } } return n; }
private Node tryReduceVoid(Node n) { Node child = n.getFirstChild(); if ((!child.isNumber() || child.getDouble() != 0.0) && !mayHaveSideEffects(n)) { n.replaceChild(child, IR.number(0)); reportChangeToEnclosingScope(n); } return n; }
private Node tryReduceVoid(Node n) { Node child = n.getFirstChild(); if ((!child.isNumber() || child.getDouble() != 0.0) && !mayHaveSideEffects(n)) { n.replaceChild(child, IR.number(0)); reportCodeChange(); } return n; }
private Node reduceSubstractionAssignment(Node n) { Node right = n.getLastChild(); if (right.isNumber()) { if (right.getDouble() == 1) { Node newNode = IR.dec(n.removeFirstChild(), false); n.getParent().replaceChild(n, newNode); reportCodeChange(); return newNode; } else if (right.getDouble() == -1) { Node newNode = IR.inc(n.removeFirstChild(), false); n.getParent().replaceChild(n, newNode); reportCodeChange(); return newNode; } } return n; }
private Node transformMembers(Node members, boolean enumIsOfNumberType) { assert members.isObjectLit(); int lastCount = -1; Node enumMembers = new Node(Token.ENUM_MEMBERS); for (Node child : members.children()) { Node name = Node.newString(Token.NAME, child.getString()); Node value = child.getFirstChild().detach(); Node newMember; // Check whether we can emit simply the name, and rely on the automatic numeric assignment // in TypeScript. For example, enum E { A, B } is equivalent to enum E { A = 0, B = 1 }. if (enumIsOfNumberType && value.isNumber() && value.getDouble() == lastCount + 1) { newMember = name; } else { // We cannot reuse the STRING_KEY node here, because it pretty prints as a: 0, and we // want a = 1. Instead we recreate an ASSIGN node with same contents as STRING_KEY newMember = new Node(Token.ASSIGN, name, value); } if (enumIsOfNumberType && value.isNumber()) { lastCount = (int) value.getDouble(); } enumMembers.addChildToBack(newMember); nodeComments.moveComment(child, newMember); } return enumMembers; } }
/** * Applies optimizations to all previously marked nodes. */ public void applyChanges() { for (Node n : toRemove) { // Don't remove any nodes twice since doing so would violate change reporting constraints. if (alreadyRemoved(n)) { continue; } compiler.reportChangeToEnclosingScope(n); n.detach(); NodeUtil.markFunctionsDeleted(n, compiler); } for (Node n : toReplaceWithZero) { Preconditions.checkState(!n.isNumber() || n.getDouble() != 0.0); // Don't remove any nodes twice since doing so would violate change reporting constraints. if (alreadyRemoved(n)) { continue; } compiler.reportChangeToEnclosingScope(n); n.replaceWith(IR.number(0).srcref(n)); NodeUtil.markFunctionsDeleted(n, compiler); } } }
Node processUnaryExpression(UnaryExpressionTree exprNode) { Token type = transformUnaryTokenType(exprNode.operator.type); Node operand = transform(exprNode.operand); if (type == Token.NEG && operand.isNumber()) { operand.setDouble(-operand.getDouble()); return operand; } else { if (type == Token.DELPROP && !(operand.isGetProp() || operand.isGetElem() || operand.isName())) { String msg = "Invalid delete operand. Only properties can be deleted."; errorReporter.error( msg, sourceName, operand.getLineno(), 0); } return newNode(type, operand); } }
private void addKeyValueToObjLit(Node objNode, Node keyNode, Node valueNode) { if (keyNode.isNumber() || keyNode.isString()) { if (keyNode.isNumber()) { keyNode = IR.string(numberToString(keyNode.getDouble())) .srcref(keyNode); } keyNode.setToken(Token.STRING_KEY); keyNode.setQuotedString(); objNode.addChildToBack(IR.propdef(keyNode, valueNode)); } else { objNode.addChildToBack(IR.computedProp(keyNode, valueNode).srcref(keyNode)); } }
Node processUnaryExpression(UnaryExpressionTree exprNode) { int type = transformUnaryTokenType(exprNode.operator.type); Node operand = transform(exprNode.operand); if (type == Token.NEG && operand.isNumber()) { operand.setDouble(-operand.getDouble()); return operand; } else { if (type == Token.DELPROP && !(operand.isGetProp() || operand.isGetElem() || operand.isName())) { String msg = "Invalid delete operand. Only properties can be deleted."; errorReporter.error( msg, sourceName, operand.getLineno(), 0); } else if (type == Token.INC || type == Token.DEC) { return createIncrDecrNode(type, false, operand); } return newNode(type, operand); } }