Skip to content
Open
75 changes: 75 additions & 0 deletions src/auto-hmr/ast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type { AstNode } from 'rollup'
import type { VariableDeclarator, ImportDeclaration } from 'estree'

export function nameFromDeclaration(node?: VariableDeclarator) {
return node?.id.type === 'Identifier' ? node.id.name : ''
}

export function getRouterDeclaration(nodes?: VariableDeclarator[]) {
return nodes?.find(
(x) =>
x.init?.type === 'CallExpression' &&
x.init.callee.type === 'Identifier' &&
(x.init.callee.name === 'createRouter' ||
x.init.callee.name === 'experimental_createRouter')
)
}

export function getHandleHotUpdateDeclaration(node?: ImportDeclaration, modulePath?: string) {
return (
node?.type === 'ImportDeclaration' &&
node.source.value === modulePath &&
node.specifiers.some(
(x) =>
x.type === 'ImportSpecifier' &&
x.imported.type === 'Identifier' &&
x.imported.name === 'handleHotUpdate'
)
)
}

export function hasHandleHotUpdateCall(ast: AstNode) {
const visited = new WeakSet()

function traverse(node: any) {
if (!node || typeof node !== 'object' || visited.has(node)) return false
visited.add(node)

if (
node.type === 'CallExpression' &&
node.callee.type === 'Identifier' &&
node.callee.name === 'handleHotUpdate'
) {
return true
}

// e.g.: autoRouter.handleHotUpdate()
if (
node.type === 'CallExpression' &&
node.callee.type === 'MemberExpression' &&
node.callee.property.type === 'Identifier' &&
node.callee.property.name === 'handleHotUpdate'
) {
return true
}

if (typeof node !== 'object') return false

for (const key in node) {
if (key === 'type' || key === 'loc' || key === 'range') continue

const child = node[key]
if (Array.isArray(child)) {
for (const item of child) {
if (traverse(item)) return true
}
} else if (typeof child === 'object' && child !== null) {
if (traverse(child)) return true
}
}

return false
}

return traverse(ast);
}
Loading