com.google.javascript.jscomp.ExpressionDecomposer.DecompositionType Java Examples

The following examples show how to use com.google.javascript.jscomp.ExpressionDecomposer.DecompositionType. 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: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
private void helperCanExposeFunctionExpression(
    DecompositionType expectedResult, String code, int call) {
  Compiler compiler = getCompiler();
  Set<String> knownConstants = Sets.newHashSet();
  ExpressionDecomposer decomposer = new ExpressionDecomposer(
      compiler, compiler.getUniqueNameIdSupplier(), knownConstants);
  Node tree = parse(compiler, code);
  assertNotNull(tree);

  Node externsRoot = parse(compiler,
      "function goo() {}" +
      "function foo() {}");
  assertNotNull(externsRoot);
  Node mainRoot = tree;

  Node callSite = findCall(tree, null, 2);
  assertNotNull("Call " + call + " was not found.", callSite);

  compiler.resetUniqueNameId();
  DecompositionType result = decomposer.canExposeExpression(
      callSite);
  assertEquals(expectedResult, result);
}
 
Example #2
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
public void testCanExposeExpression1() {
  // Can't move or decompose some classes of expressions.
  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "while(foo());", "foo");
  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "while(x = goo()&&foo()){}", "foo");
  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "while(x += goo()&&foo()){}", "foo");

  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "do{}while(foo());", "foo");
  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "for(;foo(););", "foo");
  // This case could be supported for loops without conditional continues
  // by moving the increment into the loop body.
  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "for(;;foo());", "foo");
  // FOR initializer could be supported but they never occur
  // as they are normalized away.

  // This is potentially doable but a bit too complex currently.
  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "switch(1){case foo():;}", "foo");
}
 
Example #3
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
public void testCanExposeExpression2() {
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "foo()", "foo");
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "x = foo()", "foo");
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "var x = foo()", "foo");
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "if(foo()){}", "foo");
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "switch(foo()){}", "foo");
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "switch(foo()){}", "foo");
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "function f(){ return foo();}", "foo");

  helperCanExposeExpression(
      DecompositionType.MOVABLE, "x = foo() && 1", "foo");
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "x = foo() || 1", "foo");
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "x = foo() ? 0 : 1", "foo");
  helperCanExposeExpression(
      DecompositionType.MOVABLE, "(function(a){b = a})(foo())", "foo");
}
 
Example #4
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
public void testCanExposeExpression3() {
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "x = 0 && foo()", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "x = 1 || foo()", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "var x = 1 ? foo() : 0", "foo");

  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "goo() && foo()", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "x = goo() && foo()", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "x += goo() && foo()", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "var x = goo() && foo()", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "if(goo() && foo()){}", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "switch(goo() && foo()){}", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "switch(goo() && foo()){}", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE, "switch(x = goo() && foo()){}", "foo");
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE,
      "function f(){ return goo() && foo();}", "foo");
}
 
Example #5
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
private void helperExposeExpression(
    String code,
    String fnName,
    String expectedResult,
    Set<String> knownConstants
    ) {
  Compiler compiler = getCompiler();
  if (knownConstants == null) {
    knownConstants = Sets.newHashSet();
  }
  ExpressionDecomposer decomposer = new ExpressionDecomposer(
      compiler, compiler.getUniqueNameIdSupplier(), knownConstants);
  decomposer.setTempNamePrefix("temp");
  decomposer.setResultNamePrefix("result");
  Node expectedRoot = parse(compiler, expectedResult);
  Node tree = parse(compiler, code);
  assertNotNull(tree);

  Node externsRoot = new Node(Token.EMPTY);
  Node mainRoot = tree;

  Node callSite = findCall(tree, fnName);
  assertNotNull("Call to " + fnName + " was not found.", callSite);

  DecompositionType result = decomposer.canExposeExpression(callSite);
  assertTrue(result == DecompositionType.DECOMPOSABLE);

  compiler.resetUniqueNameId();
  decomposer.exposeExpression(callSite);
  validateSourceInfo(compiler, tree);
  String explanation = expectedRoot.checkTreeEquals(tree);
  assertNull("\nExpected: " + compiler.toSource(expectedRoot) +
      "\nResult: " + compiler.toSource(tree) +
      "\n" + explanation, explanation);
}
 
