Skip to content

Commit

Permalink
Small NodeUtil changes:
Browse files Browse the repository at this point in the history
 - Added NodeUtil.isNamedFunctionExpression
 - deprecated isVarArgsFunction in favor of doesFunctionReferenceOwnArgumentsObject
 - small cleanup of isExpressionResultUsed

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=173940187
  • Loading branch information
concavelenz authored and brad4d committed Oct 31, 2017
1 parent 467c690 commit a933e16
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 20 deletions.
63 changes: 47 additions & 16 deletions src/com/google/javascript/jscomp/NodeUtil.java
Expand Up @@ -3061,6 +3061,13 @@ static boolean isFunctionExpression(Node n) {
return n.isFunction() && (!isNamedFunction(n) || !isDeclarationParent(n.getParent())); return n.isFunction() && (!isNamedFunction(n) || !isDeclarationParent(n.getParent()));
} }


/**
* @return Whether the node is both a function expression and the function is named.
*/
static boolean isNamedFunctionExpression(Node n) {
return NodeUtil.isFunctionExpression(n) && !n.getFirstChild().getString().isEmpty();
}

/** /**
* see {@link #isFunctionExpression} * see {@link #isFunctionExpression}
* *
Expand Down Expand Up @@ -3124,13 +3131,42 @@ static boolean isEmptyFunctionExpression(Node node) {
* Determines if a function takes a variable number of arguments by * Determines if a function takes a variable number of arguments by
* looking for references to the "arguments" var_args object. * looking for references to the "arguments" var_args object.
*/ */
static boolean isVarArgsFunction(Node function) { @Deprecated
// TODO(johnlenz): rename this function static boolean isVarArgsFunction(Node fn) {
checkArgument(function.isFunction()); return doesFunctionReferenceOwnArgumentsObject(fn);
return !function.isArrowFunction() && isNameReferenced( }
function.getLastChild(),
"arguments", /**
MATCH_NOT_THIS_BINDING); * @return Whether a function has a reference to its own "arguments" object.
*/
static boolean doesFunctionReferenceOwnArgumentsObject(Node fn) {
checkArgument(fn.isFunction());
if (fn.isArrowFunction()) {
return false;
}
return referencesArgumentsHelper(fn.getLastChild());
}

/** @return Whether any child is a reference to the "arguments" object of the root. Effectively,
* this includes arrow method bodies (which don't have their own) and excludes other functions
* which shadow the "arguments" value with their own.
*/
private static boolean referencesArgumentsHelper(Node node) {
if (node.isName() && node.getString().equals("arguments")) {
return true;
}

if (NodeUtil.isVanillaFunction(node)) {
return false;
}

for (Node c = node.getFirstChild(); c != null; c = c.getNext()) {
if (referencesArgumentsHelper(c)) {
return true;
}
}

return false;
} }


/** /**
Expand Down Expand Up @@ -4890,10 +4926,9 @@ static String getBestLValueName(@Nullable Node lValue) {
} }


/** /**
* @return false iff the result of the expression is not consumed. * @return true iff the result of the expression is consumed.
*/ */
static boolean isExpressionResultUsed(Node expr) { static boolean isExpressionResultUsed(Node expr) {
// TODO(johnlenz): consider sharing some code with trySimpleUnusedResult.
Node parent = expr.getParent(); Node parent = expr.getParent();
switch (parent.getToken()) { switch (parent.getToken()) {
case BLOCK: case BLOCK:
Expand Down Expand Up @@ -4922,13 +4957,9 @@ static boolean isExpressionResultUsed(Node expr) {


return (expr == parent.getFirstChild()) ? false : isExpressionResultUsed(parent); return (expr == parent.getFirstChild()) ? false : isExpressionResultUsed(parent);
case FOR: case FOR:
case FOR_IN: // Only an expression whose result is in the condition part of the
if (!parent.isForIn()) { // expression is used.
// Only an expression whose result is in the condition part of the return (parent.getSecondChild() == expr);
// expression is used.
return (parent.getSecondChild() == expr);
}
break;
default: default:
break; break;
} }
Expand Down
33 changes: 29 additions & 4 deletions test/com/google/javascript/jscomp/NodeUtilTest.java
Expand Up @@ -2927,13 +2927,38 @@ public void testGetAllVars2() {
} }


public void testIsVarArgs() { public void testIsVarArgs() {
assertTrue(NodeUtil.isVarArgsFunction(getNode("function() {return () => arguments}"))); assertTrue(NodeUtil.doesFunctionReferenceOwnArgumentsObject(
assertFalse(NodeUtil.isVarArgsFunction(getNode("() => arguments"))); getNode("function() {return () => arguments}")));
assertFalse(NodeUtil.doesFunctionReferenceOwnArgumentsObject(
getNode("() => arguments")));
} }


private boolean executedOnceTestCase(String code) { /**
* When the left side is a destructuring pattern, generally it's not possible to identify the
* RHS for a specific name on the LHS.
*/
public void testIsExpressionResultUsed() {
assertThat(NodeUtil.isExpressionResultUsed(getNameNodeFrom("for (x in y) z", "x"))).isTrue();
assertThat(NodeUtil.isExpressionResultUsed(getNameNodeFrom("for (x in y) z", "y"))).isTrue();
assertThat(NodeUtil.isExpressionResultUsed(getNameNodeFrom("for (x in y) z", "z"))).isFalse();

assertThat(NodeUtil.isExpressionResultUsed(getNameNodeFrom("for (x of y) z", "x"))).isTrue();
assertThat(NodeUtil.isExpressionResultUsed(getNameNodeFrom("for (x of y) z", "y"))).isTrue();
assertThat(NodeUtil.isExpressionResultUsed(getNameNodeFrom("for (x of y) z", "z"))).isFalse();

assertThat(NodeUtil.isExpressionResultUsed(getNameNodeFrom("for (x; y; z) a", "x"))).isFalse();
assertThat(NodeUtil.isExpressionResultUsed(getNameNodeFrom("for (x; y; z) a", "y"))).isTrue();
assertThat(NodeUtil.isExpressionResultUsed(getNameNodeFrom("for (x; y; z) a", "z"))).isFalse();
}

private Node getNameNodeFrom(String code, String name) {
Node ast = parse(code); Node ast = parse(code);
Node nameNode = getNameNode(ast, "x"); Node nameNode = getNameNode(ast, name);
return nameNode;
}

private boolean executedOnceTestCase(String code) {
Node nameNode = getNameNodeFrom(code, "x");
return NodeUtil.isExecutedExactlyOnce(nameNode); return NodeUtil.isExecutedExactlyOnce(nameNode);
} }


Expand Down

0 comments on commit a933e16

Please sign in to comment.