@conorroberts/utils 0.0.35 → 0.0.37

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 (39) hide show
  1. package/dist/{env.d.ts → env.d.mts} +10 -7
  2. package/dist/env.mjs +32 -0
  3. package/dist/env.mjs.map +1 -0
  4. package/dist/images.d.mts +79 -0
  5. package/dist/images.mjs +129 -0
  6. package/dist/images.mjs.map +1 -0
  7. package/dist/oxlint/jsx-component-pascal-case.d.mts +25 -0
  8. package/dist/oxlint/jsx-component-pascal-case.mjs +159 -0
  9. package/dist/oxlint/jsx-component-pascal-case.mjs.map +1 -0
  10. package/dist/oxlint/no-component-date-instantiation.d.mts +27 -0
  11. package/dist/oxlint/no-component-date-instantiation.mjs +160 -0
  12. package/dist/oxlint/no-component-date-instantiation.mjs.map +1 -0
  13. package/dist/oxlint/no-emoji.d.mts +16 -0
  14. package/dist/oxlint/no-emoji.mjs +89 -0
  15. package/dist/oxlint/no-emoji.mjs.map +1 -0
  16. package/dist/oxlint/no-finally.d.mts +16 -0
  17. package/dist/oxlint/no-finally.mjs +32 -0
  18. package/dist/oxlint/no-finally.mjs.map +1 -0
  19. package/dist/oxlint/no-inline-components.d.mts +44 -0
  20. package/dist/oxlint/no-inline-components.mjs +350 -0
  21. package/dist/oxlint/no-inline-components.mjs.map +1 -0
  22. package/dist/oxlint/no-react-namespace.d.mts +16 -0
  23. package/dist/oxlint/no-react-namespace.mjs +75 -0
  24. package/dist/oxlint/no-react-namespace.mjs.map +1 -0
  25. package/dist/oxlint/no-switch-plugin.d.mts +15 -0
  26. package/dist/oxlint/no-switch-plugin.mjs +31 -0
  27. package/dist/oxlint/no-switch-plugin.mjs.map +1 -0
  28. package/dist/oxlint/no-top-level-let.d.mts +16 -0
  29. package/dist/oxlint/no-top-level-let.mjs +66 -0
  30. package/dist/oxlint/no-top-level-let.mjs.map +1 -0
  31. package/dist/oxlint/no-type-cast.d.mts +16 -0
  32. package/dist/oxlint/no-type-cast.mjs +49 -0
  33. package/dist/oxlint/no-type-cast.mjs.map +1 -0
  34. package/package.json +44 -6
  35. package/dist/env.js +0 -30
  36. package/dist/env.js.map +0 -1
  37. package/dist/images.d.ts +0 -77
  38. package/dist/images.js +0 -151
  39. package/dist/images.js.map +0 -1
