no-debugging-utils.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.RULE_NAME = void 0;
  4. const utils_1 = require("@typescript-eslint/utils");
  5. const create_testing_library_rule_1 = require("../create-testing-library-rule");
  6. const node_utils_1 = require("../node-utils");
  7. const utils_2 = require("../utils");
  8. exports.RULE_NAME = 'no-debugging-utils';
  9. exports.default = (0, create_testing_library_rule_1.createTestingLibraryRule)({
  10. name: exports.RULE_NAME,
  11. meta: {
  12. type: 'problem',
  13. docs: {
  14. description: 'Disallow the use of debugging utilities like `debug`',
  15. recommendedConfig: {
  16. dom: false,
  17. angular: 'error',
  18. react: 'error',
  19. vue: 'error',
  20. marko: 'error',
  21. },
  22. },
  23. messages: {
  24. noDebug: 'Unexpected debug statement',
  25. },
  26. schema: [
  27. {
  28. type: 'object',
  29. properties: {
  30. utilsToCheckFor: {
  31. type: 'object',
  32. properties: utils_2.DEBUG_UTILS.reduce((obj, name) => (Object.assign({ [name]: { type: 'boolean' } }, obj)), {}),
  33. additionalProperties: false,
  34. },
  35. },
  36. additionalProperties: false,
  37. },
  38. ],
  39. },
  40. defaultOptions: [
  41. { utilsToCheckFor: { debug: true, logTestingPlaygroundURL: true } },
  42. ],
  43. create(context, [{ utilsToCheckFor = {} }], helpers) {
  44. const suspiciousDebugVariableNames = [];
  45. const suspiciousReferenceNodes = [];
  46. const renderWrapperNames = [];
  47. const builtInConsoleNodes = [];
  48. const utilsToReport = Object.entries(utilsToCheckFor)
  49. .filter(([, shouldCheckFor]) => shouldCheckFor)
  50. .map(([name]) => name);
  51. function detectRenderWrapper(node) {
  52. const innerFunction = (0, node_utils_1.getInnermostReturningFunction)(context, node);
  53. if (innerFunction) {
  54. renderWrapperNames.push((0, node_utils_1.getFunctionName)(innerFunction));
  55. }
  56. }
  57. return {
  58. VariableDeclarator(node) {
  59. if (!node.init) {
  60. return;
  61. }
  62. const initIdentifierNode = (0, node_utils_1.getDeepestIdentifierNode)(node.init);
  63. if (!initIdentifierNode) {
  64. return;
  65. }
  66. if (initIdentifierNode.name === 'console') {
  67. builtInConsoleNodes.push(node);
  68. return;
  69. }
  70. const isRenderWrapperVariableDeclarator = renderWrapperNames.includes(initIdentifierNode.name);
  71. if (!helpers.isRenderVariableDeclarator(node) &&
  72. !isRenderWrapperVariableDeclarator) {
  73. return;
  74. }
  75. if ((0, node_utils_1.isObjectPattern)(node.id)) {
  76. for (const property of node.id.properties) {
  77. if ((0, node_utils_1.isProperty)(property) &&
  78. utils_1.ASTUtils.isIdentifier(property.key) &&
  79. utilsToReport.includes(property.key.name)) {
  80. const identifierNode = (0, node_utils_1.getDeepestIdentifierNode)(property.value);
  81. if (identifierNode) {
  82. suspiciousDebugVariableNames.push(identifierNode.name);
  83. }
  84. }
  85. }
  86. }
  87. if (utils_1.ASTUtils.isIdentifier(node.id)) {
  88. suspiciousReferenceNodes.push(node.id);
  89. }
  90. },
  91. CallExpression(node) {
  92. const callExpressionIdentifier = (0, node_utils_1.getDeepestIdentifierNode)(node);
  93. if (!callExpressionIdentifier) {
  94. return;
  95. }
  96. if (helpers.isRenderUtil(callExpressionIdentifier)) {
  97. detectRenderWrapper(callExpressionIdentifier);
  98. }
  99. const referenceNode = (0, node_utils_1.getReferenceNode)(node);
  100. const referenceIdentifier = (0, node_utils_1.getPropertyIdentifierNode)(referenceNode);
  101. if (!referenceIdentifier) {
  102. return;
  103. }
  104. const isDebugUtil = helpers.isDebugUtil(callExpressionIdentifier, utilsToReport);
  105. const isDeclaredDebugVariable = suspiciousDebugVariableNames.includes(callExpressionIdentifier.name);
  106. const isChainedReferenceDebug = suspiciousReferenceNodes.some((suspiciousReferenceIdentifier) => {
  107. return (utilsToReport.includes(callExpressionIdentifier.name) &&
  108. suspiciousReferenceIdentifier.name === referenceIdentifier.name);
  109. });
  110. const isVariableFromBuiltInConsole = builtInConsoleNodes.some((variableDeclarator) => {
  111. const variables = context.getDeclaredVariables(variableDeclarator);
  112. return variables.some(({ name }) => name === callExpressionIdentifier.name &&
  113. (0, node_utils_1.isCallExpression)(callExpressionIdentifier.parent));
  114. });
  115. if (!isVariableFromBuiltInConsole &&
  116. (isDebugUtil || isDeclaredDebugVariable || isChainedReferenceDebug)) {
  117. context.report({
  118. node: callExpressionIdentifier,
  119. messageId: 'noDebug',
  120. });
  121. }
  122. },
  123. };
  124. },
  125. });