Example #6
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
private void helperCanExposeExpression(
    DecompositionType expectedResult,
    String code,
    String fnName,
    Set<String> knownConstants
    ) {
  Compiler compiler = getCompiler();
  if (knownConstants == null) {
    knownConstants = Sets.newHashSet();
  }
  ExpressionDecomposer decomposer = new ExpressionDecomposer(
      compiler, compiler.getUniqueNameIdSupplier(), knownConstants);
  Node tree = parse(compiler, code);
  assertNotNull(tree);

  Node externsRoot = parse(compiler,
      "function goo() {}" +
      "function foo() {}");
  assertNotNull(externsRoot);
  Node mainRoot = tree;

  Node callSite = findCall(tree, fnName);
  assertNotNull("Call to " + fnName + " was not found.", callSite);

  compiler.resetUniqueNameId();
  DecompositionType result = decomposer.canExposeExpression(
      callSite);
  assertEquals(expectedResult, result);
}
 
Example #7
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/** Test case helpers. */

  private void helperCanExposeExpression(
      DecompositionType expectedResult,
      String code,
      String fnName
      ) {
    helperCanExposeExpression(expectedResult, code, fnName, null);
  }
 
Example #8
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
public void testCanExposeExpression8() {
  // Can it be decompose?
  helperCanExposeExpression(
      DecompositionType.DECOMPOSABLE,
      "HangoutStarter.prototype.launchHangout = function() {\n" +
      "  var self = a.b;\n" +
      "  var myUrl = new goog.Uri(getDomServices_(self).getDomHelper()." +
      "getWindow().location.href);\n" +
      "};",
      "getDomServices_");

  // Verify it is properly expose the target expression.
  helperExposeExpression(
      "HangoutStarter.prototype.launchHangout = function() {\n" +
      "  var self = a.b;\n" +
      "  var myUrl = new goog.Uri(getDomServices_(self).getDomHelper()." +
      "getWindow().location.href);\n" +
      "};",
      "getDomServices_",
      "HangoutStarter.prototype.launchHangout = function() {" +
      "  var self = a.b;" +
      "  var temp_const$$0 = goog.Uri;" +
      "  var myUrl = new temp_const$$0(getDomServices_(self)." +
      "      getDomHelper().getWindow().location.href)}");

  // Verify the results can be properly moved.
  helperMoveExpression(
      "HangoutStarter.prototype.launchHangout = function() {" +
      "  var self = a.b;" +
      "  var temp_const$$0 = goog.Uri;" +
      "  var myUrl = new temp_const$$0(getDomServices_(self)." +
      "      getDomHelper().getWindow().location.href)}",
      "getDomServices_",
      "HangoutStarter.prototype.launchHangout = function() {" +
      "  var self=a.b;" +
      "  var temp_const$$0=goog.Uri;" +
      "  var result$$0=getDomServices_(self);" +
      "  var myUrl=new temp_const$$0(result$$0.getDomHelper()." +
      "      getWindow().location.href)}");
}
 
Example #9
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
public void testCanExposeExpression7() {
  // Verify calls to function expressions are movable.
  helperCanExposeFunctionExpression(
      DecompositionType.MOVABLE,
      "(function(map){descriptions_=map})(\n" +
          "function(){\n" +
              "var ret={};\n" +
              "ret[INIT]='a';\n" +
              "ret[MIGRATION_BANNER_DISMISS]='b';\n" +
              "return ret\n" +
          "}()\n" +
      ");", 2);
}
 
Example #10
Source File: 1_FunctionInjector.java    From SimFix with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Determine which, if any, of the supported types the call site is.
 */
private CallSiteType classifyCallSite(Node callNode) {
  Node parent = callNode.getParent();
  Node grandParent = parent.getParent();

  // Verify the call site:
  if (NodeUtil.isExprCall(parent)) {
    // This is a simple call?  Example: "foo();".
    return CallSiteType.SIMPLE_CALL;
  } else if (NodeUtil.isExprAssign(grandParent)
      && !NodeUtil.isVarOrSimpleAssignLhs(callNode, parent)
      && parent.getFirstChild().isName()
      && !NodeUtil.isConstantName(parent.getFirstChild())) {
    // This is a simple assignment.  Example: "x = foo();"
    return CallSiteType.SIMPLE_ASSIGNMENT;
  } else if (parent.isName()
      && !NodeUtil.isConstantName(parent)
      && grandParent.isVar()
      && grandParent.hasOneChild()) {
    // This is a var declaration.  Example: "var x = foo();"
    // TODO(johnlenz): Should we be checking for constants on the
    // left-hand-side of the assignments and handling them as EXPRESSION?
    return CallSiteType.VAR_DECL_SIMPLE_ASSIGNMENT;
  } else {
    Node expressionRoot = ExpressionDecomposer.findExpressionRoot(callNode);
    if (expressionRoot != null) {
      ExpressionDecomposer decomposer = new ExpressionDecomposer(
          compiler, safeNameIdSupplier, knownConstants);
      DecompositionType type = decomposer.canExposeExpression(
          callNode);
      if (type == DecompositionType.MOVABLE) {
        return CallSiteType.EXPRESSION;
      } else if (type == DecompositionType.DECOMPOSABLE) {
        return CallSiteType.DECOMPOSABLE_EXPRESSION;
      } else {
        Preconditions.checkState(type == DecompositionType.UNDECOMPOSABLE);
      }
    }
  }

  return CallSiteType.UNSUPPORTED;
}
 
