lazy-loading-rule-map.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /**
  2. * @fileoverview `Map` to load rules lazily.
  3. * @author Toru Nagashima <https://github.com/mysticatea>
  4. */
  5. "use strict";
  6. const debug = require("debug")("eslint:rules");
  7. /** @typedef {import("./types").Rule} Rule */
  8. /**
  9. * The `Map` object that loads each rule when it's accessed.
  10. * @example
  11. * const rules = new LazyLoadingRuleMap([
  12. * ["eqeqeq", () => require("eqeqeq")],
  13. * ["semi", () => require("semi")],
  14. * ["no-unused-vars", () => require("no-unused-vars")],
  15. * ])
  16. *
  17. * rules.get("semi") // call `() => require("semi")` here.
  18. *
  19. * @extends {Map<string, () => Rule>}
  20. */
  21. class LazyLoadingRuleMap extends Map {
  22. /**
  23. * Initialize this map.
  24. * @param {Array<[string, function(): Rule]>} loaders The rule loaders.
  25. */
  26. constructor(loaders) {
  27. let remaining = loaders.length;
  28. super(
  29. debug.enabled
  30. ? loaders.map(([ruleId, load]) => {
  31. let cache = null;
  32. return [
  33. ruleId,
  34. () => {
  35. if (!cache) {
  36. debug("Loading rule %o (remaining=%d)", ruleId, --remaining);
  37. cache = load();
  38. }
  39. return cache;
  40. }
  41. ];
  42. })
  43. : loaders
  44. );
  45. // `super(...iterable)` uses `this.set()`, so disable it here.
  46. Object.defineProperty(LazyLoadingRuleMap.prototype, "set", {
  47. configurable: true,
  48. value: void 0
  49. });
  50. }
  51. /**
  52. * Get a rule.
  53. * Each rule will be loaded on the first access.
  54. * @param {string} ruleId The rule ID to get.
  55. * @returns {Rule|undefined} The rule.
  56. */
  57. get(ruleId) {
  58. const load = super.get(ruleId);
  59. return load && load();
  60. }
  61. /**
  62. * Iterate rules.
  63. * @returns {IterableIterator<Rule>} Rules.
  64. */
  65. *values() {
  66. for (const load of super.values()) {
  67. yield load();
  68. }
  69. }
  70. /**
  71. * Iterate rules.
  72. * @returns {IterableIterator<[string, Rule]>} Rules.
  73. */
  74. *entries() {
  75. for (const [ruleId, load] of super.entries()) {
  76. yield [ruleId, load()];
  77. }
  78. }
  79. /**
  80. * Call a function with each rule.
  81. * @param {Function} callbackFn The callback function.
  82. * @param {any} [thisArg] The object to pass to `this` of the callback function.
  83. * @returns {void}
  84. */
  85. forEach(callbackFn, thisArg) {
  86. for (const [ruleId, load] of super.entries()) {
  87. callbackFn.call(thisArg, load(), ruleId, this);
  88. }
  89. }
  90. }
  91. // Forbid mutation.
  92. Object.defineProperties(LazyLoadingRuleMap.prototype, {
  93. clear: { configurable: true, value: void 0 },
  94. delete: { configurable: true, value: void 0 },
  95. [Symbol.iterator]: {
  96. configurable: true,
  97. writable: true,
  98. value: LazyLoadingRuleMap.prototype.entries
  99. }
  100. });
  101. module.exports = { LazyLoadingRuleMap };