index.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. var desc = Object.getOwnPropertyDescriptor(m, k);
  5. if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
  6. desc = { enumerable: true, get: function() { return m[k]; } };
  7. }
  8. Object.defineProperty(o, k2, desc);
  9. }) : (function(o, m, k, k2) {
  10. if (k2 === undefined) k2 = k;
  11. o[k2] = m[k];
  12. }));
  13. var __exportStar = (this && this.__exportStar) || function(m, exports) {
  14. for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
  15. };
  16. Object.defineProperty(exports, "__esModule", { value: true });
  17. exports.findImportSpecifier = exports.isEmptyFunction = exports.getStatementCallExpression = exports.hasImportMatch = exports.getInnermostReturningFunction = exports.hasClosestExpectResolvesRejects = exports.getAssertNodeInfo = exports.getImportModuleName = exports.getFunctionName = exports.getReferenceNode = exports.getDeepestIdentifierNode = exports.getPropertyIdentifierNode = exports.getFunctionReturnStatementNode = exports.getInnermostFunctionScope = exports.getVariableReferences = exports.isPromiseHandled = exports.isPromisesArrayResolved = exports.isPromiseAllSettled = exports.isPromiseAll = exports.isPromiseIdentifier = exports.hasChainedThen = exports.hasThenProperty = exports.findClosestCallNode = exports.findClosestVariableDeclaratorNode = exports.findClosestCallExpressionNode = void 0;
  18. const utils_1 = require("@typescript-eslint/utils");
  19. const is_node_of_type_1 = require("./is-node-of-type");
  20. __exportStar(require("./is-node-of-type"), exports);
  21. const ValidLeftHandSideExpressions = [
  22. utils_1.AST_NODE_TYPES.CallExpression,
  23. utils_1.AST_NODE_TYPES.ClassExpression,
  24. utils_1.AST_NODE_TYPES.ClassDeclaration,
  25. utils_1.AST_NODE_TYPES.FunctionExpression,
  26. utils_1.AST_NODE_TYPES.Literal,
  27. utils_1.AST_NODE_TYPES.TemplateLiteral,
  28. utils_1.AST_NODE_TYPES.MemberExpression,
  29. utils_1.AST_NODE_TYPES.ArrayExpression,
  30. utils_1.AST_NODE_TYPES.ArrayPattern,
  31. utils_1.AST_NODE_TYPES.ClassExpression,
  32. utils_1.AST_NODE_TYPES.FunctionExpression,
  33. utils_1.AST_NODE_TYPES.Identifier,
  34. utils_1.AST_NODE_TYPES.JSXElement,
  35. utils_1.AST_NODE_TYPES.JSXFragment,
  36. utils_1.AST_NODE_TYPES.JSXOpeningElement,
  37. utils_1.AST_NODE_TYPES.MetaProperty,
  38. utils_1.AST_NODE_TYPES.ObjectExpression,
  39. utils_1.AST_NODE_TYPES.ObjectPattern,
  40. utils_1.AST_NODE_TYPES.Super,
  41. utils_1.AST_NODE_TYPES.ThisExpression,
  42. utils_1.AST_NODE_TYPES.TSNullKeyword,
  43. utils_1.AST_NODE_TYPES.TaggedTemplateExpression,
  44. utils_1.AST_NODE_TYPES.TSNonNullExpression,
  45. utils_1.AST_NODE_TYPES.TSAsExpression,
  46. utils_1.AST_NODE_TYPES.ArrowFunctionExpression,
  47. ];
  48. function findClosestCallExpressionNode(node, shouldRestrictInnerScope = false) {
  49. if ((0, is_node_of_type_1.isCallExpression)(node)) {
  50. return node;
  51. }
  52. if (!(node === null || node === void 0 ? void 0 : node.parent)) {
  53. return null;
  54. }
  55. if (shouldRestrictInnerScope &&
  56. !ValidLeftHandSideExpressions.includes(node.parent.type)) {
  57. return null;
  58. }
  59. return findClosestCallExpressionNode(node.parent, shouldRestrictInnerScope);
  60. }
  61. exports.findClosestCallExpressionNode = findClosestCallExpressionNode;
  62. function findClosestVariableDeclaratorNode(node) {
  63. if (!node) {
  64. return null;
  65. }
  66. if (utils_1.ASTUtils.isVariableDeclarator(node)) {
  67. return node;
  68. }
  69. return findClosestVariableDeclaratorNode(node.parent);
  70. }
  71. exports.findClosestVariableDeclaratorNode = findClosestVariableDeclaratorNode;
  72. function findClosestCallNode(node, name) {
  73. if (!node.parent) {
  74. return null;
  75. }
  76. if ((0, is_node_of_type_1.isCallExpression)(node) &&
  77. utils_1.ASTUtils.isIdentifier(node.callee) &&
  78. node.callee.name === name) {
  79. return node;
  80. }
  81. else {
  82. return findClosestCallNode(node.parent, name);
  83. }
  84. }
  85. exports.findClosestCallNode = findClosestCallNode;
  86. function hasThenProperty(node) {
  87. return ((0, is_node_of_type_1.isMemberExpression)(node) &&
  88. utils_1.ASTUtils.isIdentifier(node.property) &&
  89. node.property.name === 'then');
  90. }
  91. exports.hasThenProperty = hasThenProperty;
  92. function hasChainedThen(node) {
  93. const parent = node.parent;
  94. if ((0, is_node_of_type_1.isCallExpression)(parent) && parent.parent) {
  95. return hasThenProperty(parent.parent);
  96. }
  97. return !!parent && hasThenProperty(parent);
  98. }
  99. exports.hasChainedThen = hasChainedThen;
  100. function isPromiseIdentifier(node) {
  101. return utils_1.ASTUtils.isIdentifier(node) && node.name === 'Promise';
  102. }
  103. exports.isPromiseIdentifier = isPromiseIdentifier;
  104. function isPromiseAll(node) {
  105. return ((0, is_node_of_type_1.isMemberExpression)(node.callee) &&
  106. isPromiseIdentifier(node.callee.object) &&
  107. utils_1.ASTUtils.isIdentifier(node.callee.property) &&
  108. node.callee.property.name === 'all');
  109. }
  110. exports.isPromiseAll = isPromiseAll;
  111. function isPromiseAllSettled(node) {
  112. return ((0, is_node_of_type_1.isMemberExpression)(node.callee) &&
  113. isPromiseIdentifier(node.callee.object) &&
  114. utils_1.ASTUtils.isIdentifier(node.callee.property) &&
  115. node.callee.property.name === 'allSettled');
  116. }
  117. exports.isPromiseAllSettled = isPromiseAllSettled;
  118. function isPromisesArrayResolved(node) {
  119. const closestCallExpression = findClosestCallExpressionNode(node, true);
  120. if (!closestCallExpression) {
  121. return false;
  122. }
  123. return (!!closestCallExpression.parent &&
  124. (0, is_node_of_type_1.isArrayExpression)(closestCallExpression.parent) &&
  125. (0, is_node_of_type_1.isCallExpression)(closestCallExpression.parent.parent) &&
  126. (isPromiseAll(closestCallExpression.parent.parent) ||
  127. isPromiseAllSettled(closestCallExpression.parent.parent)));
  128. }
  129. exports.isPromisesArrayResolved = isPromisesArrayResolved;
  130. function isPromiseHandled(nodeIdentifier) {
  131. const closestCallExpressionNode = findClosestCallExpressionNode(nodeIdentifier, true);
  132. const suspiciousNodes = [nodeIdentifier, closestCallExpressionNode].filter(Boolean);
  133. for (const node of suspiciousNodes) {
  134. if (!(node === null || node === void 0 ? void 0 : node.parent)) {
  135. continue;
  136. }
  137. if (utils_1.ASTUtils.isAwaitExpression(node.parent)) {
  138. return true;
  139. }
  140. if ((0, is_node_of_type_1.isArrowFunctionExpression)(node.parent) ||
  141. (0, is_node_of_type_1.isReturnStatement)(node.parent)) {
  142. return true;
  143. }
  144. if (hasClosestExpectResolvesRejects(node.parent)) {
  145. return true;
  146. }
  147. if (hasChainedThen(node)) {
  148. return true;
  149. }
  150. if (isPromisesArrayResolved(node)) {
  151. return true;
  152. }
  153. }
  154. return false;
  155. }
  156. exports.isPromiseHandled = isPromiseHandled;
  157. function getVariableReferences(context, node) {
  158. var _a, _b, _c;
  159. if (utils_1.ASTUtils.isVariableDeclarator(node)) {
  160. return (_c = (_b = (_a = context.getDeclaredVariables(node)[0]) === null || _a === void 0 ? void 0 : _a.references) === null || _b === void 0 ? void 0 : _b.slice(1)) !== null && _c !== void 0 ? _c : [];
  161. }
  162. return [];
  163. }
  164. exports.getVariableReferences = getVariableReferences;
  165. function getInnermostFunctionScope(context, asyncQueryNode) {
  166. const innermostScope = utils_1.ASTUtils.getInnermostScope(context.getScope(), asyncQueryNode);
  167. if (innermostScope.type === 'function' &&
  168. utils_1.ASTUtils.isFunction(innermostScope.block)) {
  169. return innermostScope;
  170. }
  171. return null;
  172. }
  173. exports.getInnermostFunctionScope = getInnermostFunctionScope;
  174. function getFunctionReturnStatementNode(functionNode) {
  175. if ((0, is_node_of_type_1.isBlockStatement)(functionNode.body)) {
  176. const returnStatementNode = functionNode.body.body.find((statement) => (0, is_node_of_type_1.isReturnStatement)(statement));
  177. if (!returnStatementNode) {
  178. return null;
  179. }
  180. return returnStatementNode.argument;
  181. }
  182. else if (functionNode.expression) {
  183. return functionNode.body;
  184. }
  185. return null;
  186. }
  187. exports.getFunctionReturnStatementNode = getFunctionReturnStatementNode;
  188. function getPropertyIdentifierNode(node) {
  189. if (utils_1.ASTUtils.isIdentifier(node)) {
  190. return node;
  191. }
  192. if ((0, is_node_of_type_1.isMemberExpression)(node)) {
  193. return getPropertyIdentifierNode(node.object);
  194. }
  195. if ((0, is_node_of_type_1.isCallExpression)(node)) {
  196. return getPropertyIdentifierNode(node.callee);
  197. }
  198. if ((0, is_node_of_type_1.isExpressionStatement)(node)) {
  199. return getPropertyIdentifierNode(node.expression);
  200. }
  201. return null;
  202. }
  203. exports.getPropertyIdentifierNode = getPropertyIdentifierNode;
  204. function getDeepestIdentifierNode(node) {
  205. if (utils_1.ASTUtils.isIdentifier(node)) {
  206. return node;
  207. }
  208. if ((0, is_node_of_type_1.isMemberExpression)(node) && utils_1.ASTUtils.isIdentifier(node.property)) {
  209. return node.property;
  210. }
  211. if ((0, is_node_of_type_1.isCallExpression)(node)) {
  212. return getDeepestIdentifierNode(node.callee);
  213. }
  214. if (utils_1.ASTUtils.isAwaitExpression(node)) {
  215. return getDeepestIdentifierNode(node.argument);
  216. }
  217. return null;
  218. }
  219. exports.getDeepestIdentifierNode = getDeepestIdentifierNode;
  220. function getReferenceNode(node) {
  221. if (node.parent &&
  222. ((0, is_node_of_type_1.isMemberExpression)(node.parent) || (0, is_node_of_type_1.isCallExpression)(node.parent))) {
  223. return getReferenceNode(node.parent);
  224. }
  225. return node;
  226. }
  227. exports.getReferenceNode = getReferenceNode;
  228. function getFunctionName(node) {
  229. var _a, _b;
  230. return ((_b = (_a = utils_1.ASTUtils.getFunctionNameWithKind(node)
  231. .match(/('\w+')/g)) === null || _a === void 0 ? void 0 : _a[0].replace(/'/g, '')) !== null && _b !== void 0 ? _b : '');
  232. }
  233. exports.getFunctionName = getFunctionName;
  234. function getImportModuleName(node) {
  235. if ((0, is_node_of_type_1.isImportDeclaration)(node) && typeof node.source.value === 'string') {
  236. return node.source.value;
  237. }
  238. if ((0, is_node_of_type_1.isCallExpression)(node) &&
  239. (0, is_node_of_type_1.isLiteral)(node.arguments[0]) &&
  240. typeof node.arguments[0].value === 'string') {
  241. return node.arguments[0].value;
  242. }
  243. return undefined;
  244. }
  245. exports.getImportModuleName = getImportModuleName;
  246. function getAssertNodeInfo(node) {
  247. const emptyInfo = { matcher: null, isNegated: false };
  248. if (!(0, is_node_of_type_1.isCallExpression)(node.object) ||
  249. !utils_1.ASTUtils.isIdentifier(node.object.callee)) {
  250. return emptyInfo;
  251. }
  252. if (node.object.callee.name !== 'expect') {
  253. return emptyInfo;
  254. }
  255. let matcher = utils_1.ASTUtils.getPropertyName(node);
  256. const isNegated = matcher === 'not';
  257. if (isNegated) {
  258. matcher =
  259. node.parent && (0, is_node_of_type_1.isMemberExpression)(node.parent)
  260. ? utils_1.ASTUtils.getPropertyName(node.parent)
  261. : null;
  262. }
  263. if (!matcher) {
  264. return emptyInfo;
  265. }
  266. return { matcher, isNegated };
  267. }
  268. exports.getAssertNodeInfo = getAssertNodeInfo;
  269. const matcherNamesHandlePromise = [
  270. 'resolves',
  271. 'rejects',
  272. 'toResolve',
  273. 'toReject',
  274. ];
  275. function hasClosestExpectResolvesRejects(node) {
  276. if ((0, is_node_of_type_1.isCallExpression)(node) &&
  277. utils_1.ASTUtils.isIdentifier(node.callee) &&
  278. node.parent &&
  279. (0, is_node_of_type_1.isMemberExpression)(node.parent) &&
  280. node.callee.name === 'expect') {
  281. const expectMatcher = node.parent.property;
  282. return (utils_1.ASTUtils.isIdentifier(expectMatcher) &&
  283. matcherNamesHandlePromise.includes(expectMatcher.name));
  284. }
  285. if (!node.parent) {
  286. return false;
  287. }
  288. return hasClosestExpectResolvesRejects(node.parent);
  289. }
  290. exports.hasClosestExpectResolvesRejects = hasClosestExpectResolvesRejects;
  291. function getInnermostReturningFunction(context, node) {
  292. const functionScope = getInnermostFunctionScope(context, node);
  293. if (!functionScope) {
  294. return undefined;
  295. }
  296. const returnStatementNode = getFunctionReturnStatementNode(functionScope.block);
  297. if (!returnStatementNode) {
  298. return undefined;
  299. }
  300. const returnStatementIdentifier = getDeepestIdentifierNode(returnStatementNode);
  301. if ((returnStatementIdentifier === null || returnStatementIdentifier === void 0 ? void 0 : returnStatementIdentifier.name) !== node.name) {
  302. return undefined;
  303. }
  304. return functionScope.block;
  305. }
  306. exports.getInnermostReturningFunction = getInnermostReturningFunction;
  307. function hasImportMatch(importNode, identifierName) {
  308. if (utils_1.ASTUtils.isIdentifier(importNode)) {
  309. return importNode.name === identifierName;
  310. }
  311. return importNode.local.name === identifierName;
  312. }
  313. exports.hasImportMatch = hasImportMatch;
  314. function getStatementCallExpression(statement) {
  315. if ((0, is_node_of_type_1.isExpressionStatement)(statement)) {
  316. const { expression } = statement;
  317. if ((0, is_node_of_type_1.isCallExpression)(expression)) {
  318. return expression;
  319. }
  320. if (utils_1.ASTUtils.isAwaitExpression(expression) &&
  321. (0, is_node_of_type_1.isCallExpression)(expression.argument)) {
  322. return expression.argument;
  323. }
  324. if ((0, is_node_of_type_1.isAssignmentExpression)(expression)) {
  325. if ((0, is_node_of_type_1.isCallExpression)(expression.right)) {
  326. return expression.right;
  327. }
  328. if (utils_1.ASTUtils.isAwaitExpression(expression.right) &&
  329. (0, is_node_of_type_1.isCallExpression)(expression.right.argument)) {
  330. return expression.right.argument;
  331. }
  332. }
  333. }
  334. if ((0, is_node_of_type_1.isReturnStatement)(statement) && (0, is_node_of_type_1.isCallExpression)(statement.argument)) {
  335. return statement.argument;
  336. }
  337. if ((0, is_node_of_type_1.isVariableDeclaration)(statement)) {
  338. for (const declaration of statement.declarations) {
  339. if ((0, is_node_of_type_1.isCallExpression)(declaration.init)) {
  340. return declaration.init;
  341. }
  342. }
  343. }
  344. return undefined;
  345. }
  346. exports.getStatementCallExpression = getStatementCallExpression;
  347. function isEmptyFunction(node) {
  348. if (utils_1.ASTUtils.isFunction(node) && (0, is_node_of_type_1.isBlockStatement)(node.body)) {
  349. return node.body.body.length === 0;
  350. }
  351. return false;
  352. }
  353. exports.isEmptyFunction = isEmptyFunction;
  354. function findImportSpecifier(specifierName, node) {
  355. if ((0, is_node_of_type_1.isImportDeclaration)(node)) {
  356. const namedExport = node.specifiers.find((n) => {
  357. return ((0, is_node_of_type_1.isImportSpecifier)(n) &&
  358. [n.imported.name, n.local.name].includes(specifierName));
  359. });
  360. if (namedExport) {
  361. return namedExport;
  362. }
  363. return node.specifiers.find((n) => (0, is_node_of_type_1.isImportNamespaceSpecifier)(n));
  364. }
  365. else {
  366. if (!utils_1.ASTUtils.isVariableDeclarator(node.parent)) {
  367. return undefined;
  368. }
  369. const requireNode = node.parent;
  370. if (utils_1.ASTUtils.isIdentifier(requireNode.id)) {
  371. return requireNode.id;
  372. }
  373. if (!(0, is_node_of_type_1.isObjectPattern)(requireNode.id)) {
  374. return undefined;
  375. }
  376. const property = requireNode.id.properties.find((n) => (0, is_node_of_type_1.isProperty)(n) &&
  377. utils_1.ASTUtils.isIdentifier(n.key) &&
  378. n.key.name === specifierName);
  379. if (!property) {
  380. return undefined;
  381. }
  382. return property.key;
  383. }
  384. }
  385. exports.findImportSpecifier = findImportSpecifier;