@fookiejs/eslint-plugin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/README.md +512 -0
  2. package/dist/index.d.ts +164 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +167 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/rules/consistent-return.d.ts +7 -0
  7. package/dist/rules/consistent-return.d.ts.map +1 -0
  8. package/dist/rules/consistent-return.js +56 -0
  9. package/dist/rules/consistent-return.js.map +1 -0
  10. package/dist/rules/exhaustive-switch.d.ts +5 -0
  11. package/dist/rules/exhaustive-switch.d.ts.map +1 -0
  12. package/dist/rules/exhaustive-switch.js +83 -0
  13. package/dist/rules/exhaustive-switch.js.map +1 -0
  14. package/dist/rules/index.d.ts +50 -0
  15. package/dist/rules/index.d.ts.map +1 -0
  16. package/dist/rules/index.js +50 -0
  17. package/dist/rules/index.js.map +1 -0
  18. package/dist/rules/no-any.d.ts +5 -0
  19. package/dist/rules/no-any.d.ts.map +1 -0
  20. package/dist/rules/no-any.js +20 -0
  21. package/dist/rules/no-any.js.map +1 -0
  22. package/dist/rules/no-array-mutating-methods.d.ts +5 -0
  23. package/dist/rules/no-array-mutating-methods.d.ts.map +1 -0
  24. package/dist/rules/no-array-mutating-methods.js +65 -0
  25. package/dist/rules/no-array-mutating-methods.js.map +1 -0
  26. package/dist/rules/no-async-without-await.d.ts +5 -0
  27. package/dist/rules/no-async-without-await.d.ts.map +1 -0
  28. package/dist/rules/no-async-without-await.js +45 -0
  29. package/dist/rules/no-async-without-await.js.map +1 -0
  30. package/dist/rules/no-catch-instanceof.d.ts +5 -0
  31. package/dist/rules/no-catch-instanceof.d.ts.map +1 -0
  32. package/dist/rules/no-catch-instanceof.js +55 -0
  33. package/dist/rules/no-catch-instanceof.js.map +1 -0
  34. package/dist/rules/no-catch-unknown.d.ts +5 -0
  35. package/dist/rules/no-catch-unknown.d.ts.map +1 -0
  36. package/dist/rules/no-catch-unknown.js +32 -0
  37. package/dist/rules/no-catch-unknown.js.map +1 -0
  38. package/dist/rules/no-class-mutation.d.ts +5 -0
  39. package/dist/rules/no-class-mutation.d.ts.map +1 -0
  40. package/dist/rules/no-class-mutation.js +44 -0
  41. package/dist/rules/no-class-mutation.js.map +1 -0
  42. package/dist/rules/no-comments.d.ts +5 -0
  43. package/dist/rules/no-comments.d.ts.map +1 -0
  44. package/dist/rules/no-comments.js +27 -0
  45. package/dist/rules/no-comments.js.map +1 -0
  46. package/dist/rules/no-default-export.d.ts +5 -0
  47. package/dist/rules/no-default-export.d.ts.map +1 -0
  48. package/dist/rules/no-default-export.js +22 -0
  49. package/dist/rules/no-default-export.js.map +1 -0
  50. package/dist/rules/no-define-property.d.ts +5 -0
  51. package/dist/rules/no-define-property.d.ts.map +1 -0
  52. package/dist/rules/no-define-property.js +37 -0
  53. package/dist/rules/no-define-property.js.map +1 -0
  54. package/dist/rules/no-delete.d.ts +5 -0
  55. package/dist/rules/no-delete.d.ts.map +1 -0
  56. package/dist/rules/no-delete.js +35 -0
  57. package/dist/rules/no-delete.js.map +1 -0
  58. package/dist/rules/no-empty-string.d.ts +5 -0
  59. package/dist/rules/no-empty-string.d.ts.map +1 -0
  60. package/dist/rules/no-empty-string.js +24 -0
  61. package/dist/rules/no-empty-string.js.map +1 -0
  62. package/dist/rules/no-eval.d.ts +5 -0
  63. package/dist/rules/no-eval.d.ts.map +1 -0
  64. package/dist/rules/no-eval.js +33 -0
  65. package/dist/rules/no-eval.js.map +1 -0
  66. package/dist/rules/no-floating-promise.d.ts +5 -0
  67. package/dist/rules/no-floating-promise.d.ts.map +1 -0
  68. package/dist/rules/no-floating-promise.js +74 -0
  69. package/dist/rules/no-floating-promise.js.map +1 -0
  70. package/dist/rules/no-for-in.d.ts +5 -0
  71. package/dist/rules/no-for-in.d.ts.map +1 -0
  72. package/dist/rules/no-for-in.js +24 -0
  73. package/dist/rules/no-for-in.js.map +1 -0
  74. package/dist/rules/no-generic-names.d.ts +12 -0
  75. package/dist/rules/no-generic-names.d.ts.map +1 -0
  76. package/dist/rules/no-generic-names.js +104 -0
  77. package/dist/rules/no-generic-names.js.map +1 -0
  78. package/dist/rules/no-implicit-coercion.d.ts +7 -0
  79. package/dist/rules/no-implicit-coercion.d.ts.map +1 -0
  80. package/dist/rules/no-implicit-coercion.js +33 -0
  81. package/dist/rules/no-implicit-coercion.js.map +1 -0
  82. package/dist/rules/no-legacy-globals.d.ts +7 -0
  83. package/dist/rules/no-legacy-globals.d.ts.map +1 -0
  84. package/dist/rules/no-legacy-globals.js +58 -0
  85. package/dist/rules/no-legacy-globals.js.map +1 -0
  86. package/dist/rules/no-loop-func.d.ts +5 -0
  87. package/dist/rules/no-loop-func.d.ts.map +1 -0
  88. package/dist/rules/no-loop-func.js +50 -0
  89. package/dist/rules/no-loop-func.js.map +1 -0
  90. package/dist/rules/no-map-set-mutation.d.ts +5 -0
  91. package/dist/rules/no-map-set-mutation.d.ts.map +1 -0
  92. package/dist/rules/no-map-set-mutation.js +69 -0
  93. package/dist/rules/no-map-set-mutation.js.map +1 -0
  94. package/dist/rules/no-mutable-exports.d.ts +5 -0
  95. package/dist/rules/no-mutable-exports.d.ts.map +1 -0
  96. package/dist/rules/no-mutable-exports.js +29 -0
  97. package/dist/rules/no-mutable-exports.js.map +1 -0
  98. package/dist/rules/no-nan-array-indexof.d.ts +5 -0
  99. package/dist/rules/no-nan-array-indexof.d.ts.map +1 -0
  100. package/dist/rules/no-nan-array-indexof.js +33 -0
  101. package/dist/rules/no-nan-array-indexof.js.map +1 -0
  102. package/dist/rules/no-nan-in-math-result.d.ts +5 -0
  103. package/dist/rules/no-nan-in-math-result.d.ts.map +1 -0
  104. package/dist/rules/no-nan-in-math-result.js +58 -0
  105. package/dist/rules/no-nan-in-math-result.js.map +1 -0
  106. package/dist/rules/no-nan.d.ts +5 -0
  107. package/dist/rules/no-nan.d.ts.map +1 -0
  108. package/dist/rules/no-nan.js +26 -0
  109. package/dist/rules/no-nan.js.map +1 -0
  110. package/dist/rules/no-new-wrappers.d.ts +5 -0
  111. package/dist/rules/no-new-wrappers.d.ts.map +1 -0
  112. package/dist/rules/no-new-wrappers.js +47 -0
  113. package/dist/rules/no-new-wrappers.js.map +1 -0
  114. package/dist/rules/no-new.d.ts +5 -0
  115. package/dist/rules/no-new.d.ts.map +1 -0
  116. package/dist/rules/no-new.js +111 -0
  117. package/dist/rules/no-new.js.map +1 -0
  118. package/dist/rules/no-non-null-assertion.d.ts +5 -0
  119. package/dist/rules/no-non-null-assertion.d.ts.map +1 -0
  120. package/dist/rules/no-non-null-assertion.js +22 -0
  121. package/dist/rules/no-non-null-assertion.js.map +1 -0
  122. package/dist/rules/no-null-undefined.d.ts +7 -0
  123. package/dist/rules/no-null-undefined.d.ts.map +1 -0
  124. package/dist/rules/no-null-undefined.js +34 -0
  125. package/dist/rules/no-null-undefined.js.map +1 -0
  126. package/dist/rules/no-nullish-operators.d.ts +7 -0
  127. package/dist/rules/no-nullish-operators.d.ts.map +1 -0
  128. package/dist/rules/no-nullish-operators.js +31 -0
  129. package/dist/rules/no-nullish-operators.js.map +1 -0
  130. package/dist/rules/no-object-assign-mutation.d.ts +5 -0
  131. package/dist/rules/no-object-assign-mutation.d.ts.map +1 -0
  132. package/dist/rules/no-object-assign-mutation.js +36 -0
  133. package/dist/rules/no-object-assign-mutation.js.map +1 -0
  134. package/dist/rules/no-param-reassign.d.ts +5 -0
  135. package/dist/rules/no-param-reassign.d.ts.map +1 -0
  136. package/dist/rules/no-param-reassign.js +89 -0
  137. package/dist/rules/no-param-reassign.js.map +1 -0
  138. package/dist/rules/no-parseint-nan.d.ts +5 -0
  139. package/dist/rules/no-parseint-nan.d.ts.map +1 -0
  140. package/dist/rules/no-parseint-nan.js +64 -0
  141. package/dist/rules/no-parseint-nan.js.map +1 -0
  142. package/dist/rules/no-placeholder-names.d.ts +12 -0
  143. package/dist/rules/no-placeholder-names.d.ts.map +1 -0
  144. package/dist/rules/no-placeholder-names.js +107 -0
  145. package/dist/rules/no-placeholder-names.js.map +1 -0
  146. package/dist/rules/no-process-env.d.ts +5 -0
  147. package/dist/rules/no-process-env.d.ts.map +1 -0
  148. package/dist/rules/no-process-env.js +31 -0
  149. package/dist/rules/no-process-env.js.map +1 -0
  150. package/dist/rules/no-prototype-mutation.d.ts +5 -0
  151. package/dist/rules/no-prototype-mutation.d.ts.map +1 -0
  152. package/dist/rules/no-prototype-mutation.js +30 -0
  153. package/dist/rules/no-prototype-mutation.js.map +1 -0
  154. package/dist/rules/no-require.d.ts +5 -0
  155. package/dist/rules/no-require.d.ts.map +1 -0
  156. package/dist/rules/no-require.js +37 -0
  157. package/dist/rules/no-require.js.map +1 -0
  158. package/dist/rules/no-shadow.d.ts +5 -0
  159. package/dist/rules/no-shadow.d.ts.map +1 -0
  160. package/dist/rules/no-shadow.js +103 -0
  161. package/dist/rules/no-shadow.js.map +1 -0
  162. package/dist/rules/no-string-concat.d.ts +5 -0
  163. package/dist/rules/no-string-concat.d.ts.map +1 -0
  164. package/dist/rules/no-string-concat.js +36 -0
  165. package/dist/rules/no-string-concat.js.map +1 -0
  166. package/dist/rules/no-throw-literal.d.ts +5 -0
  167. package/dist/rules/no-throw-literal.d.ts.map +1 -0
  168. package/dist/rules/no-throw-literal.js +33 -0
  169. package/dist/rules/no-throw-literal.js.map +1 -0
  170. package/dist/rules/no-type-assertion.d.ts +5 -0
  171. package/dist/rules/no-type-assertion.d.ts.map +1 -0
  172. package/dist/rules/no-type-assertion.js +25 -0
  173. package/dist/rules/no-type-assertion.js.map +1 -0
  174. package/dist/rules/no-typeof.d.ts +5 -0
  175. package/dist/rules/no-typeof.d.ts.map +1 -0
  176. package/dist/rules/no-typeof.js +24 -0
  177. package/dist/rules/no-typeof.js.map +1 -0
  178. package/dist/rules/no-unknown.d.ts +5 -0
  179. package/dist/rules/no-unknown.d.ts.map +1 -0
  180. package/dist/rules/no-unknown.js +22 -0
  181. package/dist/rules/no-unknown.js.map +1 -0
  182. package/dist/rules/prefer-includes.d.ts +5 -0
  183. package/dist/rules/prefer-includes.d.ts.map +1 -0
  184. package/dist/rules/prefer-includes.js +50 -0
  185. package/dist/rules/prefer-includes.js.map +1 -0
  186. package/dist/rules/prefer-readonly-params.d.ts +5 -0
  187. package/dist/rules/prefer-readonly-params.d.ts.map +1 -0
  188. package/dist/rules/prefer-readonly-params.js +100 -0
  189. package/dist/rules/prefer-readonly-params.js.map +1 -0
  190. package/dist/rules/require-boolean-condition.d.ts +5 -0
  191. package/dist/rules/require-boolean-condition.d.ts.map +1 -0
  192. package/dist/rules/require-boolean-condition.js +60 -0
  193. package/dist/rules/require-boolean-condition.js.map +1 -0
  194. package/dist/rules/require-curly.d.ts +5 -0
  195. package/dist/rules/require-curly.d.ts.map +1 -0
  196. package/dist/rules/require-curly.js +55 -0
  197. package/dist/rules/require-curly.js.map +1 -0
  198. package/dist/rules/require-explicit-return-type.d.ts +5 -0
  199. package/dist/rules/require-explicit-return-type.d.ts.map +1 -0
  200. package/dist/rules/require-explicit-return-type.js +66 -0
  201. package/dist/rules/require-explicit-return-type.js.map +1 -0
  202. package/dist/rules/require-private-constructor.d.ts +5 -0
  203. package/dist/rules/require-private-constructor.d.ts.map +1 -0
  204. package/dist/rules/require-private-constructor.js +34 -0
  205. package/dist/rules/require-private-constructor.js.map +1 -0
  206. package/dist/rules/same-type-comparison.d.ts +5 -0
  207. package/dist/rules/same-type-comparison.d.ts.map +1 -0
  208. package/dist/rules/same-type-comparison.js +71 -0
  209. package/dist/rules/same-type-comparison.js.map +1 -0
  210. package/package.json +46 -0
