private CallSiteType classifyCallSite ( Reference ref ) { Node callNode = ref . 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 . isNameDeclOrSimpleAssignLhs ( callNode , parent ) && parent . getFirstChild ( ) . isName ( ) // TODO(nicksantos): Remove this once everyone is using // the CONSTANT_VAR annotation. We know how to remove that. && ! NodeUtil . isConstantName ( parent . getFirstChild ( ) ) ) { // This is a simple assignment. Example: "x = foo();" return CallSiteType . SIMPLE_ASSIGNMENT ; } else if ( parent . isName ( ) // TODO(nicksantos): Remove this once everyone is using the CONSTANT_VAR annotation. && ! NodeUtil . isConstantName ( parent ) // Note: not let or const. See InlineFunctionsTest.testInlineFunctions35 && 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 { ExpressionDecomposer decomposer = getDecomposer ( ref . scope ) ; switch ( decomposer . canExposeExpression ( callNode ) ) { case MOVABLE : return CallSiteType . EXPRESSION ; case DECOMPOSABLE : return CallSiteType . DECOMPOSABLE_EXPRESSION ; case UNDECOMPOSABLE : break ; } } return CallSiteType . UNSUPPORTED ; }
Determine which if any of the supported types the call site is .