private void rewriteAliasReferences ( Name aliasingName , Ref aliasingRef , Set < AstChange > newNodes ) { List < Ref > refs = new ArrayList <> ( aliasingName . getRefs ( ) ) ; for ( Ref ref : refs ) { switch ( ref . type ) { case SET_FROM_GLOBAL : continue ; case DIRECT_GET : case ALIASING_GET : case PROTOTYPE_GET : case CALL_GET : case SUBCLASSING_GET : if ( ref . getTwin ( ) != null ) { // The reference is the left-hand side of a nested assignment. This means we store two // separate 'twin' Refs with the same node of types ALIASING_GET and SET_FROM_GLOBAL. // For example, the read of `c.d` has a twin reference in // a.b = c.d = e.f; // We handle this case later. checkState ( ref . type == Type . ALIASING_GET , ref ) ; break ; } if ( ref . getNode ( ) . isStringKey ( ) ) { // e.g. `y` in `const {y} = x;` DestructuringGlobalNameExtractor . reassignDestructringLvalue ( ref . getNode ( ) , aliasingRef . getNode ( ) . cloneTree ( ) , newNodes , ref , compiler ) ; } else { // e.g. `x.y` checkState ( ref . getNode ( ) . isGetProp ( ) || ref . getNode ( ) . isName ( ) ) ; Node newNode = aliasingRef . getNode ( ) . cloneTree ( ) ; Node node = ref . getNode ( ) ; node . replaceWith ( newNode ) ; compiler . reportChangeToEnclosingScope ( newNode ) ; newNodes . add ( new AstChange ( ref . module , ref . scope , newNode ) ) ; } aliasingName . removeRef ( ref ) ; break ; default : throw new IllegalStateException ( ) ; } } }
Replaces all reads of a name with the name it aliases