oxlint-plugin-arch 0.12.5 → 0.13.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.
- package/CHANGELOG.md +106 -0
- package/README.md +4 -4
- package/dist/index.js +1204 -170
- package/dist/preset/preset-effect.d.ts +3 -0
- package/dist/preset/preset-recipes.d.ts +10 -0
- package/dist/preset/preset.constants.d.ts +17 -2
- package/dist/preset/preset.d.ts +11 -1
- package/dist/preset/preset.js +756 -223
- package/dist/preset/preset.utils.d.ts +6 -0
- package/dist/rules/code/code-delegate.d.ts +1 -0
- package/dist/rules/effect/effect-layer-file.d.ts +1 -0
- package/dist/rules/effect/effect-layers.d.ts +1 -0
- package/dist/rules/effect/effect-merge-pipe.d.ts +1 -0
- package/dist/rules/effect/effect-schema-first.d.ts +1 -0
- package/dist/rules/effect/effect-values-first.d.ts +1 -0
- package/dist/rules/react/react-query-props.d.ts +1 -0
- package/dist/rules/types/types-duplicate.d.ts +1 -0
- package/dist/types/backend.types.d.ts +2 -3
- package/dist/types/code.types.d.ts +6 -0
- package/dist/types/effect.types.d.ts +46 -0
- package/dist/types/files.types.d.ts +3 -2
- package/dist/types/preset.types.d.ts +34 -23
- package/dist/types/react.types.d.ts +4 -0
- package/dist/types/schemas.types.d.ts +2 -0
- package/dist/types/types.types.d.ts +8 -0
- package/dist/utils/effect.utils.d.ts +5 -0
- package/dist/vendor/dillon-anti-slop/index.js +4 -1
- package/package.json +25 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
+
|
|
1
4
|
// src/index.ts
|
|
2
5
|
import { eslintCompatPlugin } from "@oxlint/plugins";
|
|
3
6
|
|
|
@@ -34,7 +37,7 @@ function optionsPatternsTest(patterns, value) {
|
|
|
34
37
|
function optionsGlob(pattern) {
|
|
35
38
|
const negated = [];
|
|
36
39
|
const source = pattern.replaceAll(/!\(([^()]*)\)/g, (_, options) => {
|
|
37
|
-
negated.push(options.split("|").map((option) => option.replaceAll(/[.+^$()|[\]
|
|
40
|
+
negated.push(options.split("|").map((option) => option.replaceAll(/[.+^$()|[\]\\?{}]/g, "\\$&").replaceAll("*", "[^/]*")).join("|"));
|
|
38
41
|
return `\x02${negated.length - 1}\x03`;
|
|
39
42
|
}).replaceAll(/[.+^$()|[\]\\]/g, "\\$&").replaceAll("?", "[^/]").replaceAll("**/", "\x00").replaceAll("**", "\x01").replaceAll("*", "[^/]*").replaceAll("\x00", "(?:.*/)?").replaceAll("\x01", ".*").replaceAll(/\{([^}]*)\}/g, (_, options) => `(?:${options.split(",").join("|")})`);
|
|
40
43
|
return new RegExp(`^${negated.reduce((text, names, index) => text.replace(`\x02${index}\x03`, `(?!(?:${names})(?:/|$))[^/]*`), source)}$`);
|
|
@@ -280,16 +283,14 @@ var backendOrpcOutput = defineRule2({
|
|
|
280
283
|
type: "object",
|
|
281
284
|
additionalProperties: false,
|
|
282
285
|
properties: {
|
|
283
|
-
composers: { type: "array", items: { type: "string" } },
|
|
284
286
|
handler: { type: "string" },
|
|
285
287
|
output: { type: "string" }
|
|
286
|
-
}
|
|
287
|
-
required: ["composers"]
|
|
288
|
+
}
|
|
288
289
|
}
|
|
289
290
|
],
|
|
290
291
|
messages: {
|
|
291
292
|
missing: "oRPC procedures must declare .output() before .handler().",
|
|
292
|
-
invalid: "oRPC .output() must use a named schema or
|
|
293
|
+
invalid: "oRPC .output() must use a named schema or a plain function called with a named schema."
|
|
293
294
|
}
|
|
294
295
|
},
|
|
295
296
|
createOnce(context) {
|
|
@@ -298,7 +299,7 @@ var backendOrpcOutput = defineRule2({
|
|
|
298
299
|
if (node.callee.type !== "MemberExpression") {
|
|
299
300
|
return;
|
|
300
301
|
}
|
|
301
|
-
const {
|
|
302
|
+
const { handler: handlerMethod = "handler", output: outputMethod = "output" } = optionsFirst(context, {});
|
|
302
303
|
if (astMemberName(node.callee) !== handlerMethod) {
|
|
303
304
|
return;
|
|
304
305
|
}
|
|
@@ -308,7 +309,7 @@ var backendOrpcOutput = defineRule2({
|
|
|
308
309
|
return;
|
|
309
310
|
}
|
|
310
311
|
const schema = output.arguments.at(0);
|
|
311
|
-
const named = schema?.type === "Identifier" || schema?.type === "CallExpression" && schema.callee.type === "Identifier" &&
|
|
312
|
+
const named = schema?.type === "Identifier" || schema?.type === "CallExpression" && schema.callee.type === "Identifier" && schema.arguments[0]?.type === "Identifier";
|
|
312
313
|
if (!named) {
|
|
313
314
|
context.report({ node: output, messageId: "invalid" });
|
|
314
315
|
}
|
|
@@ -968,6 +969,12 @@ function boundariesResolveTarget(options, file, source) {
|
|
|
968
969
|
}
|
|
969
970
|
|
|
970
971
|
// src/rules/backend/backend-sql-like.ts
|
|
972
|
+
var backendSqlLikeDefaults = {
|
|
973
|
+
methods: ["like", "ilike"],
|
|
974
|
+
sanitizers: ["escapeLikeWildcards"],
|
|
975
|
+
bindings: true,
|
|
976
|
+
operators: ["where"]
|
|
977
|
+
};
|
|
971
978
|
var backendSqlLike = defineRule5({
|
|
972
979
|
meta: {
|
|
973
980
|
type: "problem",
|
|
@@ -980,17 +987,16 @@ var backendSqlLike = defineRule5({
|
|
|
980
987
|
sanitizers: { type: "array", items: { type: "string" } },
|
|
981
988
|
bindings: { type: "boolean" },
|
|
982
989
|
operators: { type: "array", items: { type: "string" } }
|
|
983
|
-
}
|
|
984
|
-
required: ["methods", "sanitizers"]
|
|
990
|
+
}
|
|
985
991
|
}
|
|
986
992
|
],
|
|
987
993
|
messages: { unescaped: ".{{method}}() values must use a configured sanitizer." }
|
|
988
994
|
},
|
|
989
995
|
createOnce(context) {
|
|
990
|
-
let options =
|
|
996
|
+
let options = backendSqlLikeDefaults;
|
|
991
997
|
const seen = new Set;
|
|
992
998
|
function sanitizedBinding(identifier, name) {
|
|
993
|
-
const variable = options.bindings
|
|
999
|
+
const variable = options.bindings ? boundariesDeclaredVariable(context.sourceCode.getScope(identifier), name) : null;
|
|
994
1000
|
const declarator = variable?.defs.length === 1 && variable.defs[0].type === "Variable" ? variable.defs[0].node : undefined;
|
|
995
1001
|
const statement = declarator?.parent?.parent;
|
|
996
1002
|
if (!variable || declarator?.type !== "VariableDeclarator" || seen.has(variable) || !(statement?.type === "Program" || statement?.type === "ExportNamedDeclaration" && statement.parent.type === "Program") || variable.references.some((reference) => reference.isWrite() && !reference.init)) {
|
|
@@ -1031,8 +1037,8 @@ var backendSqlLike = defineRule5({
|
|
|
1031
1037
|
if (node.callee.type !== "MemberExpression") {
|
|
1032
1038
|
return;
|
|
1033
1039
|
}
|
|
1034
|
-
options = optionsFirst(context);
|
|
1035
|
-
const { methods, operators: operatorMethods
|
|
1040
|
+
options = { ...backendSqlLikeDefaults, ...optionsFirst(context, {}) };
|
|
1041
|
+
const { methods, operators: operatorMethods } = options;
|
|
1036
1042
|
const method = astMemberName(node.callee);
|
|
1037
1043
|
if (!method) {
|
|
1038
1044
|
return;
|
|
@@ -2013,12 +2019,82 @@ var codeConstructor = defineRule13({
|
|
|
2013
2019
|
}
|
|
2014
2020
|
});
|
|
2015
2021
|
|
|
2022
|
+
// src/rules/code/code-delegate.ts
|
|
2023
|
+
import { defineRule as defineRule14 } from "@oxlint/plugins";
|
|
2024
|
+
var codeDelegate = defineRule14({
|
|
2025
|
+
meta: {
|
|
2026
|
+
type: "suggestion",
|
|
2027
|
+
schema: [
|
|
2028
|
+
{
|
|
2029
|
+
type: "object",
|
|
2030
|
+
additionalProperties: false,
|
|
2031
|
+
properties: {
|
|
2032
|
+
methods: { type: "array", items: { type: "string" } },
|
|
2033
|
+
reads: { type: "array", items: { type: "string" } },
|
|
2034
|
+
max: { type: "integer", minimum: 0 }
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
],
|
|
2038
|
+
messages: {
|
|
2039
|
+
statement: "A handler only delegates: read services, make one call, return. Move this to an action.",
|
|
2040
|
+
calls: "A handler's yielded or awaited calls are limited to {{max}}; move the rest into the action it calls.",
|
|
2041
|
+
ternary: "A handler does not branch; move the condition into the action it calls.",
|
|
2042
|
+
nested: "A handler holds no function; move it into the action it calls."
|
|
2043
|
+
}
|
|
2044
|
+
},
|
|
2045
|
+
createOnce(context) {
|
|
2046
|
+
return {
|
|
2047
|
+
CallExpression(node) {
|
|
2048
|
+
const { methods = ["handler", "effect"], reads = ["Effect.serviceOption"], max = 1 } = optionsFirst(context, {});
|
|
2049
|
+
if (!methods.includes(astCallName(node) ?? "")) {
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
const awaited = (value) => value?.type === "YieldExpression" || value?.type === "AwaitExpression";
|
|
2053
|
+
for (const handler of node.arguments.filter(astIsInlineFunction)) {
|
|
2054
|
+
let calls = 0;
|
|
2055
|
+
const scan = (value) => astSome(value, (child) => {
|
|
2056
|
+
if (child.type === "ConditionalExpression") {
|
|
2057
|
+
context.report({ node: child, messageId: "ternary" });
|
|
2058
|
+
}
|
|
2059
|
+
if (child.type === "FunctionDeclaration" || astIsInlineFunction(child)) {
|
|
2060
|
+
context.report({ node: child, messageId: "nested" });
|
|
2061
|
+
}
|
|
2062
|
+
const target = awaited(child) && "argument" in child ? child.argument : null;
|
|
2063
|
+
if (target?.type === "CallExpression" && !reads.includes(astDottedName(target.callee) ?? "")) {
|
|
2064
|
+
calls += 1;
|
|
2065
|
+
if (calls > max) {
|
|
2066
|
+
context.report({
|
|
2067
|
+
node: child,
|
|
2068
|
+
messageId: "calls",
|
|
2069
|
+
data: { max: String(max) }
|
|
2070
|
+
});
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
return false;
|
|
2074
|
+
}, (child) => child.type !== "FunctionDeclaration" && !astIsInlineFunction(child));
|
|
2075
|
+
const { body } = handler;
|
|
2076
|
+
if (body && body.type !== "BlockStatement") {
|
|
2077
|
+
scan(body);
|
|
2078
|
+
}
|
|
2079
|
+
for (const statement of body?.type === "BlockStatement" ? body.body : []) {
|
|
2080
|
+
const allowed = statement.type === "ReturnStatement" || statement.type === "VariableDeclaration" && statement.declarations.every((declarator) => awaited(declarator.init)) || statement.type === "ExpressionStatement" && awaited(statement.expression) && "argument" in statement.expression && statement.expression.argument?.type === "CallExpression";
|
|
2081
|
+
if (!allowed) {
|
|
2082
|
+
context.report({ node: statement, messageId: "statement" });
|
|
2083
|
+
}
|
|
2084
|
+
scan(statement);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
});
|
|
2091
|
+
|
|
2016
2092
|
// src/rules/code/code-double-negation.ts
|
|
2017
2093
|
var codeDoubleNegation = astSelectorRule('UnaryExpression[operator="!"] > UnaryExpression[operator="!"]', "Use Boolean(value) or an explicit comparison.");
|
|
2018
2094
|
|
|
2019
2095
|
// src/rules/code/code-function-nesting.ts
|
|
2020
|
-
import { defineRule as
|
|
2021
|
-
var codeFunctionNesting =
|
|
2096
|
+
import { defineRule as defineRule15 } from "@oxlint/plugins";
|
|
2097
|
+
var codeFunctionNesting = defineRule15({
|
|
2022
2098
|
meta: {
|
|
2023
2099
|
type: "suggestion",
|
|
2024
2100
|
schema: [
|
|
@@ -2059,7 +2135,7 @@ var codeFunctionNesting = defineRule14({
|
|
|
2059
2135
|
});
|
|
2060
2136
|
|
|
2061
2137
|
// src/rules/code/code-inline.ts
|
|
2062
|
-
import { defineRule as
|
|
2138
|
+
import { defineRule as defineRule16 } from "@oxlint/plugins";
|
|
2063
2139
|
|
|
2064
2140
|
// src/utils/source.utils.ts
|
|
2065
2141
|
var sourceDirective = /^\s*(?:\/\s*<(?:reference\b|amd-[\w-]+\b)|@ts-(?:check|ignore|expect-error|nocheck)\b|(?:#|@)__(?:PURE|NO_SIDE_EFFECTS)__\b|@jsx(?:ImportSource|Runtime|Frag)?\b|@vite-ignore\b|(?:[#@]\s*)?sourceMappingURL=|(?:es|ox)lint-(?:disable|enable)|prettier-ignore|biome-ignore|[cv]8 ignore|istanbul ignore|webpack[A-Z])/;
|
|
@@ -2144,7 +2220,7 @@ var codeInlineEffects = new Set([
|
|
|
2144
2220
|
function codeInlineEffectBetween(program, start, end) {
|
|
2145
2221
|
return astSome(program, (node) => node.range[0] >= start && node.range[1] <= end && (codeInlineEffects.has(node.type) || node.type === "UnaryExpression" && node.operator === "delete"), (node) => node.range[1] > start && node.range[0] < end && !(node.range[0] >= start && (node.type === "FunctionDeclaration" || astIsInlineFunction(node))));
|
|
2146
2222
|
}
|
|
2147
|
-
var codeInline =
|
|
2223
|
+
var codeInline = defineRule16({
|
|
2148
2224
|
meta: {
|
|
2149
2225
|
type: "suggestion",
|
|
2150
2226
|
schema: [
|
|
@@ -2257,8 +2333,8 @@ var codeInline = defineRule15({
|
|
|
2257
2333
|
});
|
|
2258
2334
|
|
|
2259
2335
|
// src/rules/code/code-justified-call.ts
|
|
2260
|
-
import { defineRule as
|
|
2261
|
-
var codeJustifiedCall =
|
|
2336
|
+
import { defineRule as defineRule17 } from "@oxlint/plugins";
|
|
2337
|
+
var codeJustifiedCall = defineRule17({
|
|
2262
2338
|
meta: {
|
|
2263
2339
|
type: "problem",
|
|
2264
2340
|
schema: [
|
|
@@ -2312,8 +2388,8 @@ var codeJustifiedCall = defineRule16({
|
|
|
2312
2388
|
});
|
|
2313
2389
|
|
|
2314
2390
|
// src/rules/code/code-literal-in.ts
|
|
2315
|
-
import { defineRule as
|
|
2316
|
-
var codeLiteralIn =
|
|
2391
|
+
import { defineRule as defineRule18 } from "@oxlint/plugins";
|
|
2392
|
+
var codeLiteralIn = defineRule18({
|
|
2317
2393
|
meta: {
|
|
2318
2394
|
type: "suggestion",
|
|
2319
2395
|
schema: [
|
|
@@ -2354,7 +2430,7 @@ var codeLiteralIn = defineRule17({
|
|
|
2354
2430
|
});
|
|
2355
2431
|
|
|
2356
2432
|
// src/rules/code/code-mutable-state.ts
|
|
2357
|
-
import { defineRule as
|
|
2433
|
+
import { defineRule as defineRule19 } from "@oxlint/plugins";
|
|
2358
2434
|
var functionScopes = new Set([
|
|
2359
2435
|
"FunctionDeclaration",
|
|
2360
2436
|
"FunctionExpression",
|
|
@@ -2371,7 +2447,7 @@ function hasAncestor(node, test) {
|
|
|
2371
2447
|
}
|
|
2372
2448
|
return false;
|
|
2373
2449
|
}
|
|
2374
|
-
var codeMutableState =
|
|
2450
|
+
var codeMutableState = defineRule19({
|
|
2375
2451
|
meta: {
|
|
2376
2452
|
type: "problem",
|
|
2377
2453
|
schema: [
|
|
@@ -2429,7 +2505,7 @@ var codeMutableState = defineRule18({
|
|
|
2429
2505
|
});
|
|
2430
2506
|
|
|
2431
2507
|
// src/rules/code/code-object-params.ts
|
|
2432
|
-
import { defineRule as
|
|
2508
|
+
import { defineRule as defineRule20 } from "@oxlint/plugins";
|
|
2433
2509
|
function isObjectParam(node) {
|
|
2434
2510
|
if (node.type === "ObjectPattern") {
|
|
2435
2511
|
return true;
|
|
@@ -2443,7 +2519,7 @@ function isObjectParam(node) {
|
|
|
2443
2519
|
const annotation = node.typeAnnotation?.typeAnnotation;
|
|
2444
2520
|
return !annotation || annotation.type === "TSTypeReference" || annotation.type === "TSTypeLiteral" || annotation.type === "TSIntersectionType";
|
|
2445
2521
|
}
|
|
2446
|
-
var codeObjectParams =
|
|
2522
|
+
var codeObjectParams = defineRule20({
|
|
2447
2523
|
meta: {
|
|
2448
2524
|
type: "problem",
|
|
2449
2525
|
schema: [
|
|
@@ -2492,8 +2568,8 @@ var codeObjectParams = defineRule19({
|
|
|
2492
2568
|
});
|
|
2493
2569
|
|
|
2494
2570
|
// src/rules/code/code-paired-call.ts
|
|
2495
|
-
import { defineRule as
|
|
2496
|
-
var codePairedCall =
|
|
2571
|
+
import { defineRule as defineRule21 } from "@oxlint/plugins";
|
|
2572
|
+
var codePairedCall = defineRule21({
|
|
2497
2573
|
meta: {
|
|
2498
2574
|
type: "problem",
|
|
2499
2575
|
schema: [
|
|
@@ -2560,7 +2636,7 @@ var codePairedCall = defineRule20({
|
|
|
2560
2636
|
});
|
|
2561
2637
|
|
|
2562
2638
|
// src/rules/code/code-promise-mutation.ts
|
|
2563
|
-
import { defineRule as
|
|
2639
|
+
import { defineRule as defineRule22 } from "@oxlint/plugins";
|
|
2564
2640
|
function mutationBinding(node) {
|
|
2565
2641
|
if (node.type === "Identifier") {
|
|
2566
2642
|
return node;
|
|
@@ -2589,7 +2665,7 @@ function mutationBindings(node) {
|
|
|
2589
2665
|
const binding = mutationBinding(node);
|
|
2590
2666
|
return binding ? [binding] : [];
|
|
2591
2667
|
}
|
|
2592
|
-
var codePromiseMutation =
|
|
2668
|
+
var codePromiseMutation = defineRule22({
|
|
2593
2669
|
meta: {
|
|
2594
2670
|
type: "problem",
|
|
2595
2671
|
schema: [
|
|
@@ -2682,8 +2758,8 @@ var codePromiseMutation = defineRule21({
|
|
|
2682
2758
|
var codeSwitch = astSelectorRule("SwitchStatement", "Avoid switch statements.");
|
|
2683
2759
|
|
|
2684
2760
|
// src/rules/code/code-traced.ts
|
|
2685
|
-
import { defineRule as
|
|
2686
|
-
var codeTraced =
|
|
2761
|
+
import { defineRule as defineRule23 } from "@oxlint/plugins";
|
|
2762
|
+
var codeTraced = defineRule23({
|
|
2687
2763
|
meta: {
|
|
2688
2764
|
type: "problem",
|
|
2689
2765
|
schema: [
|
|
@@ -2770,7 +2846,7 @@ var codeTraced = defineRule22({
|
|
|
2770
2846
|
});
|
|
2771
2847
|
|
|
2772
2848
|
// src/rules/code/code-trivial-functions.ts
|
|
2773
|
-
import { defineRule as
|
|
2849
|
+
import { defineRule as defineRule24 } from "@oxlint/plugins";
|
|
2774
2850
|
var codeTrivialFunctionsBanned = [
|
|
2775
2851
|
"isRecord",
|
|
2776
2852
|
"isPlainObject",
|
|
@@ -2900,7 +2976,35 @@ function guardStatement(node, state) {
|
|
|
2900
2976
|
return guardFallback(declaration.init);
|
|
2901
2977
|
});
|
|
2902
2978
|
}
|
|
2903
|
-
|
|
2979
|
+
function codeTrivialFunctionsDefaults(program) {
|
|
2980
|
+
const starts = [];
|
|
2981
|
+
const names = new Set;
|
|
2982
|
+
for (const statement of program.body) {
|
|
2983
|
+
const declaration = statement.type === "ExportDefaultDeclaration" ? statement.declaration : undefined;
|
|
2984
|
+
if (declaration?.type === "FunctionDeclaration" || declaration && astIsInlineFunction(declaration)) {
|
|
2985
|
+
starts.push(declaration.start);
|
|
2986
|
+
} else if (declaration?.type === "Identifier") {
|
|
2987
|
+
names.add(declaration.name);
|
|
2988
|
+
} else if (statement.type === "ExportNamedDeclaration" && !statement.source) {
|
|
2989
|
+
const specifier = statement.specifiers.find((item) => astModuleName(item.exported) === "default");
|
|
2990
|
+
if (specifier) {
|
|
2991
|
+
names.add(astModuleName(specifier.local));
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
for (const statement of program.body) {
|
|
2996
|
+
if (statement.type === "FunctionDeclaration" && statement.id && names.has(statement.id.name)) {
|
|
2997
|
+
starts.push(statement.start);
|
|
2998
|
+
}
|
|
2999
|
+
for (const declarator of statement.type === "VariableDeclaration" ? statement.declarations : []) {
|
|
3000
|
+
if (declarator.id.type === "Identifier" && names.has(declarator.id.name) && declarator.init && astIsInlineFunction(declarator.init)) {
|
|
3001
|
+
starts.push(declarator.init.start);
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
}
|
|
3005
|
+
return starts;
|
|
3006
|
+
}
|
|
3007
|
+
var codeTrivialFunctions = defineRule24({
|
|
2904
3008
|
meta: {
|
|
2905
3009
|
type: "problem",
|
|
2906
3010
|
schema: [
|
|
@@ -2914,7 +3018,8 @@ var codeTrivialFunctions = defineRule23({
|
|
|
2914
3018
|
services: { type: "boolean" },
|
|
2915
3019
|
mode: { type: "string", enum: ["legacy", "precise"] },
|
|
2916
3020
|
deny: { type: "array", items: { type: "string" }, uniqueItems: true },
|
|
2917
|
-
guards: { type: "boolean" }
|
|
3021
|
+
guards: { type: "boolean" },
|
|
3022
|
+
defaults: { type: "boolean" }
|
|
2918
3023
|
}
|
|
2919
3024
|
}
|
|
2920
3025
|
],
|
|
@@ -2934,8 +3039,10 @@ var codeTrivialFunctions = defineRule23({
|
|
|
2934
3039
|
let checkServiceMethods = false;
|
|
2935
3040
|
const reported = new Set;
|
|
2936
3041
|
const checked = new Set;
|
|
3042
|
+
const defaults = new Set;
|
|
3043
|
+
let checkDefaults = true;
|
|
2937
3044
|
function checkHelper(node) {
|
|
2938
|
-
if (bannedNames.size === 0 && !checkGenericGuards || checked.has(node.start)) {
|
|
3045
|
+
if (bannedNames.size === 0 && !checkGenericGuards || checked.has(node.start) || defaults.has(node.start)) {
|
|
2939
3046
|
return;
|
|
2940
3047
|
}
|
|
2941
3048
|
checked.add(node.start);
|
|
@@ -3000,12 +3107,20 @@ var codeTrivialFunctions = defineRule23({
|
|
|
3000
3107
|
allowAsync = options.async ?? false;
|
|
3001
3108
|
reported.clear();
|
|
3002
3109
|
checked.clear();
|
|
3110
|
+
defaults.clear();
|
|
3111
|
+
checkDefaults = options.defaults ?? true;
|
|
3003
3112
|
},
|
|
3004
3113
|
FunctionDeclaration: checkHelper,
|
|
3005
3114
|
FunctionExpression: checkHelper,
|
|
3006
3115
|
ArrowFunctionExpression: checkHelper,
|
|
3007
3116
|
Program(program) {
|
|
3117
|
+
for (const start of checkDefaults ? [] : codeTrivialFunctionsDefaults(program)) {
|
|
3118
|
+
defaults.add(start);
|
|
3119
|
+
}
|
|
3008
3120
|
for (const { name, node } of exportsCheckedFunctions(program, true, checkServiceMethods, allowed)) {
|
|
3121
|
+
if (defaults.has(node.start)) {
|
|
3122
|
+
continue;
|
|
3123
|
+
}
|
|
3009
3124
|
checkHelper(node);
|
|
3010
3125
|
if (reported.has(node.start) || node.returnType?.typeAnnotation.type === "TSTypePredicate") {
|
|
3011
3126
|
continue;
|
|
@@ -3031,8 +3146,8 @@ var codeTrivialFunctions = defineRule23({
|
|
|
3031
3146
|
});
|
|
3032
3147
|
|
|
3033
3148
|
// src/rules/code/code-yield-argument.ts
|
|
3034
|
-
import { defineRule as
|
|
3035
|
-
var codeYieldArgument =
|
|
3149
|
+
import { defineRule as defineRule25 } from "@oxlint/plugins";
|
|
3150
|
+
var codeYieldArgument = defineRule25({
|
|
3036
3151
|
meta: {
|
|
3037
3152
|
type: "suggestion",
|
|
3038
3153
|
messages: {
|
|
@@ -3054,7 +3169,7 @@ var codeYieldArgument = defineRule24({
|
|
|
3054
3169
|
});
|
|
3055
3170
|
|
|
3056
3171
|
// src/rules/comments/comments-code.ts
|
|
3057
|
-
import { defineRule as
|
|
3172
|
+
import { defineRule as defineRule26 } from "@oxlint/plugins";
|
|
3058
3173
|
var commentsLineGap = /^[\t \r\n\u2028\u2029]*$/;
|
|
3059
3174
|
var commentsLineTerminator = /\r\n|[\n\r\u2028\u2029]/;
|
|
3060
3175
|
var commentsUnicodeTerminator = /[\u2028\u2029]/;
|
|
@@ -3105,7 +3220,7 @@ function commentsFollowsOpeningBrace(text, offset) {
|
|
|
3105
3220
|
}
|
|
3106
3221
|
return false;
|
|
3107
3222
|
}
|
|
3108
|
-
var commentsCode =
|
|
3223
|
+
var commentsCode = defineRule26({
|
|
3109
3224
|
meta: {
|
|
3110
3225
|
type: "suggestion",
|
|
3111
3226
|
fixable: "code",
|
|
@@ -3271,9 +3386,9 @@ var commentsCode = defineRule25({
|
|
|
3271
3386
|
});
|
|
3272
3387
|
|
|
3273
3388
|
// src/rules/comments/comments-directives.ts
|
|
3274
|
-
import { defineRule as
|
|
3389
|
+
import { defineRule as defineRule27 } from "@oxlint/plugins";
|
|
3275
3390
|
var directive = /^\s*(?:oxlint|eslint)-disable(?:-next-line|-line)?\b(.*)$/s;
|
|
3276
|
-
var commentsDirectives =
|
|
3391
|
+
var commentsDirectives = defineRule27({
|
|
3277
3392
|
meta: {
|
|
3278
3393
|
type: "problem",
|
|
3279
3394
|
schema: [],
|
|
@@ -3293,17 +3408,665 @@ var commentsDirectives = defineRule26({
|
|
|
3293
3408
|
if (rules.trim() && reason.join("--").trim()) {
|
|
3294
3409
|
continue;
|
|
3295
3410
|
}
|
|
3296
|
-
context.report({ loc: comment.loc, messageId: "directive" });
|
|
3411
|
+
context.report({ loc: comment.loc, messageId: "directive" });
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
};
|
|
3415
|
+
}
|
|
3416
|
+
});
|
|
3417
|
+
|
|
3418
|
+
// src/rules/copy/copy-dashes.ts
|
|
3419
|
+
import { defineRule as defineRule28 } from "@oxlint/plugins";
|
|
3420
|
+
var copyDashesMessage = "Use a comma, colon, period or parentheses instead.";
|
|
3421
|
+
var copyDashes = defineRule28({
|
|
3422
|
+
meta: {
|
|
3423
|
+
type: "suggestion",
|
|
3424
|
+
schema: [
|
|
3425
|
+
{
|
|
3426
|
+
type: "object",
|
|
3427
|
+
additionalProperties: false,
|
|
3428
|
+
properties: {
|
|
3429
|
+
deny: { type: "array", items: { type: "string", minLength: 1 } },
|
|
3430
|
+
message: { type: "string" }
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
],
|
|
3434
|
+
messages: {
|
|
3435
|
+
dash: "Remove '{{dash}}' from this text. {{message}}"
|
|
3436
|
+
}
|
|
3437
|
+
},
|
|
3438
|
+
createOnce(context) {
|
|
3439
|
+
let deny = ["—"];
|
|
3440
|
+
let message = copyDashesMessage;
|
|
3441
|
+
function check(node) {
|
|
3442
|
+
const text = context.sourceCode.text;
|
|
3443
|
+
const raw = text.slice(node.range[0], node.range[1]);
|
|
3444
|
+
for (const dash of deny) {
|
|
3445
|
+
for (let index = raw.indexOf(dash);index !== -1; index = raw.indexOf(dash, index + dash.length)) {
|
|
3446
|
+
const start = node.range[0] + index;
|
|
3447
|
+
context.report({
|
|
3448
|
+
loc: { start: context.sourceCode.getLocFromIndex(start), end: context.sourceCode.getLocFromIndex(start + dash.length) },
|
|
3449
|
+
messageId: "dash",
|
|
3450
|
+
data: { dash, message }
|
|
3451
|
+
});
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
return {
|
|
3456
|
+
before() {
|
|
3457
|
+
const options = optionsFirst(context, {});
|
|
3458
|
+
const text = context.sourceCode.text;
|
|
3459
|
+
deny = options.deny ?? ["—"];
|
|
3460
|
+
message = options.message ?? copyDashesMessage;
|
|
3461
|
+
if (!deny.some((dash) => text.includes(dash))) {
|
|
3462
|
+
return false;
|
|
3463
|
+
}
|
|
3464
|
+
},
|
|
3465
|
+
Literal(node) {
|
|
3466
|
+
if (typeof node.value === "string") {
|
|
3467
|
+
check(node);
|
|
3468
|
+
}
|
|
3469
|
+
},
|
|
3470
|
+
TemplateElement: check,
|
|
3471
|
+
JSXText: check
|
|
3472
|
+
};
|
|
3473
|
+
}
|
|
3474
|
+
});
|
|
3475
|
+
|
|
3476
|
+
// src/rules/effect/effect-layer-file.ts
|
|
3477
|
+
import { defineRule as defineRule29 } from "@oxlint/plugins";
|
|
3478
|
+
|
|
3479
|
+
// src/utils/effect.utils.ts
|
|
3480
|
+
var effectBuilders = ["Effect.gen", "Effect.fn", "Effect.fnUntraced"];
|
|
3481
|
+
function effectIsBuilder(node, builders) {
|
|
3482
|
+
const value = node ? astUnwrap(node) : undefined;
|
|
3483
|
+
if (value?.type !== "CallExpression") {
|
|
3484
|
+
return false;
|
|
3485
|
+
}
|
|
3486
|
+
const callee = value.callee.type === "CallExpression" ? value.callee.callee : value.callee;
|
|
3487
|
+
return builders.has(astDottedName(callee) ?? "");
|
|
3488
|
+
}
|
|
3489
|
+
function effectGenerator(node, builders) {
|
|
3490
|
+
const value = node ? astUnwrap(node) : undefined;
|
|
3491
|
+
return effectIsBuilder(value, builders) ? value.arguments.find((argument) => argument.type === "FunctionExpression") : undefined;
|
|
3492
|
+
}
|
|
3493
|
+
function effectMatches(node, patterns) {
|
|
3494
|
+
if (!node || node.type === "Super") {
|
|
3495
|
+
return false;
|
|
3496
|
+
}
|
|
3497
|
+
const value = astUnwrap(node);
|
|
3498
|
+
const target = value.type === "CallExpression" ? value.callee : value;
|
|
3499
|
+
const name = astDottedName(target);
|
|
3500
|
+
if (name !== undefined && optionsPatternsTest(patterns, name)) {
|
|
3501
|
+
return true;
|
|
3502
|
+
}
|
|
3503
|
+
return value.type === "CallExpression" && target.type === "MemberExpression" && astMemberName(target) === "pipe" && effectMatches(target.object, patterns);
|
|
3504
|
+
}
|
|
3505
|
+
|
|
3506
|
+
// src/rules/effect/effect-layer-file.ts
|
|
3507
|
+
var effectLayerFileDefaultLayers = ["^Layer\\.", "^HttpRouter\\.add(?:All)?$", "(?:^|\\.)layer[^.]*$"];
|
|
3508
|
+
var effectLayerFileDefaultServices = ["(?:^|\\.)of$", "^Context\\."];
|
|
3509
|
+
var effectLayerFileDefaultConstructors = [
|
|
3510
|
+
"Layer.effect",
|
|
3511
|
+
"Layer.effectContext",
|
|
3512
|
+
"Layer.effectDiscard",
|
|
3513
|
+
"Layer.scoped",
|
|
3514
|
+
"Layer.scopedContext",
|
|
3515
|
+
"Layer.scopedDiscard",
|
|
3516
|
+
"Layer.sync",
|
|
3517
|
+
"Layer.unwrap"
|
|
3518
|
+
];
|
|
3519
|
+
var effectLayerFile = defineRule29({
|
|
3520
|
+
meta: {
|
|
3521
|
+
type: "problem",
|
|
3522
|
+
schema: [
|
|
3523
|
+
{
|
|
3524
|
+
type: "object",
|
|
3525
|
+
additionalProperties: false,
|
|
3526
|
+
properties: {
|
|
3527
|
+
layer: { type: "string" },
|
|
3528
|
+
make: { type: "string" },
|
|
3529
|
+
prefix: { type: "string" },
|
|
3530
|
+
builders: { type: "array", items: { type: "string" } },
|
|
3531
|
+
layers: optionsPatternSchema,
|
|
3532
|
+
services: optionsPatternSchema,
|
|
3533
|
+
constructors: { type: "array", items: { type: "string" } }
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
],
|
|
3537
|
+
messages: {
|
|
3538
|
+
missing: "A layer file exports `{{layer}}`.",
|
|
3539
|
+
notLayer: "`{{layer}}` is built with Layer: a Layer call, a Layer pipe, or a function returning one.",
|
|
3540
|
+
builderName: "The Effect that builds the service is named `{{make}}`, one per layer file.",
|
|
3541
|
+
moduleMethod: "Only `{{make}}` is an Effect at module level; move this into `{{make}}`, or into a utils file if two files use it.",
|
|
3542
|
+
moduleHelper: "A layer file holds only `{{make}}`, {{prefix}}<Role> layers and `{{layer}}`; move this into `{{make}}`, or into a utils file if two files use it.",
|
|
3543
|
+
localLayer: "A Layer other than `{{layer}}` is named {{prefix}}<Role> and is not exported.",
|
|
3544
|
+
makeReturn: "`{{make}}` returns the service through its tag (Tag.of({ … })), a Context, or a Layer.",
|
|
3545
|
+
inlineBuilder: "Build this layer from `{{make}}`, not an inline Effect: Layer.effect(Tag, {{make}}). One built layer per file."
|
|
3546
|
+
}
|
|
3547
|
+
},
|
|
3548
|
+
createOnce(context) {
|
|
3549
|
+
let layer = "layer";
|
|
3550
|
+
let make = "make";
|
|
3551
|
+
let prefix = "layer";
|
|
3552
|
+
let builders = new Set(effectBuilders);
|
|
3553
|
+
let layers = [];
|
|
3554
|
+
let services = [];
|
|
3555
|
+
let constructors = new Set(effectLayerFileDefaultConstructors);
|
|
3556
|
+
const returned = (node) => {
|
|
3557
|
+
const value = node ? astUnwrap(node) : node;
|
|
3558
|
+
if (!value || !astIsInlineFunction(value)) {
|
|
3559
|
+
return value;
|
|
3560
|
+
}
|
|
3561
|
+
return value.body?.type === "BlockStatement" ? returned(value.body.body.findLast((statement) => statement.type === "ReturnStatement")?.argument) : returned(value.body);
|
|
3562
|
+
};
|
|
3563
|
+
return {
|
|
3564
|
+
before() {
|
|
3565
|
+
const options = optionsFirst(context, {});
|
|
3566
|
+
layer = options.layer ?? "layer";
|
|
3567
|
+
make = options.make ?? "make";
|
|
3568
|
+
prefix = options.prefix ?? "layer";
|
|
3569
|
+
builders = new Set(options.builders ?? effectBuilders);
|
|
3570
|
+
constructors = new Set(options.constructors ?? effectLayerFileDefaultConstructors);
|
|
3571
|
+
layers = optionsPatterns(options.layers ?? effectLayerFileDefaultLayers);
|
|
3572
|
+
services = [...optionsPatterns(options.services ?? effectLayerFileDefaultServices), ...layers];
|
|
3573
|
+
},
|
|
3574
|
+
Program(program) {
|
|
3575
|
+
const data = { layer, make, prefix };
|
|
3576
|
+
const declarators = program.body.flatMap((statement) => {
|
|
3577
|
+
const declaration = astDeclaration(statement);
|
|
3578
|
+
const exported = statement.type === "ExportNamedDeclaration";
|
|
3579
|
+
return declaration?.type === "VariableDeclaration" ? declaration.declarations.map((node) => ({ exported, node, name: node.id.type === "Identifier" ? node.id.name : "" })) : [];
|
|
3580
|
+
});
|
|
3581
|
+
const exportedLayer = declarators.find(({ exported, name }) => exported && name === layer);
|
|
3582
|
+
if (!exportedLayer) {
|
|
3583
|
+
context.report({
|
|
3584
|
+
node: program,
|
|
3585
|
+
messageId: "missing",
|
|
3586
|
+
data
|
|
3587
|
+
});
|
|
3588
|
+
} else if (!effectMatches(returned(exportedLayer.node.init), layers)) {
|
|
3589
|
+
context.report({
|
|
3590
|
+
node: exportedLayer.node,
|
|
3591
|
+
messageId: "notLayer",
|
|
3592
|
+
data
|
|
3593
|
+
});
|
|
3594
|
+
}
|
|
3595
|
+
const wired = new Set;
|
|
3596
|
+
const wiring = declarators.filter((item) => item === exportedLayer || effectMatches(item.node.init, layers));
|
|
3597
|
+
astVisit(wiring.map(({ node }) => node.init), [], (call) => {
|
|
3598
|
+
if (call.type !== "CallExpression" || !optionsPatternsTest(layers, astDottedName(call.callee) ?? "")) {
|
|
3599
|
+
return;
|
|
3600
|
+
}
|
|
3601
|
+
for (const argument of call.arguments) {
|
|
3602
|
+
const target = argument.type === "CallExpression" ? argument.callee : argument;
|
|
3603
|
+
if (target.type === "Identifier") {
|
|
3604
|
+
wired.add(target.name);
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3607
|
+
});
|
|
3608
|
+
const locals = declarators.filter(({ exported }) => !exported);
|
|
3609
|
+
const effects = locals.filter(({ node }) => effectIsBuilder(node.init, builders));
|
|
3610
|
+
const builder = effects.find(({ name }) => name === make) ?? effects.find(({ name }) => wired.has(name));
|
|
3611
|
+
if (builder && builder.name !== make) {
|
|
3612
|
+
context.report({
|
|
3613
|
+
node: builder.node,
|
|
3614
|
+
messageId: "builderName",
|
|
3615
|
+
data
|
|
3616
|
+
});
|
|
3617
|
+
}
|
|
3618
|
+
for (const { node, name, exported } of declarators) {
|
|
3619
|
+
const isLayer = effectMatches(node.init, layers);
|
|
3620
|
+
const isEffect = effectIsBuilder(node.init, builders);
|
|
3621
|
+
if (!exported && isEffect && name !== builder?.name) {
|
|
3622
|
+
context.report({
|
|
3623
|
+
node,
|
|
3624
|
+
messageId: "moduleMethod",
|
|
3625
|
+
data
|
|
3626
|
+
});
|
|
3627
|
+
}
|
|
3628
|
+
if (!exported && !isEffect && !isLayer && name !== make) {
|
|
3629
|
+
context.report({
|
|
3630
|
+
node,
|
|
3631
|
+
messageId: "moduleHelper",
|
|
3632
|
+
data
|
|
3633
|
+
});
|
|
3634
|
+
}
|
|
3635
|
+
if (isLayer && name !== layer && (exported || !name.startsWith(prefix) || !/^[A-Z]\w*$/.test(name.slice(prefix.length)))) {
|
|
3636
|
+
context.report({
|
|
3637
|
+
node,
|
|
3638
|
+
messageId: "localLayer",
|
|
3639
|
+
data
|
|
3640
|
+
});
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
for (const statement of program.body) {
|
|
3644
|
+
if (statement.type === "FunctionDeclaration") {
|
|
3645
|
+
context.report({
|
|
3646
|
+
node: statement,
|
|
3647
|
+
messageId: "moduleHelper",
|
|
3648
|
+
data
|
|
3649
|
+
});
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
const generator = builder?.name === make ? effectGenerator(builder.node.init, builders) : undefined;
|
|
3653
|
+
for (const statement of generator?.body?.body ?? []) {
|
|
3654
|
+
if (statement.type === "ReturnStatement" && !effectMatches(statement.argument, services)) {
|
|
3655
|
+
context.report({
|
|
3656
|
+
node: statement,
|
|
3657
|
+
messageId: "makeReturn",
|
|
3658
|
+
data
|
|
3659
|
+
});
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3662
|
+
},
|
|
3663
|
+
CallExpression(node) {
|
|
3664
|
+
if (!constructors.has(astDottedName(node.callee) ?? "")) {
|
|
3665
|
+
return;
|
|
3666
|
+
}
|
|
3667
|
+
for (const argument of node.arguments) {
|
|
3668
|
+
if (argument.type !== "SpreadElement" && (astIsInlineFunction(astUnwrap(argument)) || effectIsBuilder(argument, builders))) {
|
|
3669
|
+
context.report({
|
|
3670
|
+
node: argument,
|
|
3671
|
+
messageId: "inlineBuilder",
|
|
3672
|
+
data: { layer, make, prefix }
|
|
3673
|
+
});
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
};
|
|
3678
|
+
}
|
|
3679
|
+
});
|
|
3680
|
+
|
|
3681
|
+
// src/rules/effect/effect-layers.ts
|
|
3682
|
+
import { defineRule as defineRule30 } from "@oxlint/plugins";
|
|
3683
|
+
var effectLayersDefaultMerge = ["Layer.mergeAll"];
|
|
3684
|
+
var effectLayersDefaultProvide = ["Effect.provide", "Layer.provide", "Layer.provideMerge"];
|
|
3685
|
+
var effectLayersDefaultMin = 2;
|
|
3686
|
+
var effectLayersGroupSchema = {
|
|
3687
|
+
type: "object",
|
|
3688
|
+
additionalProperties: false,
|
|
3689
|
+
properties: {
|
|
3690
|
+
callees: { type: "array", items: { type: "string" } },
|
|
3691
|
+
min: { type: "integer", minimum: 1 }
|
|
3692
|
+
}
|
|
3693
|
+
};
|
|
3694
|
+
var effectLayers = defineRule30({
|
|
3695
|
+
meta: {
|
|
3696
|
+
type: "layout",
|
|
3697
|
+
fixable: "whitespace",
|
|
3698
|
+
schema: [
|
|
3699
|
+
{
|
|
3700
|
+
type: "object",
|
|
3701
|
+
additionalProperties: false,
|
|
3702
|
+
properties: {
|
|
3703
|
+
merge: effectLayersGroupSchema,
|
|
3704
|
+
provide: effectLayersGroupSchema,
|
|
3705
|
+
indent: sourceIndentSchema
|
|
3706
|
+
}
|
|
3707
|
+
}
|
|
3708
|
+
],
|
|
3709
|
+
messages: {
|
|
3710
|
+
merge: "Put every layer in this merge on its own line.",
|
|
3711
|
+
provide: "Put every layer in this array on its own line."
|
|
3712
|
+
}
|
|
3713
|
+
},
|
|
3714
|
+
createOnce(context) {
|
|
3715
|
+
let merge = new Set(effectLayersDefaultMerge);
|
|
3716
|
+
let provide = new Set(effectLayersDefaultProvide);
|
|
3717
|
+
let mergeMin = effectLayersDefaultMin;
|
|
3718
|
+
let provideMin = effectLayersDefaultMin;
|
|
3719
|
+
let indentUnit = sourceIndentUnit();
|
|
3720
|
+
const check = (node) => {
|
|
3721
|
+
const source = context.sourceCode;
|
|
3722
|
+
const call = node.type === "CallExpression";
|
|
3723
|
+
const items = call ? node.arguments : node.elements;
|
|
3724
|
+
const present = items.filter((item) => item !== null);
|
|
3725
|
+
const open = call ? source.getTokenAfter(node.typeArguments ?? node.callee) : source.getFirstToken(node);
|
|
3726
|
+
const close = source.getLastToken(node);
|
|
3727
|
+
if (open?.value !== (call ? "(" : "[") || close === null || present.length < (call ? mergeMin : provideMin)) {
|
|
3728
|
+
return;
|
|
3729
|
+
}
|
|
3730
|
+
const packed = [open, ...present].some((item, index) => item.loc.end.line === (present.at(index) ?? close).loc.start.line);
|
|
3731
|
+
if (!packed) {
|
|
3732
|
+
return;
|
|
3733
|
+
}
|
|
3734
|
+
const text = source.text;
|
|
3735
|
+
const newline = sourceNewline(text);
|
|
3736
|
+
const base = sourceLineIndent(text, open.range[0]);
|
|
3737
|
+
const gaps = sourceItemGaps(open.range[1], present, close.range[0]);
|
|
3738
|
+
context.report({
|
|
3739
|
+
node,
|
|
3740
|
+
messageId: call ? "merge" : "provide",
|
|
3741
|
+
fix: (fixer) => {
|
|
3742
|
+
if (present.length !== items.length) {
|
|
3743
|
+
return null;
|
|
3744
|
+
}
|
|
3745
|
+
return sourceRespace(fixer, text, gaps, (_, end) => `${newline}${base}${end ? "" : indentUnit}`);
|
|
3746
|
+
}
|
|
3747
|
+
});
|
|
3748
|
+
};
|
|
3749
|
+
return {
|
|
3750
|
+
before() {
|
|
3751
|
+
const options = optionsFirst(context, {});
|
|
3752
|
+
merge = new Set(options.merge?.callees ?? effectLayersDefaultMerge);
|
|
3753
|
+
provide = new Set(options.provide?.callees ?? effectLayersDefaultProvide);
|
|
3754
|
+
mergeMin = options.merge?.min ?? effectLayersDefaultMin;
|
|
3755
|
+
provideMin = options.provide?.min ?? effectLayersDefaultMin;
|
|
3756
|
+
indentUnit = sourceIndentUnit(options.indent);
|
|
3757
|
+
},
|
|
3758
|
+
CallExpression(node) {
|
|
3759
|
+
const name = astDottedName(node.callee);
|
|
3760
|
+
if (name !== undefined && merge.has(name)) {
|
|
3761
|
+
check(node);
|
|
3762
|
+
}
|
|
3763
|
+
if (name !== undefined && provide.has(name)) {
|
|
3764
|
+
for (const argument of node.arguments) {
|
|
3765
|
+
if (argument.type === "ArrayExpression") {
|
|
3766
|
+
check(argument);
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
};
|
|
3772
|
+
}
|
|
3773
|
+
});
|
|
3774
|
+
|
|
3775
|
+
// src/rules/effect/effect-merge-pipe.ts
|
|
3776
|
+
import { defineRule as defineRule31 } from "@oxlint/plugins";
|
|
3777
|
+
var effectMergePipeDefaultMerge = ["Layer.mergeAll"];
|
|
3778
|
+
var effectMergePipeDefaultPipe = ["pipe", "Function.pipe"];
|
|
3779
|
+
var effectMergePipeDefaultMethods = ["pipe"];
|
|
3780
|
+
var effectMergePipe = defineRule31({
|
|
3781
|
+
meta: {
|
|
3782
|
+
type: "layout",
|
|
3783
|
+
schema: [
|
|
3784
|
+
{
|
|
3785
|
+
type: "object",
|
|
3786
|
+
additionalProperties: false,
|
|
3787
|
+
properties: {
|
|
3788
|
+
merge: { type: "array", items: { type: "string" } },
|
|
3789
|
+
pipe: { type: "array", items: { type: "string" } },
|
|
3790
|
+
methods: { type: "array", items: { type: "string" } }
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
],
|
|
3794
|
+
messages: {
|
|
3795
|
+
piped: "A merge that spans lines is never piped. Name it first, then pipe the name."
|
|
3796
|
+
}
|
|
3797
|
+
},
|
|
3798
|
+
createOnce(context) {
|
|
3799
|
+
let merge = new Set(effectMergePipeDefaultMerge);
|
|
3800
|
+
let pipe = new Set(effectMergePipeDefaultPipe);
|
|
3801
|
+
let methods = new Set(effectMergePipeDefaultMethods);
|
|
3802
|
+
const isMultilineMerge = (node) => node?.type === "CallExpression" && merge.has(astDottedName(node.callee) ?? "") && !astIsOneLine(node);
|
|
3803
|
+
return {
|
|
3804
|
+
before() {
|
|
3805
|
+
const options = optionsFirst(context, {});
|
|
3806
|
+
merge = new Set(options.merge ?? effectMergePipeDefaultMerge);
|
|
3807
|
+
pipe = new Set(options.pipe ?? effectMergePipeDefaultPipe);
|
|
3808
|
+
methods = new Set(options.methods ?? effectMergePipeDefaultMethods);
|
|
3809
|
+
},
|
|
3810
|
+
CallExpression(node) {
|
|
3811
|
+
const callee = node.callee;
|
|
3812
|
+
const first = node.arguments.at(0);
|
|
3813
|
+
if (callee.type === "MemberExpression" && methods.has(astMemberName(callee) ?? "") && isMultilineMerge(callee.object)) {
|
|
3814
|
+
context.report({ node: callee.property, messageId: "piped" });
|
|
3815
|
+
}
|
|
3816
|
+
if (pipe.has(astDottedName(callee) ?? "") && first !== undefined && isMultilineMerge(first)) {
|
|
3817
|
+
context.report({ node: first, messageId: "piped" });
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
});
|
|
3823
|
+
|
|
3824
|
+
// src/rules/effect/effect-schema-first.ts
|
|
3825
|
+
import { defineRule as defineRule32 } from "@oxlint/plugins";
|
|
3826
|
+
var effectSchemaFirstDefaultRuntime = [
|
|
3827
|
+
"Effect",
|
|
3828
|
+
"Layer",
|
|
3829
|
+
"Stream",
|
|
3830
|
+
"Context",
|
|
3831
|
+
"Scope",
|
|
3832
|
+
"Kysely",
|
|
3833
|
+
"React",
|
|
3834
|
+
"Fiber",
|
|
3835
|
+
"Queue",
|
|
3836
|
+
"PubSub",
|
|
3837
|
+
"Ref",
|
|
3838
|
+
"Deferred",
|
|
3839
|
+
"ManagedRuntime",
|
|
3840
|
+
"Sink",
|
|
3841
|
+
"Channel",
|
|
3842
|
+
"Request",
|
|
3843
|
+
"Response",
|
|
3844
|
+
"Headers",
|
|
3845
|
+
"ReadableStream",
|
|
3846
|
+
"WritableStream",
|
|
3847
|
+
"Blob",
|
|
3848
|
+
"File",
|
|
3849
|
+
"AbortSignal",
|
|
3850
|
+
"WebSocket",
|
|
3851
|
+
"Socket",
|
|
3852
|
+
"Worker",
|
|
3853
|
+
"Uint8Array",
|
|
3854
|
+
"ArrayBuffer",
|
|
3855
|
+
"globalThis"
|
|
3856
|
+
];
|
|
3857
|
+
var effectSchemaFirstSections = {
|
|
3858
|
+
values: ["VariableDeclaration", "ClassDeclaration"],
|
|
3859
|
+
interfaces: ["TSInterfaceDeclaration"],
|
|
3860
|
+
modules: ["TSModuleDeclaration"],
|
|
3861
|
+
aliases: ["TSTypeAliasDeclaration"]
|
|
3862
|
+
};
|
|
3863
|
+
var effectSchemaFirstLabels = {
|
|
3864
|
+
values: "Schemas and values",
|
|
3865
|
+
interfaces: "interfaces",
|
|
3866
|
+
modules: "`declare module`",
|
|
3867
|
+
aliases: "type aliases"
|
|
3868
|
+
};
|
|
3869
|
+
var effectSchemaFirstDefaultOrder = ["values", ["interfaces", "modules"], "aliases"];
|
|
3870
|
+
var effectSchemaFirstSectionSchema = { type: "string", enum: ["values", "interfaces", "modules", "aliases"] };
|
|
3871
|
+
function effectSchemaFirstTypeName(node) {
|
|
3872
|
+
if (node.type === "TSQualifiedName") {
|
|
3873
|
+
const left = effectSchemaFirstTypeName(node.left);
|
|
3874
|
+
return left === undefined ? undefined : `${left}.${node.right.name}`;
|
|
3875
|
+
}
|
|
3876
|
+
return astDottedName(node);
|
|
3877
|
+
}
|
|
3878
|
+
function effectSchemaFirstReference(node) {
|
|
3879
|
+
if (node.type === "TSTypeReference") {
|
|
3880
|
+
return effectSchemaFirstTypeName(node.typeName);
|
|
3881
|
+
}
|
|
3882
|
+
if (node.type === "TSTypeQuery") {
|
|
3883
|
+
return effectSchemaFirstTypeName(node.exprName);
|
|
3884
|
+
}
|
|
3885
|
+
return node.type === "TSInterfaceHeritage" ? astDottedName(node.expression) : undefined;
|
|
3886
|
+
}
|
|
3887
|
+
var effectSchemaFirst = defineRule32({
|
|
3888
|
+
meta: {
|
|
3889
|
+
type: "suggestion",
|
|
3890
|
+
schema: [
|
|
3891
|
+
{
|
|
3892
|
+
type: "object",
|
|
3893
|
+
additionalProperties: false,
|
|
3894
|
+
properties: {
|
|
3895
|
+
member: { type: "string" },
|
|
3896
|
+
keep: optionsPatternSchema,
|
|
3897
|
+
runtime: { type: "array", items: { type: "string" } },
|
|
3898
|
+
rows: {
|
|
3899
|
+
type: "object",
|
|
3900
|
+
additionalProperties: false,
|
|
3901
|
+
properties: { types: { type: "array", items: { type: "string" } }, suffix: { type: "string" } }
|
|
3902
|
+
},
|
|
3903
|
+
order: {
|
|
3904
|
+
type: "array",
|
|
3905
|
+
items: { anyOf: [effectSchemaFirstSectionSchema, { type: "array", items: effectSchemaFirstSectionSchema, minItems: 1 }] }
|
|
3906
|
+
},
|
|
3907
|
+
derived: {
|
|
3908
|
+
type: "object",
|
|
3909
|
+
additionalProperties: false,
|
|
3910
|
+
properties: { first: { type: "boolean" }, sorted: { type: "boolean" } }
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
],
|
|
3915
|
+
messages: {
|
|
3916
|
+
order: "Order a types file as {{order}}.",
|
|
3917
|
+
schemaType: "Add `export type {{name}} = typeof {{name}}.{{member}}` to the final type block.",
|
|
3918
|
+
typeOrder: "Move {{name}}: the type block lists the `typeof` aliases first, in Schema order, then the other aliases.",
|
|
3919
|
+
dataInterface: "Every field of {{name}} fits a Schema: make it a Schema and derive its type.",
|
|
3920
|
+
rowItem: "{{name}} is built from a database row: make it a Schema; only a `…{{suffix}}` alias may read the row type."
|
|
3921
|
+
}
|
|
3922
|
+
},
|
|
3923
|
+
createOnce(context) {
|
|
3924
|
+
let member = "Type";
|
|
3925
|
+
let keep = [];
|
|
3926
|
+
let runtime = new Set(effectSchemaFirstDefaultRuntime);
|
|
3927
|
+
let rows;
|
|
3928
|
+
let suffix = "Record";
|
|
3929
|
+
let ranks = new Map;
|
|
3930
|
+
let orderText = "";
|
|
3931
|
+
let derivedFirst = true;
|
|
3932
|
+
let derivedSorted = true;
|
|
3933
|
+
const derives = (alias) => {
|
|
3934
|
+
const annotation = alias.typeAnnotation;
|
|
3935
|
+
const name = annotation.type === "TSTypeQuery" ? annotation.exprName : undefined;
|
|
3936
|
+
return name?.type === "TSQualifiedName" && name.left.type === "Identifier" && name.left.name === alias.id.name && name.right.name === member;
|
|
3937
|
+
};
|
|
3938
|
+
const refers = (node, names) => astSome(node, (child) => {
|
|
3939
|
+
if (child.type === "TSFunctionType" || child.type === "TSConstructorType" || child.type === "TSMethodSignature") {
|
|
3940
|
+
return true;
|
|
3941
|
+
}
|
|
3942
|
+
return (effectSchemaFirstReference(child)?.split(".") ?? []).some((name) => names.has(name));
|
|
3943
|
+
});
|
|
3944
|
+
const readsRow = (node) => astSome(node, (child) => Boolean(rows?.has(effectSchemaFirstReference(child) ?? "")));
|
|
3945
|
+
const checkOrder = (program) => {
|
|
3946
|
+
let highest = 0;
|
|
3947
|
+
for (const statement of program.body) {
|
|
3948
|
+
const rank = ranks.get(astDeclaration(statement)?.type ?? "") ?? 0;
|
|
3949
|
+
if (rank > 0 && rank < highest) {
|
|
3950
|
+
context.report({
|
|
3951
|
+
node: statement,
|
|
3952
|
+
messageId: "order",
|
|
3953
|
+
data: { order: orderText }
|
|
3954
|
+
});
|
|
3955
|
+
}
|
|
3956
|
+
highest = Math.max(highest, rank);
|
|
3957
|
+
}
|
|
3958
|
+
};
|
|
3959
|
+
const keptNames = (program, aliases, interfaces) => {
|
|
3960
|
+
const kept = new Set(aliases.filter((alias) => refers(alias.typeAnnotation, runtime)).map((alias) => alias.id.name));
|
|
3961
|
+
for (const statement of program.body) {
|
|
3962
|
+
if (statement.type === "ImportDeclaration" && statement.source.value.startsWith(".")) {
|
|
3963
|
+
for (const specifier of statement.specifiers) {
|
|
3964
|
+
if (statement.importKind === "type" || specifier.type === "ImportSpecifier" && specifier.importKind === "type") {
|
|
3965
|
+
kept.add(specifier.local.name);
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
const names = new Set([...runtime, ...kept]);
|
|
3971
|
+
let grew = true;
|
|
3972
|
+
while (grew) {
|
|
3973
|
+
grew = false;
|
|
3974
|
+
for (const node of interfaces) {
|
|
3975
|
+
const stays = node.body.body.length === 0 || Boolean(node.typeParameters) || optionsPatternsTest(keep, node.id.name) || refers(node, names);
|
|
3976
|
+
if (!kept.has(node.id.name) && stays) {
|
|
3977
|
+
names.add(node.id.name);
|
|
3978
|
+
kept.add(node.id.name);
|
|
3979
|
+
grew = true;
|
|
3980
|
+
}
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
return kept;
|
|
3984
|
+
};
|
|
3985
|
+
return {
|
|
3986
|
+
before() {
|
|
3987
|
+
const options = optionsFirst(context, {});
|
|
3988
|
+
member = options.member ?? "Type";
|
|
3989
|
+
keep = optionsPatterns(options.keep);
|
|
3990
|
+
runtime = new Set(options.runtime ?? effectSchemaFirstDefaultRuntime);
|
|
3991
|
+
rows = options.rows ? new Set(options.rows.types ?? ["Kysely.Selectable"]) : undefined;
|
|
3992
|
+
suffix = options.rows?.suffix ?? "Record";
|
|
3993
|
+
const order = (options.order ?? effectSchemaFirstDefaultOrder).map((group) => [group].flat());
|
|
3994
|
+
ranks = new Map(order.flatMap((group, index) => group.flatMap((section) => effectSchemaFirstSections[section].map((type) => [type, index + 1]))));
|
|
3995
|
+
orderText = order.map((group) => group.map((section) => effectSchemaFirstLabels[section]).join(" and ")).join(", then ");
|
|
3996
|
+
derivedFirst = options.derived?.first ?? true;
|
|
3997
|
+
derivedSorted = options.derived?.sorted ?? true;
|
|
3998
|
+
},
|
|
3999
|
+
Program(program) {
|
|
4000
|
+
checkOrder(program);
|
|
4001
|
+
const declarations = program.body.flatMap((statement) => astDeclaration(statement) ?? []);
|
|
4002
|
+
const aliases = declarations.filter((node) => node.type === "TSTypeAliasDeclaration");
|
|
4003
|
+
const interfaces = declarations.filter((node) => node.type === "TSInterfaceDeclaration");
|
|
4004
|
+
const schemas = declarations.flatMap((node) => node.type === "VariableDeclaration" ? node.declarations : []).map(({ id }) => id.type === "Identifier" ? id.name : "");
|
|
4005
|
+
const exported = program.body.flatMap((statement) => statement.type === "ExportNamedDeclaration" && statement.declaration ? [statement.declaration] : []);
|
|
4006
|
+
const typed = new Set(exported.flatMap((node) => node.type === "TSTypeAliasDeclaration" && derives(node) ? [node.id.name] : []));
|
|
4007
|
+
for (const node of exported.flatMap((declaration) => declaration.type === "VariableDeclaration" ? declaration.declarations : [])) {
|
|
4008
|
+
const isSchema = node.init?.type === "CallExpression" || node.init?.type === "MemberExpression";
|
|
4009
|
+
if (isSchema && node.id.type === "Identifier" && !typed.has(node.id.name)) {
|
|
4010
|
+
context.report({
|
|
4011
|
+
node,
|
|
4012
|
+
messageId: "schemaType",
|
|
4013
|
+
data: { name: node.id.name, member }
|
|
4014
|
+
});
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
let order = -1;
|
|
4018
|
+
let other = false;
|
|
4019
|
+
for (const alias of aliases) {
|
|
4020
|
+
if (!derives(alias)) {
|
|
4021
|
+
other = true;
|
|
4022
|
+
continue;
|
|
4023
|
+
}
|
|
4024
|
+
const index = schemas.indexOf(alias.id.name);
|
|
4025
|
+
if (derivedFirst && other || derivedSorted && index < order) {
|
|
4026
|
+
context.report({
|
|
4027
|
+
node: alias,
|
|
4028
|
+
messageId: "typeOrder",
|
|
4029
|
+
data: { name: alias.id.name }
|
|
4030
|
+
});
|
|
4031
|
+
}
|
|
4032
|
+
order = Math.max(order, index);
|
|
4033
|
+
}
|
|
4034
|
+
const kept = keptNames(program, aliases, interfaces);
|
|
4035
|
+
for (const node of interfaces) {
|
|
4036
|
+
if (!kept.has(node.id.name)) {
|
|
4037
|
+
context.report({
|
|
4038
|
+
node,
|
|
4039
|
+
messageId: "dataInterface",
|
|
4040
|
+
data: { name: node.id.name }
|
|
4041
|
+
});
|
|
4042
|
+
}
|
|
4043
|
+
}
|
|
4044
|
+
for (const node of rows ? declarations : []) {
|
|
4045
|
+
const fromRow = node.type === "TSTypeAliasDeclaration" && !node.id.name.endsWith(suffix) && readsRow(node.typeAnnotation) || node.type === "TSInterfaceDeclaration" && node.extends.some(readsRow);
|
|
4046
|
+
if (fromRow) {
|
|
4047
|
+
context.report({
|
|
4048
|
+
node,
|
|
4049
|
+
messageId: "rowItem",
|
|
4050
|
+
data: { name: node.id.name, suffix }
|
|
4051
|
+
});
|
|
4052
|
+
}
|
|
3297
4053
|
}
|
|
3298
4054
|
}
|
|
3299
4055
|
};
|
|
3300
4056
|
}
|
|
3301
4057
|
});
|
|
3302
4058
|
|
|
3303
|
-
// src/rules/
|
|
3304
|
-
import { defineRule as
|
|
3305
|
-
var
|
|
3306
|
-
|
|
4059
|
+
// src/rules/effect/effect-values-first.ts
|
|
4060
|
+
import { defineRule as defineRule33 } from "@oxlint/plugins";
|
|
4061
|
+
var effectValuesFirstDefaultPinned = [
|
|
4062
|
+
"^Layer\\.",
|
|
4063
|
+
"^Context\\.",
|
|
4064
|
+
"^HttpRouter\\.add(?:All)?$",
|
|
4065
|
+
"(?:^|\\.)of$",
|
|
4066
|
+
"(?:^|\\.)layer[^.]*$",
|
|
4067
|
+
"^Schema\\.(?:asserts|decode\\w*|encode\\w*|is|isSchema|isSchemaError|resolveAnnotations)$"
|
|
4068
|
+
];
|
|
4069
|
+
var effectValuesFirst = defineRule33({
|
|
3307
4070
|
meta: {
|
|
3308
4071
|
type: "suggestion",
|
|
3309
4072
|
schema: [
|
|
@@ -3311,55 +4074,82 @@ var copyDashes = defineRule27({
|
|
|
3311
4074
|
type: "object",
|
|
3312
4075
|
additionalProperties: false,
|
|
3313
4076
|
properties: {
|
|
3314
|
-
|
|
3315
|
-
|
|
4077
|
+
builders: { type: "array", items: { type: "string" } },
|
|
4078
|
+
pinned: optionsPatternSchema
|
|
3316
4079
|
}
|
|
3317
4080
|
}
|
|
3318
4081
|
],
|
|
3319
4082
|
messages: {
|
|
3320
|
-
|
|
4083
|
+
value: "`{{name}}` is a value declared after `{{after}}`: declare values first, then helpers and methods."
|
|
3321
4084
|
}
|
|
3322
4085
|
},
|
|
3323
4086
|
createOnce(context) {
|
|
3324
|
-
let
|
|
3325
|
-
let
|
|
3326
|
-
|
|
3327
|
-
const
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
4087
|
+
let builders = new Set(effectBuilders);
|
|
4088
|
+
let pinned = [];
|
|
4089
|
+
const check = (statements) => {
|
|
4090
|
+
const tied = new Set;
|
|
4091
|
+
let first;
|
|
4092
|
+
let barrier = false;
|
|
4093
|
+
for (const statement of statements) {
|
|
4094
|
+
const declaration = astDeclaration(statement);
|
|
4095
|
+
if (declaration?.type === "FunctionDeclaration" && declaration.id) {
|
|
4096
|
+
tied.add(declaration.id.name);
|
|
4097
|
+
first ??= declaration.id.name;
|
|
4098
|
+
continue;
|
|
4099
|
+
}
|
|
4100
|
+
if (declaration?.type !== "VariableDeclaration") {
|
|
4101
|
+
barrier ||= statement.type === "ExpressionStatement" && first !== undefined;
|
|
4102
|
+
continue;
|
|
4103
|
+
}
|
|
4104
|
+
for (const declarator of declaration.declarations) {
|
|
4105
|
+
const init = declarator.init;
|
|
4106
|
+
const names = astBindings(declarator.id).map((binding) => binding.name);
|
|
4107
|
+
const helper = Boolean(init && (astIsInlineFunction(astUnwrap(init)) || effectIsBuilder(init, builders)));
|
|
4108
|
+
const kept = helper || effectMatches(init, pinned) || astSome(init, (node) => node.type === "Identifier" && tied.has(node.name));
|
|
4109
|
+
if (first !== undefined && !kept && !barrier) {
|
|
4110
|
+
context.report({
|
|
4111
|
+
node: declarator,
|
|
4112
|
+
messageId: "value",
|
|
4113
|
+
data: { name: names.join(", "), after: first }
|
|
4114
|
+
});
|
|
4115
|
+
}
|
|
4116
|
+
if (kept) {
|
|
4117
|
+
names.forEach((name) => tied.add(name));
|
|
4118
|
+
}
|
|
4119
|
+
barrier ||= kept && first !== undefined && astSome(init, (node) => node.type === "YieldExpression");
|
|
4120
|
+
first ??= helper ? names.join(", ") : undefined;
|
|
3337
4121
|
}
|
|
3338
4122
|
}
|
|
3339
|
-
}
|
|
4123
|
+
};
|
|
4124
|
+
const body = (init) => {
|
|
4125
|
+
const value = init ? astUnwrap(init) : null;
|
|
4126
|
+
const target = value && astIsInlineFunction(value) ? value : effectGenerator(value, builders);
|
|
4127
|
+
return target?.body?.type === "BlockStatement" ? target.body.body : [];
|
|
4128
|
+
};
|
|
3340
4129
|
return {
|
|
3341
4130
|
before() {
|
|
3342
4131
|
const options = optionsFirst(context, {});
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
message = options.message ?? copyDashesMessage;
|
|
3346
|
-
if (!deny.some((dash) => text.includes(dash))) {
|
|
3347
|
-
return false;
|
|
3348
|
-
}
|
|
4132
|
+
builders = new Set(options.builders ?? effectBuilders);
|
|
4133
|
+
pinned = optionsPatterns(options.pinned ?? effectValuesFirstDefaultPinned);
|
|
3349
4134
|
},
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
4135
|
+
Program(program) {
|
|
4136
|
+
check(program.body);
|
|
4137
|
+
for (const statement of program.body) {
|
|
4138
|
+
const declaration = astDeclaration(statement);
|
|
4139
|
+
if (declaration?.type === "FunctionDeclaration") {
|
|
4140
|
+
check(declaration.body?.body ?? []);
|
|
4141
|
+
}
|
|
4142
|
+
if (declaration?.type === "VariableDeclaration") {
|
|
4143
|
+
declaration.declarations.forEach((declarator) => check(body(declarator.init)));
|
|
4144
|
+
}
|
|
3353
4145
|
}
|
|
3354
|
-
}
|
|
3355
|
-
TemplateElement: check,
|
|
3356
|
-
JSXText: check
|
|
4146
|
+
}
|
|
3357
4147
|
};
|
|
3358
4148
|
}
|
|
3359
4149
|
});
|
|
3360
4150
|
|
|
3361
4151
|
// src/rules/files/files-components-only.ts
|
|
3362
|
-
import { defineRule as
|
|
4152
|
+
import { defineRule as defineRule34 } from "@oxlint/plugins";
|
|
3363
4153
|
|
|
3364
4154
|
// src/utils/react.utils.ts
|
|
3365
4155
|
function reactReturnsOutput(program, node) {
|
|
@@ -3431,7 +4221,7 @@ function reactIsComponent(program, candidate) {
|
|
|
3431
4221
|
function componentName(basename2) {
|
|
3432
4222
|
return basename2.replace(/\.(tsx?|jsx?)$/, "").replaceAll(/(?:^[-.]*|[-.]+)(.?)/g, (_, char) => char.toUpperCase());
|
|
3433
4223
|
}
|
|
3434
|
-
var filesComponentsOnly =
|
|
4224
|
+
var filesComponentsOnly = defineRule34({
|
|
3435
4225
|
meta: {
|
|
3436
4226
|
type: "problem",
|
|
3437
4227
|
schema: [
|
|
@@ -3519,7 +4309,7 @@ var filesComponentsOnly = defineRule28({
|
|
|
3519
4309
|
});
|
|
3520
4310
|
|
|
3521
4311
|
// src/rules/files/files-constants-only.ts
|
|
3522
|
-
import { defineRule as
|
|
4312
|
+
import { defineRule as defineRule35 } from "@oxlint/plugins";
|
|
3523
4313
|
function unwrap(expression) {
|
|
3524
4314
|
if (expression.type === "ParenthesizedExpression" || expression.type === "TSAsExpression" || expression.type === "TSSatisfiesExpression" || expression.type === "TSTypeAssertion" || expression.type === "TSNonNullExpression" || expression.type === "TSInstantiationExpression") {
|
|
3525
4315
|
return unwrap(expression.expression);
|
|
@@ -3574,7 +4364,7 @@ function collectBindings(program) {
|
|
|
3574
4364
|
}
|
|
3575
4365
|
return bindings;
|
|
3576
4366
|
}
|
|
3577
|
-
var filesConstantsOnly =
|
|
4367
|
+
var filesConstantsOnly = defineRule35({
|
|
3578
4368
|
meta: {
|
|
3579
4369
|
type: "problem",
|
|
3580
4370
|
schema: [
|
|
@@ -3673,7 +4463,7 @@ var filesConstantsOnly = defineRule29({
|
|
|
3673
4463
|
});
|
|
3674
4464
|
|
|
3675
4465
|
// src/rules/files/files-domain-constants.ts
|
|
3676
|
-
import { defineRule as
|
|
4466
|
+
import { defineRule as defineRule36 } from "@oxlint/plugins";
|
|
3677
4467
|
import { basename as basename2, dirname as dirname2 } from "node:path";
|
|
3678
4468
|
function isData(expression) {
|
|
3679
4469
|
const value = astUnwrap(expression);
|
|
@@ -3691,7 +4481,7 @@ function isData(expression) {
|
|
|
3691
4481
|
}
|
|
3692
4482
|
return value.type === "NewExpression" && value.callee.type === "Identifier" && ["Map", "Set"].includes(value.callee.name) && value.arguments[0]?.type === "ArrayExpression" && value.arguments[0].elements.length > 0;
|
|
3693
4483
|
}
|
|
3694
|
-
var filesDomainConstants =
|
|
4484
|
+
var filesDomainConstants = defineRule36({
|
|
3695
4485
|
meta: {
|
|
3696
4486
|
type: "problem",
|
|
3697
4487
|
schema: [
|
|
@@ -3756,11 +4546,12 @@ var filesDomainConstants = defineRule30({
|
|
|
3756
4546
|
});
|
|
3757
4547
|
|
|
3758
4548
|
// src/rules/files/files-exports.ts
|
|
3759
|
-
import { defineRule as
|
|
4549
|
+
import { defineRule as defineRule37 } from "@oxlint/plugins";
|
|
4550
|
+
import { posix as posix2 } from "node:path";
|
|
3760
4551
|
function escapeRegExp(value) {
|
|
3761
4552
|
return value.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3762
4553
|
}
|
|
3763
|
-
var filesExports =
|
|
4554
|
+
var filesExports = defineRule37({
|
|
3764
4555
|
meta: {
|
|
3765
4556
|
type: "problem",
|
|
3766
4557
|
schema: [
|
|
@@ -3770,7 +4561,8 @@ var filesExports = defineRule31({
|
|
|
3770
4561
|
properties: {
|
|
3771
4562
|
names: { type: "array", items: { type: "string" } },
|
|
3772
4563
|
patterns: { type: "array", items: { type: "string" } },
|
|
3773
|
-
stem: { type: "string", enum: [...namingStemModes] },
|
|
4564
|
+
stem: { type: "string", enum: [...namingStemModes, "folder"] },
|
|
4565
|
+
singularize: { type: "string", enum: ["none", "trailing-s"] },
|
|
3774
4566
|
roles: { type: "array", items: { type: "string" } },
|
|
3775
4567
|
separators: { type: "array", items: { type: "string" } },
|
|
3776
4568
|
types: { type: "boolean" },
|
|
@@ -3813,7 +4605,9 @@ var filesExports = defineRule31({
|
|
|
3813
4605
|
if (options.names === undefined && options.patterns === undefined) {
|
|
3814
4606
|
return;
|
|
3815
4607
|
}
|
|
3816
|
-
const
|
|
4608
|
+
const read = options.stem === "folder" ? namingBasename(posix2.dirname(context.filename.replaceAll("\\", "/"))) : namingFileStem(basename3, options.stem, options.roles, options.separators);
|
|
4609
|
+
const last = read.split(/[-_]+/).at(-1) ?? "";
|
|
4610
|
+
const domain = options.singularize === "trailing-s" && last.length > 1 && last.endsWith("s") ? read.slice(0, -1) : read;
|
|
3817
4611
|
const pascalDomain = namingPascalCase(domain);
|
|
3818
4612
|
const camelDomain = namingCamelCase(domain);
|
|
3819
4613
|
const allowed = (options.names ?? []).map((template) => template.replaceAll("{Domain}", pascalDomain).replaceAll("{domain}", camelDomain));
|
|
@@ -3841,12 +4635,12 @@ var filesExports = defineRule31({
|
|
|
3841
4635
|
});
|
|
3842
4636
|
|
|
3843
4637
|
// src/rules/files/files-externals.ts
|
|
3844
|
-
import { defineRule as
|
|
4638
|
+
import { defineRule as defineRule38 } from "@oxlint/plugins";
|
|
3845
4639
|
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
3846
4640
|
import { builtinModules as builtinModules2 } from "node:module";
|
|
3847
4641
|
import { dirname as dirname3, join as join2 } from "node:path";
|
|
3848
4642
|
var filesExternalsConfigs = "^(?:vite|next)\\.config\\.[cm]?[jt]s$";
|
|
3849
|
-
var filesExternals =
|
|
4643
|
+
var filesExternals = defineRule38({
|
|
3850
4644
|
meta: {
|
|
3851
4645
|
type: "problem",
|
|
3852
4646
|
schema: [
|
|
@@ -3939,7 +4733,7 @@ var filesExternals = defineRule32({
|
|
|
3939
4733
|
});
|
|
3940
4734
|
|
|
3941
4735
|
// src/rules/files/files-factory-keys.ts
|
|
3942
|
-
import { defineRule as
|
|
4736
|
+
import { defineRule as defineRule39 } from "@oxlint/plugins";
|
|
3943
4737
|
function returnedObject(expression) {
|
|
3944
4738
|
if (expression?.type === "TSAsExpression" || expression?.type === "TSSatisfiesExpression" || expression?.type === "TSTypeAssertion" || expression?.type === "TSNonNullExpression") {
|
|
3945
4739
|
return returnedObject(expression.expression);
|
|
@@ -3950,7 +4744,7 @@ function compileKeys(pattern, keys, requireKeys) {
|
|
|
3950
4744
|
const allowedList = keys.concat(requireKeys.filter((key) => !keys.includes(key)));
|
|
3951
4745
|
return { patterns: optionsPatternsWithEmpty(pattern), allowed: new Set(allowedList), allowedList, required: requireKeys };
|
|
3952
4746
|
}
|
|
3953
|
-
var filesFactoryKeys =
|
|
4747
|
+
var filesFactoryKeys = defineRule39({
|
|
3954
4748
|
meta: {
|
|
3955
4749
|
type: "problem",
|
|
3956
4750
|
schema: [
|
|
@@ -4068,8 +4862,8 @@ var filesFactoryKeys = defineRule33({
|
|
|
4068
4862
|
});
|
|
4069
4863
|
|
|
4070
4864
|
// src/rules/files/files-helpers.ts
|
|
4071
|
-
import { defineRule as
|
|
4072
|
-
var filesHelpers =
|
|
4865
|
+
import { defineRule as defineRule40 } from "@oxlint/plugins";
|
|
4866
|
+
var filesHelpers = defineRule40({
|
|
4073
4867
|
meta: {
|
|
4074
4868
|
type: "problem",
|
|
4075
4869
|
schema: [
|
|
@@ -4117,8 +4911,8 @@ var filesHelpers = defineRule34({
|
|
|
4117
4911
|
});
|
|
4118
4912
|
|
|
4119
4913
|
// src/rules/files/files-no-functions.ts
|
|
4120
|
-
import { defineRule as
|
|
4121
|
-
var filesNoFunctions =
|
|
4914
|
+
import { defineRule as defineRule41 } from "@oxlint/plugins";
|
|
4915
|
+
var filesNoFunctions = defineRule41({
|
|
4122
4916
|
meta: {
|
|
4123
4917
|
type: "problem",
|
|
4124
4918
|
schema: [
|
|
@@ -4172,8 +4966,8 @@ var filesNoFunctions = defineRule35({
|
|
|
4172
4966
|
});
|
|
4173
4967
|
|
|
4174
4968
|
// src/rules/files/files-restricted.ts
|
|
4175
|
-
import { defineRule as
|
|
4176
|
-
var filesRestricted =
|
|
4969
|
+
import { defineRule as defineRule42 } from "@oxlint/plugins";
|
|
4970
|
+
var filesRestricted = defineRule42({
|
|
4177
4971
|
meta: {
|
|
4178
4972
|
type: "problem",
|
|
4179
4973
|
schema: [
|
|
@@ -4205,7 +4999,7 @@ var filesRestricted = defineRule36({
|
|
|
4205
4999
|
});
|
|
4206
5000
|
|
|
4207
5001
|
// src/rules/files/files-route.ts
|
|
4208
|
-
import { defineRule as
|
|
5002
|
+
import { defineRule as defineRule43 } from "@oxlint/plugins";
|
|
4209
5003
|
function inspectAdapter(context, item, bannedHooks, banIntrinsicJsx) {
|
|
4210
5004
|
astVisit(item.node.body, [item.node], (node) => {
|
|
4211
5005
|
if (banIntrinsicJsx && node.type === "JSXOpeningElement" && node.name.type === "JSXIdentifier" && /^[a-z]/.test(node.name.name)) {
|
|
@@ -4225,7 +5019,7 @@ function inspectAdapter(context, item, bannedHooks, banIntrinsicJsx) {
|
|
|
4225
5019
|
}
|
|
4226
5020
|
});
|
|
4227
5021
|
}
|
|
4228
|
-
var filesRoute =
|
|
5022
|
+
var filesRoute = defineRule43({
|
|
4229
5023
|
meta: {
|
|
4230
5024
|
type: "problem",
|
|
4231
5025
|
schema: [
|
|
@@ -4295,7 +5089,7 @@ var filesRoute = defineRule37({
|
|
|
4295
5089
|
});
|
|
4296
5090
|
|
|
4297
5091
|
// src/rules/files/files-types-only.ts
|
|
4298
|
-
import { defineRule as
|
|
5092
|
+
import { defineRule as defineRule44 } from "@oxlint/plugins";
|
|
4299
5093
|
function runtimeImportLocalNames(statement) {
|
|
4300
5094
|
return statement.specifiers.flatMap((specifier) => specifier.type !== "ImportSpecifier" || specifier.importKind !== "type" ? [specifier.local.name] : []);
|
|
4301
5095
|
}
|
|
@@ -4464,7 +5258,7 @@ function runtimeKind(node) {
|
|
|
4464
5258
|
}
|
|
4465
5259
|
return node.type === "FunctionDeclaration" ? "function" : "variable";
|
|
4466
5260
|
}
|
|
4467
|
-
var filesTypesOnly =
|
|
5261
|
+
var filesTypesOnly = defineRule44({
|
|
4468
5262
|
meta: {
|
|
4469
5263
|
type: "problem",
|
|
4470
5264
|
schema: [
|
|
@@ -4572,8 +5366,8 @@ var filesTypesOnly = defineRule38({
|
|
|
4572
5366
|
});
|
|
4573
5367
|
|
|
4574
5368
|
// src/rules/layout/layout-arrow-body.ts
|
|
4575
|
-
import { defineRule as
|
|
4576
|
-
var layoutArrowBody =
|
|
5369
|
+
import { defineRule as defineRule45 } from "@oxlint/plugins";
|
|
5370
|
+
var layoutArrowBody = defineRule45({
|
|
4577
5371
|
meta: {
|
|
4578
5372
|
type: "layout",
|
|
4579
5373
|
fixable: "whitespace",
|
|
@@ -4625,12 +5419,12 @@ var layoutArrowBody = defineRule39({
|
|
|
4625
5419
|
});
|
|
4626
5420
|
|
|
4627
5421
|
// src/rules/layout/layout-call-arguments.ts
|
|
4628
|
-
import { defineRule as
|
|
5422
|
+
import { defineRule as defineRule46 } from "@oxlint/plugins";
|
|
4629
5423
|
function layoutCallArgumentsHuggable(node) {
|
|
4630
5424
|
return astIsInlineFunction(node) || node.type === "ObjectExpression" || node.type === "ArrayExpression" || astIsCall(node) && node.arguments.length === 1 && (node.callee.type !== "MemberExpression" || astIsOneLine(node.callee)) && node.arguments.every(layoutCallArgumentsHuggable);
|
|
4631
5425
|
}
|
|
4632
5426
|
var layoutCallArgumentsMax = { type: "integer", minimum: 1 };
|
|
4633
|
-
var layoutCallArguments =
|
|
5427
|
+
var layoutCallArguments = defineRule46({
|
|
4634
5428
|
meta: {
|
|
4635
5429
|
type: "layout",
|
|
4636
5430
|
fixable: "whitespace",
|
|
@@ -4812,12 +5606,12 @@ var layoutCallArguments = defineRule40({
|
|
|
4812
5606
|
});
|
|
4813
5607
|
|
|
4814
5608
|
// src/rules/layout/layout-call-array.ts
|
|
4815
|
-
import { defineRule as
|
|
5609
|
+
import { defineRule as defineRule47 } from "@oxlint/plugins";
|
|
4816
5610
|
var layoutCallArrayDefaultCallees = ["Promise.all", "Promise.allSettled"];
|
|
4817
5611
|
function layoutCallArrayRoot(node) {
|
|
4818
5612
|
return node.type === "MemberExpression" ? layoutCallArrayRoot(node.object) : node;
|
|
4819
5613
|
}
|
|
4820
|
-
var layoutCallArray =
|
|
5614
|
+
var layoutCallArray = defineRule47({
|
|
4821
5615
|
meta: {
|
|
4822
5616
|
type: "layout",
|
|
4823
5617
|
fixable: "whitespace",
|
|
@@ -4933,7 +5727,7 @@ var layoutCallArray = defineRule41({
|
|
|
4933
5727
|
});
|
|
4934
5728
|
|
|
4935
5729
|
// src/rules/layout/layout-call-depth.ts
|
|
4936
|
-
import { defineRule as
|
|
5730
|
+
import { defineRule as defineRule48 } from "@oxlint/plugins";
|
|
4937
5731
|
function layoutCallDepthOuter(node) {
|
|
4938
5732
|
const parent = node.parent;
|
|
4939
5733
|
if (!parent || parent.type === "ArrowFunctionExpression" || parent.type === "FunctionExpression" || parent.type.endsWith("Statement")) {
|
|
@@ -4941,7 +5735,7 @@ function layoutCallDepthOuter(node) {
|
|
|
4941
5735
|
}
|
|
4942
5736
|
return astIsCall(parent) && parent.arguments.some((argument) => argument === node) ? parent : layoutCallDepthOuter(parent);
|
|
4943
5737
|
}
|
|
4944
|
-
var layoutCallDepth =
|
|
5738
|
+
var layoutCallDepth = defineRule48({
|
|
4945
5739
|
meta: {
|
|
4946
5740
|
type: "layout",
|
|
4947
5741
|
schema: [
|
|
@@ -4980,8 +5774,8 @@ var layoutCallDepth = defineRule42({
|
|
|
4980
5774
|
});
|
|
4981
5775
|
|
|
4982
5776
|
// src/rules/layout/layout-chain.ts
|
|
4983
|
-
import { defineRule as
|
|
4984
|
-
var layoutChain =
|
|
5777
|
+
import { defineRule as defineRule49 } from "@oxlint/plugins";
|
|
5778
|
+
var layoutChain = defineRule49({
|
|
4985
5779
|
meta: {
|
|
4986
5780
|
type: "layout",
|
|
4987
5781
|
fixable: "whitespace",
|
|
@@ -5100,8 +5894,8 @@ var layoutChain = defineRule43({
|
|
|
5100
5894
|
});
|
|
5101
5895
|
|
|
5102
5896
|
// src/rules/layout/layout-items.ts
|
|
5103
|
-
import { defineRule as
|
|
5104
|
-
var layoutItems =
|
|
5897
|
+
import { defineRule as defineRule50 } from "@oxlint/plugins";
|
|
5898
|
+
var layoutItems = defineRule50({
|
|
5105
5899
|
meta: {
|
|
5106
5900
|
type: "layout",
|
|
5107
5901
|
fixable: "whitespace",
|
|
@@ -5156,8 +5950,8 @@ var layoutItems = defineRule44({
|
|
|
5156
5950
|
});
|
|
5157
5951
|
|
|
5158
5952
|
// src/rules/layout/layout-jsx-attributes.ts
|
|
5159
|
-
import { defineRule as
|
|
5160
|
-
var layoutJsxAttributes =
|
|
5953
|
+
import { defineRule as defineRule51 } from "@oxlint/plugins";
|
|
5954
|
+
var layoutJsxAttributes = defineRule51({
|
|
5161
5955
|
meta: {
|
|
5162
5956
|
type: "layout",
|
|
5163
5957
|
fixable: "whitespace",
|
|
@@ -5245,8 +6039,8 @@ var layoutJsxAttributes = defineRule45({
|
|
|
5245
6039
|
});
|
|
5246
6040
|
|
|
5247
6041
|
// src/rules/layout/layout-key-value.ts
|
|
5248
|
-
import { defineRule as
|
|
5249
|
-
var layoutKeyValue =
|
|
6042
|
+
import { defineRule as defineRule52 } from "@oxlint/plugins";
|
|
6043
|
+
var layoutKeyValue = defineRule52({
|
|
5250
6044
|
meta: {
|
|
5251
6045
|
type: "layout",
|
|
5252
6046
|
fixable: "whitespace",
|
|
@@ -5282,7 +6076,7 @@ var layoutKeyValue = defineRule46({
|
|
|
5282
6076
|
});
|
|
5283
6077
|
|
|
5284
6078
|
// src/rules/layout/layout-object.ts
|
|
5285
|
-
import { defineRule as
|
|
6079
|
+
import { defineRule as defineRule53 } from "@oxlint/plugins";
|
|
5286
6080
|
function layoutObjectIsWhitespace(text) {
|
|
5287
6081
|
return /^[\t\n\r\f ]*$/.test(text);
|
|
5288
6082
|
}
|
|
@@ -5290,7 +6084,7 @@ function layoutObjectIsFlat(property) {
|
|
|
5290
6084
|
const value = property.type === "SpreadElement" ? property.argument : property.value;
|
|
5291
6085
|
return astIsOneLine(property) && (property.type === "SpreadElement" || !property.method && property.kind === "init") && value.type !== "ObjectExpression" && value.type !== "ArrayExpression" && !astIsInlineFunction(value);
|
|
5292
6086
|
}
|
|
5293
|
-
var layoutObject =
|
|
6087
|
+
var layoutObject = defineRule53({
|
|
5294
6088
|
meta: {
|
|
5295
6089
|
type: "layout",
|
|
5296
6090
|
fixable: "whitespace",
|
|
@@ -5407,7 +6201,7 @@ var layoutObject = defineRule47({
|
|
|
5407
6201
|
});
|
|
5408
6202
|
|
|
5409
6203
|
// src/rules/layout/layout-padding.ts
|
|
5410
|
-
import { defineRule as
|
|
6204
|
+
import { defineRule as defineRule54 } from "@oxlint/plugins";
|
|
5411
6205
|
var layoutPaddingControl = new Set([
|
|
5412
6206
|
"IfStatement",
|
|
5413
6207
|
"ForStatement",
|
|
@@ -5436,7 +6230,7 @@ function layoutPaddingKind(node) {
|
|
|
5436
6230
|
function layoutPaddingIsMultilineVariable(node, kind) {
|
|
5437
6231
|
return kind === "variable" && node.loc.start.line !== node.loc.end.line;
|
|
5438
6232
|
}
|
|
5439
|
-
var layoutPadding =
|
|
6233
|
+
var layoutPadding = defineRule54({
|
|
5440
6234
|
meta: {
|
|
5441
6235
|
type: "layout",
|
|
5442
6236
|
fixable: "whitespace",
|
|
@@ -5525,8 +6319,8 @@ var layoutPadding = defineRule48({
|
|
|
5525
6319
|
});
|
|
5526
6320
|
|
|
5527
6321
|
// src/rules/layout/layout-pipe.ts
|
|
5528
|
-
import { defineRule as
|
|
5529
|
-
var layoutPipe =
|
|
6322
|
+
import { defineRule as defineRule55 } from "@oxlint/plugins";
|
|
6323
|
+
var layoutPipe = defineRule55({
|
|
5530
6324
|
meta: {
|
|
5531
6325
|
type: "layout",
|
|
5532
6326
|
messages: {
|
|
@@ -5557,7 +6351,7 @@ var layoutPipe = defineRule49({
|
|
|
5557
6351
|
});
|
|
5558
6352
|
|
|
5559
6353
|
// src/rules/layout/layout-ternary.ts
|
|
5560
|
-
import { defineRule as
|
|
6354
|
+
import { defineRule as defineRule56 } from "@oxlint/plugins";
|
|
5561
6355
|
function layoutTernaryLines(node) {
|
|
5562
6356
|
return node.loc.end.line - node.loc.start.line + 1;
|
|
5563
6357
|
}
|
|
@@ -5565,7 +6359,7 @@ function layoutTernaryBreak(between, operator, newline) {
|
|
|
5565
6359
|
const at = between.indexOf(operator);
|
|
5566
6360
|
return `${between.slice(0, at).trimEnd()}${newline}${operator} ${between.slice(at + 1).trimStart()}`;
|
|
5567
6361
|
}
|
|
5568
|
-
var layoutTernary =
|
|
6362
|
+
var layoutTernary = defineRule56({
|
|
5569
6363
|
meta: {
|
|
5570
6364
|
type: "layout",
|
|
5571
6365
|
fixable: "whitespace",
|
|
@@ -5681,9 +6475,9 @@ var layoutTernary = defineRule50({
|
|
|
5681
6475
|
});
|
|
5682
6476
|
|
|
5683
6477
|
// src/rules/naming/naming-declarations.ts
|
|
5684
|
-
import { defineRule as
|
|
6478
|
+
import { defineRule as defineRule57 } from "@oxlint/plugins";
|
|
5685
6479
|
var namingDeclarationsKinds = ["function", "const", "let", "var", "class", "type", "interface", "enum"];
|
|
5686
|
-
var namingDeclarations =
|
|
6480
|
+
var namingDeclarations = defineRule57({
|
|
5687
6481
|
meta: {
|
|
5688
6482
|
type: "problem",
|
|
5689
6483
|
schema: [
|
|
@@ -5760,7 +6554,7 @@ var namingDeclarations = defineRule51({
|
|
|
5760
6554
|
});
|
|
5761
6555
|
|
|
5762
6556
|
// src/rules/naming/naming-exports.ts
|
|
5763
|
-
import { defineRule as
|
|
6557
|
+
import { defineRule as defineRule58 } from "@oxlint/plugins";
|
|
5764
6558
|
var namingExportsScopeProperties = {
|
|
5765
6559
|
scope: { type: "string", enum: ["exports", "functions", "declarations"] },
|
|
5766
6560
|
types: { type: "boolean" },
|
|
@@ -5786,7 +6580,7 @@ function matchTemplate(basename3, template, placeholder = "[a-z0-9-]+") {
|
|
|
5786
6580
|
}
|
|
5787
6581
|
return new RegExp(`^${pattern}$`).exec(basename3)?.groups ?? null;
|
|
5788
6582
|
}
|
|
5789
|
-
var namingExports =
|
|
6583
|
+
var namingExports = defineRule58({
|
|
5790
6584
|
meta: {
|
|
5791
6585
|
type: "problem",
|
|
5792
6586
|
schema: {
|
|
@@ -5923,10 +6717,10 @@ var namingExports = defineRule52({
|
|
|
5923
6717
|
});
|
|
5924
6718
|
|
|
5925
6719
|
// src/rules/naming/naming-file.ts
|
|
5926
|
-
import { defineRule as
|
|
6720
|
+
import { defineRule as defineRule59 } from "@oxlint/plugins";
|
|
5927
6721
|
import { readdirSync as readdirSync2 } from "node:fs";
|
|
5928
6722
|
import { dirname as dirname4 } from "node:path";
|
|
5929
|
-
var namingFile =
|
|
6723
|
+
var namingFile = defineRule59({
|
|
5930
6724
|
meta: {
|
|
5931
6725
|
type: "problem",
|
|
5932
6726
|
schema: {
|
|
@@ -5996,9 +6790,9 @@ var namingFile = defineRule53({
|
|
|
5996
6790
|
});
|
|
5997
6791
|
|
|
5998
6792
|
// src/rules/naming/naming-folder.ts
|
|
5999
|
-
import { defineRule as
|
|
6000
|
-
import { posix as
|
|
6001
|
-
var namingFolder =
|
|
6793
|
+
import { defineRule as defineRule60 } from "@oxlint/plugins";
|
|
6794
|
+
import { posix as posix3 } from "node:path";
|
|
6795
|
+
var namingFolder = defineRule60({
|
|
6002
6796
|
meta: {
|
|
6003
6797
|
type: "problem",
|
|
6004
6798
|
schema: [
|
|
@@ -6021,7 +6815,7 @@ var namingFolder = defineRule54({
|
|
|
6021
6815
|
return {
|
|
6022
6816
|
Program(program) {
|
|
6023
6817
|
const { singularize = "trailing-s", separators = ["-"], after, prefixes: stripPrefixes = [] } = optionsFirst(context, {});
|
|
6024
|
-
const all =
|
|
6818
|
+
const all = posix3.dirname(context.filename.replaceAll("\\", "/")).split("/").filter((part) => part && part !== ".");
|
|
6025
6819
|
const parent = [all.at(-1) ?? ""];
|
|
6026
6820
|
let folders = after ? undefined : parent;
|
|
6027
6821
|
const marker = (after ?? "").split("/").filter(Boolean);
|
|
@@ -6072,9 +6866,9 @@ var reactDynamicClasses = astSelectorRule(':matches(JSXAttribute[name.name="clas
|
|
|
6072
6866
|
var reactEmptyEffect = astSelectorRule(':matches(CallExpression[callee.name=/^use(Layout)?Effect$/], CallExpression[callee.object.name="React"][callee.property.name=/^use(Layout)?Effect$/]) > :matches(ArrowFunctionExpression, FunctionExpression) > BlockStatement[body.length=0]', "Remove the empty effect.");
|
|
6073
6867
|
|
|
6074
6868
|
// src/rules/react/react-memo.ts
|
|
6075
|
-
import { defineRule as
|
|
6869
|
+
import { defineRule as defineRule61 } from "@oxlint/plugins";
|
|
6076
6870
|
var reactMemoNames = ["memo", "useMemo", "useCallback"];
|
|
6077
|
-
var reactMemo =
|
|
6871
|
+
var reactMemo = defineRule61({
|
|
6078
6872
|
meta: {
|
|
6079
6873
|
type: "problem",
|
|
6080
6874
|
schema: [],
|
|
@@ -6109,7 +6903,7 @@ var reactMemo = defineRule55({
|
|
|
6109
6903
|
});
|
|
6110
6904
|
|
|
6111
6905
|
// src/rules/react/react-props.ts
|
|
6112
|
-
import { defineRule as
|
|
6906
|
+
import { defineRule as defineRule62 } from "@oxlint/plugins";
|
|
6113
6907
|
function reactPropsTarget(node) {
|
|
6114
6908
|
if (node?.type === "FunctionDeclaration" || node?.type === "FunctionExpression" || node?.type === "ArrowFunctionExpression") {
|
|
6115
6909
|
return { fn: node };
|
|
@@ -6136,7 +6930,7 @@ function reactIsPassThrough(type) {
|
|
|
6136
6930
|
const argument = type.typeArguments?.params.length === 1 ? type.typeArguments.params[0] : undefined;
|
|
6137
6931
|
return name.type === "Identifier" && name.name === "ComponentProps" && (argument?.type === "TSTypeQuery" || argument?.type === "TSLiteralType" && argument.literal.type === "Literal" && typeof argument.literal.value === "string");
|
|
6138
6932
|
}
|
|
6139
|
-
var reactProps =
|
|
6933
|
+
var reactProps = defineRule62({
|
|
6140
6934
|
meta: {
|
|
6141
6935
|
type: "problem",
|
|
6142
6936
|
schema: [
|
|
@@ -6234,8 +7028,90 @@ var reactProps = defineRule56({
|
|
|
6234
7028
|
}
|
|
6235
7029
|
});
|
|
6236
7030
|
|
|
7031
|
+
// src/rules/react/react-query-props.ts
|
|
7032
|
+
import { defineRule as defineRule63 } from "@oxlint/plugins";
|
|
7033
|
+
var reactQueryProps = defineRule63({
|
|
7034
|
+
meta: {
|
|
7035
|
+
type: "problem",
|
|
7036
|
+
schema: [
|
|
7037
|
+
{
|
|
7038
|
+
type: "object",
|
|
7039
|
+
additionalProperties: false,
|
|
7040
|
+
properties: {
|
|
7041
|
+
hooks: { type: "array", items: { type: "string" } },
|
|
7042
|
+
functions: { type: "array", items: { type: "string" } }
|
|
7043
|
+
}
|
|
7044
|
+
}
|
|
7045
|
+
],
|
|
7046
|
+
messages: {
|
|
7047
|
+
options: "Build the {{hook}} options here from props; ready-made options hide where the data comes from.",
|
|
7048
|
+
source: "{{key}} must be a prop or call one; pass the data function in from the app."
|
|
7049
|
+
}
|
|
7050
|
+
},
|
|
7051
|
+
createOnce(context) {
|
|
7052
|
+
return {
|
|
7053
|
+
CallExpression(node) {
|
|
7054
|
+
const { hooks = ["useQuery", "useMutation", "useInfiniteQuery", "useSuspenseQuery"], functions = ["queryFn", "mutationFn"] } = optionsFirst(context, {});
|
|
7055
|
+
const hook = astCallName(node);
|
|
7056
|
+
let owner = node.parent;
|
|
7057
|
+
while (owner && owner.type !== "FunctionDeclaration" && !astIsInlineFunction(owner)) {
|
|
7058
|
+
owner = owner.parent;
|
|
7059
|
+
}
|
|
7060
|
+
if (!hook || !hooks.includes(hook) || !owner || owner.type !== "FunctionDeclaration" && !astIsInlineFunction(owner)) {
|
|
7061
|
+
return;
|
|
7062
|
+
}
|
|
7063
|
+
const component = owner;
|
|
7064
|
+
const first = component.params.at(0);
|
|
7065
|
+
const parameter = first?.type === "AssignmentPattern" ? first.left : first;
|
|
7066
|
+
const definition = (identifier) => boundariesDeclaredVariable(context.sourceCode.getScope(identifier), identifier.name)?.defs.at(0);
|
|
7067
|
+
const isProps = (value) => {
|
|
7068
|
+
const found = value?.type === "Identifier" ? definition(value) : undefined;
|
|
7069
|
+
return found?.type === "Parameter" && found.node === component && parameter?.type === "Identifier";
|
|
7070
|
+
};
|
|
7071
|
+
const isProp = (value) => {
|
|
7072
|
+
if (value.type === "MemberExpression") {
|
|
7073
|
+
return isProps(value.object);
|
|
7074
|
+
}
|
|
7075
|
+
const found = value.type === "Identifier" ? definition(value) : undefined;
|
|
7076
|
+
if (found?.type === "Parameter") {
|
|
7077
|
+
return found.node === component && parameter?.type === "ObjectPattern";
|
|
7078
|
+
}
|
|
7079
|
+
return found?.type === "Variable" && found.node.type === "VariableDeclarator" && found.node.id.type === "ObjectPattern" && isProps(found.node.init);
|
|
7080
|
+
};
|
|
7081
|
+
const options = node.arguments.at(0);
|
|
7082
|
+
if (options?.type !== "ObjectExpression" || options.properties.some((property) => property.type === "SpreadElement")) {
|
|
7083
|
+
context.report({
|
|
7084
|
+
node: options ?? node,
|
|
7085
|
+
messageId: "options",
|
|
7086
|
+
data: { hook }
|
|
7087
|
+
});
|
|
7088
|
+
return;
|
|
7089
|
+
}
|
|
7090
|
+
for (const property of options.properties) {
|
|
7091
|
+
if (property.type !== "Property") {
|
|
7092
|
+
continue;
|
|
7093
|
+
}
|
|
7094
|
+
const key = property.key.type === "Identifier" && !property.computed ? property.key.name : astStaticString(property.key);
|
|
7095
|
+
if (key === undefined || !functions.includes(key)) {
|
|
7096
|
+
continue;
|
|
7097
|
+
}
|
|
7098
|
+
const { value } = property;
|
|
7099
|
+
const calls = astIsInlineFunction(value) && astSome(value.body, (child) => child.type === "CallExpression" && isProp(child.callee));
|
|
7100
|
+
if (!isProp(value) && !calls) {
|
|
7101
|
+
context.report({
|
|
7102
|
+
node: value,
|
|
7103
|
+
messageId: "source",
|
|
7104
|
+
data: { key }
|
|
7105
|
+
});
|
|
7106
|
+
}
|
|
7107
|
+
}
|
|
7108
|
+
}
|
|
7109
|
+
};
|
|
7110
|
+
}
|
|
7111
|
+
});
|
|
7112
|
+
|
|
6237
7113
|
// src/rules/schemas/schemas-inline.ts
|
|
6238
|
-
import { defineRule as
|
|
7114
|
+
import { defineRule as defineRule64 } from "@oxlint/plugins";
|
|
6239
7115
|
|
|
6240
7116
|
// src/utils/schemas.utils.ts
|
|
6241
7117
|
var schemasElementOptionsSchema = {
|
|
@@ -6271,7 +7147,7 @@ function schemasIsAllowedElement(node, allowScalars, namespaces, structuralMetho
|
|
|
6271
7147
|
}
|
|
6272
7148
|
|
|
6273
7149
|
// src/rules/schemas/schemas-inline.ts
|
|
6274
|
-
var schemasInline =
|
|
7150
|
+
var schemasInline = defineRule64({
|
|
6275
7151
|
meta: {
|
|
6276
7152
|
type: "problem",
|
|
6277
7153
|
schema: [schemasElementOptionsSchema],
|
|
@@ -6320,11 +7196,11 @@ var schemasInline = defineRule57({
|
|
|
6320
7196
|
});
|
|
6321
7197
|
|
|
6322
7198
|
// src/rules/schemas/schemas-local.ts
|
|
6323
|
-
import { defineRule as
|
|
7199
|
+
import { defineRule as defineRule65 } from "@oxlint/plugins";
|
|
6324
7200
|
var schemasLocalImportMessage = "Do not import runtime schema constructors from {{source}}; import a named schema instead.";
|
|
6325
7201
|
var schemasLocalConstructionMessage = "Do not construct schemas locally; import a named schema instead.";
|
|
6326
7202
|
var schemasLocalCalls = ["config", "prettifyError", "treeifyError", "flattenError", "formatError"];
|
|
6327
|
-
var schemasLocal =
|
|
7203
|
+
var schemasLocal = defineRule65({
|
|
6328
7204
|
meta: {
|
|
6329
7205
|
type: "problem",
|
|
6330
7206
|
schema: [
|
|
@@ -6337,6 +7213,8 @@ var schemasLocal = defineRule58({
|
|
|
6337
7213
|
calls: { type: "array", items: { type: "string" } },
|
|
6338
7214
|
allow: { type: "array", items: { type: "string" } },
|
|
6339
7215
|
patterns: { type: "array", items: { type: "string" } },
|
|
7216
|
+
imports: { type: "boolean" },
|
|
7217
|
+
values: { type: "boolean" },
|
|
6340
7218
|
message: { type: "string" },
|
|
6341
7219
|
importMessage: { type: "string" },
|
|
6342
7220
|
constructionMessage: { type: "string" }
|
|
@@ -6356,6 +7234,32 @@ var schemasLocal = defineRule58({
|
|
|
6356
7234
|
let pending = [];
|
|
6357
7235
|
let importMessage = schemasLocalImportMessage;
|
|
6358
7236
|
let constructionMessage = schemasLocalConstructionMessage;
|
|
7237
|
+
let imports = true;
|
|
7238
|
+
let values = false;
|
|
7239
|
+
let inline = new Set;
|
|
7240
|
+
function isInline(node) {
|
|
7241
|
+
if (inline.size === 0) {
|
|
7242
|
+
return false;
|
|
7243
|
+
}
|
|
7244
|
+
for (let parent = node.parent;parent; parent = parent.parent) {
|
|
7245
|
+
if (inline.has(parent)) {
|
|
7246
|
+
return true;
|
|
7247
|
+
}
|
|
7248
|
+
}
|
|
7249
|
+
return false;
|
|
7250
|
+
}
|
|
7251
|
+
function readsLocal(node) {
|
|
7252
|
+
const scope = context.sourceCode.getScope(node);
|
|
7253
|
+
return astSome(node, (child) => {
|
|
7254
|
+
if (child.type !== "Identifier") {
|
|
7255
|
+
return false;
|
|
7256
|
+
}
|
|
7257
|
+
const parent = child.parent;
|
|
7258
|
+
const named = parent.type === "MemberExpression" && parent.property === child && !parent.computed || parent.type === "Property" && parent.key === child && !parent.computed && !parent.shorthand;
|
|
7259
|
+
const type = named ? undefined : boundariesDeclaredVariable(scope, child.name)?.scope.type;
|
|
7260
|
+
return type !== undefined && type !== "module" && type !== "global";
|
|
7261
|
+
});
|
|
7262
|
+
}
|
|
6359
7263
|
function isAllowedCall(node, member) {
|
|
6360
7264
|
return member?.type === "MemberExpression" && member.object === node && !member.computed && member.property.type === "Identifier" && calls.has(member.property.name) && member.parent.type === "CallExpression" && member.parent.callee === member;
|
|
6361
7265
|
}
|
|
@@ -6363,6 +7267,9 @@ var schemasLocal = defineRule58({
|
|
|
6363
7267
|
return packages.has(source) || [...packages].some((name) => source.startsWith(`${name}/`));
|
|
6364
7268
|
}
|
|
6365
7269
|
function reportRuntimeImport(node, source) {
|
|
7270
|
+
if (!imports) {
|
|
7271
|
+
return;
|
|
7272
|
+
}
|
|
6366
7273
|
context.report({
|
|
6367
7274
|
node,
|
|
6368
7275
|
messageId: "runtimeImport",
|
|
@@ -6387,6 +7294,9 @@ var schemasLocal = defineRule58({
|
|
|
6387
7294
|
pending = [];
|
|
6388
7295
|
importMessage = options.importMessage ?? options.message ?? schemasLocalImportMessage;
|
|
6389
7296
|
constructionMessage = options.constructionMessage ?? options.message ?? schemasLocalConstructionMessage;
|
|
7297
|
+
imports = options.imports ?? true;
|
|
7298
|
+
values = options.values ?? false;
|
|
7299
|
+
inline = new Set;
|
|
6390
7300
|
if ((options.allow ?? []).some((suffix) => filename.endsWith(suffix)) || (options.patterns ?? []).some((pattern) => new RegExp(pattern).test(filename))) {
|
|
6391
7301
|
return false;
|
|
6392
7302
|
}
|
|
@@ -6409,7 +7319,7 @@ var schemasLocal = defineRule58({
|
|
|
6409
7319
|
pending.push({ node, locals });
|
|
6410
7320
|
},
|
|
6411
7321
|
"Program:exit"() {
|
|
6412
|
-
const runtime = pending.filter(({ node, locals }) => context.sourceCode.getDeclaredVariables(node).filter((variable) => locals.includes(variable.name)).some((variable) => variable.references.length === 0 || variable.references.some((reference) => !isAllowedCall(reference.identifier, reference.identifier.parent))));
|
|
7322
|
+
const runtime = pending.filter(({ node, locals }) => context.sourceCode.getDeclaredVariables(node).filter((variable) => locals.includes(variable.name)).some((variable) => variable.references.length === 0 || variable.references.some((reference) => !isAllowedCall(reference.identifier, reference.identifier.parent) && !isInline(reference.identifier))));
|
|
6413
7323
|
for (const { node } of runtime) {
|
|
6414
7324
|
reportRuntimeImport(node, node.source.value);
|
|
6415
7325
|
}
|
|
@@ -6424,6 +7334,10 @@ var schemasLocal = defineRule58({
|
|
|
6424
7334
|
if (root.type !== "Identifier" || !constructors.has(root.name) || node.callee.type === "MemberExpression" && node.callee.object === root && isAllowedCall(root, root.parent)) {
|
|
6425
7335
|
return;
|
|
6426
7336
|
}
|
|
7337
|
+
if (values && (isInline(node) || readsLocal(node))) {
|
|
7338
|
+
inline.add(node);
|
|
7339
|
+
return;
|
|
7340
|
+
}
|
|
6427
7341
|
context.report({
|
|
6428
7342
|
node,
|
|
6429
7343
|
messageId: "construction",
|
|
@@ -6435,8 +7349,8 @@ var schemasLocal = defineRule58({
|
|
|
6435
7349
|
});
|
|
6436
7350
|
|
|
6437
7351
|
// src/rules/schemas/schemas-rederive.ts
|
|
6438
|
-
import { defineRule as
|
|
6439
|
-
var schemasRederive =
|
|
7352
|
+
import { defineRule as defineRule66 } from "@oxlint/plugins";
|
|
7353
|
+
var schemasRederive = defineRule66({
|
|
6440
7354
|
meta: {
|
|
6441
7355
|
type: "problem",
|
|
6442
7356
|
schema: [
|
|
@@ -6482,7 +7396,7 @@ var schemasRederive = defineRule59({
|
|
|
6482
7396
|
});
|
|
6483
7397
|
|
|
6484
7398
|
// src/rules/schemas/schemas-single-use.ts
|
|
6485
|
-
import { defineRule as
|
|
7399
|
+
import { defineRule as defineRule67 } from "@oxlint/plugins";
|
|
6486
7400
|
function isScalarSchema(node, namespaces, structuralMethods) {
|
|
6487
7401
|
if (node.type !== "CallExpression" || node.callee.type !== "MemberExpression") {
|
|
6488
7402
|
return false;
|
|
@@ -6496,7 +7410,7 @@ function isScalarSchema(node, namespaces, structuralMethods) {
|
|
|
6496
7410
|
}
|
|
6497
7411
|
return node.callee.object.type === "CallExpression" && isScalarSchema(node.callee.object, namespaces, structuralMethods);
|
|
6498
7412
|
}
|
|
6499
|
-
var schemasSingleUse =
|
|
7413
|
+
var schemasSingleUse = defineRule67({
|
|
6500
7414
|
meta: {
|
|
6501
7415
|
type: "suggestion",
|
|
6502
7416
|
schema: [schemasElementOptionsSchema],
|
|
@@ -6572,7 +7486,7 @@ var schemasSingleUse = defineRule60({
|
|
|
6572
7486
|
});
|
|
6573
7487
|
|
|
6574
7488
|
// src/rules/tests/tests-assertions.ts
|
|
6575
|
-
import { defineRule as
|
|
7489
|
+
import { defineRule as defineRule68 } from "@oxlint/plugins";
|
|
6576
7490
|
var testsAssertionsModifiers = new Set(["for", "each", "concurrent", "sequential", "only", "skip"]);
|
|
6577
7491
|
var testsAssertionsFunctions = [
|
|
6578
7492
|
"expect",
|
|
@@ -6762,7 +7676,7 @@ function isAssertedTest(registration, sourceCode, state) {
|
|
|
6762
7676
|
}
|
|
6763
7677
|
return rows.length > 0 && rows.every((row) => hasAssertion(callback, row.bindings, new Set, state));
|
|
6764
7678
|
}
|
|
6765
|
-
var testsAssertions =
|
|
7679
|
+
var testsAssertions = defineRule68({
|
|
6766
7680
|
meta: {
|
|
6767
7681
|
type: "problem",
|
|
6768
7682
|
schema: [
|
|
@@ -6888,8 +7802,8 @@ var testsAssertions = defineRule61({
|
|
|
6888
7802
|
});
|
|
6889
7803
|
|
|
6890
7804
|
// src/rules/tests/tests-concurrent-db.ts
|
|
6891
|
-
import { defineRule as
|
|
6892
|
-
var testsConcurrentDb =
|
|
7805
|
+
import { defineRule as defineRule69 } from "@oxlint/plugins";
|
|
7806
|
+
var testsConcurrentDb = defineRule69({
|
|
6893
7807
|
meta: {
|
|
6894
7808
|
type: "problem",
|
|
6895
7809
|
schema: [
|
|
@@ -6945,7 +7859,7 @@ var testsConcurrentDb = defineRule62({
|
|
|
6945
7859
|
});
|
|
6946
7860
|
|
|
6947
7861
|
// src/rules/tests/tests-modifiers.ts
|
|
6948
|
-
import { defineRule as
|
|
7862
|
+
import { defineRule as defineRule70 } from "@oxlint/plugins";
|
|
6949
7863
|
var testsModifiersNames = ["test", "it", "describe", "suite"];
|
|
6950
7864
|
var testsModifiersPackages = new Set(["vitest", "bun:test", "@playwright/test", "@jest/globals"]);
|
|
6951
7865
|
var testsModifiersBanned = ["only", "skip", "todo"];
|
|
@@ -6964,7 +7878,7 @@ function modifierName(node) {
|
|
|
6964
7878
|
const property = astMemberName(node);
|
|
6965
7879
|
return object && property ? `${object}.${property}` : undefined;
|
|
6966
7880
|
}
|
|
6967
|
-
var testsModifiers =
|
|
7881
|
+
var testsModifiers = defineRule70({
|
|
6968
7882
|
meta: {
|
|
6969
7883
|
type: "problem",
|
|
6970
7884
|
schema: [
|
|
@@ -7018,9 +7932,9 @@ var testsModifiers = defineRule63({
|
|
|
7018
7932
|
});
|
|
7019
7933
|
|
|
7020
7934
|
// src/rules/tests/tests-titles.ts
|
|
7021
|
-
import { defineRule as
|
|
7935
|
+
import { defineRule as defineRule71 } from "@oxlint/plugins";
|
|
7022
7936
|
var testsTitlesModifiers = ["only", "skip", "concurrent", "sequential", "todo", "each", "for"];
|
|
7023
|
-
var testsTitles =
|
|
7937
|
+
var testsTitles = defineRule71({
|
|
7024
7938
|
meta: {
|
|
7025
7939
|
type: "suggestion",
|
|
7026
7940
|
schema: [
|
|
@@ -7098,11 +8012,11 @@ var testsTitles = defineRule64({
|
|
|
7098
8012
|
});
|
|
7099
8013
|
|
|
7100
8014
|
// src/rules/types/types-declarations.ts
|
|
7101
|
-
import { defineRule as
|
|
8015
|
+
import { defineRule as defineRule72 } from "@oxlint/plugins";
|
|
7102
8016
|
function isValuePattern(source) {
|
|
7103
8017
|
return /^\^?=/.test(source);
|
|
7104
8018
|
}
|
|
7105
|
-
var typesDeclarations =
|
|
8019
|
+
var typesDeclarations = defineRule72({
|
|
7106
8020
|
meta: {
|
|
7107
8021
|
type: "problem",
|
|
7108
8022
|
schema: [
|
|
@@ -7110,7 +8024,8 @@ var typesDeclarations = defineRule65({
|
|
|
7110
8024
|
type: "object",
|
|
7111
8025
|
additionalProperties: false,
|
|
7112
8026
|
properties: {
|
|
7113
|
-
allow: optionsPatternSchema
|
|
8027
|
+
allow: optionsPatternSchema,
|
|
8028
|
+
modules: { type: "boolean" }
|
|
7114
8029
|
}
|
|
7115
8030
|
}
|
|
7116
8031
|
],
|
|
@@ -7121,8 +8036,14 @@ var typesDeclarations = defineRule65({
|
|
|
7121
8036
|
createOnce(context) {
|
|
7122
8037
|
let allowedNames = [];
|
|
7123
8038
|
let allowedValues = [];
|
|
8039
|
+
let allowModules = false;
|
|
7124
8040
|
function check(node) {
|
|
7125
|
-
|
|
8041
|
+
let ancestor = node.parent;
|
|
8042
|
+
while (allowModules && ancestor && ancestor.type !== "TSModuleDeclaration") {
|
|
8043
|
+
ancestor = ancestor.parent;
|
|
8044
|
+
}
|
|
8045
|
+
const ambient = ancestor?.type === "TSModuleDeclaration" && (ancestor.kind === "global" || ancestor.id.type === "Literal");
|
|
8046
|
+
if (allowModules && ambient || optionsPatternsTest(allowedNames, node.id.name) || node.type === "TSTypeAliasDeclaration" && allowedValues.length > 0 && optionsPatternsTest(allowedValues, `= ${context.sourceCode.getText(node.typeAnnotation)}`)) {
|
|
7126
8047
|
return;
|
|
7127
8048
|
}
|
|
7128
8049
|
context.report({
|
|
@@ -7133,7 +8054,8 @@ var typesDeclarations = defineRule65({
|
|
|
7133
8054
|
}
|
|
7134
8055
|
return {
|
|
7135
8056
|
before() {
|
|
7136
|
-
const { allow: allowPattern } = optionsFirst(context, {});
|
|
8057
|
+
const { allow: allowPattern, modules = false } = optionsFirst(context, {});
|
|
8058
|
+
allowModules = modules;
|
|
7137
8059
|
const sources = allowPattern === undefined ? [] : [allowPattern].flat();
|
|
7138
8060
|
allowedNames = optionsPatterns(sources.filter((source) => !isValuePattern(source)));
|
|
7139
8061
|
allowedValues = optionsPatterns(sources.filter(isValuePattern));
|
|
@@ -7144,8 +8066,73 @@ var typesDeclarations = defineRule65({
|
|
|
7144
8066
|
}
|
|
7145
8067
|
});
|
|
7146
8068
|
|
|
8069
|
+
// src/rules/types/types-duplicate.ts
|
|
8070
|
+
import { defineRule as defineRule73 } from "@oxlint/plugins";
|
|
8071
|
+
var typesDuplicate = defineRule73({
|
|
8072
|
+
meta: {
|
|
8073
|
+
type: "suggestion",
|
|
8074
|
+
schema: [
|
|
8075
|
+
{
|
|
8076
|
+
type: "object",
|
|
8077
|
+
additionalProperties: false,
|
|
8078
|
+
properties: {
|
|
8079
|
+
structs: { type: "array", items: { type: "string" } },
|
|
8080
|
+
min: { type: "integer", minimum: 1 }
|
|
8081
|
+
}
|
|
8082
|
+
}
|
|
8083
|
+
],
|
|
8084
|
+
messages: { duplicate: "{{name}} has the same members as {{first}}; use {{first}}, or derive one from the other." }
|
|
8085
|
+
},
|
|
8086
|
+
createOnce(context) {
|
|
8087
|
+
let structs = new Set(["Schema.Struct"]);
|
|
8088
|
+
let min = 2;
|
|
8089
|
+
let seen = new Map;
|
|
8090
|
+
const check = (node, name, kind, members) => {
|
|
8091
|
+
if (members.length < min) {
|
|
8092
|
+
return;
|
|
8093
|
+
}
|
|
8094
|
+
const signature = members.map((item) => context.sourceCode.getText(item).replaceAll(/\breadonly\s+/g, "").replaceAll(/\s+/g, "").replace(/[;,]$/, "")).sort().join(";");
|
|
8095
|
+
const key = `${kind}:${signature}`;
|
|
8096
|
+
const first = seen.get(key);
|
|
8097
|
+
if (first === undefined) {
|
|
8098
|
+
seen.set(key, name);
|
|
8099
|
+
return;
|
|
8100
|
+
}
|
|
8101
|
+
context.report({
|
|
8102
|
+
node,
|
|
8103
|
+
messageId: "duplicate",
|
|
8104
|
+
data: { name, first }
|
|
8105
|
+
});
|
|
8106
|
+
};
|
|
8107
|
+
return {
|
|
8108
|
+
before() {
|
|
8109
|
+
const options = optionsFirst(context, {});
|
|
8110
|
+
structs = new Set(options.structs ?? ["Schema.Struct"]);
|
|
8111
|
+
min = options.min ?? 2;
|
|
8112
|
+
seen = new Map;
|
|
8113
|
+
},
|
|
8114
|
+
TSInterfaceDeclaration(node) {
|
|
8115
|
+
const heritage = node.extends.map((item) => context.sourceCode.getText(item)).join(",");
|
|
8116
|
+
check(node, node.id.name, `type:${heritage}`, node.body.body);
|
|
8117
|
+
},
|
|
8118
|
+
TSTypeAliasDeclaration(node) {
|
|
8119
|
+
if (node.typeAnnotation.type === "TSTypeLiteral") {
|
|
8120
|
+
check(node, node.id.name, "type:", node.typeAnnotation.members);
|
|
8121
|
+
}
|
|
8122
|
+
},
|
|
8123
|
+
VariableDeclarator(node) {
|
|
8124
|
+
const init = node.init ? astUnwrap(node.init) : undefined;
|
|
8125
|
+
const fields = init?.type === "CallExpression" && structs.has(astDottedName(init.callee) ?? "") ? init.arguments[0] : undefined;
|
|
8126
|
+
if (fields?.type === "ObjectExpression" && node.id.type === "Identifier") {
|
|
8127
|
+
check(node, node.id.name, "struct", fields.properties);
|
|
8128
|
+
}
|
|
8129
|
+
}
|
|
8130
|
+
};
|
|
8131
|
+
}
|
|
8132
|
+
});
|
|
8133
|
+
|
|
7147
8134
|
// src/rules/types/types-imported-alias.ts
|
|
7148
|
-
import { defineRule as
|
|
8135
|
+
import { defineRule as defineRule74 } from "@oxlint/plugins";
|
|
7149
8136
|
function importedAliasTarget(declaration, imports) {
|
|
7150
8137
|
if (declaration?.type !== "TSTypeAliasDeclaration") {
|
|
7151
8138
|
return;
|
|
@@ -7157,7 +8144,7 @@ function importedAliasTarget(declaration, imports) {
|
|
|
7157
8144
|
const { name } = type.typeName;
|
|
7158
8145
|
return imports.has(name) && !declaration.typeParameters?.params.some((parameter) => parameter.name.name === name) ? name : undefined;
|
|
7159
8146
|
}
|
|
7160
|
-
var typesImportedAlias =
|
|
8147
|
+
var typesImportedAlias = defineRule74({
|
|
7161
8148
|
meta: {
|
|
7162
8149
|
type: "problem",
|
|
7163
8150
|
schema: [],
|
|
@@ -7219,7 +8206,7 @@ var typesImportedAlias = defineRule66({
|
|
|
7219
8206
|
});
|
|
7220
8207
|
|
|
7221
8208
|
// src/rules/types/types-inline.ts
|
|
7222
|
-
import { defineRule as
|
|
8209
|
+
import { defineRule as defineRule75 } from "@oxlint/plugins";
|
|
7223
8210
|
function parameterAnnotation(parameter) {
|
|
7224
8211
|
if (parameter.type === "TSParameterProperty") {
|
|
7225
8212
|
return parameterAnnotation(parameter.parameter);
|
|
@@ -7229,7 +8216,7 @@ function parameterAnnotation(parameter) {
|
|
|
7229
8216
|
}
|
|
7230
8217
|
return parameter.typeAnnotation;
|
|
7231
8218
|
}
|
|
7232
|
-
var typesInline =
|
|
8219
|
+
var typesInline = defineRule75({
|
|
7233
8220
|
meta: {
|
|
7234
8221
|
type: "problem",
|
|
7235
8222
|
schema: [
|
|
@@ -7240,6 +8227,9 @@ var typesInline = defineRule67({
|
|
|
7240
8227
|
parameters: { type: "boolean" },
|
|
7241
8228
|
returns: { type: "boolean" },
|
|
7242
8229
|
functions: { type: "boolean" },
|
|
8230
|
+
variables: { type: "boolean" },
|
|
8231
|
+
assertions: { type: "boolean" },
|
|
8232
|
+
arguments: { type: "boolean" },
|
|
7243
8233
|
min: { type: "integer", minimum: 1 }
|
|
7244
8234
|
}
|
|
7245
8235
|
}
|
|
@@ -7252,6 +8242,9 @@ var typesInline = defineRule67({
|
|
|
7252
8242
|
let checkParameters = true;
|
|
7253
8243
|
let checkReturns = true;
|
|
7254
8244
|
let checkFunctionTypes = true;
|
|
8245
|
+
let checkVariables = false;
|
|
8246
|
+
let checkAssertions = false;
|
|
8247
|
+
let checkArguments = false;
|
|
7255
8248
|
let minMembers = 1;
|
|
7256
8249
|
function isInline(node) {
|
|
7257
8250
|
if (node.type === "TSTypeLiteral") {
|
|
@@ -7287,11 +8280,44 @@ var typesInline = defineRule67({
|
|
|
7287
8280
|
checkParameters = options.parameters ?? true;
|
|
7288
8281
|
checkReturns = options.returns ?? true;
|
|
7289
8282
|
checkFunctionTypes = options.functions ?? true;
|
|
8283
|
+
checkVariables = options.variables ?? false;
|
|
8284
|
+
checkAssertions = options.assertions ?? false;
|
|
8285
|
+
checkArguments = options.arguments ?? false;
|
|
7290
8286
|
minMembers = options.min ?? 1;
|
|
7291
|
-
if (!checkParameters && !checkReturns) {
|
|
8287
|
+
if (!checkParameters && !checkReturns && !checkVariables && !checkAssertions && !checkArguments) {
|
|
7292
8288
|
return false;
|
|
7293
8289
|
}
|
|
7294
8290
|
},
|
|
8291
|
+
VariableDeclarator(node) {
|
|
8292
|
+
if (checkVariables) {
|
|
8293
|
+
check(parameterAnnotation(node.id), "variable");
|
|
8294
|
+
}
|
|
8295
|
+
},
|
|
8296
|
+
PropertyDefinition(node) {
|
|
8297
|
+
if (checkVariables) {
|
|
8298
|
+
check(node.typeAnnotation, "variable");
|
|
8299
|
+
}
|
|
8300
|
+
},
|
|
8301
|
+
TSAsExpression(node) {
|
|
8302
|
+
if (checkAssertions) {
|
|
8303
|
+
check(node.typeAnnotation, "assertion");
|
|
8304
|
+
}
|
|
8305
|
+
},
|
|
8306
|
+
TSSatisfiesExpression(node) {
|
|
8307
|
+
if (checkAssertions) {
|
|
8308
|
+
check(node.typeAnnotation, "assertion");
|
|
8309
|
+
}
|
|
8310
|
+
},
|
|
8311
|
+
CallExpression(node) {
|
|
8312
|
+
if (checkArguments) {
|
|
8313
|
+
check(node.typeArguments, "type argument");
|
|
8314
|
+
}
|
|
8315
|
+
},
|
|
8316
|
+
NewExpression(node) {
|
|
8317
|
+
if (checkArguments) {
|
|
8318
|
+
check(node.typeArguments, "type argument");
|
|
8319
|
+
}
|
|
8320
|
+
},
|
|
7295
8321
|
FunctionDeclaration: checkFunction,
|
|
7296
8322
|
FunctionExpression: checkFunction,
|
|
7297
8323
|
ArrowFunctionExpression: checkFunction,
|
|
@@ -7305,8 +8331,8 @@ var typesInline = defineRule67({
|
|
|
7305
8331
|
var typesLocalAlias = astSelectorRule("TSTypeAliasDeclaration", "Local component/hook contracts use interfaces named for their owner. Derived or reusable aliases belong in domain types; do not substitute an empty interface.");
|
|
7306
8332
|
|
|
7307
8333
|
// src/rules/types/types-namespace-import.ts
|
|
7308
|
-
import { defineRule as
|
|
7309
|
-
var typesNamespaceImport =
|
|
8334
|
+
import { defineRule as defineRule76 } from "@oxlint/plugins";
|
|
8335
|
+
var typesNamespaceImport = defineRule76({
|
|
7310
8336
|
meta: {
|
|
7311
8337
|
type: "suggestion",
|
|
7312
8338
|
schema: [
|
|
@@ -7348,8 +8374,8 @@ var typesNamespaceImport = defineRule68({
|
|
|
7348
8374
|
});
|
|
7349
8375
|
|
|
7350
8376
|
// src/rules/types/types-service.ts
|
|
7351
|
-
import { defineRule as
|
|
7352
|
-
var typesService =
|
|
8377
|
+
import { defineRule as defineRule77 } from "@oxlint/plugins";
|
|
8378
|
+
var typesService = defineRule77({
|
|
7353
8379
|
meta: {
|
|
7354
8380
|
type: "problem",
|
|
7355
8381
|
schema: [
|
|
@@ -7399,12 +8425,12 @@ var typesService = defineRule69({
|
|
|
7399
8425
|
});
|
|
7400
8426
|
|
|
7401
8427
|
// src/rules/types/types-unknown.ts
|
|
7402
|
-
import { defineRule as
|
|
8428
|
+
import { defineRule as defineRule78 } from "@oxlint/plugins";
|
|
7403
8429
|
function isCatchName(node) {
|
|
7404
8430
|
const key = "key" in node && !(("computed" in node) && node.computed) ? node.key : undefined;
|
|
7405
8431
|
return key?.type === "Identifier" && key.name === "catch";
|
|
7406
8432
|
}
|
|
7407
|
-
var typesUnknown =
|
|
8433
|
+
var typesUnknown = defineRule78({
|
|
7408
8434
|
meta: { type: "problem", schema: [], messages: { forbidden: "Use an owned domain type rather than unknown." } },
|
|
7409
8435
|
createOnce(context) {
|
|
7410
8436
|
return {
|
|
@@ -7443,6 +8469,7 @@ var src_default = eslintCompatPlugin({
|
|
|
7443
8469
|
"boundaries-token-owner": boundariesTokenOwner,
|
|
7444
8470
|
"code-branch-once": codeBranchOnce,
|
|
7445
8471
|
"code-constructor": codeConstructor,
|
|
8472
|
+
"code-delegate": codeDelegate,
|
|
7446
8473
|
"code-double-negation": codeDoubleNegation,
|
|
7447
8474
|
"code-function-nesting": codeFunctionNesting,
|
|
7448
8475
|
"code-inline": codeInline,
|
|
@@ -7459,6 +8486,11 @@ var src_default = eslintCompatPlugin({
|
|
|
7459
8486
|
"comments-code": commentsCode,
|
|
7460
8487
|
"comments-directives": commentsDirectives,
|
|
7461
8488
|
"copy-dashes": copyDashes,
|
|
8489
|
+
"effect-layer-file": effectLayerFile,
|
|
8490
|
+
"effect-layers": effectLayers,
|
|
8491
|
+
"effect-merge-pipe": effectMergePipe,
|
|
8492
|
+
"effect-schema-first": effectSchemaFirst,
|
|
8493
|
+
"effect-values-first": effectValuesFirst,
|
|
7462
8494
|
"files-components-only": filesComponentsOnly,
|
|
7463
8495
|
"files-constants-only": filesConstantsOnly,
|
|
7464
8496
|
"files-domain-constants": filesDomainConstants,
|
|
@@ -7491,6 +8523,7 @@ var src_default = eslintCompatPlugin({
|
|
|
7491
8523
|
"react-empty-effect": reactEmptyEffect,
|
|
7492
8524
|
"react-memo": reactMemo,
|
|
7493
8525
|
"react-props": reactProps,
|
|
8526
|
+
"react-query-props": reactQueryProps,
|
|
7494
8527
|
"schemas-inline": schemasInline,
|
|
7495
8528
|
"schemas-local": schemasLocal,
|
|
7496
8529
|
"schemas-rederive": schemasRederive,
|
|
@@ -7500,6 +8533,7 @@ var src_default = eslintCompatPlugin({
|
|
|
7500
8533
|
"tests-modifiers": testsModifiers,
|
|
7501
8534
|
"tests-titles": testsTitles,
|
|
7502
8535
|
"types-declarations": typesDeclarations,
|
|
8536
|
+
"types-duplicate": typesDuplicate,
|
|
7503
8537
|
"types-imported-alias": typesImportedAlias,
|
|
7504
8538
|
"types-inline": typesInline,
|
|
7505
8539
|
"types-local-alias": typesLocalAlias,
|