Example #11
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
public void testCanExposeExpression4() {
  // 'this' must be preserved in call.
  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "if (goo.a(1, foo()));", "foo");
}
 
Example #12
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
public void testCanExposeExpression5() {
  // 'this' must be preserved in call.
  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "if (goo['a'](foo()));", "foo");
}
 
Example #13
Source File: ExpressionDecomposerTest.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
public void testCanExposeExpression6() {
  // 'this' must be preserved in call.
  helperCanExposeExpression(
      DecompositionType.UNDECOMPOSABLE, "z:if (goo.a(1, foo()));", "foo");
}
 
Example #14
Source File: FunctionInjector.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Determine which, if any, of the supported types the call site is.
 */
private CallSiteType classifyCallSite(Node callNode) {
  Node parent = callNode.getParent();
  Node grandParent = parent.getParent();

  // Verify the call site:
  if (NodeUtil.isExprCall(parent)) {
    // This is a simple call?  Example: "foo();".
    return CallSiteType.SIMPLE_CALL;
  } else if (NodeUtil.isExprAssign(grandParent)
      && !NodeUtil.isVarOrSimpleAssignLhs(callNode, parent)
      && parent.getFirstChild().isName()
      && !NodeUtil.isConstantName(parent.getFirstChild())) {
    // This is a simple assignment.  Example: "x = foo();"
    return CallSiteType.SIMPLE_ASSIGNMENT;
  } else if (parent.isName()
      && !NodeUtil.isConstantName(parent)
      && grandParent.isVar()
      && grandParent.hasOneChild()) {
    // This is a var declaration.  Example: "var x = foo();"
    // TODO(johnlenz): Should we be checking for constants on the
    // left-hand-side of the assignments and handling them as EXPRESSION?
    return CallSiteType.VAR_DECL_SIMPLE_ASSIGNMENT;
  } else {
    Node expressionRoot = ExpressionDecomposer.findExpressionRoot(callNode);
    if (expressionRoot != null) {
      ExpressionDecomposer decomposer = new ExpressionDecomposer(
          compiler, safeNameIdSupplier, knownConstants);
      DecompositionType type = decomposer.canExposeExpression(
          callNode);
      if (type == DecompositionType.MOVABLE) {
        return CallSiteType.EXPRESSION;
      } else if (type == DecompositionType.DECOMPOSABLE) {
        return CallSiteType.DECOMPOSABLE_EXPRESSION;
      } else {
        Preconditions.checkState(type == DecompositionType.UNDECOMPOSABLE);
      }
    }
  }

  return CallSiteType.UNSUPPORTED;
}
 
Example #15
Source File: Closure_115_FunctionInjector_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Determine which, if any, of the supported types the call site is.
 */
private CallSiteType classifyCallSite(Node callNode) {
  Node parent = callNode.getParent();
  Node grandParent = parent.getParent();

  // Verify the call site:
  if (NodeUtil.isExprCall(parent)) {
    // This is a simple call?  Example: "foo();".
    return CallSiteType.SIMPLE_CALL;
  } else if (NodeUtil.isExprAssign(grandParent)
      && !NodeUtil.isVarOrSimpleAssignLhs(callNode, parent)
      && parent.getFirstChild().isName()
      && !NodeUtil.isConstantName(parent.getFirstChild())) {
    // This is a simple assignment.  Example: "x = foo();"
    return CallSiteType.SIMPLE_ASSIGNMENT;
  } else if (parent.isName()
      && !NodeUtil.isConstantName(parent)
      && grandParent.isVar()
      && grandParent.hasOneChild()) {
    // This is a var declaration.  Example: "var x = foo();"
    // TODO(johnlenz): Should we be checking for constants on the
    // left-hand-side of the assignments and handling them as EXPRESSION?
    return CallSiteType.VAR_DECL_SIMPLE_ASSIGNMENT;
  } else {
    Node expressionRoot = ExpressionDecomposer.findExpressionRoot(callNode);
    if (expressionRoot != null) {
      ExpressionDecomposer decomposer = new ExpressionDecomposer(
          compiler, safeNameIdSupplier, knownConstants);
      DecompositionType type = decomposer.canExposeExpression(
          callNode);
      if (type == DecompositionType.MOVABLE) {
        return CallSiteType.EXPRESSION;
      } else if (type == DecompositionType.DECOMPOSABLE) {
        return CallSiteType.DECOMPOSABLE_EXPRESSION;
      } else {
        Preconditions.checkState(type == DecompositionType.UNDECOMPOSABLE);
      }
    }
  }

  return CallSiteType.UNSUPPORTED;
}
 
