getMembers.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. /**
  2. * Given a "nested" Member/CallExpression, e.g.
  3. *
  4. * foo.bar()[baz][42]
  5. *
  6. * this returns a list of "members". In this example it would be something like
  7. * [
  8. * {path: NodePath<bar>, arguments: NodePath<empty>, computed: false},
  9. * {path: NodePath<baz>, arguments: null, computed: true},
  10. * {path: NodePath<42>, arguments: null, computed: false}
  11. * ]
  12. */
  13. export default function getMembers(path, includeRoot = false) {
  14. const result = [];
  15. let argumentPaths = [];
  16. let resultPath = path;
  17. // eslint-disable-next-line no-constant-condition
  18. while (true) {
  19. if (resultPath.isMemberExpression()) {
  20. const property = resultPath.get('property');
  21. result.push({
  22. path: property,
  23. computed: resultPath.node.computed,
  24. argumentPaths,
  25. });
  26. argumentPaths = [];
  27. resultPath = resultPath.get('object');
  28. }
  29. else if (resultPath.isCallExpression()) {
  30. const callee = resultPath.get('callee');
  31. if (callee.isExpression()) {
  32. argumentPaths = resultPath.get('arguments');
  33. resultPath = callee;
  34. }
  35. else {
  36. break;
  37. }
  38. }
  39. else {
  40. break;
  41. }
  42. }
  43. if (includeRoot && result.length > 0) {
  44. result.push({
  45. path: resultPath,
  46. computed: false,
  47. argumentPaths,
  48. });
  49. }
  50. return result.reverse();
  51. }