@@ -0,0 +1,350 @@
1
+ import { defineRule } from "oxlint";
2
+
3
+ //#region src/oxlint-plugins/no-inline-components.js
4
+ /**
5
+ * @typedef {import("oxlint").Context} RuleContext
6
+ * @typedef {import("oxlint").ESTree.Node} ESTNode
7
+ * @typedef {import("oxlint").ESTree.Expression} ESTExpression
8
+ * @typedef {import("oxlint").ESTree.Pattern} ESTPattern
9
+ * @typedef {import("oxlint").ESTree.ReturnStatement} ReturnStatementNode
10
+ * @typedef {import("oxlint").ESTree.VariableDeclarator} VariableDeclaratorNode
11
+ * @typedef {import("oxlint").ESTree.AssignmentExpression} AssignmentExpressionNode
12
+ * @typedef {import("oxlint").ESTree.Function | import("oxlint").ESTree.ArrowFunctionExpression} FunctionLikeNode
13
+ */
14
+ /**
15
+ * @typedef {object} RecordedAssignment
16
+ * @property {ESTExpression} node
17
+ * @property {string[]} names
18
+ */
19
+ /**
20
+ * @typedef {object} NestedFunctionRecord
21
+ * @property {FunctionLikeNode} node
22
+ * @property {string} name
23
+ */
24
+ /**
25
+ * @typedef {object} FunctionContext
26
+ * @property {FunctionLikeNode} node
27
+ * @property {FunctionContext | null} parent
28
+ * @property {string} name
29
+ * @property {boolean} returnsJsx
30
+ * @property {Set<string>} jsxBindingNames
31
+ * @property {RecordedAssignment[]} jsxAssignments
32
+ * @property {NestedFunctionRecord[]} nestedJsxChildren
33
+ */
34
+ const JSX_NODE_TYPES = new Set(["JSXElement", "JSXFragment"]);
35
+ const FUNCTION_NODE_TYPES = new Set([
36
+ "FunctionDeclaration",
37
+ "FunctionExpression",
38
+ "ArrowFunctionExpression"
39
+ ]);
40
+ /**
41
+ * @param {unknown} name
42
+ * @returns {name is string}
43
+ */
44
+ const isComponentName = (name) => typeof name === "string" && /^[A-Z]/.test(name);
45
+ /**
46
+ * @param {unknown} name
47
+ * @returns {name is string}
48
+ */
49
+ const isHookName = (name) => typeof name === "string" && name.startsWith("use");
50
+ /**
51
+ * @param {unknown} node
52
+ * @returns {node is ESTNode & { type: string }}
53
+ */
54
+ const isNode = (node) => Boolean(node && typeof node === "object" && "type" in node);
55
+ /**
56
+ * @param {unknown} node
57
+ * @returns {node is FunctionLikeNode}
58
+ */
59
+ const isFunctionLike = (node) => isNode(node) && FUNCTION_NODE_TYPES.has(node.type);
60
+ /**
61
+ * @param {ESTNode | null | undefined} node
62
+ * @returns {FunctionLikeNode | null}
63
+ */
64
+ const getEnclosingFunction = (node) => {
65
+ const findFunction = (current) => {
66
+ if (!current) return null;
67
+ if (isFunctionLike(current)) return current;
68
+ return findFunction(isNode(current) ? current.parent ?? null : null);
69
+ };
70
+ return findFunction(isNode(node) ? node.parent ?? null : null);
71
+ };
72
+ /**
73
+ * @param {FunctionLikeNode} node
74
+ */
75
+ const isFunctionUsedAsJsxProp = (node) => {
76
+ const checkJsxProp = (current) => {
77
+ if (!current) return false;
78
+ if (current.type === "JSXAttribute") return true;
79
+ if (isFunctionLike(current)) return false;
80
+ return checkJsxProp(isNode(current) ? current.parent ?? null : null);
81
+ };
82
+ return checkJsxProp(isNode(node) ? node.parent ?? null : null);
83
+ };
84
+ /**
85
+ * @param {FunctionLikeNode} node
86
+ */
87
+ const isFunctionImmediatelyInvoked = (node) => {
88
+ const parent = isNode(node) ? node.parent ?? null : null;
89
+ if (!parent) return false;
90
+ if (parent.type === "CallExpression" && parent.callee === node) return true;
91
+ return false;
92
+ };
93
+ /**
94
+ * @param {ESTExpression | null | undefined} root
95
+ */
96
+ const expressionContainsJsx = (root) => {
97
+ if (!root || !isNode(root)) return false;
98
+ const stack = [root];
99
+ while (stack.length > 0) {
100
+ const current = stack.pop();
101
+ if (!current || !isNode(current)) continue;
102
+ if (JSX_NODE_TYPES.has(current.type)) return true;
103
+ if (FUNCTION_NODE_TYPES.has(current.type) && current !== root) continue;
104
+ for (const key of Object.keys(current)) {
105
+ if (key === "parent") continue;
106
+ const value = current[key];
107
+ if (!value) continue;
108
+ if (Array.isArray(value)) {
109
+ for (const element of value) if (isNode(element)) stack.push(element);
110
+ } else if (isNode(value)) stack.push(value);
111
+ }
112
+ }
113
+ return false;
114
+ };
115
+ /**
116
+ * @param {ESTExpression | null | undefined} root
117
+ * @param {Set<string>} bindingNames
118
+ */
119
+ const expressionProducesJsx = (root, bindingNames) => {
120
+ if (!root) return false;
121
+ if (expressionContainsJsx(root)) return true;
122
+ if (!isNode(root)) return false;
123
+ const type = root.type;
124
+ if (type === "Identifier") return bindingNames.has(root.name);
125
+ if (type === "ConditionalExpression") return expressionProducesJsx(root.consequent, bindingNames) || expressionProducesJsx(root.alternate, bindingNames);
126
+ if (type === "LogicalExpression") return expressionProducesJsx(root.left, bindingNames) || expressionProducesJsx(root.right, bindingNames);
127
+ if (type === "SequenceExpression") {
128
+ const expressions = root.expressions ?? [];
129
+ return expressionProducesJsx(expressions[expressions.length - 1] ?? null, bindingNames);
130
+ }
131
+ if (type === "ArrayExpression") return root.elements.some((element) => {
132
+ if (!element) return false;
133
+ if (element.type === "SpreadElement") return expressionProducesJsx(element.argument, bindingNames);
134
+ return expressionProducesJsx(element, bindingNames);
135
+ });
136
+ if (type === "ParenthesizedExpression") return expressionProducesJsx(root.expression, bindingNames);
137
+ if (type === "AwaitExpression" || type === "UnaryExpression" || type === "UpdateExpression") return expressionProducesJsx(root.argument, bindingNames);
138
+ if (type === "TSAsExpression" || type === "TSTypeAssertion" || type === "TSNonNullExpression" || type === "ChainExpression") return expressionProducesJsx(root.expression, bindingNames);
139
+ return false;
140
+ };
141
+ /**
142
+ * @param {ESTPattern | null | undefined} pattern
143
+ * @param {string[]} names
144
+ */
145
+ const collectBindingNames = (pattern, names) => {
146
+ if (!pattern || !isNode(pattern)) return;
147
+ const type = pattern.type;
148
+ if (type === "Identifier") {
149
+ names.push(pattern.name);
150
+ return;
151
+ }
152
+ if (type === "ArrayPattern") {
153
+ for (const element of pattern.elements) {
154
+ if (!element) continue;
155
+ if (element.type === "RestElement") collectBindingNames(element.argument, names);
156
+ else collectBindingNames(element, names);
157
+ }
158
+ return;
159
+ }
160
+ if (type === "ObjectPattern") {
161
+ for (const property of pattern.properties) {
162
+ if (!property) continue;
163
+ if (property.type === "Property") collectBindingNames(property.value, names);
164
+ else if (property.type === "RestElement") collectBindingNames(property.argument, names);
165
+ }
166
+ return;
167
+ }
168
+ if (type === "AssignmentPattern") {
169
+ collectBindingNames(pattern.left, names);
170
+ return;
171
+ }
172
+ if (type === "RestElement") collectBindingNames(pattern.argument, names);
173
+ };
174
+ /**
175
+ * @param {FunctionLikeNode} node
176
+ */
177
+ const getFunctionName = (node) => {
178
+ if (node.type === "FunctionDeclaration" && node.id && node.id.type === "Identifier") return node.id.name;
179
+ if ((node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") && node.id) {
180
+ if (node.id.type === "Identifier") return node.id.name;
181
+ }
182
+ const parent = node.parent;
183
+ if (!parent || !isNode(parent)) return "";
184
+ if (parent.type === "VariableDeclarator") return parent.id && parent.id.type === "Identifier" ? parent.id.name : "";
185
+ if (parent.type === "AssignmentExpression") return parent.left && parent.left.type === "Identifier" ? parent.left.name : "";
186
+ if (parent.type === "Property" || parent.type === "MethodDefinition") return parent.key && parent.key.type === "Identifier" ? parent.key.name : "";
187
+ if (parent.type === "CallExpression") {
188
+ const callParent = parent.parent;
189
+ if (callParent && isNode(callParent)) {
190
+ if (callParent.type === "VariableDeclarator") return callParent.id && callParent.id.type === "Identifier" ? callParent.id.name : "";
191
+ if (callParent.type === "AssignmentExpression") return callParent.left && callParent.left.type === "Identifier" ? callParent.left.name : "";
192
+ }
193
+ }
194
+ return "";
195
+ };
196
+ /**
197
+ * @param {string} name
198
+ */
199
+ const describeFunction = (name) => name ? `function '${name}'` : "this function";
200
+ /**
201
+ * @param {string} name
202
+ */
203
+ const describeNested = (name) => name ? `function '${name}'` : "an anonymous function";
204
+ /**
205
+ * @param {string[]} names
206
+ * @param {string} fnName
207
+ */
208
+ const createAssignmentMessage = (names, fnName) => {
209
+ return `Avoid storing JSX in ${names.length === 0 ? "local variables" : names.length === 1 ? `local '${names[0]}'` : `locals ${names.map((name) => `'${name}'`).join(", ")}`} inside ${describeFunction(fnName)}; return the JSX directly instead.`;
210
+ };
211
+ /**
212
+ * @param {string} childName
213
+ * @param {string} parentName
214
+ */
215
+ const createNestedFunctionMessage = (childName, parentName) => `JSX-returning ${describeNested(childName)} should not be declared inside ${describeFunction(parentName)}. Extract it to module scope.`;
216
+ /**
217
+ * @param {string} name
218
+ */
219
+ const createIIFEMessage = (name) => `JSX-returning ${describeNested(name)} should not be declared as an immediately invoked function expression (IIFE). Extract it to a named function at module scope.`;
220
+ const rule = defineRule({
221
+ meta: {
222
+ type: "problem",
223
+ docs: {
224
+ description: "Disallow JSX-returning functions and JSX-valued assignments within other functions that also return JSX.",
225
+ recommended: false
226
+ },
227
+ schema: []
228
+ },
229
+ createOnce(context) {
230
+ /** @type {FunctionContext[]} */
231
+ const functionStack = [];
232
+ const currentFunction = () => functionStack[functionStack.length - 1] ?? null;
233
+ /**
234
+ * @param {FunctionLikeNode} node
235
+ */
236
+ const enterFunction = (node) => {
237
+ /** @type {FunctionContext} */
238
+ const fnCtx = {
239
+ node,
240
+ parent: currentFunction(),
241
+ name: getFunctionName(node),
242
+ returnsJsx: false,
243
+ jsxBindingNames: /* @__PURE__ */ new Set(),
244
+ jsxAssignments: [],
245
+ nestedJsxChildren: []
246
+ };
247
+ functionStack.push(fnCtx);
248
+ if (node.type === "ArrowFunctionExpression" && node.body && node.body.type !== "BlockStatement") {
249
+ if (expressionProducesJsx(node.body, fnCtx.jsxBindingNames)) fnCtx.returnsJsx = true;
250
+ }
251
+ };
252
+ const exitFunction = () => {
253
+ const fnCtx = functionStack.pop();
254
+ if (!fnCtx) return;
255
+ if (fnCtx.returnsJsx && isFunctionImmediatelyInvoked(fnCtx.node)) {
256
+ context.report({
257
+ node: fnCtx.node,
258
+ message: createIIFEMessage(fnCtx.name)
259
+ });
260
+ return;
261
+ }
262
+ if (fnCtx.parent && fnCtx.returnsJsx && fnCtx.name && !isFunctionUsedAsJsxProp(fnCtx.node)) fnCtx.parent.nestedJsxChildren.push({
263
+ node: fnCtx.node,
264
+ name: fnCtx.name
265
+ });
266
+ if (!fnCtx.returnsJsx) return;
267
+ for (const assignment of fnCtx.jsxAssignments) context.report({
268
+ node: assignment.node,
269
+ message: createAssignmentMessage(assignment.names, fnCtx.name)
270
+ });
271
+ for (const nested of fnCtx.nestedJsxChildren) context.report({
272
+ node: nested.node,
273
+ message: createNestedFunctionMessage(nested.name, fnCtx.name)
274
+ });
275
+ };
276
+ /** @param {ReturnStatementNode} node */
277
+ const handleReturnStatement = (node) => {
278
+ const fnCtx = currentFunction();
279
+ if (!fnCtx) return;
280
+ const argument = node.argument;
281
+ if (!argument || isFunctionLike(argument)) return;
282
+ if (expressionProducesJsx(argument, fnCtx.jsxBindingNames)) fnCtx.returnsJsx = true;
283
+ };
284
+ /** @param {VariableDeclaratorNode} node */
285
+ const handleVariableDeclarator = (node) => {
286
+ const fnCtx = currentFunction();
287
+ if (!fnCtx) return;
288
+ const init = node.init;
289
+ if (!init || isFunctionLike(init)) return;
290
+ if (!expressionContainsJsx(init)) return;
291
+ const names = [];
292
+ collectBindingNames(node.id, names);
293
+ for (const name of names) fnCtx.jsxBindingNames.add(name);
294
+ fnCtx.jsxAssignments.push({
295
+ node: init,
296
+ names
297
+ });
298
+ };
299
+ /** @param {AssignmentExpressionNode} node */
300
+ const handleAssignmentExpression = (node) => {
301
+ if (node.operator !== "=") return;
302
+ const fnCtx = currentFunction();
303
+ if (!fnCtx) return;
304
+ const right = node.right;
305
+ if (!right || isFunctionLike(right)) return;
306
+ if (!expressionContainsJsx(right)) return;
307
+ const names = [];
308
+ if (node.left && node.left.type === "Identifier") {
309
+ names.push(node.left.name);
310
+ fnCtx.jsxBindingNames.add(node.left.name);
311
+ }
312
+ fnCtx.jsxAssignments.push({
313
+ node: right,
314
+ names
315
+ });
316
+ };
317
+ return {
318
+ FunctionDeclaration(node) {
319
+ if (isFunctionLike(node)) enterFunction(node);
320
+ },
321
+ "FunctionDeclaration:exit": exitFunction,
322
+ FunctionExpression(node) {
323
+ if (isFunctionLike(node)) enterFunction(node);
324
+ },
325
+ "FunctionExpression:exit": exitFunction,
326
+ ArrowFunctionExpression(node) {
327
+ if (isFunctionLike(node)) enterFunction(node);
328
+ },
329
+ "ArrowFunctionExpression:exit": exitFunction,
330
+ ReturnStatement(node) {
331
+ if (node.type === "ReturnStatement") handleReturnStatement(node);
332
+ },
333
+ VariableDeclarator(node) {
334
+ if (node.type === "VariableDeclarator") handleVariableDeclarator(node);
335
+ },
336
+ AssignmentExpression(node) {
337
+ if (node.type === "AssignmentExpression") handleAssignmentExpression(node);
338
+ }
339
+ };
340
+ }
341
+ });
342
+ const noInlineComponentsRule = rule;
343
+ var no_inline_components_default = {
344
+ meta: { name: "no-inline-components" },
345
+ rules: { "no-inline-components": rule }
346
+ };
347
+
348
+ //#endregion
349
+ export { no_inline_components_default as default, getEnclosingFunction, getFunctionName, isComponentName, isHookName, noInlineComponentsRule };
350
+ //# sourceMappingURL=no-inline-components.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-inline-components.mjs","names":[],"sources":["../../src/oxlint-plugins/no-inline-components.js"],"sourcesContent":["import { defineRule } from \"oxlint\";\r\n\r\n/**\r\n * @typedef {import(\"oxlint\").Context} RuleContext\r\n * @typedef {import(\"oxlint\").ESTree.Node} ESTNode\r\n * @typedef {import(\"oxlint\").ESTree.Expression} ESTExpression\r\n * @typedef {import(\"oxlint\").ESTree.Pattern} ESTPattern\r\n * @typedef {import(\"oxlint\").ESTree.ReturnStatement} ReturnStatementNode\r\n * @typedef {import(\"oxlint\").ESTree.VariableDeclarator} VariableDeclaratorNode\r\n * @typedef {import(\"oxlint\").ESTree.AssignmentExpression} AssignmentExpressionNode\r\n * @typedef {import(\"oxlint\").ESTree.Function | import(\"oxlint\").ESTree.ArrowFunctionExpression} FunctionLikeNode\r\n */\r\n\r\n/**\r\n * @typedef {object} RecordedAssignment\r\n * @property {ESTExpression} node\r\n * @property {string[]} names\r\n */\r\n\r\n/**\r\n * @typedef {object} NestedFunctionRecord\r\n * @property {FunctionLikeNode} node\r\n * @property {string} name\r\n */\r\n\r\n/**\r\n * @typedef {object} FunctionContext\r\n * @property {FunctionLikeNode} node\r\n * @property {FunctionContext | null} parent\r\n * @property {string} name\r\n * @property {boolean} returnsJsx\r\n * @property {Set<string>} jsxBindingNames\r\n * @property {RecordedAssignment[]} jsxAssignments\r\n * @property {NestedFunctionRecord[]} nestedJsxChildren\r\n */\r\n\r\nconst JSX_NODE_TYPES = new Set([\"JSXElement\", \"JSXFragment\"]);\r\nconst FUNCTION_NODE_TYPES = new Set([\"FunctionDeclaration\", \"FunctionExpression\", \"ArrowFunctionExpression\"]);\r\n\r\n/**\r\n * @param {unknown} name\r\n * @returns {name is string}\r\n */\r\nexport const isComponentName = (name) => typeof name === \"string\" && /^[A-Z]/.test(name);\r\n\r\n/**\r\n * @param {unknown} name\r\n * @returns {name is string}\r\n */\r\nexport const isHookName = (name) => typeof name === \"string\" && name.startsWith(\"use\");\r\n\r\n/**\r\n * @param {unknown} node\r\n * @returns {node is ESTNode & { type: string }}\r\n */\r\nconst isNode = (node) => Boolean(node && typeof node === \"object\" && \"type\" in node);\r\n\r\n/**\r\n * @param {unknown} node\r\n * @returns {node is FunctionLikeNode}\r\n */\r\nconst isFunctionLike = (node) => isNode(node) && FUNCTION_NODE_TYPES.has(node.type);\r\n\r\n/**\r\n * @param {ESTNode | null | undefined} node\r\n * @returns {FunctionLikeNode | null}\r\n */\r\nexport const getEnclosingFunction = (node) => {\r\n const findFunction = (current) => {\r\n if (!current) return null;\r\n if (isFunctionLike(current)) {\r\n return current;\r\n }\r\n return findFunction(isNode(current) ? (current.parent ?? null) : null);\r\n };\r\n return findFunction(isNode(node) ? (node.parent ?? null) : null);\r\n};\r\n\r\n/**\r\n * @param {FunctionLikeNode} node\r\n */\r\nconst isFunctionUsedAsJsxProp = (node) => {\r\n const checkJsxProp = (current) => {\r\n if (!current) return false;\r\n if (current.type === \"JSXAttribute\") {\r\n return true;\r\n }\r\n if (isFunctionLike(current)) {\r\n return false;\r\n }\r\n return checkJsxProp(isNode(current) ? (current.parent ?? null) : null);\r\n };\r\n return checkJsxProp(isNode(node) ? (node.parent ?? null) : null);\r\n};\r\n\r\n/**\r\n * @param {FunctionLikeNode} node\r\n */\r\nconst isFunctionImmediatelyInvoked = (node) => {\r\n const parent = isNode(node) ? (node.parent ?? null) : null;\r\n if (!parent) return false;\r\n\r\n // Check if the function is the callee of a CallExpression (i.e., it's immediately invoked)\r\n if (parent.type === \"CallExpression\" && parent.callee === node) {\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * @param {ESTExpression | null | undefined} root\r\n */\r\nconst expressionContainsJsx = (root) => {\r\n if (!root || !isNode(root)) return false;\r\n\r\n const stack = [root];\r\n\r\n while (stack.length > 0) {\r\n const current = stack.pop();\r\n if (!current || !isNode(current)) continue;\r\n\r\n if (JSX_NODE_TYPES.has(current.type)) {\r\n return true;\r\n }\r\n\r\n if (FUNCTION_NODE_TYPES.has(current.type) && current !== root) {\r\n continue;\r\n }\r\n\r\n for (const key of Object.keys(current)) {\r\n if (key === \"parent\") continue;\r\n\r\n const value = current[key];\r\n if (!value) continue;\r\n\r\n if (Array.isArray(value)) {\r\n for (const element of value) {\r\n if (isNode(element)) {\r\n stack.push(element);\r\n }\r\n }\r\n } else if (isNode(value)) {\r\n stack.push(value);\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * @param {ESTExpression | null | undefined} root\r\n * @param {Set<string>} bindingNames\r\n */\r\nconst expressionProducesJsx = (root, bindingNames) => {\r\n if (!root) return false;\r\n if (expressionContainsJsx(root)) return true;\r\n\r\n if (!isNode(root)) return false;\r\n\r\n const type = root.type;\r\n\r\n if (type === \"Identifier\") {\r\n return bindingNames.has(root.name);\r\n }\r\n\r\n if (type === \"ConditionalExpression\") {\r\n return expressionProducesJsx(root.consequent, bindingNames) || expressionProducesJsx(root.alternate, bindingNames);\r\n }\r\n\r\n if (type === \"LogicalExpression\") {\r\n return expressionProducesJsx(root.left, bindingNames) || expressionProducesJsx(root.right, bindingNames);\r\n }\r\n\r\n if (type === \"SequenceExpression\") {\r\n const expressions = root.expressions ?? [];\r\n const last = expressions[expressions.length - 1] ?? null;\r\n return expressionProducesJsx(last, bindingNames);\r\n }\r\n\r\n if (type === \"ArrayExpression\") {\r\n return root.elements.some((element) => {\r\n if (!element) return false;\r\n if (element.type === \"SpreadElement\") {\r\n return expressionProducesJsx(element.argument, bindingNames);\r\n }\r\n return expressionProducesJsx(element, bindingNames);\r\n });\r\n }\r\n\r\n if (type === \"ParenthesizedExpression\") {\r\n return expressionProducesJsx(root.expression, bindingNames);\r\n }\r\n\r\n if (type === \"AwaitExpression\" || type === \"UnaryExpression\" || type === \"UpdateExpression\") {\r\n return expressionProducesJsx(root.argument, bindingNames);\r\n }\r\n\r\n if (\r\n type === \"TSAsExpression\" ||\r\n type === \"TSTypeAssertion\" ||\r\n type === \"TSNonNullExpression\" ||\r\n type === \"ChainExpression\"\r\n ) {\r\n return expressionProducesJsx(root.expression, bindingNames);\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * @param {ESTPattern | null | undefined} pattern\r\n * @param {string[]} names\r\n */\r\nconst collectBindingNames = (pattern, names) => {\r\n if (!pattern || !isNode(pattern)) return;\r\n\r\n const type = pattern.type;\r\n\r\n if (type === \"Identifier\") {\r\n names.push(pattern.name);\r\n return;\r\n }\r\n\r\n if (type === \"ArrayPattern\") {\r\n for (const element of pattern.elements) {\r\n if (!element) continue;\r\n if (element.type === \"RestElement\") {\r\n collectBindingNames(element.argument, names);\r\n } else {\r\n collectBindingNames(element, names);\r\n }\r\n }\r\n return;\r\n }\r\n\r\n if (type === \"ObjectPattern\") {\r\n for (const property of pattern.properties) {\r\n if (!property) continue;\r\n if (property.type === \"Property\") {\r\n collectBindingNames(property.value, names);\r\n } else if (property.type === \"RestElement\") {\r\n collectBindingNames(property.argument, names);\r\n }\r\n }\r\n return;\r\n }\r\n\r\n if (type === \"AssignmentPattern\") {\r\n collectBindingNames(pattern.left, names);\r\n return;\r\n }\r\n\r\n if (type === \"RestElement\") {\r\n collectBindingNames(pattern.argument, names);\r\n }\r\n};\r\n\r\n/**\r\n * @param {FunctionLikeNode} node\r\n */\r\nexport const getFunctionName = (node) => {\r\n if (node.type === \"FunctionDeclaration\" && node.id && node.id.type === \"Identifier\") {\r\n return node.id.name;\r\n }\r\n\r\n if ((node.type === \"FunctionExpression\" || node.type === \"ArrowFunctionExpression\") && node.id) {\r\n if (node.id.type === \"Identifier\") return node.id.name;\r\n }\r\n\r\n const parent = node.parent;\r\n if (!parent || !isNode(parent)) return \"\";\r\n\r\n if (parent.type === \"VariableDeclarator\") {\r\n return parent.id && parent.id.type === \"Identifier\" ? parent.id.name : \"\";\r\n }\r\n\r\n if (parent.type === \"AssignmentExpression\") {\r\n return parent.left && parent.left.type === \"Identifier\" ? parent.left.name : \"\";\r\n }\r\n\r\n if (parent.type === \"Property\" || parent.type === \"MethodDefinition\") {\r\n return parent.key && parent.key.type === \"Identifier\" ? parent.key.name : \"\";\r\n }\r\n\r\n // Handle functions passed as arguments to calls (e.g., useCallback, useMemo)\r\n if (parent.type === \"CallExpression\") {\r\n const callParent = parent.parent;\r\n if (callParent && isNode(callParent)) {\r\n if (callParent.type === \"VariableDeclarator\") {\r\n return callParent.id && callParent.id.type === \"Identifier\" ? callParent.id.name : \"\";\r\n }\r\n if (callParent.type === \"AssignmentExpression\") {\r\n return callParent.left && callParent.left.type === \"Identifier\" ? callParent.left.name : \"\";\r\n }\r\n }\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\n/**\r\n * @param {string} name\r\n */\r\nconst describeFunction = (name) => (name ? `function '${name}'` : \"this function\");\r\n\r\n/**\r\n * @param {string} name\r\n */\r\nconst describeNested = (name) => (name ? `function '${name}'` : \"an anonymous function\");\r\n\r\n/**\r\n * @param {string[]} names\r\n * @param {string} fnName\r\n */\r\nconst createAssignmentMessage = (names, fnName) => {\r\n const target =\r\n names.length === 0\r\n ? \"local variables\"\r\n : names.length === 1\r\n ? `local '${names[0]}'`\r\n : `locals ${names.map((name) => `'${name}'`).join(\", \")}`;\r\n\r\n return `Avoid storing JSX in ${target} inside ${describeFunction(fnName)}; return the JSX directly instead.`;\r\n};\r\n\r\n/**\r\n * @param {string} childName\r\n * @param {string} parentName\r\n */\r\nconst createNestedFunctionMessage = (childName, parentName) =>\r\n `JSX-returning ${describeNested(childName)} should not be declared inside ${describeFunction(parentName)}. Extract it to module scope.`;\r\n\r\n/**\r\n * @param {string} name\r\n */\r\nconst createIIFEMessage = (name) =>\r\n `JSX-returning ${describeNested(name)} should not be declared as an immediately invoked function expression (IIFE). Extract it to a named function at module scope.`;\r\n\r\nconst rule = defineRule({\r\n meta: {\r\n type: \"problem\",\r\n docs: {\r\n description:\r\n \"Disallow JSX-returning functions and JSX-valued assignments within other functions that also return JSX.\",\r\n recommended: false,\r\n },\r\n schema: [],\r\n },\r\n\r\n createOnce(context) {\r\n /** @type {FunctionContext[]} */\r\n const functionStack = [];\r\n\r\n const currentFunction = () => functionStack[functionStack.length - 1] ?? null;\r\n\r\n /**\r\n * @param {FunctionLikeNode} node\r\n */\r\n const enterFunction = (node) => {\r\n const parent = currentFunction();\r\n /** @type {FunctionContext} */\r\n const fnCtx = {\r\n node,\r\n parent,\r\n name: getFunctionName(node),\r\n returnsJsx: false,\r\n jsxBindingNames: new Set(),\r\n jsxAssignments: [],\r\n nestedJsxChildren: [],\r\n };\r\n\r\n functionStack.push(fnCtx);\r\n\r\n if (node.type === \"ArrowFunctionExpression\" && node.body && node.body.type !== \"BlockStatement\") {\r\n if (expressionProducesJsx(node.body, fnCtx.jsxBindingNames)) {\r\n fnCtx.returnsJsx = true;\r\n }\r\n }\r\n };\r\n\r\n const exitFunction = () => {\r\n const fnCtx = functionStack.pop();\r\n if (!fnCtx) return;\r\n\r\n if (fnCtx.returnsJsx && isFunctionImmediatelyInvoked(fnCtx.node)) {\r\n context.report({\r\n node: fnCtx.node,\r\n message: createIIFEMessage(fnCtx.name),\r\n });\r\n return;\r\n }\r\n\r\n if (fnCtx.parent && fnCtx.returnsJsx && fnCtx.name && !isFunctionUsedAsJsxProp(fnCtx.node)) {\r\n fnCtx.parent.nestedJsxChildren.push({ node: fnCtx.node, name: fnCtx.name });\r\n }\r\n\r\n if (!fnCtx.returnsJsx) return;\r\n\r\n for (const assignment of fnCtx.jsxAssignments) {\r\n context.report({\r\n node: assignment.node,\r\n message: createAssignmentMessage(assignment.names, fnCtx.name),\r\n });\r\n }\r\n\r\n for (const nested of fnCtx.nestedJsxChildren) {\r\n context.report({\r\n node: nested.node,\r\n message: createNestedFunctionMessage(nested.name, fnCtx.name),\r\n });\r\n }\r\n };\r\n\r\n /** @param {ReturnStatementNode} node */\r\n const handleReturnStatement = (node) => {\r\n const fnCtx = currentFunction();\r\n if (!fnCtx) return;\r\n\r\n const argument = node.argument;\r\n if (!argument || isFunctionLike(argument)) return;\r\n\r\n if (expressionProducesJsx(argument, fnCtx.jsxBindingNames)) {\r\n fnCtx.returnsJsx = true;\r\n }\r\n };\r\n\r\n /** @param {VariableDeclaratorNode} node */\r\n const handleVariableDeclarator = (node) => {\r\n const fnCtx = currentFunction();\r\n if (!fnCtx) return;\r\n\r\n const init = node.init;\r\n if (!init || isFunctionLike(init)) return;\r\n if (!expressionContainsJsx(init)) return;\r\n\r\n const names = [];\r\n collectBindingNames(node.id, names);\r\n for (const name of names) {\r\n fnCtx.jsxBindingNames.add(name);\r\n }\r\n\r\n fnCtx.jsxAssignments.push({ node: init, names });\r\n };\r\n\r\n /** @param {AssignmentExpressionNode} node */\r\n const handleAssignmentExpression = (node) => {\r\n if (node.operator !== \"=\") return;\r\n\r\n const fnCtx = currentFunction();\r\n if (!fnCtx) return;\r\n\r\n const right = node.right;\r\n if (!right || isFunctionLike(right)) return;\r\n if (!expressionContainsJsx(right)) return;\r\n\r\n const names = [];\r\n if (node.left && node.left.type === \"Identifier\") {\r\n names.push(node.left.name);\r\n fnCtx.jsxBindingNames.add(node.left.name);\r\n }\r\n\r\n fnCtx.jsxAssignments.push({ node: right, names });\r\n };\r\n\r\n return /** @type {import(\"oxlint\").VisitorWithHooks} */ ({\r\n FunctionDeclaration(node) {\r\n if (isFunctionLike(node)) enterFunction(node);\r\n },\r\n \"FunctionDeclaration:exit\": exitFunction,\r\n FunctionExpression(node) {\r\n if (isFunctionLike(node)) enterFunction(node);\r\n },\r\n \"FunctionExpression:exit\": exitFunction,\r\n ArrowFunctionExpression(node) {\r\n if (isFunctionLike(node)) enterFunction(node);\r\n },\r\n \"ArrowFunctionExpression:exit\": exitFunction,\r\n ReturnStatement(node) {\r\n if (node.type === \"ReturnStatement\") handleReturnStatement(node);\r\n },\r\n VariableDeclarator(node) {\r\n if (node.type === \"VariableDeclarator\") handleVariableDeclarator(node);\r\n },\r\n AssignmentExpression(node) {\r\n if (node.type === \"AssignmentExpression\") handleAssignmentExpression(node);\r\n },\r\n });\r\n },\r\n});\r\n\r\nexport const noInlineComponentsRule = rule;\r\n\r\nexport default {\r\n meta: { name: \"no-inline-components\" },\r\n rules: { \"no-inline-components\": rule },\r\n};\r\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import * as oxlint27 from "oxlint";
2
+
3
+ //#region src/oxlint-plugins/no-react-namespace.d.ts
4
+ declare const noReactNamespaceRule: oxlint27.Rule;
5
+ declare namespace _default {
6
+ namespace meta {
7
+ let name: string;
8
+ }
9
+ let rules: {
10
+ "no-react-namespace": oxlint27.Rule;
11
+ };
12
+ }
13
+ type ESTNode = oxlint27.ESTree.Node;
14
+ //#endregion
15
+ export { ESTNode, _default as default, noReactNamespaceRule };
16
+ //# sourceMappingURL=no-react-namespace.d.mts.map
@@ -0,0 +1,75 @@
1
+ import { defineRule } from "oxlint";
2
+
3
+ //#region src/oxlint-plugins/no-react-namespace.js
4
+ /** @typedef {import("oxlint").ESTree.Node} ESTNode */
5
+ /**
6
+ * Check if a MemberExpression is accessing the React namespace
7
+ * @param {ESTNode} node
8
+ * @returns {boolean}
9
+ */
10
+ const isReactNamespaceAccess = (node) => {
11
+ if (node.type !== "MemberExpression") return false;
12
+ const object = node.object;
13
+ if (!object || object.type !== "Identifier" || object.name !== "React") return false;
14
+ return true;
15
+ };
16
+ /**
17
+ * Check if this is a type annotation context (TypeScript)
18
+ * @param {ESTNode} node
19
+ * @returns {boolean}
20
+ */
21
+ const isTypeContext = (node) => {
22
+ const checkParent = (current) => {
23
+ if (!current) return false;
24
+ if (new Set([
25
+ "TSTypeReference",
26
+ "TSTypeAnnotation",
27
+ "TSTypeParameterInstantiation",
28
+ "TSInterfaceHeritage",
29
+ "TSTypeQuery",
30
+ "TSTypeAliasDeclaration",
31
+ "TSInterfaceDeclaration",
32
+ "TSTypeLiteral",
33
+ "TSPropertySignature",
34
+ "TSIndexSignature",
35
+ "TSMethodSignature",
36
+ "TSCallSignatureDeclaration",
37
+ "TSConstructSignatureDeclaration",
38
+ "TSExpressionWithTypeArguments"
39
+ ]).has(current.type)) return true;
40
+ if (current.type === "ExpressionStatement" || current.type === "VariableDeclarator" || current.type === "CallExpression" || current.type === "ReturnStatement") return false;
41
+ return checkParent(current.parent);
42
+ };
43
+ return checkParent(node.parent);
44
+ };
45
+ const rule = defineRule({
46
+ meta: {
47
+ type: "problem",
48
+ docs: {
49
+ description: "Disallow using the React namespace for accessing React APIs. Use destructured imports instead (e.g., import { useState } from 'react').",
50
+ recommended: true
51
+ },
52
+ schema: []
53
+ },
54
+ createOnce(context) {
55
+ return { MemberExpression(node) {
56
+ if (node.type !== "MemberExpression") return;
57
+ if (!isReactNamespaceAccess(node)) return;
58
+ if (isTypeContext(node)) return;
59
+ const propertyName = node.property && node.property.type === "Identifier" ? node.property.name : "property";
60
+ context.report({
61
+ node,
62
+ message: `Avoid using 'React.${propertyName}'. Import '${propertyName}' directly from 'react' instead (e.g., import { ${propertyName} } from 'react').`
63
+ });
64
+ } };
65
+ }
66
+ });
67
+ const noReactNamespaceRule = rule;
68
+ var no_react_namespace_default = {
69
+ meta: { name: "no-react-namespace" },
70
+ rules: { "no-react-namespace": rule }
71
+ };
72
+
73
+ //#endregion
74
+ export { no_react_namespace_default as default, noReactNamespaceRule };
75
+ //# sourceMappingURL=no-react-namespace.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-react-namespace.mjs","names":[],"sources":["../../src/oxlint-plugins/no-react-namespace.js"],"sourcesContent":["import { defineRule } from \"oxlint\";\r\n\r\n/** @typedef {import(\"oxlint\").ESTree.Node} ESTNode */\r\n\r\n/**\r\n * Check if a MemberExpression is accessing the React namespace\r\n * @param {ESTNode} node\r\n * @returns {boolean}\r\n */\r\nconst isReactNamespaceAccess = (node) => {\r\n if (node.type !== \"MemberExpression\") return false;\r\n\r\n const object = node.object;\r\n if (!object || object.type !== \"Identifier\" || object.name !== \"React\") {\r\n return false;\r\n }\r\n\r\n return true;\r\n};\r\n\r\n/**\r\n * Check if this is a type annotation context (TypeScript)\r\n * @param {ESTNode} node\r\n * @returns {boolean}\r\n */\r\nconst isTypeContext = (node) => {\r\n const checkParent = (current) => {\r\n if (!current) return false;\r\n\r\n // Type annotation contexts where React namespace is allowed\r\n const typeContextTypes = new Set([\r\n \"TSTypeReference\",\r\n \"TSTypeAnnotation\",\r\n \"TSTypeParameterInstantiation\",\r\n \"TSInterfaceHeritage\",\r\n \"TSTypeQuery\",\r\n \"TSTypeAliasDeclaration\",\r\n \"TSInterfaceDeclaration\",\r\n \"TSTypeLiteral\",\r\n \"TSPropertySignature\",\r\n \"TSIndexSignature\",\r\n \"TSMethodSignature\",\r\n \"TSCallSignatureDeclaration\",\r\n \"TSConstructSignatureDeclaration\",\r\n \"TSExpressionWithTypeArguments\",\r\n ]);\r\n\r\n if (typeContextTypes.has(current.type)) {\r\n return true;\r\n }\r\n\r\n // Stop at statement or expression boundaries\r\n if (\r\n current.type === \"ExpressionStatement\" ||\r\n current.type === \"VariableDeclarator\" ||\r\n current.type === \"CallExpression\" ||\r\n current.type === \"ReturnStatement\"\r\n ) {\r\n return false;\r\n }\r\n\r\n return checkParent(current.parent);\r\n };\r\n\r\n return checkParent(node.parent);\r\n};\r\n\r\nconst rule = defineRule({\r\n meta: {\r\n type: \"problem\",\r\n docs: {\r\n description:\r\n \"Disallow using the React namespace for accessing React APIs. Use destructured imports instead (e.g., import { useState } from 'react').\",\r\n recommended: true,\r\n },\r\n schema: [],\r\n },\r\n createOnce(context) {\r\n return /** @type {import(\"oxlint\").VisitorWithHooks} */ ({\r\n /**\r\n * @param {ESTNode} node\r\n */\r\n MemberExpression(node) {\r\n if (node.type !== \"MemberExpression\") return;\r\n\r\n if (!isReactNamespaceAccess(node)) return;\r\n\r\n // Allow React namespace in type annotations\r\n if (isTypeContext(node)) return;\r\n\r\n const propertyName = node.property && node.property.type === \"Identifier\" ? node.property.name : \"property\";\r\n\r\n context.report({\r\n node,\r\n message: `Avoid using 'React.${propertyName}'. Import '${propertyName}' directly from 'react' instead (e.g., import { ${propertyName} } from 'react').`,\r\n });\r\n },\r\n });\r\n },\r\n});\r\n\r\nexport const noReactNamespaceRule = rule;\r\n\r\nexport default {\r\n meta: { name: \"no-react-namespace\" },\r\n rules: { \"no-react-namespace\": rule },\r\n};\r\n"],"mappings":";;;;;;;;;AASA,MAAM,0BAA0B,SAAS;AACvC,KAAI,KAAK,SAAS,mBAAoB,QAAO;CAE7C,MAAM,SAAS,KAAK;AACpB,KAAI,CAAC,UAAU,OAAO,SAAS,gBAAgB,OAAO,SAAS,QAC7D,QAAO;AAGT,QAAO;;;;;;;AAQT,MAAM,iBAAiB,SAAS;CAC9B,MAAM,eAAe,YAAY;AAC/B,MAAI,CAAC,QAAS,QAAO;AAoBrB,MAjByB,IAAI,IAAI;GAC/B;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC,CAEmB,IAAI,QAAQ,KAAK,CACpC,QAAO;AAIT,MACE,QAAQ,SAAS,yBACjB,QAAQ,SAAS,wBACjB,QAAQ,SAAS,oBACjB,QAAQ,SAAS,kBAEjB,QAAO;AAGT,SAAO,YAAY,QAAQ,OAAO;;AAGpC,QAAO,YAAY,KAAK,OAAO;;AAGjC,MAAM,OAAO,WAAW;CACtB,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aACE;GACF,aAAa;GACd;EACD,QAAQ,EAAE;EACX;CACD,WAAW,SAAS;AAClB,SAAyD,EAIvD,iBAAiB,MAAM;AACrB,OAAI,KAAK,SAAS,mBAAoB;AAEtC,OAAI,CAAC,uBAAuB,KAAK,CAAE;AAGnC,OAAI,cAAc,KAAK,CAAE;GAEzB,MAAM,eAAe,KAAK,YAAY,KAAK,SAAS,SAAS,eAAe,KAAK,SAAS,OAAO;AAEjG,WAAQ,OAAO;IACb;IACA,SAAS,sBAAsB,aAAa,aAAa,aAAa,kDAAkD,aAAa;IACtI,CAAC;KAEL;;CAEJ,CAAC;AAEF,MAAa,uBAAuB;AAEpC,iCAAe;CACb,MAAM,EAAE,MAAM,sBAAsB;CACpC,OAAO,EAAE,sBAAsB,MAAM;CACtC"}
@@ -0,0 +1,15 @@
1
+ import * as oxlint33 from "oxlint";
2
+
3
+ //#region src/oxlint-plugins/no-switch-plugin.d.ts
4
+ declare namespace _default {
5
+ namespace meta {
6
+ let name: string;
7
+ }
8
+ let rules: {
9
+ "no-switch": oxlint33.Rule;
10
+ };
11
+ }
12
+ type ESTNode = oxlint33.ESTree.Node;
13
+ //#endregion
14
+ export { ESTNode, _default as default };
15
+ //# sourceMappingURL=no-switch-plugin.d.mts.map
@@ -0,0 +1,31 @@
1
+ import { defineRule } from "oxlint";
2
+
3
+ //#region src/oxlint-plugins/no-switch-plugin.js
4
+ /** @typedef {import("oxlint").ESTree.Node} ESTNode */
5
+ const noSwitchRule = defineRule({
6
+ meta: {
7
+ type: "problem",
8
+ docs: {
9
+ description: "Disallow switch/case statements",
10
+ recommended: true
11
+ },
12
+ schema: []
13
+ },
14
+ createOnce(context) {
15
+ return { SwitchStatement(node) {
16
+ if (node.type !== "SwitchStatement") return;
17
+ context.report({
18
+ node,
19
+ message: "Use of switch/case is disallowed. Use object map or if/else instead."
20
+ });
21
+ } };
22
+ }
23
+ });
24
+ var no_switch_plugin_default = {
25
+ meta: { name: "no-switch-plugin" },
26
+ rules: { "no-switch": noSwitchRule }
27
+ };
28
+
29
+ //#endregion
30
+ export { no_switch_plugin_default as default };
31
+ //# sourceMappingURL=no-switch-plugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-switch-plugin.mjs","names":[],"sources":["../../src/oxlint-plugins/no-switch-plugin.js"],"sourcesContent":["import { defineRule } from \"oxlint\";\n\n/** @typedef {import(\"oxlint\").ESTree.Node} ESTNode */\n\nconst noSwitchRule = defineRule({\n meta: {\n type: \"problem\",\n docs: {\n description: \"Disallow switch/case statements\",\n recommended: true,\n },\n schema: [],\n },\n createOnce(context) {\n return /** @type {import(\"oxlint\").VisitorWithHooks} */ ({\n /**\n * @param {ESTNode} node\n */\n SwitchStatement(node) {\n if (node.type !== \"SwitchStatement\") return;\n\n context.report({\n node,\n message: \"Use of switch/case is disallowed. Use object map or if/else instead.\",\n });\n },\n });\n },\n});\n\nexport default {\n meta: {\n name: \"no-switch-plugin\",\n },\n rules: {\n \"no-switch\": noSwitchRule,\n },\n};\n"],"mappings":";;;;AAIA,MAAM,eAAe,WAAW;CAC9B,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aAAa;GACb,aAAa;GACd;EACD,QAAQ,EAAE;EACX;CACD,WAAW,SAAS;AAClB,SAAyD,EAIvD,gBAAgB,MAAM;AACpB,OAAI,KAAK,SAAS,kBAAmB;AAErC,WAAQ,OAAO;IACb;IACA,SAAS;IACV,CAAC;KAEL;;CAEJ,CAAC;AAEF,+BAAe;CACb,MAAM,EACJ,MAAM,oBACP;CACD,OAAO,EACL,aAAa,cACd;CACF"}
@@ -0,0 +1,16 @@
1
+ import * as oxlint10 from "oxlint";
2
+
3
+ //#region src/oxlint-plugins/no-top-level-let.d.ts
4
+ declare const noTopLevelLetRule: oxlint10.Rule;
5
+ declare namespace _default {
6
+ namespace meta {
7
+ let name: string;
8
+ }
9
+ let rules: {
10
+ "no-top-level-let": oxlint10.Rule;
11
+ };
12
+ }
13
+ type ESTNode = oxlint10.ESTree.Node;
14
+ //#endregion
15
+ export { ESTNode, _default as default, noTopLevelLetRule };
16
+ //# sourceMappingURL=no-top-level-let.d.mts.map
@@ -0,0 +1,66 @@
1
+ import { defineRule } from "oxlint";
2
+
3
+ //#region src/oxlint-plugins/no-top-level-let.js
4
+ /** @typedef {import("oxlint").ESTree.Node} ESTNode */
5
+ /**
6
+ * Get the enclosing function node for a given node
7
+ * @param {ESTNode} node
8
+ * @returns {ESTNode | null}
9
+ */
10
+ const getEnclosingFunction = (node) => {
11
+ const findFunction = (current) => {
12
+ if (!current) return null;
13
+ if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") return current;
14
+ return findFunction(current.parent);
15
+ };
16
+ return findFunction(node.parent);
17
+ };
18
+ /**
19
+ * Check if a node is inside a loop
20
+ * @param {ESTNode} node
21
+ * @param {ESTNode} stopAt - Stop searching when we reach this node
22
+ * @returns {boolean}
23
+ */
24
+ const isInsideLoop = (node, stopAt) => {
25
+ const checkLoop = (current) => {
26
+ if (!current || current === stopAt) return false;
27
+ if (current.type === "ForStatement" || current.type === "ForInStatement" || current.type === "ForOfStatement" || current.type === "WhileStatement" || current.type === "DoWhileStatement") return true;
28
+ return checkLoop(current.parent);
29
+ };
30
+ return checkLoop(node.parent);
31
+ };
32
+ const rule = defineRule({
33
+ meta: {
34
+ type: "problem",
35
+ docs: {
36
+ description: "Disallow top-level `let` declarations inside functions to prevent conditional reassignment.",
37
+ recommended: false
38
+ },
39
+ schema: []
40
+ },
41
+ createOnce(context) {
42
+ return { VariableDeclaration(rawNode) {
43
+ if (rawNode.type !== "VariableDeclaration") return;
44
+ const node = rawNode;
45
+ if (node.kind !== "let") return;
46
+ const fn = getEnclosingFunction(node);
47
+ if (!fn || fn.type !== "FunctionDeclaration" && fn.type !== "FunctionExpression" && fn.type !== "ArrowFunctionExpression") return;
48
+ const parent = node.parent;
49
+ if (!parent || parent.type !== "BlockStatement" || parent.parent !== fn) return;
50
+ if (isInsideLoop(node, fn)) return;
51
+ context.report({
52
+ node,
53
+ message: "Avoid using `let` at the top level of functions; prefer `const` with extracted functions to avoid conditional reassignment. Extract conditional logic into a separate function that returns the appropriate value."
54
+ });
55
+ } };
56
+ }
57
+ });
58
+ const noTopLevelLetRule = rule;
59
+ var no_top_level_let_default = {
60
+ meta: { name: "no-top-level-let" },
61
+ rules: { "no-top-level-let": rule }
62
+ };
63
+
64
+ //#endregion
65
+ export { no_top_level_let_default as default, noTopLevelLetRule };
66
+ //# sourceMappingURL=no-top-level-let.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-top-level-let.mjs","names":[],"sources":["../../src/oxlint-plugins/no-top-level-let.js"],"sourcesContent":["import { defineRule } from \"oxlint\";\r\n\r\n/** @typedef {import(\"oxlint\").ESTree.Node} ESTNode */\r\n\r\n/**\r\n * Get the enclosing function node for a given node\r\n * @param {ESTNode} node\r\n * @returns {ESTNode | null}\r\n */\r\nconst getEnclosingFunction = (node) => {\r\n const findFunction = (current) => {\r\n if (!current) return null;\r\n if (\r\n current.type === \"FunctionDeclaration\" ||\r\n current.type === \"FunctionExpression\" ||\r\n current.type === \"ArrowFunctionExpression\"\r\n ) {\r\n return current;\r\n }\r\n return findFunction(current.parent);\r\n };\r\n return findFunction(node.parent);\r\n};\r\n\r\n/**\r\n * Check if a node is inside a loop\r\n * @param {ESTNode} node\r\n * @param {ESTNode} stopAt - Stop searching when we reach this node\r\n * @returns {boolean}\r\n */\r\nconst isInsideLoop = (node, stopAt) => {\r\n const checkLoop = (current) => {\r\n if (!current || current === stopAt) return false;\r\n if (\r\n current.type === \"ForStatement\" ||\r\n current.type === \"ForInStatement\" ||\r\n current.type === \"ForOfStatement\" ||\r\n current.type === \"WhileStatement\" ||\r\n current.type === \"DoWhileStatement\"\r\n ) {\r\n return true;\r\n }\r\n return checkLoop(current.parent);\r\n };\r\n return checkLoop(node.parent);\r\n};\r\n\r\nconst rule = defineRule({\r\n meta: {\r\n type: \"problem\",\r\n docs: {\r\n description: \"Disallow top-level `let` declarations inside functions to prevent conditional reassignment.\",\r\n recommended: false,\r\n },\r\n schema: [],\r\n },\r\n\r\n createOnce(context) {\r\n return /** @type {import(\"oxlint\").VisitorWithHooks} */ ({\r\n /**\r\n * @param {ESTNode} rawNode\r\n */\r\n VariableDeclaration(rawNode) {\r\n if (rawNode.type !== \"VariableDeclaration\") return;\r\n const node = rawNode;\r\n\r\n if (node.kind !== \"let\") return;\r\n\r\n const fn = getEnclosingFunction(node);\r\n if (\r\n !fn ||\r\n (fn.type !== \"FunctionDeclaration\" &&\r\n fn.type !== \"FunctionExpression\" &&\r\n fn.type !== \"ArrowFunctionExpression\")\r\n ) {\r\n return;\r\n }\r\n\r\n const parent = node.parent;\r\n if (!parent || parent.type !== \"BlockStatement\" || parent.parent !== fn) return;\r\n\r\n // Allow let declarations inside loops\r\n if (isInsideLoop(node, fn)) return;\r\n\r\n context.report({\r\n node,\r\n message:\r\n \"Avoid using `let` at the top level of functions; prefer `const` with extracted functions to avoid conditional reassignment. Extract conditional logic into a separate function that returns the appropriate value.\",\r\n });\r\n },\r\n });\r\n },\r\n});\r\n\r\nexport const noTopLevelLetRule = rule;\r\n\r\nexport default {\r\n meta: { name: \"no-top-level-let\" },\r\n rules: { \"no-top-level-let\": rule },\r\n};\r\n"],"mappings":";;;;;;;;;AASA,MAAM,wBAAwB,SAAS;CACrC,MAAM,gBAAgB,YAAY;AAChC,MAAI,CAAC,QAAS,QAAO;AACrB,MACE,QAAQ,SAAS,yBACjB,QAAQ,SAAS,wBACjB,QAAQ,SAAS,0BAEjB,QAAO;AAET,SAAO,aAAa,QAAQ,OAAO;;AAErC,QAAO,aAAa,KAAK,OAAO;;;;;;;;AASlC,MAAM,gBAAgB,MAAM,WAAW;CACrC,MAAM,aAAa,YAAY;AAC7B,MAAI,CAAC,WAAW,YAAY,OAAQ,QAAO;AAC3C,MACE,QAAQ,SAAS,kBACjB,QAAQ,SAAS,oBACjB,QAAQ,SAAS,oBACjB,QAAQ,SAAS,oBACjB,QAAQ,SAAS,mBAEjB,QAAO;AAET,SAAO,UAAU,QAAQ,OAAO;;AAElC,QAAO,UAAU,KAAK,OAAO;;AAG/B,MAAM,OAAO,WAAW;CACtB,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aAAa;GACb,aAAa;GACd;EACD,QAAQ,EAAE;EACX;CAED,WAAW,SAAS;AAClB,SAAyD,EAIvD,oBAAoB,SAAS;AAC3B,OAAI,QAAQ,SAAS,sBAAuB;GAC5C,MAAM,OAAO;AAEb,OAAI,KAAK,SAAS,MAAO;GAEzB,MAAM,KAAK,qBAAqB,KAAK;AACrC,OACE,CAAC,MACA,GAAG,SAAS,yBACX,GAAG,SAAS,wBACZ,GAAG,SAAS,0BAEd;GAGF,MAAM,SAAS,KAAK;AACpB,OAAI,CAAC,UAAU,OAAO,SAAS,oBAAoB,OAAO,WAAW,GAAI;AAGzE,OAAI,aAAa,MAAM,GAAG,CAAE;AAE5B,WAAQ,OAAO;IACb;IACA,SACE;IACH,CAAC;KAEL;;CAEJ,CAAC;AAEF,MAAa,oBAAoB;AAEjC,+BAAe;CACb,MAAM,EAAE,MAAM,oBAAoB;CAClC,OAAO,EAAE,oBAAoB,MAAM;CACpC"}