member-expr.js 2.1 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
const t = require('@babel/types')

function isMatch (name, forItem, forIndex) {
  return name === forItem || name === forIndex
}

function getIdentifierName (element) {
  if (t.isMemberExpression(element)) {
    return getIdentifierName(element.object)
  } else if (t.isCallExpression(element)) {
    return getIdentifierName(element.callee)
  }
  return element.name && element.name.split('.')[0]
}

function findScoped (path, state) {
  if (!path) {
    return state
  }
  const scoped = state.scoped.find(scoped => {
    const {
      forItem,
      forIndex
    } = scoped
    let match = false
    if (path.isIdentifier() || path.isMemberExpression()) {
      match = isMatch(getIdentifierName(path.node), forItem, forIndex)
    } else {
      path.traverse({
        noScope: true,
        Identifier (path) {
          if (!match) {
            match = isMatch(path.node.name, forItem, forIndex)
            if (match) {
              path.stop()
            }
          }
        },
        MemberExpression (path) {
          if (!match) {
            match = isMatch(getIdentifierName(path.node), forItem, forIndex)
            if (match) {
              path.stop()
            }
            path.skip()
          }
        }
      })
    }
    return match
  })
  if (!scoped && state.scoped.length > 1) {
    return state.scoped[1] // 取父
  }
  return scoped || state
}

module.exports = function getMemberExpr (path, name, init, state, variableDeclaration = true) {
  const scoped = findScoped(path, state)

  if (!variableDeclaration) {
    scoped.declarationArray.push(t.expressionStatement(init))
    return
  }

  const identifier = t.identifier(name)

  scoped.propertyArray.push(t.objectProperty(identifier, identifier))
  scoped.declarationArray.push(
    t.variableDeclaration('var', [t.variableDeclarator(identifier, init)])
  )

  state.identifierArray.push(identifier)

  const contextIdentifier = t.identifier(scoped.context)
  contextIdentifier.$mpProcessed = true
  return t.memberExpression(contextIdentifier, identifier)
}