const t = require('@babel/types') const babelTraverse = require('@babel/traverse').default const { METHOD_RENDER_LIST } = require('../constants') function getDataPath (identifier, parent, scope) { if ( !(t.isCallExpression(parent)) && // not id of a Declaration !(t.isDeclaration(parent) && parent.id === identifier) && // not a params of a function !(t.isFunction(parent) && parent.params.indexOf(identifier) > -1) && // not a key of Property !(parent.type === 'ObjectProperty' && parent.key === identifier && !parent.computed) && // not in an Array destructure pattern !(parent.type === 'ArrayPattern') && // not in an Object destructure pattern !(parent.parent && parent.parent.type === 'ObjectPattern') && // not already in scope !scope.hasBinding(identifier.name) ) { return identifier.name } } function getDataPathByMemberExpression (node, ret) { if (t.isMemberExpression(node.object)) { getDataPathByMemberExpression(node.object, ret) } else if (t.isIdentifier(node.object)) { ret.push(node.object.name) } ret.push(node.property.name || node.property.value) } const visitor = { Identifier (path) { const dataPath = getDataPath(path.node, path.parent, path.scope) if (dataPath) { console.log('....identifier', dataPath) } else { // console.log('....ignore', path.node.name) } }, MemberExpression (path) { const dataPathArray = [] getDataPathByMemberExpression(path.node, dataPathArray) path.skip() }, CallExpression (path) { const callee = path.node.callee if (callee.name === METHOD_RENDER_LIST) { // for // path.skip() } } } module.exports = function traverse (ast, state) { const data = Object.create(null) babelTraverse(ast, visitor, undefined, { data }) }