@@ -162,7 +162,7 @@ module.exports = (file, api, options) => {
162162 const hasNoCallsToDeprecatedAPIs = classPath => {
163163 if ( checkDeprecatedAPICalls ( classPath ) ) {
164164 console . warn (
165- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
165+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
166166 'was skipped because of deprecated API calls. Remove calls to ' +
167167 DEPRECATED_APIS . join ( ', ' ) + ' in your React component and re-run ' +
168168 'this script.'
@@ -186,7 +186,7 @@ module.exports = (file, api, options) => {
186186
187187 if ( hasInvalidCalls ) {
188188 console . warn (
189- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
189+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
190190 'was skipped because of API calls that will be removed. Remove calls to `' +
191191 DEFAULT_PROPS_FIELD + '` and/or `' + GET_INITIAL_STATE_FIELD +
192192 '` in your React component and re-run this script.'
@@ -202,7 +202,7 @@ module.exports = (file, api, options) => {
202202 ) ;
203203 if ( hasArguments ) {
204204 console . warn (
205- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
205+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
206206 'was skipped because `arguments` was found in your functions. ' +
207207 'Arrow functions do not expose an `arguments` object; ' +
208208 'consider changing to use ES6 spread operator and re-run this script.'
@@ -260,14 +260,14 @@ module.exports = (file, api, options) => {
260260 } ;
261261
262262 const isInitialStateConvertible = classPath => {
263- const specPath = ReactUtils . getReactCreateClassSpec ( classPath ) ;
263+ const specPath = ReactUtils . directlyGetCreateClassSpec ( classPath ) ;
264264 if ( ! specPath ) {
265265 return false ;
266266 }
267267 const result = isGetInitialStateConstructorSafe ( findGetInitialState ( specPath ) ) ;
268268 if ( ! result ) {
269269 console . warn (
270- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
270+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
271271 'was skipped because of potential shadowing issues were found in ' +
272272 'the React component. Rename variable declarations of `props` and/or `context` ' +
273273 'in your `getInitialState` and re-run this script.'
@@ -277,7 +277,7 @@ module.exports = (file, api, options) => {
277277 } ;
278278
279279 const canConvertToClass = classPath => {
280- const specPath = ReactUtils . getReactCreateClassSpec ( classPath ) ;
280+ const specPath = ReactUtils . directlyGetCreateClassSpec ( classPath ) ;
281281 if ( ! specPath ) {
282282 return false ;
283283 }
@@ -299,7 +299,7 @@ module.exports = (file, api, options) => {
299299 . map ( prop => prop . key . name ? prop . key . name : prop . key )
300300 . join ( ', ' ) ;
301301 console . warn (
302- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
302+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
303303 'was skipped because of invalid field(s) `' + invalidText + '` on ' +
304304 'the React component. Remove any right-hand-side expressions that ' +
305305 'are not simple, like: `componentWillUpdate: createWillUpdate()` or ' +
@@ -311,8 +311,8 @@ module.exports = (file, api, options) => {
311311
312312 const areMixinsConvertible = ( mixinIdentifierNames , classPath ) => {
313313 if (
314- ReactUtils . hasMixins ( classPath ) &&
315- ! ReactUtils . hasSpecificMixins ( classPath , mixinIdentifierNames )
314+ ReactUtils . directlyHasMixinsField ( classPath ) &&
315+ ! ReactUtils . directlyHasSpecificMixins ( classPath , mixinIdentifierNames )
316316 ) {
317317 return false ;
318318 }
@@ -1023,34 +1023,39 @@ module.exports = (file, api, options) => {
10231023 ) ;
10241024 } ) ;
10251025
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 ) ;
10291029 const statics = collectStatics ( specPath ) ;
10301030 const properties = collectNonStaticProperties ( specPath ) ;
10311031 const comments = getComments ( classPath ) ;
10321032
10331033 const getInitialState = findGetInitialState ( specPath ) ;
10341034
1035- var path ;
1035+ var path = classPath ;
1036+
10361037 if (
1037- type == 'moduleExports' ||
1038- type == 'exportDefault' ||
1039- type == 'anonymousInCallExpression'
1038+ classPath . parentPath . value &&
1039+ classPath . parentPath . value . type === 'VariableDeclarator'
10401040 ) {
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 ;
10441049 }
10451050
10461051 const staticProperties = createStaticClassProperties ( statics ) ;
10471052 const baseClassName =
10481053 pureRenderMixinPathAndBinding &&
1049- ReactUtils . hasSpecificMixins ( classPath , [ pureRenderMixinPathAndBinding . binding ] ) ?
1054+ ReactUtils . directlyHasSpecificMixins ( classPath , [ pureRenderMixinPathAndBinding . binding ] ) ?
10501055 'PureComponent' :
10511056 'Component' ;
10521057
1053- path . replaceWith (
1058+ j ( path ) . replaceWith (
10541059 createESClass (
10551060 name ,
10561061 baseClassName ,
@@ -1071,7 +1076,7 @@ module.exports = (file, api, options) => {
10711076 // class mixins is an array and only contains the identifier -> true
10721077 // otherwise -> false
10731078 const mixinsFilter = ( classPath ) => {
1074- if ( ! ReactUtils . hasMixins ( classPath ) ) {
1079+ if ( ! ReactUtils . directlyHasMixinsField ( classPath ) ) {
10751080 return true ;
10761081 } else if ( options [ 'pure-component' ] && pureRenderMixinPathAndBinding ) {
10771082 const { binding} = pureRenderMixinPathAndBinding ;
@@ -1080,32 +1085,30 @@ module.exports = (file, api, options) => {
10801085 }
10811086 }
10821087 console . warn (
1083- file . path + ': `' + ReactUtils . getComponentName ( classPath ) + '` ' +
1088+ file . path + ': `' + ReactUtils . directlyGetComponentName ( classPath ) + '` ' +
10841089 'was skipped because of inconvertible mixins.'
10851090 ) ;
1091+
10861092 return false ;
10871093 } ;
10881094
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 ) =>
10901100 path
10911101 . filter ( mixinsFilter )
10921102 . filter ( hasNoCallsToDeprecatedAPIs )
10931103 . filter ( hasNoRefsToAPIsThatWillBeRemoved )
10941104 . filter ( doesNotUseArguments )
10951105 . filter ( isInitialStateConvertible )
10961106 . 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 ;
11091112
11101113 if ( didTransform ) {
11111114 // prune removed requires
@@ -1118,7 +1121,6 @@ module.exports = (file, api, options) => {
11181121
11191122 return root . toSource ( printOptions ) ;
11201123 }
1121-
11221124 }
11231125
11241126 return null ;
0 commit comments