@@ -30,101 +30,128 @@ module.exports = {
3030 schema : [ ] ,
3131 } ,
3232
33- create : Components . detect ( ( context , components , utils ) => {
34- let reactImportLocalName ;
35- let reactUseStateLocalName ;
36-
37- return {
38- CallExpression ( node ) {
39- const isReactUseStateCall = (
40- reactImportLocalName
33+ create : Components . detect ( ( context , components ) => ( {
34+ CallExpression ( node ) {
35+ const defaultReactImport = components . getDefaultReactImport ( ) ;
36+ const defaultReactImportName = defaultReactImport ? defaultReactImport . local . name : undefined ;
37+ const namedReactImports = components . getNamedReactImports ( ) ;
38+ const useStateReactImportSpecifier = namedReactImports
39+ ? namedReactImports . find ( ( specifier ) => specifier . imported . name === 'useState' )
40+ : undefined ;
41+ const useStateReactImportName = useStateReactImportSpecifier
42+ ? useStateReactImportSpecifier . local . name
43+ : undefined ;
44+
45+ const isReactUseStateCall = (
46+ defaultReactImportName
4147 && node . callee . type === 'MemberExpression'
4248 && node . callee . object . type === 'Identifier'
43- && node . callee . object . name === reactImportLocalName
49+ && node . callee . object . name === defaultReactImportName
4450 && node . callee . property . type === 'Identifier'
4551 && node . callee . property . name === 'useState'
46- ) ;
52+ ) ;
4753
48- const isUseStateCall = (
49- reactUseStateLocalName
54+ const isUseStateCall = (
55+ useStateReactImportName
5056 && node . callee . type === 'Identifier'
51- && node . callee . name === reactUseStateLocalName
52- ) ;
57+ && node . callee . name === useStateReactImportName
58+ ) ;
59+
60+ // Ignore unless this is a useState() or React.useState() call.
61+ if ( ! isReactUseStateCall && ! isUseStateCall ) {
62+ return ;
63+ }
5364
54- // Ignore unless this is a useState() or React.useState() call.
55- if ( ! isReactUseStateCall && ! isUseStateCall ) {
56- return ;
57- }
65+ const isImmediateReturn = node . parent && node . parent . type === 'ReturnStatement' ;
66+ if ( isImmediateReturn ) {
67+ return ;
68+ }
5869
59- const isDestructuringDeclarator = (
60- node . parent . type === 'VariableDeclarator'
70+ const isDestructuringDeclarator = (
71+ node . parent . type === 'VariableDeclarator'
6172 && node . parent . id . type === 'ArrayPattern'
73+ ) ;
74+
75+ if ( ! isDestructuringDeclarator ) {
76+ report (
77+ context ,
78+ messages . useStateErrorMessage ,
79+ 'useStateErrorMessage' ,
80+ { node }
6281 ) ;
82+ return ;
83+ }
84+
85+ const variableNodes = node . parent . id . elements ;
86+ const valueVariable = variableNodes [ 0 ] ;
87+ const setterVariable = variableNodes [ 1 ] ;
88+
89+ const valueVariableName = valueVariable
90+ ? valueVariable . name
91+ : undefined ;
6392
64- if ( ! isDestructuringDeclarator ) {
65- report (
66- context ,
67- messages . useStateErrorMessage ,
68- 'useStateErrorMessage' ,
69- { node }
70- ) ;
71- return ;
72- }
73-
74- const variableNodes = node . parent . id . elements ;
75- const valueVariable = variableNodes [ 0 ] ;
76- const setterVariable = variableNodes [ 1 ] ;
77-
78- const valueVariableName = valueVariable
79- ? valueVariable . name
80- : undefined ;
81-
82- const setterVariableName = setterVariable
83- ? setterVariable . name
84- : undefined ;
85-
86- const expectedSetterVariableName = valueVariableName ? (
87- `set${ valueVariableName . charAt ( 0 ) . toUpperCase ( ) } ${ valueVariableName . slice ( 1 ) } `
88- ) : undefined ;
89-
90- if (
91- ! valueVariable
93+ const setterVariableName = setterVariable
94+ ? setterVariable . name
95+ : undefined ;
96+
97+ const expectedSetterVariableName = valueVariableName ? (
98+ `set${ valueVariableName . charAt ( 0 ) . toUpperCase ( ) } ${ valueVariableName . slice ( 1 ) } `
99+ ) : undefined ;
100+
101+ if (
102+ ! valueVariable
92103 || ! setterVariable
93104 || setterVariableName !== expectedSetterVariableName
94105 || variableNodes . length !== 2
95- ) {
96- report (
97- context ,
98- messages . useStateErrorMessage ,
99- 'useStateErrorMessage' ,
100- {
101- node : node . parent . id ,
102- fix : valueVariableName ? ( fixer ) => fixer . replaceTextRange (
103- [ node . parent . id . range [ 0 ] , node . parent . id . range [ 1 ] ] ,
104- `[${ valueVariableName } , ${ expectedSetterVariableName } ]`
105- ) : undefined ,
106- }
107- ) ;
108- }
109- } ,
110- ImportDeclaration ( node ) {
111- const isReactImported = node . source . type === 'Literal' && node . source . value === 'react' ;
112- const reactDefaultSpecifier = node . specifiers . find ( ( specifier ) => specifier . type === 'ImportDefaultSpecifier' ) ;
113- reactImportLocalName = reactDefaultSpecifier ? reactDefaultSpecifier . local . name : undefined ;
114-
115- const reactUseStateSpecifier = isReactImported
116- ? node . specifiers . find (
117- ( specifier ) => (
118- specifier . type === 'ImportSpecifier'
119- && specifier . imported . name === 'useState'
120- )
121- )
122- : undefined ;
123-
124- reactUseStateLocalName = reactUseStateSpecifier
125- ? reactUseStateSpecifier . local . name
126- : undefined ;
127- } ,
128- } ;
129- } ) ,
106+ ) {
107+ report (
108+ context ,
109+ messages . useStateErrorMessage ,
110+ 'useStateErrorMessage' ,
111+ {
112+ node : node . parent . id ,
113+ fix : valueVariableName ? ( fixer ) => fixer . replaceTextRange (
114+ [ node . parent . id . range [ 0 ] , node . parent . id . range [ 1 ] ] ,
115+ `[${ valueVariableName } , ${ expectedSetterVariableName } ]`
116+ ) : undefined ,
117+ }
118+ ) ;
119+ }
120+ } ,
121+ } ) ) ,
122+ // create: ReactImport.detect((context) => {
123+ // // context.foo = 'foo';
124+ // // const result = WithReactImport((reactLocalName, context) => {
125+ // // return {
126+ // // CallExpression(node) {
127+
128+ // // }
129+ // // }
130+ // // })
131+ // let reactImportLocalName;
132+ // let reactUseStateLocalName;
133+
134+ // return {
135+ // // Program
136+
137+ // ImportDeclaration(node) {
138+ // const isReactImported = node.source.type === 'Literal' && node.source.value === 'react';
139+ // const reactDefaultSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportDefaultSpecifier');
140+ // reactImportLocalName = reactDefaultSpecifier ? reactDefaultSpecifier.local.name : undefined;
141+
142+ // const reactUseStateSpecifier = isReactImported
143+ // ? node.specifiers.find(
144+ // (specifier) => (
145+ // specifier.type === 'ImportSpecifier'
146+ // && specifier.imported.name === 'useState'
147+ // )
148+ // )
149+ // : undefined;
150+
151+ // reactUseStateLocalName = reactUseStateSpecifier
152+ // ? reactUseStateSpecifier.local.name
153+ // : undefined;
154+ // },
155+ // };
156+ // }),
130157} ;
0 commit comments