private void traverseFunction(Node function, Scope parentScope) {
    checkState(function.getChildCount() == 3, function);
    checkState(function.isFunction(), function);

    final Node paramlist = NodeUtil.getFunctionParameters(function);
    final Node body = function.getLastChild();
    checkState(body.getNext() == null && body.isBlock(), body);

    // Checking the parameters
    Scope fparamScope = scopeCreator.createScope(function, parentScope);

    // Checking the function body
    Scope fbodyScope = scopeCreator.createScope(body, fparamScope);

    Node nameNode = function.getFirstChild();
    if (!nameNode.getString().isEmpty()) {
      // var x = function funcName() {};
      // make sure funcName gets into the varInfoMap so it will be considered for removal.
      VarInfo varInfo = traverseNameNode(nameNode, fparamScope);
      if (NodeUtil.isExpressionResultUsed(function)) {
        // var f = function g() {};
        // The f is an alias for g, so g escapes from the scope where it is defined.
        varInfo.hasNonLocalOrNonLiteralValue = true;
      }
    }

    traverseChildren(paramlist, fparamScope);
    traverseChildren(body, fbodyScope);

    allFunctionParamScopes.add(fparamScope);
  }
private void traverseFunction ( Node function , Scope parentScope ) { checkState ( function . getChildCount ( ) == 3 , function ) ; checkState ( function . isFunction ( ) , function ) ; final Node paramlist = NodeUtil . getFunctionParameters ( function ) ; final Node body = function . getLastChild ( ) ; checkState ( body . getNext ( ) == null && body . isBlock ( ) , body ) ; Scope fparamScope = scopeCreator . createScope ( function , parentScope ) ; Scope fbodyScope = scopeCreator . createScope ( body , fparamScope ) ; Node nameNode = function . getFirstChild ( ) ; if ( ! nameNode . getString ( ) . isEmpty ( ) ) { VarInfo varInfo = traverseNameNode ( nameNode , fparamScope ) ; if ( NodeUtil . isExpressionResultUsed ( function ) ) { varInfo . hasNonLocalOrNonLiteralValue = true ; } } traverseChildren ( paramlist , fparamScope ) ; traverseChildren ( body , fbodyScope ) ; allFunctionParamScopes . add ( fparamScope ) ; }
Traverses a function

ES6 scopes of a function include the parameter scope and the body scope
of the function.

Note that CATCH blocks also create a new scope, but only for the
catch variable. Declarations within the block actually belong to the
enclosing scope. Because we don't remove catch variables, there's
no need to treat CATCH blocks differently like we do functions.