prefer-to-be.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _experimentalUtils = require("@typescript-eslint/experimental-utils");
  7. var _utils = require("./utils");
  8. const isNullLiteral = node => node.type === _experimentalUtils.AST_NODE_TYPES.Literal && node.value === null;
  9. /**
  10. * Checks if the given `ParsedEqualityMatcherCall` is a call to one of the equality matchers,
  11. * with a `null` literal as the sole argument.
  12. */
  13. const isNullEqualityMatcher = matcher => isNullLiteral(getFirstArgument(matcher));
  14. const isFirstArgumentIdentifier = (matcher, name) => (0, _utils.isIdentifier)(getFirstArgument(matcher), name);
  15. const shouldUseToBe = matcher => {
  16. const firstArg = getFirstArgument(matcher);
  17. if (firstArg.type === _experimentalUtils.AST_NODE_TYPES.Literal) {
  18. // regex literals are classed as literals, but they're actually objects
  19. // which means "toBe" will give different results than other matchers
  20. return !('regex' in firstArg);
  21. }
  22. return firstArg.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral;
  23. };
  24. const getFirstArgument = matcher => {
  25. return (0, _utils.followTypeAssertionChain)(matcher.arguments[0]);
  26. };
  27. const reportPreferToBe = (context, whatToBe, matcher, modifier) => {
  28. const modifierNode = (modifier === null || modifier === void 0 ? void 0 : modifier.negation) || (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not && (modifier === null || modifier === void 0 ? void 0 : modifier.node);
  29. context.report({
  30. messageId: `useToBe${whatToBe}`,
  31. fix(fixer) {
  32. var _matcher$arguments;
  33. const fixes = [fixer.replaceText(matcher.node.property, `toBe${whatToBe}`)];
  34. if ((_matcher$arguments = matcher.arguments) !== null && _matcher$arguments !== void 0 && _matcher$arguments.length && whatToBe !== '') {
  35. fixes.push(fixer.remove(matcher.arguments[0]));
  36. }
  37. if (modifierNode) {
  38. fixes.push(fixer.removeRange([modifierNode.property.range[0] - 1, modifierNode.property.range[1]]));
  39. }
  40. return fixes;
  41. },
  42. node: matcher.node.property
  43. });
  44. };
  45. var _default = (0, _utils.createRule)({
  46. name: __filename,
  47. meta: {
  48. docs: {
  49. category: 'Best Practices',
  50. description: 'Suggest using `toBe()` for primitive literals',
  51. recommended: false
  52. },
  53. messages: {
  54. useToBe: 'Use `toBe` when expecting primitive literals',
  55. useToBeUndefined: 'Use `toBeUndefined` instead',
  56. useToBeDefined: 'Use `toBeDefined` instead',
  57. useToBeNull: 'Use `toBeNull` instead',
  58. useToBeNaN: 'Use `toBeNaN` instead'
  59. },
  60. fixable: 'code',
  61. type: 'suggestion',
  62. schema: []
  63. },
  64. defaultOptions: [],
  65. create(context) {
  66. return {
  67. CallExpression(node) {
  68. if (!(0, _utils.isExpectCall)(node)) {
  69. return;
  70. }
  71. const {
  72. matcher,
  73. modifier
  74. } = (0, _utils.parseExpectCall)(node);
  75. if (!matcher) {
  76. return;
  77. }
  78. if (((modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation) && ['toBeUndefined', 'toBeDefined'].includes(matcher.name)) {
  79. reportPreferToBe(context, matcher.name === 'toBeDefined' ? 'Undefined' : 'Defined', matcher, modifier);
  80. return;
  81. }
  82. if (!(0, _utils.isParsedEqualityMatcherCall)(matcher)) {
  83. return;
  84. }
  85. if (isNullEqualityMatcher(matcher)) {
  86. reportPreferToBe(context, 'Null', matcher);
  87. return;
  88. }
  89. if (isFirstArgumentIdentifier(matcher, 'undefined')) {
  90. const name = (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation ? 'Defined' : 'Undefined';
  91. reportPreferToBe(context, name, matcher, modifier);
  92. return;
  93. }
  94. if (isFirstArgumentIdentifier(matcher, 'NaN')) {
  95. reportPreferToBe(context, 'NaN', matcher);
  96. return;
  97. }
  98. if (shouldUseToBe(matcher) && matcher.name !== _utils.EqualityMatcher.toBe) {
  99. reportPreferToBe(context, '', matcher);
  100. }
  101. }
  102. };
  103. }
  104. });
  105. exports.default = _default;