11
11
12
12
const Components = require ( '../util/Components' ) ;
13
13
const docsUrl = require ( '../util/docsUrl' ) ;
14
+ const ast = require ( '../util/ast' ) ;
14
15
15
16
// Descend through all wrapping TypeCastExpressions and return the expression
16
17
// that was cast.
@@ -41,7 +42,7 @@ function getName(node) {
41
42
}
42
43
43
44
function isThisExpression ( node ) {
44
- return uncast ( node ) . type === 'ThisExpression' ;
45
+ return ast . unwrapTSAsExpression ( uncast ( node ) ) . type === 'ThisExpression' ;
45
46
}
46
47
47
48
function getInitialClassInfo ( ) {
@@ -62,10 +63,12 @@ function getInitialClassInfo() {
62
63
}
63
64
64
65
function isSetStateCall ( node ) {
66
+ const unwrappedCalleeNode = ast . unwrapTSAsExpression ( node . callee ) ;
67
+
65
68
return (
66
- node . callee . type === 'MemberExpression' &&
67
- isThisExpression ( node . callee . object ) &&
68
- getName ( node . callee . property ) === 'setState'
69
+ unwrappedCalleeNode . type === 'MemberExpression' &&
70
+ isThisExpression ( unwrappedCalleeNode . object ) &&
71
+ getName ( unwrappedCalleeNode . property ) === 'setState'
69
72
) ;
70
73
}
71
74
@@ -178,16 +181,18 @@ module.exports = {
178
181
// Used to record used state fields and new aliases for both
179
182
// AssignmentExpressions and VariableDeclarators.
180
183
function handleAssignment ( left , right ) {
184
+ const unwrappedRight = ast . unwrapTSAsExpression ( right ) ;
185
+
181
186
switch ( left . type ) {
182
187
case 'Identifier' :
183
- if ( isStateReference ( right ) && classInfo . aliases ) {
188
+ if ( isStateReference ( unwrappedRight ) && classInfo . aliases ) {
184
189
classInfo . aliases . add ( left . name ) ;
185
190
}
186
191
break ;
187
192
case 'ObjectPattern' :
188
- if ( isStateReference ( right ) ) {
193
+ if ( isStateReference ( unwrappedRight ) ) {
189
194
handleStateDestructuring ( left ) ;
190
- } else if ( isThisExpression ( right ) && classInfo . aliases ) {
195
+ } else if ( isThisExpression ( unwrappedRight ) && classInfo . aliases ) {
191
196
for ( const prop of left . properties ) {
192
197
if ( prop . type === 'Property' && getName ( prop . key ) === 'state' ) {
193
198
const name = getName ( prop . value ) ;
@@ -254,24 +259,30 @@ module.exports = {
254
259
if ( ! classInfo ) {
255
260
return ;
256
261
}
262
+
263
+ const unwrappedNode = ast . unwrapTSAsExpression ( node ) ;
264
+ const unwrappedArgumentNode = ast . unwrapTSAsExpression ( unwrappedNode . arguments [ 0 ] ) ;
265
+
257
266
// If we're looking at a `this.setState({})` invocation, record all the
258
267
// properties as state fields.
259
268
if (
260
- isSetStateCall ( node ) &&
261
- node . arguments . length > 0 &&
262
- node . arguments [ 0 ] . type === 'ObjectExpression'
269
+ isSetStateCall ( unwrappedNode ) &&
270
+ unwrappedNode . arguments . length > 0 &&
271
+ unwrappedArgumentNode . type === 'ObjectExpression'
263
272
) {
264
- addStateFields ( node . arguments [ 0 ] ) ;
273
+ addStateFields ( unwrappedArgumentNode ) ;
265
274
} else if (
266
- isSetStateCall ( node ) &&
267
- node . arguments . length > 0 &&
268
- node . arguments [ 0 ] . type === 'ArrowFunctionExpression'
275
+ isSetStateCall ( unwrappedNode ) &&
276
+ unwrappedNode . arguments . length > 0 &&
277
+ unwrappedArgumentNode . type === 'ArrowFunctionExpression'
269
278
) {
270
- if ( node . arguments [ 0 ] . body . type === 'ObjectExpression' ) {
271
- addStateFields ( node . arguments [ 0 ] . body ) ;
279
+ const unwrappedBodyNode = ast . unwrapTSAsExpression ( unwrappedArgumentNode . body ) ;
280
+
281
+ if ( unwrappedBodyNode . type === 'ObjectExpression' ) {
282
+ addStateFields ( unwrappedBodyNode ) ;
272
283
}
273
- if ( node . arguments [ 0 ] . params . length > 0 && classInfo . aliases ) {
274
- const firstParam = node . arguments [ 0 ] . params [ 0 ] ;
284
+ if ( unwrappedArgumentNode . params . length > 0 && classInfo . aliases ) {
285
+ const firstParam = unwrappedArgumentNode . params [ 0 ] ;
275
286
if ( firstParam . type === 'ObjectPattern' ) {
276
287
handleStateDestructuring ( firstParam ) ;
277
288
} else {
@@ -287,19 +298,21 @@ module.exports = {
287
298
}
288
299
// If we see state being assigned as a class property using an object
289
300
// expression, record all the fields of that object as state fields.
301
+ const unwrappedValueNode = ast . unwrapTSAsExpression ( node . value ) ;
302
+
290
303
if (
291
304
getName ( node . key ) === 'state' &&
292
305
! node . static &&
293
- node . value &&
294
- node . value . type === 'ObjectExpression'
306
+ unwrappedValueNode &&
307
+ unwrappedValueNode . type === 'ObjectExpression'
295
308
) {
296
- addStateFields ( node . value ) ;
309
+ addStateFields ( unwrappedValueNode ) ;
297
310
}
298
311
299
312
if (
300
313
! node . static &&
301
- node . value &&
302
- node . value . type === 'ArrowFunctionExpression'
314
+ unwrappedValueNode &&
315
+ unwrappedValueNode . type === 'ArrowFunctionExpression'
303
316
) {
304
317
// Create a new set for this.state aliases local to this method.
305
318
classInfo . aliases = new Set ( ) ;
@@ -364,12 +377,16 @@ module.exports = {
364
377
if ( ! classInfo ) {
365
378
return ;
366
379
}
380
+
381
+ const unwrappedLeft = ast . unwrapTSAsExpression ( node . left ) ;
382
+ const unwrappedRight = ast . unwrapTSAsExpression ( node . right ) ;
383
+
367
384
// Check for assignments like `this.state = {}`
368
385
if (
369
- node . left . type === 'MemberExpression' &&
370
- isThisExpression ( node . left . object ) &&
371
- getName ( node . left . property ) === 'state' &&
372
- node . right . type === 'ObjectExpression'
386
+ unwrappedLeft . type === 'MemberExpression' &&
387
+ isThisExpression ( unwrappedLeft . object ) &&
388
+ getName ( unwrappedLeft . property ) === 'state' &&
389
+ unwrappedRight . type === 'ObjectExpression'
373
390
) {
374
391
// Find the nearest function expression containing this assignment.
375
392
let fn = node ;
@@ -383,11 +400,11 @@ module.exports = {
383
400
fn . parent . type === 'MethodDefinition' &&
384
401
fn . parent . kind === 'constructor'
385
402
) {
386
- addStateFields ( node . right ) ;
403
+ addStateFields ( unwrappedRight ) ;
387
404
}
388
405
} else {
389
406
// Check for assignments like `alias = this.state` and record the alias.
390
- handleAssignment ( node . left , node . right ) ;
407
+ handleAssignment ( unwrappedLeft , unwrappedRight ) ;
391
408
}
392
409
} ,
393
410
@@ -402,7 +419,7 @@ module.exports = {
402
419
if ( ! classInfo ) {
403
420
return ;
404
421
}
405
- if ( isStateReference ( node . object ) ) {
422
+ if ( isStateReference ( ast . unwrapTSAsExpression ( node . object ) ) ) {
406
423
// If we see this.state[foo] access, give up.
407
424
if ( node . computed && node . property . type !== 'Literal' ) {
408
425
classInfo = null ;
0 commit comments