function extractFromExpression(node, withInTemplate) {
    const ref = cacheForExpression.get(node)
    if (ref) {
      return ref
    }
    cacheForExpression.set(node, ANY)
    const result = extractWithoutCache()
    cacheForExpression.set(node, result)
    return result

    function extractWithoutCache() {
      const parent = node.parent
      switch (parent.type) {
        case 'AssignmentExpression': {
          // `({foo} = arg)`
          return !withInTemplate &&
            parent.right === node &&
            parent.operator === '='
            ? extractFromPattern(parent.left)
            : NEVER
        }
        case 'VariableDeclarator': {
          // `const {foo} = arg`
          // `const foo = arg`
          return !withInTemplate && parent.init === node
            ? extractFromPattern(parent.id)
            : NEVER
        }
        case 'MemberExpression': {
          if (parent.object === node) {
            // `arg.foo`
            const name = utils.getStaticPropertyName(parent)

            if (
              name === '$props' &&
              parent.parent.type === 'MemberExpression'
            ) {
              // `$props.arg`
              const propName = utils.getStaticPropertyName(parent.parent)

              if (!propName) return unknownMemberAsUnreferenced ? NEVER : ANY

              return new PropertyReferencesForMember(
                parent.parent,
                propName,
                withInTemplate
              )
            } else if (name) {
              return new PropertyReferencesForMember(
                parent,
                name,
                withInTemplate
              )
            } else {
              return unknownMemberAsUnreferenced ? NEVER : ANY
            }
          }
          return NEVER
        }
        case 'CallExpression': {
          const argIndex = parent.arguments.indexOf(node)
          // `foo(arg)`
          return !withInTemplate && argIndex !== -1
            ? extractFromCall(parent, argIndex)
            : NEVER
        }
        case 'ChainExpression': {
          return extractFromExpression(parent, withInTemplate)
        }
        case 'ArrowFunctionExpression':
        case 'VExpressionContainer':
        case 'Property':
        case 'ArrayExpression': {
          return maybeExternalUsed(parent) ? ANY : NEVER
        }
        case 'ReturnStatement': {
          if (returnAsUnreferenced) {
            return NEVER
          } else {
            return maybeExternalUsed(parent) ? ANY : NEVER
          }
        }
      }
      return NEVER
    }

    /**
     * @param {ASTNode} parentTarget
     * @returns {boolean}
     */
    function maybeExternalUsed(parentTarget) {
      if (
        parentTarget.type === 'ReturnStatement' ||
        parentTarget.type === 'VExpressionContainer'
      ) {
        return true
      }
      if (parentTarget.type === 'ArrayExpression') {
        return maybeExternalUsed(parentTarget.parent)
      }
      if (parentTarget.type === 'Property') {
        return maybeExternalUsed(parentTarget.parent.parent)
      }
      if (parentTarget.type === 'ArrowFunctionExpression') {
        return parentTarget.body === node
      }
      return false
    }
  }
Extract the property references from Expression.
@param {Identifier | MemberExpression | ChainExpression | ThisExpression | CallExpression} node
@param {boolean} withInTemplate
@returns {IPropertyReferences}