code: private void updateGlobalNameDeclaration(
        Name n, String alias, boolean canCollapseChildNames) {
      Ref decl = n.getDeclaration();
      if (decl == null) {
        // Some names do not have declarations, because they
        // are only defined in local scopes.
        return;
      }
  
      switch (decl.getNode().getParent().getToken()) {
        case ASSIGN:
          updateGlobalNameDeclarationAtAssignNode(
              n, alias, canCollapseChildNames);
          break;
        case VAR:
        case LET:
        case CONST:
          updateGlobalNameDeclarationAtVariableNode(n, canCollapseChildNames);
          break;
        case FUNCTION:
          updateGlobalNameDeclarationAtFunctionNode(n, canCollapseChildNames);
          break;
        case CLASS:
          updateGlobalNameDeclarationAtClassNode(n, canCollapseChildNames);
          break;
        case CLASS_MEMBERS:
          updateGlobalNameDeclarationAtStaticMemberNode(n, alias, canCollapseChildNames);
          break;
        default:
          break;
      }
    }
docs: Updates the first initialization (a.k.a "declaration") of a global name.
  This involves flattening the global name (if it's not just a global
  variable name already), collapsing object literal keys into global
  variables, declaring stub global variables for properties added later
  in a local scope.
  
  It may seem odd that this function also takes care of declaring stubs
  for direct children. The ultimate goal of this function is to eliminate
  the global name entirely (when possible), so that "middlemen" namespaces
  disappear, and to do that we need to make sure that all the direct children
  will be collapsed as well.
  
  @param n An object representing a global name (e.g. "a", "a.b.c")
  @param alias The flattened name for {@code n} (e.g. "a", "a$b$c")
  @param canCollapseChildNames Whether it's possible to collapse children of
  this name. (This is mostly passed for convenience; it's equivalent to
  n.canCollapseChildNames()).