All files / src/utils getMembers.js

100% Statements 17/17
100% Branches 8/8
100% Functions 1/1
100% Lines 16/16
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                                                    9x                                   116x 116x 116x 252x   114x         114x 114x 114x   22x 22x 22x   116x     116x 28x           116x    
/*
 * 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
 *
 */
 
/*eslint no-labels: 0*/
 
/**
 * Helper methods for dealing with MemberExpressions (and CallExpressions).
 */
 
type MemberDescriptor = { // eslint-disable-line no-undef
  path: NodePath;
  computed: boolean;
  argumentsPath?: ?NodePath;
}
 
import recast from 'recast';
 
var {types: {namedTypes: types}} = recast;
 
/**
 * Given a "nested" Member/CallExpression, e.g.
 *
 * foo.bar()[baz][42]
 *
 * this returns a list of "members". In this example it would be something like
 * [
 *   {path: NodePath<bar>, arguments: NodePath<empty>, computed: false},
 *   {path: NodePath<baz>, arguments: null, computed: true},
 *   {path: NodePath<42>, arguments: null, computed: false}
 * ]
 */
export default function getMembers(
  path: NodePath,
  includeRoot: bool = false
): Array<MemberDescriptor> {
  var result = [];
  var argumentsPath = null;
  loop: while(true) { // eslint-disable-line no-constant-condition
    switch (true) {
      case types.MemberExpression.check(path.node):
        result.push({
          path: path.get('property'),
          computed: path.node.computed,
          argumentsPath: argumentsPath,
        });
        argumentsPath = null;
        path = path.get('object');
        break;
      case types.CallExpression.check(path.node):
        argumentsPath = path.get('arguments');
        path = path.get('callee');
        break;
      default:
        break loop;
    }
  }
  if (includeRoot && result.length > 0) {
    result.push({
      path,
      computed: false,
      argumentsPath,
    });
  }
  return result.reverse();
}