Example #16
Source File: Closure_115_FunctionInjector_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Determine which, if any, of the supported types the call site is.
 */
private CallSiteType classifyCallSite(Node callNode) {
  Node parent = callNode.getParent();
  Node grandParent = parent.getParent();

  // Verify the call site:
  if (NodeUtil.isExprCall(parent)) {
    // This is a simple call?  Example: "foo();".
    return CallSiteType.SIMPLE_CALL;
  } else if (NodeUtil.isExprAssign(grandParent)
      && !NodeUtil.isVarOrSimpleAssignLhs(callNode, parent)
      && parent.getFirstChild().isName()
      && !NodeUtil.isConstantName(parent.getFirstChild())) {
    // This is a simple assignment.  Example: "x = foo();"
    return CallSiteType.SIMPLE_ASSIGNMENT;
  } else if (parent.isName()
      && !NodeUtil.isConstantName(parent)
      && grandParent.isVar()
      && grandParent.hasOneChild()) {
    // This is a var declaration.  Example: "var x = foo();"
    // TODO(johnlenz): Should we be checking for constants on the
    // left-hand-side of the assignments and handling them as EXPRESSION?
    return CallSiteType.VAR_DECL_SIMPLE_ASSIGNMENT;
  } else {
    Node expressionRoot = ExpressionDecomposer.findExpressionRoot(callNode);
    if (expressionRoot != null) {
      ExpressionDecomposer decomposer = new ExpressionDecomposer(
          compiler, safeNameIdSupplier, knownConstants);
      DecompositionType type = decomposer.canExposeExpression(
          callNode);
      if (type == DecompositionType.MOVABLE) {
        return CallSiteType.EXPRESSION;
      } else if (type == DecompositionType.DECOMPOSABLE) {
        return CallSiteType.DECOMPOSABLE_EXPRESSION;
      } else {
        Preconditions.checkState(type == DecompositionType.UNDECOMPOSABLE);
      }
    }
  }

  return CallSiteType.UNSUPPORTED;
}
 
Example #17
Source File: Closure_116_FunctionInjector_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Determine which, if any, of the supported types the call site is.
 */
private CallSiteType classifyCallSite(Node callNode) {
  Node parent = callNode.getParent();
  Node grandParent = parent.getParent();

  // Verify the call site:
  if (NodeUtil.isExprCall(parent)) {
    // This is a simple call?  Example: "foo();".
    return CallSiteType.SIMPLE_CALL;
  } else if (NodeUtil.isExprAssign(grandParent)
      && !NodeUtil.isVarOrSimpleAssignLhs(callNode, parent)
      && parent.getFirstChild().isName()
      && !NodeUtil.isConstantName(parent.getFirstChild())) {
    // This is a simple assignment.  Example: "x = foo();"
    return CallSiteType.SIMPLE_ASSIGNMENT;
  } else if (parent.isName()
      && !NodeUtil.isConstantName(parent)
      && grandParent.isVar()
      && grandParent.hasOneChild()) {
    // This is a var declaration.  Example: "var x = foo();"
    // TODO(johnlenz): Should we be checking for constants on the
    // left-hand-side of the assignments and handling them as EXPRESSION?
    return CallSiteType.VAR_DECL_SIMPLE_ASSIGNMENT;
  } else {
    Node expressionRoot = ExpressionDecomposer.findExpressionRoot(callNode);
    if (expressionRoot != null) {
      ExpressionDecomposer decomposer = new ExpressionDecomposer(
          compiler, safeNameIdSupplier, knownConstants);
      DecompositionType type = decomposer.canExposeExpression(
          callNode);
      if (type == DecompositionType.MOVABLE) {
        return CallSiteType.EXPRESSION;
      } else if (type == DecompositionType.DECOMPOSABLE) {
        return CallSiteType.DECOMPOSABLE_EXPRESSION;
      } else {
        Preconditions.checkState(type == DecompositionType.UNDECOMPOSABLE);
      }
    }
  }

  return CallSiteType.UNSUPPORTED;
}
 
