Java Code Examples for com.google.javascript.rhino.Token#EXPR_RESULT
The following examples show how to use
com.google.javascript.rhino.Token#EXPR_RESULT .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Closure_92_ProcessClosurePrimitives_s.java From coming with MIT License | 6 votes |
/** * @return Whether the node is namespace placeholder. */ private static boolean isNamespacePlaceholder(Node n) { if (!n.getBooleanProp(Node.IS_NAMESPACE)) { return false; } Node value = null; if (n.getType() == Token.EXPR_RESULT) { Node assign = n.getFirstChild(); value = assign.getLastChild(); } else if (n.getType() == Token.VAR) { Node name = n.getFirstChild(); value = name.getFirstChild(); } return value != null && value.getType() == Token.OBJECTLIT && !value.hasChildren(); }
Example 2
Source File: Closure_95_TypedScopeCreator_t.java From coming with MIT License | 6 votes |
@Override public void visit(NodeTraversal t, Node node, Node parent) { Node nameNode = null; switch (node.getType()) { case Token.VAR: for (Node child = node.getFirstChild(); child != null; child = child.getNext()) { identifyEnumInNameNode( child, NodeUtil.getInfoForNameNode(child)); } break; case Token.EXPR_RESULT: Node maybeAssign = node.getFirstChild(); if (maybeAssign.getType() == Token.ASSIGN) { identifyEnumInNameNode( maybeAssign.getFirstChild(), maybeAssign.getJSDocInfo()); } break; } }
Example 3
Source File: Closure_93_ProcessClosurePrimitives_s.java From coming with MIT License | 5 votes |
/** * Creates a dotted namespace assignment expression * (e.g. <code>foo.bar = {};</code>). * * @param namespace A dotted namespace * @param node A node from which to copy source info. */ private Node makeAssignmentExprNode(String namespace, Node node) { Node decl = new Node(Token.EXPR_RESULT, new Node(Token.ASSIGN, NodeUtil.newQualifiedNameNode(namespace, node, namespace), createNamespaceLiteral())); decl.putBooleanProp(Node.IS_NAMESPACE, true); Preconditions.checkState(isNamespacePlaceholder(decl)); decl.copyInformationFromForTree(node); return decl; }
Example 4
Source File: Closure_53_InlineObjectLiterals_s.java From coming with MIT License | 5 votes |
private boolean isVarOrAssignExprLhs(Node n) { Node parent = n.getParent(); return parent.getType() == Token.VAR || (parent.getType() == Token.ASSIGN && parent.getFirstChild() == n && parent.getParent().getType() == Token.EXPR_RESULT); }
Example 5
Source File: StatementFusion.java From astor with GNU General Public License v2.0 | 5 votes |
private boolean canFuseIntoOneStatement(Node block) { // Fold only statement block. NOT scripts block. if (!block.isBlock()) { return false; } // Nothing to do here. if (!block.hasChildren() || block.hasOneChild()) { return false; } Node last = block.getLastChild(); for (Node c = block.getFirstChild(); c != null; c = c.getNext()) { if (!c.isExprResult() && c != last) { return false; } } // TODO(user): Support more control statement for fusion. // FOR switch(last.getType()) { case Token.IF: case Token.THROW: case Token.SWITCH: case Token.EXPR_RESULT: return true; case Token.RETURN: // We don't want to add a new return value. return last.hasChildren(); case Token.FOR: return NodeUtil.isForIn(last) && // Avoid cases where we have for(var x = foo() in a) { .... !mayHaveSideEffects(last.getFirstChild()); } return false; }
Example 6
Source File: Closure_54_TypedScopeCreator_t.java From coming with MIT License | 5 votes |
@Override public void visit(NodeTraversal t, Node n, Node parent) { if (n.getType() == Token.EXPR_RESULT) { Node child = n.getFirstChild(); switch (child.getType()) { case Token.ASSIGN: maybeCollectMember(t, child.getFirstChild(), child, child.getLastChild()); break; case Token.GETPROP: maybeCollectMember(t, child, child, null); break; } } }
Example 7
Source File: 1_ControlFlowAnalysis.java From SimFix with GNU General Public License v2.0 | 4 votes |
@Override public boolean shouldTraverse( NodeTraversal nodeTraversal, Node n, Node parent) { astPosition.put(n, astPositionCounter++); switch (n.getType()) { case Token.FUNCTION: if (shouldTraverseFunctions || n == cfg.getEntry().getValue()) { exceptionHandler.push(n); return true; } return false; case Token.TRY: exceptionHandler.push(n); return true; } /* * We are going to stop the traversal depending on what the node's parent * is. * * We are only interested in adding edges between nodes that change control * flow. The most obvious ones are loops and IF-ELSE's. A statement * transfers control to its next sibling. * * In case of an expression tree, there is no control flow within the tree * even when there are short circuited operators and conditionals. When we * are doing data flow analysis, we will simply synthesize lattices up the * expression tree by finding the meet at each expression node. * * For example: within a Token.SWITCH, the expression in question does not * change the control flow and need not to be considered. */ if (parent != null) { switch (parent.getType()) { case Token.FOR: // Only traverse the body of the for loop. return n == parent.getLastChild(); // Skip the conditions. case Token.IF: case Token.WHILE: case Token.WITH: return n != parent.getFirstChild(); case Token.DO: return n != parent.getFirstChild().getNext(); // Only traverse the body of the cases case Token.SWITCH: case Token.CASE: case Token.CATCH: case Token.LABEL: return n != parent.getFirstChild(); case Token.FUNCTION: return n == parent.getFirstChild().getNext().getNext(); case Token.CONTINUE: case Token.BREAK: case Token.EXPR_RESULT: case Token.VAR: case Token.RETURN: case Token.THROW: return false; case Token.TRY: /* Just before we are about to visit the second child of the TRY node, * we know that we will be visiting either the CATCH or the FINALLY. * In other words, we know that the post order traversal of the TRY * block has been finished, no more exceptions can be caught by the * handler at this TRY block and should be taken out of the stack. */ if (n == parent.getFirstChild().getNext()) { Preconditions.checkState(exceptionHandler.peek() == parent); exceptionHandler.pop(); } } } return true; }
Example 8
Source File: jKali_0043_s.java From coming with MIT License | 4 votes |
@Override public void visit(NodeTraversal t, Node n, Node parent) { // VOID nodes appear when there are extra semicolons at the BLOCK level. // I've been unable to think of any cases where this indicates a bug, // and apparently some people like keeping these semicolons around, // so we'll allow it. if (n.isEmpty() || n.isComma()) { return; } if (parent == null) { return; } // Do not try to remove a block or an expr result. We already handle // these cases when we visit the child, and the peephole passes will // fix up the tree in more clever ways when these are removed. if (parent.getType() == Token.COMMA) { Node gramps = parent.getParent(); if (gramps.isCall() && parent == gramps.getFirstChild()) { if (n == parent.getFirstChild() && parent.getChildCount() == 2 && n.getNext().isName() && "eval".equals(n.getNext().getString())) { return; } } // This no-op statement was there so that JSDoc information could // be attached to the name. This check should not complain about it. if (n == parent.getLastChild()) { for (Node an : parent.getAncestors()) { int ancestorType = an.getType(); if (ancestorType == Token.COMMA) continue; if (ancestorType != Token.EXPR_RESULT && ancestorType != Token.BLOCK) return; else break; } } } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) { if (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext())) { } else { return; } } boolean isResultUsed = NodeUtil.isExpressionResultUsed(n); boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType()); if (!isResultUsed && (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) { if (n.isQualifiedName() && n.getJSDocInfo() != null) { return; } else if (n.isExprResult()) { return; } String msg = "This code lacks side-effects. Is there a bug?"; if (n.isString()) { msg = "Is there a missing '+' on the previous line?"; } else if (isSimpleOp) { msg = "The result of the '" + Token.name(n.getType()).toLowerCase() + "' operator is not being used."; } t.getCompiler().report( t.makeError(n, level, USELESS_CODE_ERROR, msg)); // TODO(johnlenz): determine if it is necessary to // try to protect side-effect free statements as well. if (!NodeUtil.isStatement(n)) { problemNodes.add(n); } } }
Example 9
Source File: jMutRepair_0022_s.java From coming with MIT License | 4 votes |
@Override public void visit(NodeTraversal t, Node n, Node parent) { // VOID nodes appear when there are extra semicolons at the BLOCK level. // I've been unable to think of any cases where this indicates a bug, // and apparently some people like keeping these semicolons around, // so we'll allow it. if (n.isEmpty() || n.isComma()) { return; } if (parent == null) { return; } // Do not try to remove a block or an expr result. We already handle // these cases when we visit the child, and the peephole passes will // fix up the tree in more clever ways when these are removed. if (n.isExprResult()) { return; } // This no-op statement was there so that JSDoc information could // be attached to the name. This check should not complain about it. if (n.isQualifiedName() && n.getJSDocInfo() != null) { return; } boolean isResultUsed = NodeUtil.isExpressionResultUsed(n); boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType()); if (parent.getType() == Token.COMMA) { if (isResultUsed) { return; } if (n == parent.getLastChild()) { for (Node an : parent.getAncestors()) { int ancestorType = an.getType(); if (ancestorType == Token.COMMA) continue; if (ancestorType != Token.EXPR_RESULT && ancestorType != Token.BLOCK) return; else break; } } } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) { if (! (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext()))) { return; } } if ( (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) { String msg = "This code lacks side-effects. Is there a bug?"; if (n.isString()) { msg = "Is there a missing '+' on the previous line?"; } else if (isSimpleOp) { msg = "The result of the '" + Token.name(n.getType()).toLowerCase() + "' operator is not being used."; } t.getCompiler().report( t.makeError(n, level, USELESS_CODE_ERROR, msg)); // TODO(johnlenz): determine if it is necessary to // try to protect side-effect free statements as well. if (!NodeUtil.isStatement(n)) { problemNodes.add(n); } } }
Example 10
Source File: Cardumen_0090_s.java From coming with MIT License | 4 votes |
@Override public void visit(NodeTraversal t, Node n, Node parent) { // VOID nodes appear when there are extra semicolons at the BLOCK level. // I've been unable to think of any cases where this indicates a bug, // and apparently some people like keeping these semicolons around, // so we'll allow it. if (n.isEmpty() || n.isComma()) { return; } if (parent == null) { return; } // Do not try to remove a block or an expr result. We already handle // these cases when we visit the child, and the peephole passes will // fix up the tree in more clever ways when these are removed. if (n.isExprResult()) { return; } // This no-op statement was there so that JSDoc information could // be attached to the name. This check should not complain about it. if (n.isQualifiedName() && n.getJSDocInfo() != null) { return; } boolean isResultUsed = NodeUtil.isExpressionResultUsed(n); boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType()); if (parent.getType() == Token.COMMA) { if (isResultUsed) { return; } if (n == parent.getLastChild()) { for (Node an : parent.getAncestors()) { int ancestorType = an.getType(); if (ancestorType == Token.COMMA) continue; if (ancestorType != Token.EXPR_RESULT && ancestorType != Token.BLOCK) return; else break; } } } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) { if (! (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext()))) { return; } } if ( (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) { String msg = "This code lacks side-effects. Is there a bug?"; if (n.isString()) { msg = "Is there a missing '+' on the previous line?"; } else if (isSimpleOp) { msg = "The result of the '" + Token.name(n.getType()).toLowerCase() + "' operator is not being used."; } t.getCompiler().report( t.makeError(n, level, USELESS_CODE_ERROR, msg)); // TODO(johnlenz): determine if it is necessary to // try to protect side-effect free statements as well. if (!NodeUtil.isStatement(n)) { problemNodes.add(n); } } }
Example 11
Source File: JGenProg2017_0010_t.java From coming with MIT License | 4 votes |
@Override public void visit(NodeTraversal t, Node n, Node parent) { // VOID nodes appear when there are extra semicolons at the BLOCK level. // I've been unable to think of any cases where this indicates a bug, // and apparently some people like keeping these semicolons around, // so we'll allow it. if (n.isEmpty() || n.isComma()) { return; } if (parent == null) { return; } // Do not try to remove a block or an expr result. We already handle // these cases when we visit the child, and the peephole passes will // fix up the tree in more clever ways when these are removed. if (n.isExprResult()) { return; } // This no-op statement was there so that JSDoc information could // be attached to the name. This check should not complain about it. if (n.isQualifiedName() && n.getJSDocInfo() != null) { return; } boolean isResultUsed = NodeUtil.isExpressionResultUsed(n); boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType()); if (parent.getType() == Token.COMMA) { if (isResultUsed) { return; } if (n == parent.getLastChild()) { for (Node an : parent.getAncestors()) { int ancestorType = an.getType(); if (ancestorType == Token.COMMA) continue; } } } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) { if (! (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext()))) { return; } } if ( (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) { String msg = "This code lacks side-effects. Is there a bug?"; if (n.isString()) { msg = "Is there a missing '+' on the previous line?"; } else if (isSimpleOp) { msg = "The result of the '" + Token.name(n.getType()).toLowerCase() + "' operator is not being used."; } t.getCompiler().report( t.makeError(n, level, USELESS_CODE_ERROR, msg)); // TODO(johnlenz): determine if it is necessary to // try to protect side-effect free statements as well. if (!NodeUtil.isStatement(n)) { problemNodes.add(n); } } }
Example 12
Source File: Cardumen_0018_t.java From coming with MIT License | 4 votes |
@Override public void visit(NodeTraversal t, Node n, Node parent) { // VOID nodes appear when there are extra semicolons at the BLOCK level. // I've been unable to think of any cases where this indicates a bug, // and apparently some people like keeping these semicolons around, // so we'll allow it. if (n.isEmpty() || n.isComma()) { return; } if (parent == null) { return; } // Do not try to remove a block or an expr result. We already handle // these cases when we visit the child, and the peephole passes will // fix up the tree in more clever ways when these are removed. if (n.isExprResult()) { return; } // This no-op statement was there so that JSDoc information could // be attached to the name. This check should not complain about it. if (n.isQualifiedName() && n.getJSDocInfo() != null) { return; } boolean isResultUsed = NodeUtil.isExpressionResultUsed(n); boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType()); if (parent.getType() == Token.COMMA) { if (isResultUsed) { return; } if (n == parent.getLastChild()) { for (Node an : parent.getAncestors()) { int ancestorType = an.getType(); if (ancestorType == Token.COMMA) continue; if ((((((((com.google.javascript.jscomp.NodeUtil.isAssignmentOp(n)) && ((n.getFirstChild()) == n)) || ((com.google.javascript.jscomp.NodeUtil.isForIn(n)) && ((n.getFirstChild()) == n))) || (n.isVar())) || ((n.isFunction()) && ((n.getFirstChild()) == n))) || (n.isDec())) || (n.isInc())) || (n.isParamList())) return; else break; } } } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) { if (! (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext()))) { return; } } if ( (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) { String msg = "This code lacks side-effects. Is there a bug?"; if (n.isString()) { msg = "Is there a missing '+' on the previous line?"; } else if (isSimpleOp) { msg = "The result of the '" + Token.name(n.getType()).toLowerCase() + "' operator is not being used."; } t.getCompiler().report( t.makeError(n, level, USELESS_CODE_ERROR, msg)); // TODO(johnlenz): determine if it is necessary to // try to protect side-effect free statements as well. if (!NodeUtil.isStatement(n)) { problemNodes.add(n); } } }
Example 13
Source File: Closure_40_NameAnalyzer_t.java From coming with MIT License | 4 votes |
/** * Simplify a toplevel expression, while preserving program * behavior. */ private void replaceTopLevelExpressionWithRhs(Node parent, Node n) { // validate inputs switch (parent.getType()) { case Token.BLOCK: case Token.SCRIPT: case Token.FOR: case Token.LABEL: break; default: throw new IllegalArgumentException( "Unsupported parent node type in replaceWithRhs " + Token.name(parent.getType())); } switch (n.getType()) { case Token.EXPR_RESULT: case Token.FUNCTION: case Token.VAR: break; case Token.ASSIGN: Preconditions.checkArgument(parent.isFor(), "Unsupported assignment in replaceWithRhs. parent: %s", Token.name(parent.getType())); break; default: throw new IllegalArgumentException( "Unsupported node type in replaceWithRhs " + Token.name(n.getType())); } // gather replacements List<Node> replacements = Lists.newArrayList(); for (Node rhs : getRhsSubexpressions(n)) { replacements.addAll(getSideEffectNodes(rhs)); } if (parent.isFor()) { // tweak replacements array s.t. it is a single expression node. if (replacements.isEmpty()) { replacements.add(IR.empty()); } else { Node expr = collapseReplacements(replacements); replacements.clear(); replacements.add(expr); } } changeProxy.replaceWith(parent, n, replacements); }
Example 14
Source File: jKali_003_t.java From coming with MIT License | 4 votes |
/** * @returns false iff the result of the expression is not consumed. */ static boolean isExpressionResultUsed(Node expr) { // TODO(johnlenz): consider sharing some code with trySimpleUnusedResult. Node parent = expr.getParent(); switch (parent.getType()) { case Token.BLOCK: case Token.EXPR_RESULT: return false; case Token.HOOK: case Token.AND: case Token.OR: return (expr == parent.getFirstChild()) ? true : isExpressionResultUsed(parent); case Token.COMMA: Node gramps = parent.getParent(); if (gramps.isCall() && parent == gramps.getFirstChild()) { // Semantically, a direct call to eval is different from an indirect // call to an eval. See ECMA-262 S15.1.2.1. So it's OK for the first // expression to a comma to be a no-op if it's used to indirect // an eval. This we pretend that this is "used". if (expr == parent.getFirstChild() && parent.getChildCount() == 2 && expr.getNext().isName() && "eval".equals(expr.getNext().getString())) { return true; } } return (expr == parent.getFirstChild()) ? false : isExpressionResultUsed(parent); case Token.FOR: if (!NodeUtil.isForIn(parent)) { // Only an expression whose result is in the condition part of the // expression is used. return (parent.getChildAtIndex(1) == expr); } break; } return true; }
Example 15
Source File: 1_ControlFlowAnalysis.java From SimFix with GNU General Public License v2.0 | 4 votes |
@Override public boolean shouldTraverse( NodeTraversal nodeTraversal, Node n, Node parent) { astPosition.put(n, astPositionCounter++); switch (n.getType()) { case Token.FUNCTION: if (shouldTraverseFunctions || n == cfg.getEntry().getValue()) { exceptionHandler.push(n); return true; } return false; case Token.TRY: exceptionHandler.push(n); return true; } /* * We are going to stop the traversal depending on what the node's parent * is. * * We are only interested in adding edges between nodes that change control * flow. The most obvious ones are loops and IF-ELSE's. A statement * transfers control to its next sibling. * * In case of an expression tree, there is no control flow within the tree * even when there are short circuited operators and conditionals. When we * are doing data flow analysis, we will simply synthesize lattices up the * expression tree by finding the meet at each expression node. * * For example: within a Token.SWITCH, the expression in question does not * change the control flow and need not to be considered. */ if (parent != null) { switch (parent.getType()) { case Token.FOR: // Only traverse the body of the for loop. return n == parent.getLastChild(); // Skip the conditions. case Token.IF: case Token.WHILE: case Token.WITH: return n != parent.getFirstChild(); case Token.DO: return n != parent.getFirstChild().getNext(); // Only traverse the body of the cases case Token.SWITCH: case Token.CASE: case Token.CATCH: case Token.LABEL: return n != parent.getFirstChild(); case Token.FUNCTION: return n == parent.getFirstChild().getNext().getNext(); case Token.CONTINUE: case Token.BREAK: case Token.EXPR_RESULT: case Token.VAR: case Token.RETURN: case Token.THROW: return false; case Token.TRY: /* Just before we are about to visit the second child of the TRY node, * we know that we will be visiting either the CATCH or the FINALLY. * In other words, we know that the post order traversal of the TRY * block has been finished, no more exceptions can be caught by the * handler at this TRY block and should be taken out of the stack. */ if (n == parent.getFirstChild().getNext()) { Preconditions.checkState(exceptionHandler.peek() == parent); exceptionHandler.pop(); } } } return true; }
Example 16
Source File: JGenProg2017_00108_t.java From coming with MIT License | 4 votes |
@Override public void visit(NodeTraversal t, Node n, Node parent) { // VOID nodes appear when there are extra semicolons at the BLOCK level. // I've been unable to think of any cases where this indicates a bug, // and apparently some people like keeping these semicolons around, // so we'll allow it. if (n.isEmpty() || n.isComma()) { return; } if (parent == null) { return; } // Do not try to remove a block or an expr result. We already handle // these cases when we visit the child, and the peephole passes will // fix up the tree in more clever ways when these are removed. if (parent.getType() == Token.COMMA) { Node gramps = parent.getParent(); if (gramps.isCall() && parent == gramps.getFirstChild()) { if (n == parent.getFirstChild() && parent.getChildCount() == 2 && n.getNext().isName() && "eval".equals(n.getNext().getString())) { return; } } // This no-op statement was there so that JSDoc information could // be attached to the name. This check should not complain about it. if (n == parent.getLastChild()) { for (Node an : parent.getAncestors()) { int ancestorType = an.getType(); if (ancestorType == Token.COMMA) continue; } } } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) { if (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext())) { } else { return; } } boolean isResultUsed = NodeUtil.isExpressionResultUsed(n); boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType()); if (!isResultUsed && (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) { if (n.isQualifiedName() && n.getJSDocInfo() != null) { return; } else if (n.isExprResult()) { return; } String msg = "This code lacks side-effects. Is there a bug?"; if (n.isString()) { msg = "Is there a missing '+' on the previous line?"; } else if (isSimpleOp) { msg = "The result of the '" + Token.name(n.getType()).toLowerCase() + "' operator is not being used."; } t.getCompiler().report( t.makeError(n, level, USELESS_CODE_ERROR, msg)); // TODO(johnlenz): determine if it is necessary to // try to protect side-effect free statements as well. if (!NodeUtil.isStatement(n)) { problemNodes.add(n); } } }
Example 17
Source File: Closure_60_NodeUtil_s.java From coming with MIT License | 4 votes |
static boolean isExpressionNode(Node n) { return n.getType() == Token.EXPR_RESULT; }
Example 18
Source File: jKali_0022_t.java From coming with MIT License | 4 votes |
@Override public void visit(NodeTraversal t, Node n, Node parent) { // VOID nodes appear when there are extra semicolons at the BLOCK level. // I've been unable to think of any cases where this indicates a bug, // and apparently some people like keeping these semicolons around, // so we'll allow it. if (n.isEmpty() || n.isComma()) { return; } if (parent == null) { return; } // Do not try to remove a block or an expr result. We already handle // these cases when we visit the child, and the peephole passes will // fix up the tree in more clever ways when these are removed. if (n.isExprResult()) { return; } // This no-op statement was there so that JSDoc information could // be attached to the name. This check should not complain about it. if (n.isQualifiedName() && n.getJSDocInfo() != null) { return; } boolean isResultUsed = NodeUtil.isExpressionResultUsed(n); boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType()); if (parent.getType() == Token.COMMA) { if (isResultUsed) { return; } if (n == parent.getLastChild()) { for (Node an : parent.getAncestors()) { int ancestorType = an.getType(); if (true) continue; if (ancestorType != Token.EXPR_RESULT && ancestorType != Token.BLOCK) return; else break; } } } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) { if (! (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext()))) { return; } } if ( (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) { String msg = "This code lacks side-effects. Is there a bug?"; if (n.isString()) { msg = "Is there a missing '+' on the previous line?"; } else if (isSimpleOp) { msg = "The result of the '" + Token.name(n.getType()).toLowerCase() + "' operator is not being used."; } t.getCompiler().report( t.makeError(n, level, USELESS_CODE_ERROR, msg)); // TODO(johnlenz): determine if it is necessary to // try to protect side-effect free statements as well. if (!NodeUtil.isStatement(n)) { problemNodes.add(n); } } }
Example 19
Source File: Closure_10_NodeUtil_t.java From coming with MIT License | 4 votes |
/** * @returns false iff the result of the expression is not consumed. */ static boolean isExpressionResultUsed(Node expr) { // TODO(johnlenz): consider sharing some code with trySimpleUnusedResult. Node parent = expr.getParent(); switch (parent.getType()) { case Token.BLOCK: case Token.EXPR_RESULT: return false; case Token.HOOK: case Token.AND: case Token.OR: return (expr == parent.getFirstChild()) ? true : isExpressionResultUsed(parent); case Token.COMMA: Node gramps = parent.getParent(); if (gramps.isCall() && parent == gramps.getFirstChild()) { // Semantically, a direct call to eval is different from an indirect // call to an eval. See ECMA-262 S15.1.2.1. So it's OK for the first // expression to a comma to be a no-op if it's used to indirect // an eval. This we pretend that this is "used". if (expr == parent.getFirstChild() && parent.getChildCount() == 2 && expr.getNext().isName() && "eval".equals(expr.getNext().getString())) { return true; } } return (expr == parent.getFirstChild()) ? false : isExpressionResultUsed(parent); case Token.FOR: if (!NodeUtil.isForIn(parent)) { // Only an expression whose result is in the condition part of the // expression is used. return (parent.getChildAtIndex(1) == expr); } break; } return true; }
Example 20
Source File: Closure_75_NodeUtil_t.java From coming with MIT License | 2 votes |
/** * Is this node an assignment expression statement? * * @param n The node * @return True if {@code n} is EXPR_RESULT and {@code n}'s * first child is ASSIGN */ static boolean isExprAssign(Node n) { return n.getType() == Token.EXPR_RESULT && n.getFirstChild().getType() == Token.ASSIGN; }