@@ -0,0 +1,24 @@
1
+ import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/fookiejs/eslint-plugin-fookie/blob/main/docs/rules/${name}.md`);
3
+ export const noForIn = createRule({
4
+ name: "no-for-in",
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description: "Disallow for...in loops",
9
+ },
10
+ schema: [],
11
+ messages: {
12
+ noForIn: "Do not use for...in. It iterates over the prototype chain. Use for...of with Object.keys() or Object.entries() instead.",
13
+ },
14
+ },
15
+ defaultOptions: [],
16
+ create(context) {
17
+ return {
18
+ ForInStatement(node) {
19
+ context.report({ node, messageId: "noForIn" });
20
+ },
21
+ };
22
+ },
23
+ });
24
+ //# sourceMappingURL=no-for-in.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-for-in.js","sourceRoot":"","sources":["../../src/rules/no-for-in.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEhE,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CACxC,CAAC,IAAI,EAAE,EAAE,CACP,yEAAyE,IAAI,KAAK,CACrF,CAAA;AAKD,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAAsB;IACrD,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,yBAAyB;SACvC;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,OAAO,EACL,yHAAyH;SAC5H;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,cAAc,CAAC,IAA6B;gBAC1C,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAA;YAChD,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ type Options = [
3
+ {
4
+ allow?: string[];
5
+ additionalNames?: string[];
6
+ }?
7
+ ];
8
+ export declare const noGenericNames: ESLintUtils.RuleModule<"genericName", Options, unknown, ESLintUtils.RuleListener> & {
9
+ name: string;
10
+ };
11
+ export {};
12
+ //# sourceMappingURL=no-generic-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-generic-names.d.ts","sourceRoot":"","sources":["../../src/rules/no-generic-names.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,WAAW,EAAY,MAAM,0BAA0B,CAAA;AAgBhF,KAAK,OAAO,GAAG;IACb;QACE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;QAChB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;KAC3B,CAAC;CACH,CAAA;AAyBD,eAAO,MAAM,cAAc;;CA+EzB,CAAA"}
@@ -0,0 +1,104 @@
1
+ import { AST_NODE_TYPES, ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/fookiejs/eslint-plugin-fookie/blob/main/docs/rules/${name}.md`);
3
+ const DEFAULT_GENERIC = [
4
+ "data", "result", "response",
5
+ "obj", "arr",
6
+ "info", "stuff", "things", "thing",
7
+ "value", "val",
8
+ "item", "element", "entry",
9
+ "str", "num", "bool",
10
+ ];
11
+ function isDeclarationSite(node) {
12
+ const p = node.parent;
13
+ if (!p)
14
+ return false;
15
+ if (p.type === AST_NODE_TYPES.VariableDeclarator && p.id === node)
16
+ return true;
17
+ if (p.type === AST_NODE_TYPES.FunctionDeclaration ||
18
+ p.type === AST_NODE_TYPES.FunctionExpression ||
19
+ p.type === AST_NODE_TYPES.ArrowFunctionExpression) {
20
+ if (p.params.some((param) => param === node))
21
+ return true;
22
+ }
23
+ if (p.type === AST_NODE_TYPES.Property && p.value === node) {
24
+ if (p.parent.type === AST_NODE_TYPES.ObjectPattern)
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+ export const noGenericNames = createRule({
30
+ name: "no-generic-names",
31
+ meta: {
32
+ type: "suggestion",
33
+ docs: {
34
+ description: "Warn when identifiers use overly generic names that carry no domain information",
35
+ },
36
+ schema: [
37
+ {
38
+ type: "object",
39
+ properties: {
40
+ allow: {
41
+ type: "array",
42
+ items: { type: "string" },
43
+ description: "Names to allow despite being generic",
44
+ },
45
+ additionalNames: {
46
+ type: "array",
47
+ items: { type: "string" },
48
+ description: "Extra names to treat as generic",
49
+ },
50
+ },
51
+ additionalProperties: false,
52
+ },
53
+ ],
54
+ messages: {
55
+ genericName: "'{{name}}' is too generic. Use a name that describes the domain concept (e.g. '{{suggestion}}').",
56
+ },
57
+ },
58
+ defaultOptions: [{}],
59
+ create(context) {
60
+ const [opts = {}] = context.options;
61
+ const { allow = [], additionalNames = [] } = opts;
62
+ const allowed = new Set(allow.map((n) => n.toLowerCase()));
63
+ const genericNames = new Set([
64
+ ...DEFAULT_GENERIC.map((n) => n.toLowerCase()),
65
+ ...additionalNames.map((n) => n.toLowerCase()),
66
+ ]);
67
+ for (const a of allowed)
68
+ genericNames.delete(a);
69
+ const SUGGESTIONS = {
70
+ data: "userData / orderData / pageData",
71
+ result: "parseResult / searchResult / queryResult",
72
+ response: "apiResponse / httpResponse / authResponse",
73
+ obj: "use a typed variable name",
74
+ arr: "use a typed variable name",
75
+ info: "userInfo / sessionInfo / connectionInfo",
76
+ stuff: "use a descriptive name",
77
+ thing: "use a descriptive name",
78
+ value: "fieldValue / inputValue / selectedValue",
79
+ val: "fieldValue / inputValue",
80
+ item: "menuItem / listItem / orderItem",
81
+ element: "formElement / domElement",
82
+ entry: "logEntry / cacheEntry / registryEntry",
83
+ str: "label / message / key",
84
+ num: "count / index / amount",
85
+ bool: "isEnabled / hasAccess / isVisible",
86
+ };
87
+ return {
88
+ Identifier(node) {
89
+ if (!isDeclarationSite(node))
90
+ return;
91
+ const lower = node.name.toLowerCase();
92
+ if (!genericNames.has(lower))
93
+ return;
94
+ const { [lower]: suggestion = "a domain-specific name" } = SUGGESTIONS;
95
+ context.report({
96
+ node,
97
+ messageId: "genericName",
98
+ data: { name: node.name, suggestion },
99
+ });
100
+ },
101
+ };
102
+ },
103
+ });
104
+ //# sourceMappingURL=no-generic-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-generic-names.js","sourceRoot":"","sources":["../../src/rules/no-generic-names.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ type MessageIds = "noUnaryPlus" | "noDoubleNegation";
3
+ export declare const noImplicitCoercion: ESLintUtils.RuleModule<MessageIds, [], unknown, ESLintUtils.RuleListener> & {
4
+ name: string;
5
+ };
6
+ export {};
7
+ //# sourceMappingURL=no-implicit-coercion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-implicit-coercion.d.ts","sourceRoot":"","sources":["../../src/rules/no-implicit-coercion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAY,MAAM,0BAA0B,CAAA;AAQhE,KAAK,UAAU,GAAG,aAAa,GAAG,kBAAkB,CAAA;AAEpD,eAAO,MAAM,kBAAkB;;CAmC7B,CAAA"}
@@ -0,0 +1,33 @@
1
+ import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/fookiejs/eslint-plugin-fookie/blob/main/docs/rules/${name}.md`);
3
+ export const noImplicitCoercion = createRule({
4
+ name: "no-implicit-coercion",
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description: "Disallow implicit type coercion: unary + for numbers and !! for booleans",
9
+ },
10
+ schema: [],
11
+ messages: {
12
+ noUnaryPlus: "Do not use unary + for number conversion. Use Number(x) instead.",
13
+ noDoubleNegation: "Do not use !! for boolean coercion. Use an explicit boolean expression instead.",
14
+ },
15
+ },
16
+ defaultOptions: [],
17
+ create(context) {
18
+ return {
19
+ UnaryExpression(node) {
20
+ if (node.operator === "+") {
21
+ context.report({ node, messageId: "noUnaryPlus" });
22
+ return;
23
+ }
24
+ if (node.operator === "!" &&
25
+ node.argument.type === "UnaryExpression" &&
26
+ node.argument.operator === "!") {
27
+ context.report({ node, messageId: "noDoubleNegation" });
28
+ }
29
+ },
30
+ };
31
+ },
32
+ });
33
+ //# sourceMappingURL=no-implicit-coercion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-implicit-coercion.js","sourceRoot":"","sources":["../../src/rules/no-implicit-coercion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEhE,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CACxC,CAAC,IAAI,EAAE,EAAE,CACP,yEAAyE,IAAI,KAAK,CACrF,CAAA;AAKD,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAsB;IAChE,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,0EAA0E;SAC7E;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,WAAW,EACT,kEAAkE;YACpE,gBAAgB,EACd,iFAAiF;SACpF;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,eAAe,CAAC,IAA8B;gBAC5C,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;oBAC1B,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAA;oBAClD,OAAM;gBACR,CAAC;gBAED,IACE,IAAI,CAAC,QAAQ,KAAK,GAAG;oBACrB,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,iBAAiB;oBACxC,IAAI,CAAC,QAAQ,CAAC,QAAQ,KAAK,GAAG,EAC9B,CAAC;oBACD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAA;gBACzD,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ type MessageIds = "legacyGlobal" | "noArguments";
3
+ export declare const noLegacyGlobals: ESLintUtils.RuleModule<MessageIds, [], unknown, ESLintUtils.RuleListener> & {
4
+ name: string;
5
+ };
6
+ export {};
7
+ //# sourceMappingURL=no-legacy-globals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-legacy-globals.d.ts","sourceRoot":"","sources":["../../src/rules/no-legacy-globals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,WAAW,EAAY,MAAM,0BAA0B,CAAA;AAQhF,KAAK,UAAU,GAAG,cAAc,GAAG,aAAa,CAAA;AAWhD,eAAO,MAAM,eAAe;;CAuC1B,CAAA"}
@@ -0,0 +1,58 @@
1
+ import { AST_NODE_TYPES, ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/fookiejs/eslint-plugin-fookie/blob/main/docs/rules/${name}.md`);
3
+ function getBannedReplacement(name) {
4
+ if (name === "parseInt")
5
+ return "Number.parseInt(str, 10)";
6
+ if (name === "parseFloat")
7
+ return "Number(str)";
8
+ if (name === "isNaN")
9
+ return "Number.isNaN(x)";
10
+ if (name === "isFinite")
11
+ return "Number.isFinite(x)";
12
+ if (name === "eval")
13
+ return "never — redesign without eval";
14
+ return false;
15
+ }
16
+ export const noLegacyGlobals = createRule({
17
+ name: "no-legacy-globals",
18
+ meta: {
19
+ type: "problem",
20
+ docs: {
21
+ description: "Disallow legacy global functions: parseInt, parseFloat, isNaN, isFinite, eval, arguments",
22
+ },
23
+ schema: [],
24
+ messages: {
25
+ legacyGlobal: "Do not use global '{{name}}'. Use '{{replacement}}' instead.",
26
+ noArguments: "Do not use 'arguments'. Use rest parameters (...args) instead.",
27
+ },
28
+ },
29
+ defaultOptions: [],
30
+ create(context) {
31
+ return {
32
+ CallExpression(node) {
33
+ if (node.callee.type !== AST_NODE_TYPES.Identifier)
34
+ return;
35
+ const name = node.callee.name;
36
+ const replacement = getBannedReplacement(name);
37
+ if (replacement !== false) {
38
+ context.report({
39
+ node: node.callee,
40
+ messageId: "legacyGlobal",
41
+ data: { name, replacement },
42
+ });
43
+ }
44
+ },
45
+ Identifier(node) {
46
+ if (node.name !== "arguments")
47
+ return;
48
+ const parent = node.parent;
49
+ if (parent.type === AST_NODE_TYPES.MemberExpression && parent.property === node)
50
+ return;
51
+ if (parent.type === AST_NODE_TYPES.Property && parent.key === node)
52
+ return;
53
+ context.report({ node, messageId: "noArguments" });
54
+ },
55
+ };
56
+ },
57
+ });
58
+ //# sourceMappingURL=no-legacy-globals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-legacy-globals.js","sourceRoot":"","sources":["../../src/rules/no-legacy-globals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEhF,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CACxC,CAAC,IAAI,EAAE,EAAE,CACP,yEAAyE,IAAI,KAAK,CACrF,CAAA;AAKD,SAAS,oBAAoB,CAAC,IAAY;IACxC,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,0BAA0B,CAAA;IAC1D,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,aAAa,CAAA;IAC/C,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,iBAAiB,CAAA;IAC9C,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,oBAAoB,CAAA;IACpD,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,+BAA+B,CAAA;IAC3D,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAsB;IAC7D,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,0FAA0F;SAC7F;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,YAAY,EAAE,8DAA8D;YAC5E,WAAW,EAAE,gEAAgE;SAC9E;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,cAAc,CAAC,IAA6B;gBAC1C,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;oBAAE,OAAM;gBAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAA;gBAC7B,MAAM,WAAW,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAA;gBAC9C,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;oBAC1B,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,IAAI,CAAC,MAAM;wBACjB,SAAS,EAAE,cAAc;wBACzB,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;qBAC5B,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAED,UAAU,CAAC,IAAyB;gBAClC,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;oBAAE,OAAM;gBACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;gBAC1B,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,gBAAgB,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI;oBAAE,OAAM;gBACvF,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,QAAQ,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI;oBAAE,OAAM;gBAC1E,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAA;YACpD,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noLoopFunc: ESLintUtils.RuleModule<"noLoopFunc", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ //# sourceMappingURL=no-loop-func.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-loop-func.d.ts","sourceRoot":"","sources":["../../src/rules/no-loop-func.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAY,MAAM,0BAA0B,CAAA;AAkChE,eAAO,MAAM,UAAU;;CAgCrB,CAAA"}
@@ -0,0 +1,50 @@
1
+ import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/fookiejs/eslint-plugin-fookie/blob/main/docs/rules/${name}.md`);
3
+ const LOOP_TYPES = new Set([
4
+ "ForStatement",
5
+ "ForInStatement",
6
+ "ForOfStatement",
7
+ "WhileStatement",
8
+ "DoWhileStatement",
9
+ ]);
10
+ function isInsideLoop(node) {
11
+ let current = node.parent;
12
+ while (current) {
13
+ if (LOOP_TYPES.has(current.type))
14
+ return true;
15
+ if (current.type === "FunctionDeclaration" ||
16
+ current.type === "FunctionExpression" ||
17
+ current.type === "ArrowFunctionExpression") {
18
+ return false;
19
+ }
20
+ current = current.parent;
21
+ }
22
+ return false;
23
+ }
24
+ export const noLoopFunc = createRule({
25
+ name: "no-loop-func",
26
+ meta: {
27
+ type: "problem",
28
+ docs: {
29
+ description: "Disallow function definitions inside loops",
30
+ },
31
+ schema: [],
32
+ messages: {
33
+ noLoopFunc: "Do not define functions inside loops. The function closes over the loop variable and may capture unexpected values.",
34
+ },
35
+ },
36
+ defaultOptions: [],
37
+ create(context) {
38
+ function check(node) {
39
+ if (isInsideLoop(node)) {
40
+ context.report({ node, messageId: "noLoopFunc" });
41
+ }
42
+ }
43
+ return {
44
+ FunctionDeclaration: check,
45
+ FunctionExpression: check,
46
+ ArrowFunctionExpression: check,
47
+ };
48
+ },
49
+ });
50
+ //# sourceMappingURL=no-loop-func.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-loop-func.js","sourceRoot":"","sources":["../../src/rules/no-loop-func.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEhE,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CACxC,CAAC,IAAI,EAAE,EAAE,CACP,yEAAyE,IAAI,KAAK,CACrF,CAAA;AAKD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;IACzB,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,kBAAkB;CACnB,CAAC,CAAA;AAEF,SAAS,YAAY,CAAC,IAAmB;IACvC,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,CAAA;IACzB,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;QAC7C,IACE,OAAO,CAAC,IAAI,KAAK,qBAAqB;YACtC,OAAO,CAAC,IAAI,KAAK,oBAAoB;YACrC,OAAO,CAAC,IAAI,KAAK,yBAAyB,EAC1C,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;IAC1B,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAsB;IACxD,IAAI,EAAE,cAAc;IACpB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,4CAA4C;SAC1D;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,UAAU,EACR,qHAAqH;SACxH;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,SAAS,KAAK,CACZ,IAGoC;YAEpC,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAA;YACnD,CAAC;QACH,CAAC;QAED,OAAO;YACL,mBAAmB,EAAE,KAAK;YAC1B,kBAAkB,EAAE,KAAK;YACzB,uBAAuB,EAAE,KAAK;SAC/B,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noMapSetMutation: ESLintUtils.RuleModule<"noMapSetMutation", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ //# sourceMappingURL=no-map-set-mutation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-map-set-mutation.d.ts","sourceRoot":"","sources":["../../src/rules/no-map-set-mutation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAY,MAAM,0BAA0B,CAAA;AAchE,eAAO,MAAM,gBAAgB;;CAwE3B,CAAA"}
@@ -0,0 +1,69 @@
1
+ import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/fookiejs/eslint-plugin-fookie/blob/main/docs/rules/${name}.md`);
3
+ const MAP_MUTATING_METHODS = new Set(["set", "delete", "clear"]);
4
+ const SET_MUTATING_METHODS = new Set(["add", "delete", "clear"]);
5
+ const ALL_MUTATING_METHODS = new Set([...MAP_MUTATING_METHODS, ...SET_MUTATING_METHODS]);
6
+ export const noMapSetMutation = createRule({
7
+ name: "no-map-set-mutation",
8
+ meta: {
9
+ type: "problem",
10
+ docs: {
11
+ description: "Disallow mutating Map and Set instances created with new Map() or new Set().",
12
+ },
13
+ schema: [],
14
+ messages: {
15
+ noMapSetMutation: ".{{method}}() mutates the {{collection}}. Use a new {{collection}} instance instead.",
16
+ },
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ const mutatingRefs = new Set();
21
+ return {
22
+ VariableDeclarator(node) {
23
+ if (node.init &&
24
+ node.init.type === "NewExpression" &&
25
+ node.init.callee.type === "Identifier" &&
26
+ (node.init.callee.name === "Map" || node.init.callee.name === "Set")) {
27
+ mutatingRefs.add(node.id);
28
+ }
29
+ },
30
+ CallExpression(node) {
31
+ if (node.callee.type !== "MemberExpression")
32
+ return;
33
+ const prop = node.callee.property;
34
+ if (prop.type !== "Identifier")
35
+ return;
36
+ if (!ALL_MUTATING_METHODS.has(prop.name))
37
+ return;
38
+ const obj = node.callee.object;
39
+ if (obj.type !== "Identifier")
40
+ return;
41
+ const scope = context.sourceCode.getScope(node);
42
+ let currentScope = scope;
43
+ while (currentScope) {
44
+ const variable = currentScope.variables.find((v) => v.name === obj.name);
45
+ if (variable) {
46
+ for (const def of variable.defs) {
47
+ if (def.node.type === "VariableDeclarator" &&
48
+ def.node.init?.type === "NewExpression" &&
49
+ def.node.init.callee.type === "Identifier") {
50
+ const collectionName = def.node.init.callee.name;
51
+ if (collectionName === "Map" || collectionName === "Set") {
52
+ context.report({
53
+ node,
54
+ messageId: "noMapSetMutation",
55
+ data: { method: prop.name, collection: collectionName },
56
+ });
57
+ return;
58
+ }
59
+ }
60
+ }
61
+ break;
62
+ }
63
+ currentScope = currentScope.upper;
64
+ }
65
+ },
66
+ };
67
+ },
68
+ });
69
+ //# sourceMappingURL=no-map-set-mutation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-map-set-mutation.js","sourceRoot":"","sources":["../../src/rules/no-map-set-mutation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noMutableExports: ESLintUtils.RuleModule<"noMutableExport", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ //# sourceMappingURL=no-mutable-exports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-mutable-exports.d.ts","sourceRoot":"","sources":["../../src/rules/no-mutable-exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAY,MAAM,0BAA0B,CAAA;AAUhE,eAAO,MAAM,gBAAgB;;CAyB3B,CAAA"}
@@ -0,0 +1,29 @@
1
+ import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/fookiejs/eslint-plugin-fookie/blob/main/docs/rules/${name}.md`);
3
+ export const noMutableExports = createRule({
4
+ name: "no-mutable-exports",
5
+ meta: {
6
+ type: "problem",
7
+ docs: {
8
+ description: "Disallow exporting mutable let variables",
9
+ },
10
+ schema: [],
11
+ messages: {
12
+ noMutableExport: "Do not export mutable 'let' variables. Use 'const' instead.",
13
+ },
14
+ },
15
+ defaultOptions: [],
16
+ create(context) {
17
+ return {
18
+ ExportNamedDeclaration(node) {
19
+ const decl = node.declaration;
20
+ if (!decl || decl.type !== "VariableDeclaration")
21
+ return;
22
+ if (decl.kind === "let") {
23
+ context.report({ node: decl, messageId: "noMutableExport" });
24
+ }
25
+ },
26
+ };
27
+ },
28
+ });
29
+ //# sourceMappingURL=no-mutable-exports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-mutable-exports.js","sourceRoot":"","sources":["../../src/rules/no-mutable-exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEhE,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CACxC,CAAC,IAAI,EAAE,EAAE,CACP,yEAAyE,IAAI,KAAK,CACrF,CAAA;AAKD,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAsB;IAC9D,IAAI,EAAE,oBAAoB;IAC1B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,0CAA0C;SACxD;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,eAAe,EACb,6DAA6D;SAChE;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,sBAAsB,CAAC,IAAqC;gBAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAA;gBAC7B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB;oBAAE,OAAM;gBACxD,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;oBACxB,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAA;gBAC9D,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noNanArrayIndexOf: ESLintUtils.RuleModule<"noNanArrayIndexOf", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ //# sourceMappingURL=no-nan-array-indexof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-nan-array-indexof.d.ts","sourceRoot":"","sources":["../../src/rules/no-nan-array-indexof.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAY,MAAM,0BAA0B,CAAA;AAchE,eAAO,MAAM,iBAAiB;;CA8B5B,CAAA"}
@@ -0,0 +1,33 @@
1
+ import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/fookiejs/eslint-plugin-fookie/blob/main/docs/rules/${name}.md`);
3
+ function isNaNNode(node) {
4
+ return node.type === "Identifier" && node.name === "NaN";
5
+ }
6
+ export const noNanArrayIndexOf = createRule({
7
+ name: "no-nan-array-indexof",
8
+ meta: {
9
+ type: "problem",
10
+ docs: {
11
+ description: "Disallow array.indexOf(NaN) which always returns -1. Use array.includes(NaN) or array.findIndex(Number.isNaN) instead.",
12
+ },
13
+ schema: [],
14
+ messages: {
15
+ noNanArrayIndexOf: "array.indexOf(NaN) always returns -1 because NaN !== NaN. Use array.includes(NaN) or array.findIndex(Number.isNaN) instead.",
16
+ },
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ return {
21
+ CallExpression(node) {
22
+ if (node.callee.type === "MemberExpression" &&
23
+ node.callee.property.type === "Identifier" &&
24
+ node.callee.property.name === "indexOf" &&
25
+ node.arguments.length >= 1 &&
26
+ isNaNNode(node.arguments[0])) {
27
+ context.report({ node, messageId: "noNanArrayIndexOf" });
28
+ }
29
+ },
30
+ };
31
+ },
32
+ });
33
+ //# sourceMappingURL=no-nan-array-indexof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-nan-array-indexof.js","sourceRoot":"","sources":["../../src/rules/no-nan-array-indexof.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEhE,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CACxC,CAAC,IAAI,EAAE,EAAE,CACP,yEAAyE,IAAI,KAAK,CACrF,CAAA;AAKD,SAAS,SAAS,CAAC,IAAmB;IACpC,OAAO,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAA;AAC1D,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAsB;IAC/D,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,wHAAwH;SAC3H;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,iBAAiB,EACf,6HAA6H;SAChI;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,cAAc,CAAC,IAA6B;gBAC1C,IACE,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB;oBACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;oBAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS;oBACvC,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC;oBAC1B,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC,EAC7B,CAAC;oBACD,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC,CAAA;gBAC1D,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noNanInMathResult: ESLintUtils.RuleModule<"noNanInMathResult", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ //# sourceMappingURL=no-nan-in-math-result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-nan-in-math-result.d.ts","sourceRoot":"","sources":["../../src/rules/no-nan-in-math-result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAY,MAAM,0BAA0B,CAAA;AAkChE,eAAO,MAAM,iBAAiB;;CAqC5B,CAAA"}
@@ -0,0 +1,58 @@
1
+ import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
2
+ const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/fookiejs/eslint-plugin-fookie/blob/main/docs/rules/${name}.md`);
3
+ const NAN_PRODUCING_MATH_METHODS = new Set([
4
+ "sqrt",
5
+ "log",
6
+ "log2",
7
+ "log10",
8
+ "asin",
9
+ "acos",
10
+ "atan",
11
+ "acosh",
12
+ "asinh",
13
+ "atanh",
14
+ ]);
15
+ function isMathNanCall(node) {
16
+ return (node.type === "CallExpression" &&
17
+ node.callee.type === "MemberExpression" &&
18
+ node.callee.object.type === "Identifier" &&
19
+ node.callee.object.name === "Math" &&
20
+ node.callee.property.type === "Identifier" &&
21
+ NAN_PRODUCING_MATH_METHODS.has(node.callee.property.name));
22
+ }
23
+ export const noNanInMathResult = createRule({
24
+ name: "no-nan-in-math-result",
25
+ meta: {
26
+ type: "problem",
27
+ docs: {
28
+ description: "Disallow using Math functions that can return NaN directly in arithmetic or comparisons without a NaN guard",
29
+ },
30
+ schema: [],
31
+ messages: {
32
+ noNanInMathResult: "Math.{{method}}() can return NaN for out-of-range inputs. Guard the result with Number.isNaN() before using it.",
33
+ },
34
+ },
35
+ defaultOptions: [],
36
+ create(context) {
37
+ function checkOperand(node) {
38
+ if (isMathNanCall(node)) {
39
+ const callee = node
40
+ .callee;
41
+ context.report({
42
+ node,
43
+ messageId: "noNanInMathResult",
44
+ data: {
45
+ method: callee.property.name,
46
+ },
47
+ });
48
+ }
49
+ }
50
+ return {
51
+ BinaryExpression(node) {
52
+ checkOperand(node.left);
53
+ checkOperand(node.right);
54
+ },
55
+ };
56
+ },
57
+ });
58
+ //# sourceMappingURL=no-nan-in-math-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-nan-in-math-result.js","sourceRoot":"","sources":["../../src/rules/no-nan-in-math-result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAEhE,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CACxC,CAAC,IAAI,EAAE,EAAE,CACP,yEAAyE,IAAI,KAAK,CACrF,CAAA;AAKD,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC;IACzC,MAAM;IACN,KAAK;IACL,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;CACR,CAAC,CAAA;AAEF,SAAS,aAAa,CAAC,IAAmB;IACxC,OAAO,CACL,IAAI,CAAC,IAAI,KAAK,gBAAgB;QAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB;QACvC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;QACxC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM;QAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;QAC1C,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAC1D,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAsB;IAC/D,IAAI,EAAE,uBAAuB;IAC7B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,6GAA6G;SAChH;QACD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE;YACR,iBAAiB,EACf,iHAAiH;SACpH;KACF;IACD,cAAc,EAAE,EAAE;IAClB,MAAM,CAAC,OAAO;QACZ,SAAS,YAAY,CAAC,IAAmB;YACvC,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,MAAM,GAAI,IAAgC;qBAC7C,MAAmC,CAAA;gBACtC,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,mBAAmB;oBAC9B,IAAI,EAAE;wBACJ,MAAM,EAAG,MAAM,CAAC,QAAgC,CAAC,IAAI;qBACtD;iBACF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,gBAAgB,CAAC,IAA+B;gBAC9C,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBACvB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAC1B,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from "@typescript-eslint/utils";
2
+ export declare const noNan: ESLintUtils.RuleModule<"noNaN", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ //# sourceMappingURL=no-nan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-nan.d.ts","sourceRoot":"","sources":["../../src/rules/no-nan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAY,MAAM,0BAA0B,CAAA;AAUhE,eAAO,MAAM,KAAK;;CAuBhB,CAAA"}