@@ -71,7 +71,7 @@ public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
71
71
n .getFirstChild ().isEmpty () || classNameNode .matchesQualifiedName (n .getFirstChild ()),
72
72
"Class name shadows variable declaring the class: %s" ,
73
73
n );
74
- classStack .push (new ClassRecord (n , classNameNode . getQualifiedName () , classInsertionPoint ));
74
+ classStack .push (new ClassRecord (n , classNameNode , classInsertionPoint ));
75
75
break ;
76
76
case COMPUTED_FIELD_DEF :
77
77
checkState (!classStack .isEmpty ());
@@ -125,40 +125,56 @@ public void exitScope(NodeTraversal t) {}
125
125
public void visit (NodeTraversal t , Node n , Node parent ) {
126
126
switch (n .getToken ()) {
127
127
case CLASS :
128
- visitClass (t );
129
- return ;
128
+ visitClass (t , n );
129
+ break ;
130
130
case THIS :
131
- Node rootNode = t .getClosestScopeRootNodeBindingThisOrSuper ();
132
- if (rootNode .isStaticMember ()
133
- && (rootNode .isMemberFieldDef () || rootNode .isComputedFieldDef ())) {
134
- Node className = rootNode .getGrandparent ().getFirstChild ().cloneNode ();
135
- n .replaceWith (className );
136
- t .reportCodeChange (className );
137
- }
138
- return ;
131
+ visitThis (t , n );
132
+ break ;
139
133
case SUPER :
140
- rootNode = t .getClosestScopeRootNodeBindingThisOrSuper ();
141
- if (rootNode .isMemberFieldDef () && rootNode .isStaticMember ()) {
142
- Node superclassName = rootNode .getGrandparent ().getChildAtIndex (1 ).cloneNode ();
143
- n .replaceWith (superclassName );
144
- t .reportCodeChange (superclassName );
145
- }
146
- return ;
134
+ visitSuper (t , n );
135
+ break ;
147
136
default :
148
- return ;
137
+ break ;
149
138
}
150
139
}
151
140
152
141
/** Transpile the actual class members themselves */
153
- private void visitClass (NodeTraversal t ) {
142
+ private void visitClass (NodeTraversal t , Node classNode ) {
154
143
ClassRecord currClassRecord = classStack .pop ();
144
+ checkState (currClassRecord .classNode == classNode , "unexpected node: %s" , classNode );
155
145
if (currClassRecord .cannotConvert ) {
156
146
return ;
157
147
}
158
148
rewriteInstanceMembers (t , currClassRecord );
159
149
rewriteStaticMembers (t , currClassRecord );
160
150
}
161
151
152
+ private void visitThis (NodeTraversal t , Node thisNode ) {
153
+ Node rootNode = t .getClosestScopeRootNodeBindingThisOrSuper ();
154
+ if (rootNode .isStaticMember ()
155
+ && (rootNode .isMemberFieldDef () || rootNode .isComputedFieldDef ())) {
156
+ final Node classNode = rootNode .getGrandparent ();
157
+ final ClassRecord classRecord = classStack .peek ();
158
+ checkState (
159
+ classRecord .classNode == classNode ,
160
+ "wrong class node: %s != %s" ,
161
+ classRecord .classNode ,
162
+ classNode );
163
+ Node className = classRecord .createNewNameReferenceNode ().srcrefTree (thisNode );
164
+ thisNode .replaceWith (className );
165
+ t .reportCodeChange (className );
166
+ }
167
+ }
168
+
169
+ private void visitSuper (NodeTraversal t , Node n ) {
170
+ Node rootNode = t .getClosestScopeRootNodeBindingThisOrSuper ();
171
+ if (rootNode .isMemberFieldDef () && rootNode .isStaticMember ()) {
172
+ Node superclassName = rootNode .getGrandparent ().getChildAtIndex (1 ).cloneNode ();
173
+ n .replaceWith (superclassName );
174
+ t .reportCodeChange (superclassName );
175
+ }
176
+ }
177
+
162
178
/**
163
179
* Move computed fields with side effects into a computed function (Token is COMPUTED_PROP) to
164
180
* preserve the original behavior of possible side effects such as printing something in the call
@@ -316,8 +332,7 @@ private void rewriteStaticMembers(NodeTraversal t, ClassRecord record) {
316
332
Node staticMember = staticMembers .pop ();
317
333
// if the name is a property access, we want the whole chain of accesses, while for other
318
334
// cases we only want the name node
319
- Node nameToUse =
320
- astFactory .createQNameWithUnknownType (record .classNameString ).srcrefTree (staticMember );
335
+ Node nameToUse = record .createNewNameReferenceNode ().srcrefTree (staticMember );
321
336
322
337
Node transpiledNode ;
323
338
@@ -454,17 +469,17 @@ private static final class ClassRecord {
454
469
ImmutableSet <Var > constructorVars = ImmutableSet .of ();
455
470
456
471
final Node classNode ;
457
- final String classNameString ;
472
+ final Node classNameNode ;
458
473
459
474
// Keeps track of the statement declaring the class
460
475
final Node insertionPointBeforeClass ;
461
476
462
477
// Keeps track of the last statement inserted after the class
463
478
Node insertionPointAfterClass ;
464
479
465
- ClassRecord (Node classNode , String classNameString , Node classInsertionPoint ) {
480
+ ClassRecord (Node classNode , Node classNameNode , Node classInsertionPoint ) {
466
481
this .classNode = classNode ;
467
- this .classNameString = classNameString ;
482
+ this .classNameNode = classNameNode ;
468
483
this .insertionPointBeforeClass = classInsertionPoint ;
469
484
this .insertionPointAfterClass = classInsertionPoint ;
470
485
}
@@ -492,5 +507,15 @@ void recordConstructorScope(Scope s) {
492
507
builder .addAll (argsScope .getAllSymbols ());
493
508
constructorVars = builder .build ();
494
509
}
510
+
511
+ Node createNewNameReferenceNode () {
512
+ if (classNameNode .isName ()) {
513
+ // Don't cloneTree() here, because the name may have a child node, the class itself.
514
+ return classNameNode .cloneNode ();
515
+ } else {
516
+ // Must cloneTree() for a qualified name.
517
+ return classNameNode .cloneTree ();
518
+ }
519
+ }
495
520
}
496
521
}
0 commit comments