private Node inlineFunction ( Reference ref , Node fnNode , String fnName ) { Node callNode = ref . callNode ; Node parent = callNode . getParent ( ) ; Node grandParent = parent . getParent ( ) ; // TODO(johnlenz): Consider storing the callSite classification in the // reference object and passing it in here. CallSiteType callSiteType = classifyCallSite ( ref ) ; checkArgument ( callSiteType != CallSiteType . UNSUPPORTED ) ; // Store the name for the result. This will be used to // replace "return expr" statements with "resultName = expr" // to replace String resultName = null ; boolean needsDefaultReturnResult = true ; switch ( callSiteType ) { case SIMPLE_ASSIGNMENT : resultName = parent . getFirstChild ( ) . getString ( ) ; removeConstantVarAnnotation ( ref . scope , resultName ) ; break ; case VAR_DECL_SIMPLE_ASSIGNMENT : resultName = parent . getString ( ) ; removeConstantVarAnnotation ( ref . scope , resultName ) ; break ; case SIMPLE_CALL : resultName = null ; // "foo()" doesn't need a result. needsDefaultReturnResult = false ; break ; case EXPRESSION : throw new IllegalStateException ( "Movable expressions must be moved before inlining." ) ; case DECOMPOSABLE_EXPRESSION : throw new IllegalStateException ( "Decomposable expressions must be decomposed before inlining." ) ; default : throw new IllegalStateException ( "Unexpected call site type." ) ; } FunctionToBlockMutator mutator = new FunctionToBlockMutator ( compiler , this . safeNameIdSupplier ) ; boolean isCallInLoop = NodeUtil . isWithinLoop ( callNode ) ; Node newBlock = mutator . mutate ( fnName , fnNode , callNode , resultName , needsDefaultReturnResult , isCallInLoop ) ; NodeUtil . markNewScopesChanged ( newBlock , compiler ) ; // TODO(nicksantos): Create a common mutation function that // can replace either a VAR name assignment, assignment expression or // a EXPR_RESULT. Node greatGrandParent = grandParent . getParent ( ) ; switch ( callSiteType ) { case VAR_DECL_SIMPLE_ASSIGNMENT : // Remove the call from the name node. Node firstChild = parent . removeFirstChild ( ) ; NodeUtil . markFunctionsDeleted ( firstChild , compiler ) ; Preconditions . checkState ( parent . getFirstChild ( ) == null ) ; // Add the call, after the VAR. greatGrandParent . addChildAfter ( newBlock , grandParent ) ; break ; case SIMPLE_ASSIGNMENT : // The assignment is now part of the inline function so // replace it completely. Preconditions . checkState ( grandParent . isExprResult ( ) ) ; greatGrandParent . replaceChild ( grandParent , newBlock ) ; NodeUtil . markFunctionsDeleted ( grandParent , compiler ) ; break ; case SIMPLE_CALL : // If nothing is looking at the result just replace the call. Preconditions . checkState ( parent . isExprResult ( ) ) ; grandParent . replaceChild ( parent , newBlock ) ; NodeUtil . markFunctionsDeleted ( parent , compiler ) ; break ; default : throw new IllegalStateException ( "Unexpected call site type." ) ; } return newBlock ; }
Inline a function which fulfills the requirements of canInlineReferenceAsStatementBlock into the call site replacing the parent expression .