no-undef-init.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /**
  2. * @fileoverview Rule to flag when initializing to undefined
  3. * @author Ilya Volodin
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Requirements
  8. //------------------------------------------------------------------------------
  9. const astUtils = require("./utils/ast-utils");
  10. //------------------------------------------------------------------------------
  11. // Helpers
  12. //------------------------------------------------------------------------------
  13. const CONSTANT_BINDINGS = new Set(["const", "using", "await using"]);
  14. //------------------------------------------------------------------------------
  15. // Rule Definition
  16. //------------------------------------------------------------------------------
  17. /** @type {import('../types').Rule.RuleModule} */
  18. module.exports = {
  19. meta: {
  20. type: "suggestion",
  21. docs: {
  22. description: "Disallow initializing variables to `undefined`",
  23. recommended: false,
  24. frozen: true,
  25. url: "https://eslint.org/docs/latest/rules/no-undef-init",
  26. },
  27. schema: [],
  28. fixable: "code",
  29. messages: {
  30. unnecessaryUndefinedInit:
  31. "It's not necessary to initialize '{{name}}' to undefined.",
  32. },
  33. },
  34. create(context) {
  35. const sourceCode = context.sourceCode;
  36. return {
  37. VariableDeclarator(node) {
  38. const name = sourceCode.getText(node.id),
  39. init = node.init && node.init.name,
  40. scope = sourceCode.getScope(node),
  41. undefinedVar = astUtils.getVariableByName(
  42. scope,
  43. "undefined",
  44. ),
  45. shadowed = undefinedVar && undefinedVar.defs.length > 0,
  46. lastToken = sourceCode.getLastToken(node);
  47. if (
  48. init === "undefined" &&
  49. !CONSTANT_BINDINGS.has(node.parent.kind) &&
  50. !shadowed
  51. ) {
  52. context.report({
  53. node,
  54. messageId: "unnecessaryUndefinedInit",
  55. data: { name },
  56. fix(fixer) {
  57. if (node.parent.kind === "var") {
  58. return null;
  59. }
  60. if (
  61. node.id.type === "ArrayPattern" ||
  62. node.id.type === "ObjectPattern"
  63. ) {
  64. // Don't fix destructuring assignment to `undefined`.
  65. return null;
  66. }
  67. if (
  68. sourceCode.commentsExistBetween(
  69. node.id,
  70. lastToken,
  71. )
  72. ) {
  73. return null;
  74. }
  75. return fixer.removeRange([
  76. node.id.range[1],
  77. node.range[1],
  78. ]);
  79. },
  80. });
  81. }
  82. },
  83. };
  84. },
  85. };