All files / src/utils getMemberExpressionValuePath.js

90.32% Statements 28/31
87.5% Branches 21/24
100% Functions 3/3
90.32% Lines 28/31
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                                11x     27x 9x 9x             9x 9x     18x 7x     11x       11x 1x     10x                     27x 27x 21x   27x             27x 27x   27x     1x       26x   56x 56x       56x         24x 24x     32x       26x    
/*
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 *
 */
 
import getNameOrValue from './getNameOrValue';
import { String as toString } from './expressionTo';
import recast from 'recast';
 
var {types: {namedTypes: types}} = recast;
 
function resolveName(path) {
  if (types.VariableDeclaration.check(path.node)) {
    var declarations = path.get('declarations');
    Iif (declarations.value.length && declarations.value.length !== 1) {
      throw new TypeError(
        'Got unsupported VariableDeclaration. VariableDeclaration must only ' +
        'have a single VariableDeclarator. Got ' + declarations.value.length +
        ' declarations.'
      );
    }
    var value = declarations.get(0, 'id', 'name').value;
    return value;
  }
 
  if (types.FunctionDeclaration.check(path.node)) {
    return path.get('id', 'name').value;
  }
 
  Eif (
    types.FunctionExpression.check(path.node) ||
    types.ArrowFunctionExpression.check(path.node)
  ) {
    if (!types.VariableDeclarator.check(path.parent.node)) {
      return; // eslint-disable-line consistent-return
    }
 
    return path.parent.get('id', 'name').value;
  }
 
  throw new TypeError(
    'Attempted to resolveName for an unsupported path. resolveName accepts a ' +
    'VariableDeclaration, FunctionDeclaration, or FunctionExpression. Got "' +
    path.node.type + '".'
  );
}
 
function getRoot(node) {
  var root = node.parent;
  while (root.parent) {
    root = root.parent;
  }
  return root;
}
 
export default function getMemberExpressionValuePath(
  variableDefinition: NodePath,
  memberName: string
): ?NodePath {
  var localName = resolveName(variableDefinition);
  var program = getRoot(variableDefinition);
 
  if (!localName) {
    // likely an immediately exported and therefore nameless/anonymous node
    // passed in
    return;
  }
 
  var result;
  recast.visit(program, {
    visitAssignmentExpression(path) {
      var memberPath = path.get('left');
      Iif (!types.MemberExpression.check(memberPath.node)) {
        return this.traverse(path);
      }
 
      if (
        (!memberPath.node.computed || types.Literal.check(memberPath.node.property)) &&
        getNameOrValue(memberPath.get('property')) === memberName &&
        toString(memberPath.get('object')) === localName
      ) {
        result = path.get('right');
        return false;
      }
 
      this.traverse(memberPath);
    },
  });
 
  return result; // eslint-disable-line consistent-return
}