private void inlineGlobalAliasIfPossible(Name name, Ref alias, GlobalNamespace namespace) {
    // Ensure that the alias is assigned to global name at that the
    // declaration.
    Node aliasParent = alias.getNode().getParent();
    if (((aliasParent.isAssign() || aliasParent.isName())
            && NodeUtil.isExecutedExactlyOnce(aliasParent))
        // We special-case for constructors here, to inline constructor aliases
        // more aggressively in global scope.
        // We do this because constructor properties are always collapsed,
        // so we want to inline the aliases also to avoid breakages.
        || (aliasParent.isName() && name.isConstructor())) {
      Node lvalue = aliasParent.isName() ? aliasParent : aliasParent.getFirstChild();
      if (!lvalue.isQualifiedName()) {
        return;
      }
      if (lvalue.isName()
          && compiler.getCodingConvention().isExported(lvalue.getString(), /* local */ false)) {
        return;
      }
      Name aliasingName = namespace.getSlot(lvalue.getQualifiedName());

      if (aliasingName == null) {
        // this is true for names in externs or properties on extern names
        return;
      }

      if (name.equals(aliasingName) && aliasParent.isAssign()) {
        // Ignore `a.b.c = a.b.c;` with `a.b.c;`.
        return;
      }

      Inlinability aliasInlinability = aliasingName.calculateInlinability();
      if (!aliasInlinability.shouldInlineUsages()) {
        // nothing to do here
        return;
      }
      Set<AstChange> newNodes = new LinkedHashSet<>();

      // Rewrite all references to the aliasing name, except for the initialization
      rewriteAliasReferences(aliasingName, alias, newNodes);
      rewriteAliasProps(aliasingName, alias.getNode(), 0, newNodes);

      if (aliasInlinability.shouldRemoveDeclaration()) {
        // Rewrite the initialization of the alias, unless this is an unsafe alias inline
        // caused by an @constructor. In that case, we need to leave the initialization around.
        Ref aliasDeclaration = aliasingName.getDeclaration();
        if (aliasDeclaration.getTwin() != null) {
          // This is in a nested assign.
          // Replace
          //   a.b = aliasing.name = aliased.name
          // with
          //   a.b = aliased.name
          checkState(aliasParent.isAssign(), aliasParent);
          Node aliasGrandparent = aliasParent.getParent();
          aliasParent.replaceWith(alias.getNode().detach());
          // remove both of the refs
          aliasingName.removeTwinRefs(aliasDeclaration);
          newNodes.add(new AstChange(alias.module, alias.scope, alias.getNode()));
          compiler.reportChangeToEnclosingScope(aliasGrandparent);
        } else {
          // just set the original alias to null.
          aliasParent.replaceChild(alias.getNode(), IR.nullNode());
          compiler.reportChangeToEnclosingScope(aliasParent);
        }
        codeChanged = true;
        // Update the original aliased name to say that it has one less ALIASING_REF.
        name.removeRef(alias);
      }

      // Inlining the variable may have introduced new references
      // to descendants of {@code name}. So those need to be collected now.
      namespace.scanNewNodes(newNodes);
    }
  }
private void inlineGlobalAliasIfPossible ( Name name , Ref alias , GlobalNamespace namespace ) { Node aliasParent = alias . getNode ( ) . getParent ( ) ; if ( ( ( aliasParent . isAssign ( ) || aliasParent . isName ( ) ) && NodeUtil . isExecutedExactlyOnce ( aliasParent ) ) || ( aliasParent . isName ( ) && name . isConstructor ( ) ) ) { Node lvalue = aliasParent . isName ( ) ? aliasParent : aliasParent . getFirstChild ( ) ; if ( ! lvalue . isQualifiedName ( ) ) { return ; } if ( lvalue . isName ( ) && compiler . getCodingConvention ( ) . isExported ( lvalue . getString ( ) , false ) ) { return ; } Name aliasingName = namespace . getSlot ( lvalue . getQualifiedName ( ) ) ; if ( aliasingName == null ) { return ; } if ( name . equals ( aliasingName ) && aliasParent . isAssign ( ) ) { return ; } Inlinability aliasInlinability = aliasingName . calculateInlinability ( ) ; if ( ! aliasInlinability . shouldInlineUsages ( ) ) { return ; } Set < AstChange > newNodes = new LinkedHashSet < > ( ) ; rewriteAliasReferences ( aliasingName , alias , newNodes ) ; rewriteAliasProps ( aliasingName , alias . getNode ( ) , 0 , newNodes ) ; if ( aliasInlinability . shouldRemoveDeclaration ( ) ) { Ref aliasDeclaration = aliasingName . getDeclaration ( ) ; if ( aliasDeclaration . getTwin ( ) != null ) { checkState ( aliasParent . isAssign ( ) , aliasParent ) ; Node aliasGrandparent = aliasParent . getParent ( ) ; aliasParent . replaceWith ( alias . getNode ( ) . detach ( ) ) ; aliasingName . removeTwinRefs ( aliasDeclaration ) ; newNodes . add ( new AstChange ( alias . module , alias . scope , alias . getNode ( ) ) ) ; compiler . reportChangeToEnclosingScope ( aliasGrandparent ) ; } else { aliasParent . replaceChild ( alias . getNode ( ) , IR . nullNode ( ) ) ; compiler . reportChangeToEnclosingScope ( aliasParent ) ; } codeChanged = true ; name . removeRef ( alias ) ; } namespace . scanNewNodes ( newNodes ) ; } }
Attempt to inline an global alias of a global name. This requires that the name is well
defined: assigned unconditionally, assigned exactly once. It is assumed that, the name for
which it is an alias must already meet these same requirements.

<p>If the alias is completely removed, also deletes the aliasing Ref.

@param name The global name being aliased
@param alias The alias to inline