@@ -16,7 +16,6 @@ export const writingOpExpressionTypes = ['UpdateExpression']
1616 *
1717 * isInSomething(thisNode,"FunctionExpression") // true
1818 * isInSomething(thisNode,"ExpressionStatement") // false
19- *
2019 */
2120export function isInSomething ( node , thing ) {
2221 if ( node . parent && node . parent . type !== thing ) {
@@ -30,18 +29,16 @@ export function isInSomething(node, thing) {
3029/**
3130 * @param {any } node ASTNode
3231 *
33- *
3432 * @example
3533 *
36- *const stateOne = proxy({
34+ * const stateOne = proxy({
3735 * count: 0,
3836 * inc: function () {
3937 * ++state.count //<== taking node from here
4038 * },
4139 * })
4240 *
4341 * nearestCalleeName(node) //=> "proxy" //<= proxy is the nearest callee
44- *
4542 */
4643export function nearestCalleeName ( node ) {
4744 if ( ! ( node && node . parent ) ) {
@@ -81,9 +78,12 @@ export function nearestCalleeName(node) {
8178 *
8279 * getParentOfNodeType(thisNode,"FunctionExpression") // ASTNode.type: "FunctionExpression"
8380 * getParentOfNodeType(thisNode,"ExpressionStatement") // null
84- *
8581 */
8682export function getParentOfNodeType ( node , nodeType ) {
83+ if ( ! node ?. parent ) {
84+ return null
85+ }
86+
8787 if ( node . parent && node . parent . type !== nodeType ) {
8888 return getParentOfNodeType ( node . parent , nodeType )
8989 } else if ( node . parent && node . parent . type === nodeType ) {
@@ -111,11 +111,14 @@ export function isReadOnly(node) {
111111 return isReadOnly ( node . parent )
112112 }
113113
114+ if ( node . parent . type === 'CallExpression' ) {
115+ return true
116+ }
117+
114118 return true
115119}
116120
117121/**
118- *
119122 * @param {* } node
120123 * @returns {boolean } true if the node is on the left
121124 * of an assignment expression aka being modified
@@ -152,28 +155,43 @@ export function returnFirstCallback(node) {
152155 * resulting node or not
153156 * @returns {* | boolean } - either true/false or the CallExpression node that belongs to the hook
154157 */
155- export function isInHook ( node , returnHook = false ) {
158+ export function isInReactHooks ( node , returnHook = false ) {
156159 const hookDef = getNearestHook ( node )
157160 if ( returnHook ) {
158161 return hookDef
159162 }
160163 return hookDef ? true : false
161164}
162165
166+ function isReactPrimitive ( node ) {
167+ if (
168+ node . type === 'Identifier' &&
169+ ( node . name === 'useEffect' || node . name === 'useCallback' )
170+ ) {
171+ return true
172+ }
173+
174+ if ( node . type === 'MemberExpression' ) {
175+ const flatExpr = flattenMemberExpression ( node )
176+ return flatExpr . endsWith ( 'useEffect' ) || flatExpr . endsWith ( 'useCallback' )
177+ }
178+
179+ return false
180+ }
181+
163182export function getNearestHook ( node ) {
164183 if ( ! node . parent || ! node . parent . type ) return false
165184
166- if (
167- functionTypes . includes ( node . type ) &&
168- node . parent . type == 'CallExpression' &&
169- node . parent . callee . type === 'Identifier' &&
170- ( node . parent . callee . name === 'useEffect' ||
171- node . parent . callee . name === 'useCallback' )
172- ) {
173- return node . parent
174- } else {
175- return getNearestHook ( node . parent )
185+ const parentCaller = getParentOfNodeType ( node , 'CallExpression' )
186+ if ( ! parentCaller ) {
187+ return false
188+ }
189+
190+ if ( ! isReactPrimitive ( parentCaller . callee ) ) {
191+ return getNearestHook ( parentCaller )
176192 }
193+
194+ return parentCaller
177195}
178196
179197/**
@@ -182,8 +200,8 @@ export function getNearestHook(node) {
182200 * @param {* } node
183201 * @returns {boolean }
184202 */
185- export function isInHookDeps ( node ) {
186- const hookNode = isInHook ( node , true )
203+ export function isInReactHookDeps ( node ) {
204+ const hookNode = isInReactHooks ( node , true )
187205 if ( ! hookNode ) {
188206 return false
189207 }
@@ -271,3 +289,55 @@ function flattenMemberExpression(expr, key = '') {
271289 return path
272290 }
273291}
292+
293+ export function isDepthSameAsRootComponent ( node ) {
294+ const varDef = getParentOfNodeType ( node , 'VariableDeclaration' )
295+ const parentNormalFunc = getParentOfNodeType ( varDef , 'FunctionDeclaration' )
296+ const parentArrFunc = getParentOfNodeType ( varDef , 'ArrowFunctionExpression' )
297+
298+ const parentFunc = parentNormalFunc || parentArrFunc
299+ if ( ! parentFunc ) {
300+ return false
301+ }
302+
303+ if (
304+ parentFunc ?. parent . type === 'VariableDeclarator' &&
305+ parentFunc ?. parent . parent . type === 'VariableDeclaration' &&
306+ parentFunc ?. parent . parent . parent . type === 'Program'
307+ ) {
308+ return true
309+ }
310+ }
311+
312+ export function isInCustomHookDef ( node ) {
313+ const nearestReturn = getParentOfNodeType ( node , 'ReturnStatement' )
314+ const returnInBlock = getParentOfNodeType ( nearestReturn , 'BlockStatement' )
315+ const normalFuncDef = getParentOfNodeType (
316+ returnInBlock ,
317+ 'ArrowFunctionExpression'
318+ )
319+ const arrowFuncDef = getParentOfNodeType ( returnInBlock , 'FunctionExpression' )
320+
321+ const nearestFuncDef = normalFuncDef || arrowFuncDef || false
322+
323+ if ( ! nearestFuncDef ) {
324+ return false
325+ }
326+
327+ const varDeclaratorOfFunc = getParentOfNodeType (
328+ nearestFuncDef ,
329+ 'VariableDeclarator'
330+ )
331+ const varDefOfFunc = getParentOfNodeType (
332+ varDeclaratorOfFunc ,
333+ 'VariableDeclaration'
334+ )
335+
336+ const varDefOnRoot = varDefOfFunc . parent ?. type === 'Program' || false
337+
338+ return (
339+ varDefOnRoot &&
340+ varDeclaratorOfFunc . id ?. type === 'Identifier' &&
341+ varDeclaratorOfFunc . id ?. name . startsWith ( 'use' )
342+ )
343+ }
0 commit comments