@@ -162,7 +162,7 @@ module.exports = (file, api, options) => {
162
162
const hasNoCallsToDeprecatedAPIs = classPath => {
163
163
if ( checkDeprecatedAPICalls ( classPath ) ) {
164
164
console . warn (
165
- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
165
+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
166
166
'was skipped because of deprecated API calls. Remove calls to ' +
167
167
DEPRECATED_APIS . join ( ', ' ) + ' in your React component and re-run ' +
168
168
'this script.'
@@ -186,7 +186,7 @@ module.exports = (file, api, options) => {
186
186
187
187
if ( hasInvalidCalls ) {
188
188
console . warn (
189
- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
189
+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
190
190
'was skipped because of API calls that will be removed. Remove calls to `' +
191
191
DEFAULT_PROPS_FIELD + '` and/or `' + GET_INITIAL_STATE_FIELD +
192
192
'` in your React component and re-run this script.'
@@ -202,7 +202,7 @@ module.exports = (file, api, options) => {
202
202
) ;
203
203
if ( hasArguments ) {
204
204
console . warn (
205
- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
205
+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
206
206
'was skipped because `arguments` was found in your functions. ' +
207
207
'Arrow functions do not expose an `arguments` object; ' +
208
208
'consider changing to use ES6 spread operator and re-run this script.'
@@ -260,14 +260,14 @@ module.exports = (file, api, options) => {
260
260
} ;
261
261
262
262
const isInitialStateConvertible = classPath => {
263
- const specPath = ReactUtils . getReactCreateClassSpec ( classPath ) ;
263
+ const specPath = ReactUtils . directlyGetCreateClassSpec ( classPath ) ;
264
264
if ( ! specPath ) {
265
265
return false ;
266
266
}
267
267
const result = isGetInitialStateConstructorSafe ( findGetInitialState ( specPath ) ) ;
268
268
if ( ! result ) {
269
269
console . warn (
270
- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
270
+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
271
271
'was skipped because of potential shadowing issues were found in ' +
272
272
'the React component. Rename variable declarations of `props` and/or `context` ' +
273
273
'in your `getInitialState` and re-run this script.'
@@ -277,7 +277,7 @@ module.exports = (file, api, options) => {
277
277
} ;
278
278
279
279
const canConvertToClass = classPath => {
280
- const specPath = ReactUtils . getReactCreateClassSpec ( classPath ) ;
280
+ const specPath = ReactUtils . directlyGetCreateClassSpec ( classPath ) ;
281
281
if ( ! specPath ) {
282
282
return false ;
283
283
}
@@ -299,7 +299,7 @@ module.exports = (file, api, options) => {
299
299
. map ( prop => prop . key . name ? prop . key . name : prop . key )
300
300
. join ( ', ' ) ;
301
301
console . warn (
302
- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
302
+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
303
303
'was skipped because of invalid field(s) `' + invalidText + '` on ' +
304
304
'the React component. Remove any right-hand-side expressions that ' +
305
305
'are not simple, like: `componentWillUpdate: createWillUpdate()` or ' +
@@ -311,8 +311,8 @@ module.exports = (file, api, options) => {
311
311
312
312
const areMixinsConvertible = ( mixinIdentifierNames , classPath ) => {
313
313
if (
314
- ReactUtils . hasMixins ( classPath ) &&
315
- ! ReactUtils . hasSpecificMixins ( classPath , mixinIdentifierNames )
314
+ ReactUtils . directlyHasMixinsField ( classPath ) &&
315
+ ! ReactUtils . directlyHasSpecificMixins ( classPath , mixinIdentifierNames )
316
316
) {
317
317
return false ;
318
318
}
@@ -1023,34 +1023,39 @@ module.exports = (file, api, options) => {
1023
1023
) ;
1024
1024
} ) ;
1025
1025
1026
- const updateToClass = ( classPath , type ) => {
1027
- const specPath = ReactUtils . getReactCreateClassSpec ( classPath ) ;
1028
- const name = ReactUtils . getComponentName ( classPath ) ;
1026
+ const updateToClass = ( classPath ) => {
1027
+ const specPath = ReactUtils . directlyGetCreateClassSpec ( classPath ) ;
1028
+ const name = ReactUtils . directlyGetComponentName ( classPath ) ;
1029
1029
const statics = collectStatics ( specPath ) ;
1030
1030
const properties = collectNonStaticProperties ( specPath ) ;
1031
1031
const comments = getComments ( classPath ) ;
1032
1032
1033
1033
const getInitialState = findGetInitialState ( specPath ) ;
1034
1034
1035
- var path ;
1035
+ var path = classPath ;
1036
+
1036
1037
if (
1037
- type == 'moduleExports' ||
1038
- type == 'exportDefault' ||
1039
- type == 'anonymousInCallExpression'
1038
+ classPath . parentPath . value &&
1039
+ classPath . parentPath . value . type === 'VariableDeclarator'
1040
1040
) {
1041
- path = ReactUtils . findReactCreateClassCallExpression ( classPath ) ;
1042
- } else {
1043
- path = j ( classPath ) . closest ( j . VariableDeclaration ) ;
1041
+ // the reason that we need to do this awkward dance here is that
1042
+ // for things like `var Foo = React.createClass({...})`, we need to
1043
+ // replace the _entire_ VariableDeclaration with
1044
+ // `class Foo extends React.Component {...}`.
1045
+ // it looks scary but since we already know it's a VariableDeclarator
1046
+ // it's actually safe.
1047
+ // (VariableDeclaration > declarations > VariableDeclarator > CallExpression)
1048
+ path = classPath . parentPath . parentPath . parentPath ;
1044
1049
}
1045
1050
1046
1051
const staticProperties = createStaticClassProperties ( statics ) ;
1047
1052
const baseClassName =
1048
1053
pureRenderMixinPathAndBinding &&
1049
- ReactUtils . hasSpecificMixins ( classPath , [ pureRenderMixinPathAndBinding . binding ] ) ?
1054
+ ReactUtils . directlyHasSpecificMixins ( classPath , [ pureRenderMixinPathAndBinding . binding ] ) ?
1050
1055
'PureComponent' :
1051
1056
'Component' ;
1052
1057
1053
- path . replaceWith (
1058
+ j ( path ) . replaceWith (
1054
1059
createESClass (
1055
1060
name ,
1056
1061
baseClassName ,
@@ -1071,7 +1076,7 @@ module.exports = (file, api, options) => {
1071
1076
// class mixins is an array and only contains the identifier -> true
1072
1077
// otherwise -> false
1073
1078
const mixinsFilter = ( classPath ) => {
1074
- if ( ! ReactUtils . hasMixins ( classPath ) ) {
1079
+ if ( ! ReactUtils . directlyHasMixinsField ( classPath ) ) {
1075
1080
return true ;
1076
1081
} else if ( options [ 'pure-component' ] && pureRenderMixinPathAndBinding ) {
1077
1082
const { binding} = pureRenderMixinPathAndBinding ;
@@ -1080,32 +1085,30 @@ module.exports = (file, api, options) => {
1080
1085
}
1081
1086
}
1082
1087
console . warn (
1083
- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
1088
+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
1084
1089
'was skipped because of inconvertible mixins.'
1085
1090
) ;
1091
+
1086
1092
return false ;
1087
1093
} ;
1088
1094
1089
- const apply = ( path , type ) =>
1095
+ // the only time that we can't simply replace the createClass call path
1096
+ // with a new class is when the parent of that is a variable declaration.
1097
+ // let's delay it and figure it out later (by looking at `path.parentPath`)
1098
+ // in `updateToClass`.
1099
+ const apply = ( path ) =>
1090
1100
path
1091
1101
. filter ( mixinsFilter )
1092
1102
. filter ( hasNoCallsToDeprecatedAPIs )
1093
1103
. filter ( hasNoRefsToAPIsThatWillBeRemoved )
1094
1104
. filter ( doesNotUseArguments )
1095
1105
. filter ( isInitialStateConvertible )
1096
1106
. filter ( canConvertToClass )
1097
- . forEach ( classPath => updateToClass ( classPath , type ) ) ;
1098
-
1099
- const didTransform = (
1100
- apply ( ReactUtils . findReactAnonymousCreateClassInCallExpression ( root ) , 'anonymousInCallExpression' )
1101
- . size ( ) +
1102
- apply ( ReactUtils . findReactCreateClass ( root ) , 'var' )
1103
- . size ( ) +
1104
- apply ( ReactUtils . findReactCreateClassModuleExports ( root ) , 'moduleExports' )
1105
- . size ( ) +
1106
- apply ( ReactUtils . findReactCreateClassExportDefault ( root ) , 'exportDefault' )
1107
- . size ( )
1108
- ) > 0 ;
1107
+ . forEach ( updateToClass ) ;
1108
+
1109
+ const didTransform = apply (
1110
+ ReactUtils . findAllReactCreateClassCalls ( root )
1111
+ ) . size ( ) > 0 ;
1109
1112
1110
1113
if ( didTransform ) {
1111
1114
// prune removed requires
@@ -1118,7 +1121,6 @@ module.exports = (file, api, options) => {
1118
1121
1119
1122
return root . toSource ( printOptions ) ;
1120
1123
}
1121
-
1122
1124
}
1123
1125
1124
1126
return null ;
0 commit comments