/** @param globalScope a new Global Scope to replace the scope of references with. */
 public void updateReferencesWithGlobalScope(Scope globalScope) {
   for (ReferenceCollection collection : refMap.values()) {
     List<Reference> newRefs = new ArrayList<>(collection.references.size());
     for (Reference ref : collection.references) {
       if (ref.getScope() != globalScope) {
         newRefs.add(ref.cloneWithNewScope(globalScope));
       } else {
         newRefs.add(ref);
       }
     }
     collection.references = newRefs;
   }
 }
  /**
   * Finds the range of references associated to {@code sourceName}. Note that even if there is no
   * sourceName references the returned information can be used to decide where to insert new
   * sourceName refs.
   */
  private SourceRefRange findSourceRefRange(List<Reference> refList, InputId inputId) {
    Preconditions.checkNotNull(inputId);

    // TODO(bashir): We can do binary search here, but since this is fast enough
    // right now, we just do a linear search for simplicity.
    int lastBefore = -1;
    int firstAfter = refList.size();
    int index = 0;

    Preconditions.checkState(inputOrder.containsKey(inputId), inputId.getIdName());
    int sourceInputOrder = inputOrder.get(inputId);
    for (Reference ref : refList) {
      Preconditions.checkNotNull(ref.getInputId());
      int order = inputOrder.get(ref.getInputId());
      if (order < sourceInputOrder) {
        lastBefore = index;
      } else if (order > sourceInputOrder) {
        firstAfter = index;
        break;
      }
      index++;
    }
    return new SourceRefRange(refList, lastBefore, firstAfter);
  }
  private boolean inlineAliasIfPossible(Name name, Ref alias, GlobalNamespace namespace) {
    // Ensure that the alias is assigned to a local variable at that
    // variable's declaration. If the alias's parent is a NAME,
    // then the NAME must be the child of a VAR node, and we must
    // be in a VAR assignment.
    Node aliasParent = alias.node.getParent();
    if (aliasParent.isName()) {
      // Ensure that the local variable is well defined and never reassigned.
      Scope scope = alias.scope;
      String aliasVarName = aliasParent.getString();
      Var aliasVar = scope.getVar(aliasVarName);

      ReferenceCollectingCallback collector =
          new ReferenceCollectingCallback(
              compiler,
              ReferenceCollectingCallback.DO_NOTHING_BEHAVIOR,
              Predicates.equalTo(aliasVar));
      collector.processScope(scope);

      ReferenceCollection aliasRefs = collector.getReferences(aliasVar);
      Set<AstChange> newNodes = new LinkedHashSet<>();

      if (aliasRefs.isWellDefined() && aliasRefs.firstReferenceIsAssigningDeclaration()) {
        if (!aliasRefs.isAssignedOnceInLifetime()) {
          // Static properties of constructors are always collapsed.
          // So, if a constructor is aliased and its properties are accessed from
          // the alias, we would like to inline the alias here to access the
          // properties correctly.
          // But if the aliased variable is assigned more than once, we can't
          // inline, so we warn.
          if (name.isConstructor()) {
            boolean accessPropsAfterAliasing = false;
            for (Reference ref : aliasRefs.references) {
              if (ref.getNode().getParent().isGetProp()) {
                accessPropsAfterAliasing = true;
                break;
              }
            }
            if (accessPropsAfterAliasing) {
              compiler.report(JSError.make(aliasParent, UNSAFE_CTOR_ALIASING, aliasVarName));
            }
          }
          return false;
        }

        // The alias is well-formed, so do the inlining now.
        int size = aliasRefs.references.size();
        for (int i = 1; i < size; i++) {
          ReferenceCollectingCallback.Reference aliasRef = aliasRefs.references.get(i);

          Node newNode = alias.node.cloneTree();
          aliasRef.getParent().replaceChild(aliasRef.getNode(), newNode);
          newNodes.add(new AstChange(getRefModule(aliasRef), aliasRef.getScope(), newNode));
        }

        // just set the original alias to null.
        aliasParent.replaceChild(alias.node, IR.nullNode());
        compiler.reportCodeChange();

        // Inlining the variable may have introduced new references
        // to descendants of {@code name}. So those need to be collected now.
        namespace.scanNewNodes(newNodes);
        return true;
      }
    }

    return false;
  }