getFunctionNameWithKind.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**
  2. * Determines whether the given node is a `null` literal.
  3. * @param {ASTNode} node The node to check
  4. * @returns {boolean} `true` if the node is a `null` literal
  5. */
  6. function isNullLiteral(node) {
  7. /*
  8. * Checking `node.value === null` does not guarantee that a literal is a null literal.
  9. * When parsing values that cannot be represented in the current environment (e.g. unicode
  10. * regexes in Node 4), `node.value` is set to `null` because it wouldn't be possible to
  11. * set `node.value` to a unicode regex. To make sure a literal is actually `null`, check
  12. * `node.regex` instead. Also see: https://github.com/eslint/eslint/issues/8020
  13. */
  14. return node.type === "Literal" && node.value === null && !node.regex && !node.bigint;
  15. }
  16. /**
  17. * Returns the result of the string conversion applied to the evaluated value of the given expression node,
  18. * if it can be determined statically.
  19. *
  20. * This function returns a `string` value for all `Literal` nodes and simple `TemplateLiteral` nodes only.
  21. * In all other cases, this function returns `null`.
  22. * @param {ASTNode} node Expression node.
  23. * @returns {string|null} String value if it can be determined. Otherwise, `null`.
  24. */
  25. function getStaticStringValue(node) {
  26. switch (node.type) {
  27. case "Literal":
  28. if (node.value === null) {
  29. if (isNullLiteral(node)) {
  30. return String(node.value); // "null"
  31. }
  32. if (node.regex) {
  33. return `/${node.regex.pattern}/${node.regex.flags}`;
  34. }
  35. if (node.bigint) {
  36. return node.bigint;
  37. }
  38. // Otherwise, this is an unknown literal. The function will return null.
  39. } else {
  40. return String(node.value);
  41. }
  42. break;
  43. case "TemplateLiteral":
  44. if (node.expressions.length === 0 && node.quasis.length === 1) {
  45. return node.quasis[0].value.cooked;
  46. }
  47. break;
  48. // no default
  49. }
  50. return null;
  51. }
  52. function getStaticPropertyName(node) {
  53. let prop;
  54. switch (node && node.type) {
  55. case "ChainExpression":
  56. return getStaticPropertyName(node.expression);
  57. case "Property":
  58. case "MethodDefinition":
  59. prop = node.key;
  60. break;
  61. case "MemberExpression":
  62. prop = node.property;
  63. break;
  64. // no default
  65. }
  66. if (prop) {
  67. if (prop.type === "Identifier" && !node.computed) {
  68. return prop.name;
  69. }
  70. return getStaticStringValue(prop);
  71. }
  72. return null;
  73. }
  74. function getFunctionNameWithKind(node) {
  75. const parent = node.parent;
  76. const tokens = [];
  77. if (parent.type === "MethodDefinition" && parent.static) {
  78. tokens.push("static");
  79. }
  80. if (node.async) {
  81. tokens.push("async");
  82. }
  83. if (node.generator) {
  84. tokens.push("generator");
  85. }
  86. if (node.type === "ArrowFunctionExpression") {
  87. tokens.push("arrow", "function");
  88. } else if (parent.type === "Property" || parent.type === "MethodDefinition") {
  89. if (parent.kind === "constructor") {
  90. return "constructor";
  91. }
  92. if (parent.kind === "get") {
  93. tokens.push("getter");
  94. } else if (parent.kind === "set") {
  95. tokens.push("setter");
  96. } else {
  97. tokens.push("method");
  98. }
  99. } else {
  100. tokens.push("function");
  101. }
  102. if (node.id) {
  103. tokens.push(`'${node.id.name}'`);
  104. } else {
  105. const name = getStaticPropertyName(parent);
  106. if (name !== null) {
  107. tokens.push(`'${name}'`);
  108. }
  109. }
  110. return tokens.join(" ");
  111. }
  112. module.exports = getFunctionNameWithKind;