Example #18
Source File: Closure_116_FunctionInjector_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Determine which, if any, of the supported types the call site is.
 */
private CallSiteType classifyCallSite(Node callNode) {
  Node parent = callNode.getParent();
  Node grandParent = parent.getParent();

  // Verify the call site:
  if (NodeUtil.isExprCall(parent)) {
    // This is a simple call?  Example: "foo();".
    return CallSiteType.SIMPLE_CALL;
  } else if (NodeUtil.isExprAssign(grandParent)
      && !NodeUtil.isVarOrSimpleAssignLhs(callNode, parent)
      && parent.getFirstChild().isName()
      && !NodeUtil.isConstantName(parent.getFirstChild())) {
    // This is a simple assignment.  Example: "x = foo();"
    return CallSiteType.SIMPLE_ASSIGNMENT;
  } else if (parent.isName()
      && !NodeUtil.isConstantName(parent)
      && grandParent.isVar()
      && grandParent.hasOneChild()) {
    // This is a var declaration.  Example: "var x = foo();"
    // TODO(johnlenz): Should we be checking for constants on the
    // left-hand-side of the assignments and handling them as EXPRESSION?
    return CallSiteType.VAR_DECL_SIMPLE_ASSIGNMENT;
  } else {
    Node expressionRoot = ExpressionDecomposer.findExpressionRoot(callNode);
    if (expressionRoot != null) {
      ExpressionDecomposer decomposer = new ExpressionDecomposer(
          compiler, safeNameIdSupplier, knownConstants);
      DecompositionType type = decomposer.canExposeExpression(
          callNode);
      if (type == DecompositionType.MOVABLE) {
        return CallSiteType.EXPRESSION;
      } else if (type == DecompositionType.DECOMPOSABLE) {
        return CallSiteType.DECOMPOSABLE_EXPRESSION;
      } else {
        Preconditions.checkState(type == DecompositionType.UNDECOMPOSABLE);
      }
    }
  }

  return CallSiteType.UNSUPPORTED;
}
 
Example #19
Source File: 1_FunctionInjector.java    From SimFix with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Determine which, if any, of the supported types the call site is.
 */
private CallSiteType classifyCallSite(Node callNode) {
  Node parent = callNode.getParent();
  Node grandParent = parent.getParent();

  // Verify the call site:
  if (NodeUtil.isExprCall(parent)) {
    // This is a simple call?  Example: "foo();".
    return CallSiteType.SIMPLE_CALL;
  } else if (NodeUtil.isExprAssign(grandParent)
      && !NodeUtil.isVarOrSimpleAssignLhs(callNode, parent)
      && parent.getFirstChild().isName()
      && !NodeUtil.isConstantName(parent.getFirstChild())) {
    // This is a simple assignment.  Example: "x = foo();"
    return CallSiteType.SIMPLE_ASSIGNMENT;
  } else if (parent.isName()
      && !NodeUtil.isConstantName(parent)
      && grandParent.isVar()
      && grandParent.hasOneChild()) {
    // This is a var declaration.  Example: "var x = foo();"
    // TODO(johnlenz): Should we be checking for constants on the
    // left-hand-side of the assignments and handling them as EXPRESSION?
    return CallSiteType.VAR_DECL_SIMPLE_ASSIGNMENT;
  } else {
    Node expressionRoot = ExpressionDecomposer.findExpressionRoot(callNode);
    if (expressionRoot != null) {
      ExpressionDecomposer decomposer = new ExpressionDecomposer(
          compiler, safeNameIdSupplier, knownConstants);
      DecompositionType type = decomposer.canExposeExpression(
          callNode);
      if (type == DecompositionType.MOVABLE) {
        return CallSiteType.EXPRESSION;
      } else if (type == DecompositionType.DECOMPOSABLE) {
        return CallSiteType.DECOMPOSABLE_EXPRESSION;
      } else {
        Preconditions.checkState(type == DecompositionType.UNDECOMPOSABLE);
      }
    }
  }

  return CallSiteType.UNSUPPORTED;
}