oxlint-plugin-arch 0.6.1 → 0.6.2
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 +4 -0
- package/README.md +34 -0
- package/dist/index.js +122 -122
- package/dist/presets/index.js +6 -7
- package/dist/presets/tanstack-start-react-modules-preset.js +6 -7
- package/dist/rules/dillon-anti-slop/index.d.ts +2 -0
- package/dist/rules/dillon-anti-slop/index.js +2 -2
- package/dist/rules/dillon-anti-slop/rules/no-chained-type-assertions.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-conditional-empty-object-spread.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-known-value-widening.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-module-mocking.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-object-parameters.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-reflect-apply.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-reflect-get.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-runtime-typeof.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-shape-in-symbol-names.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-unknown-parameters.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-unknown-returns.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-unknown-type-aliases.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-unsafe-dictionary-type.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/no-widen-then-assert.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/rules/require-safety-comment-for-type-assertion.d.ts +1 -0
- package/dist/rules/dillon-anti-slop/shared/dictionary-types.d.ts +19 -0
- package/dist/rules/dillon-anti-slop/shared/lexical-type-parameters.d.ts +4 -0
- package/dist/rules/dillon-anti-slop/shared/reflect-method.d.ts +2 -0
- package/dist/rules/module-policy/domain-constants.d.ts +2 -0
- package/dist/rules/module-policy/import-boundaries.d.ts +2 -0
- package/dist/rules/module-policy/index.d.ts +2 -0
- package/dist/rules/module-policy/index.js +49 -49
- package/dist/rules/module-policy/memoization.d.ts +2 -0
- package/dist/rules/module-policy/reasoned-directives.d.ts +2 -0
- package/dist/rules/module-policy/service-functions.d.ts +2 -0
- package/dist/rules/module-policy/service-types.d.ts +2 -0
- package/dist/rules/module-policy/tanstack-runtime.d.ts +2 -0
- package/dist/rules/module-policy/test-assertions.d.ts +2 -0
- package/dist/rules/module-policy/test-modifiers.d.ts +2 -0
- package/dist/types/module-policy.types.d.ts +34 -0
- package/dist/types/test-analysis.types.d.ts +11 -0
- package/dist/utils/helpers/ast.d.ts +12 -0
- package/dist/utils/helpers/boundaries.d.ts +3 -0
- package/dist/utils/helpers/comments.d.ts +6 -0
- package/dist/utils/helpers/declarations.d.ts +35 -0
- package/dist/utils/helpers/exports.d.ts +18 -0
- package/dist/utils/helpers/factories.d.ts +9 -0
- package/dist/utils/helpers/guards.d.ts +11 -0
- package/dist/utils/helpers/index.d.ts +16 -0
- package/dist/utils/helpers/layout.d.ts +15 -0
- package/dist/utils/helpers/naming.d.ts +13 -0
- package/dist/utils/helpers/options.d.ts +22 -0
- package/dist/utils/helpers/orpc.d.ts +3 -0
- package/dist/utils/helpers/react-components.d.ts +13 -0
- package/dist/utils/helpers/routes.d.ts +5 -0
- package/dist/utils/helpers/sanitizers.d.ts +3 -0
- package/dist/utils/helpers/schemas.d.ts +10 -0
- package/dist/utils/helpers/syntax.d.ts +1 -0
- package/dist/utils/helpers/test-tables.d.ts +8 -0
- package/dist/utils/helpers/trivial.d.ts +6 -0
- package/dist/utils/index.d.ts +1 -0
- package/package.json +9 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.2
|
|
4
|
+
|
|
5
|
+
- Export `oxlint-plugin-arch/rules/dillon-anti-slop` and `oxlint-plugin-arch/rules/module-policy` with TypeScript declarations. Resolve the preset's three first-party plugins through public package entry points, without changing rules or policy. Document standalone registration and third-party dependency ownership; verify built exports expose every supporting rule.
|
|
6
|
+
|
|
3
7
|
## 0.6.1
|
|
4
8
|
|
|
5
9
|
- Relax the preset's shadcn defaults for stock composition, so strict consumers need no overrides: exact padding groups on `CardContent`/`PopoverContent`, gap and padding on `TabsContent`, and gap on `Tabs`/`HoverCardContent`/`SidebarHeader`/`BreadcrumbList`; exact `truncate` everywhere. Controls such as `Button` stay protected.
|
package/README.md
CHANGED
|
@@ -264,6 +264,40 @@ export default defineConfig({
|
|
|
264
264
|
})
|
|
265
265
|
```
|
|
266
266
|
|
|
267
|
+
### Use the supporting plugins without the preset
|
|
268
|
+
|
|
269
|
+
All three first-party rule sets have public package entry points. Register only the plugins and rules you need; this does not enable the preset or its policies.
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
import { defineConfig } from 'oxlint'
|
|
273
|
+
|
|
274
|
+
export default defineConfig({
|
|
275
|
+
jsPlugins: [
|
|
276
|
+
{ name: 'arch', specifier: 'oxlint-plugin-arch' },
|
|
277
|
+
{ name: 'dillon-anti-slop', specifier: 'oxlint-plugin-arch/rules/dillon-anti-slop' },
|
|
278
|
+
{ name: 'modules', specifier: 'oxlint-plugin-arch/rules/module-policy' },
|
|
279
|
+
],
|
|
280
|
+
rules: {
|
|
281
|
+
'arch/no-literal-in': 'error',
|
|
282
|
+
'dillon-anti-slop/no-chained-type-assertions': 'error',
|
|
283
|
+
'modules/no-unknown': 'error',
|
|
284
|
+
},
|
|
285
|
+
})
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Both `/rules/` entry points also provide a default plugin export and TypeScript declarations. Do not import `dist/` paths. The preset resolves these same public entry points, including the existing package root for `arch`; it needs no other first-party plugin entry points. Individual rule implementations and helpers are bundled into those plugins.
|
|
289
|
+
|
|
290
|
+
If you copy the preset's third-party plugin registrations into your own config, install those packages directly with `bun add -d` rather than relying on transitive dependency hoisting:
|
|
291
|
+
|
|
292
|
+
| Scope | Packages |
|
|
293
|
+
| --- | --- |
|
|
294
|
+
| Always | `oxlint-plugin-eslint`, `eslint-plugin-import`, `@regru/eslint-plugin-prefer-early-return`, `eslint-plugin-unused-imports`, `eslint-plugin-perfectionist`, `eslint-plugin-tsdoc`, `@eslint-community/eslint-plugin-eslint-comments` |
|
|
295
|
+
| Web roots | `eslint-plugin-react`, `eslint-plugin-react-you-might-not-need-an-effect`, `eslint-plugin-svg-jsx` |
|
|
296
|
+
| CSS entry points with Tailwind enabled | `oxlint-tailwindcss` |
|
|
297
|
+
| Same CSS scope with shadcn enabled | `@shadcn/lint` |
|
|
298
|
+
|
|
299
|
+
These plugins remain **dependencies** of `oxlint-plugin-arch`, not peer dependencies: the preset loads its own installed copies. In an application-owned config, list directly used plugins as **devDependencies**. A reusable config package should use dependencies for plugins it resolves itself, or peerDependencies if it intentionally requires consumers to supply them. `@oxlint/plugins` is the bundled plugins' runtime dependency, not another preset rule set. `oxlint` remains a peer dependency; `oxlint-tsgolint` is an optional peer required when using the preset's type-aware checks. Native Oxlint plugin groups need no separate npm plugin packages.
|
|
300
|
+
|
|
267
301
|
## 🚀 Quick start
|
|
268
302
|
|
|
269
303
|
Rules are switched on per folder with `overrides`. Here are three small ones:
|
package/dist/index.js
CHANGED
|
@@ -121,7 +121,7 @@ function trivialExpression(node) {
|
|
|
121
121
|
}
|
|
122
122
|
if (!node.body || node.body.type !== "BlockStatement")
|
|
123
123
|
return null;
|
|
124
|
-
const statements = node.body.body.filter((
|
|
124
|
+
const statements = node.body.body.filter((statement2) => statement2.type !== "EmptyStatement" && !(statement2.type === "ExpressionStatement" && statement2.directive));
|
|
125
125
|
if (statements.length !== 1)
|
|
126
126
|
return null;
|
|
127
127
|
const statement = statements[0];
|
|
@@ -264,7 +264,7 @@ function declarationsIsTrivialFunction(node) {
|
|
|
264
264
|
if (!node.body || node.body.type !== "BlockStatement") {
|
|
265
265
|
return false;
|
|
266
266
|
}
|
|
267
|
-
const statements = node.body.body.filter((
|
|
267
|
+
const statements = node.body.body.filter((statement2) => statement2.type !== "EmptyStatement" && !(statement2.type === "ExpressionStatement" && statement2.directive));
|
|
268
268
|
if (statements.length === 0) {
|
|
269
269
|
return true;
|
|
270
270
|
}
|
|
@@ -326,8 +326,8 @@ function declarationsInsideForLoop(node) {
|
|
|
326
326
|
}
|
|
327
327
|
function declarationsNamedFromNode(node) {
|
|
328
328
|
if (node.type === "VariableDeclarator") {
|
|
329
|
-
const
|
|
330
|
-
return
|
|
329
|
+
const kind2 = declarationsNamedKind(node, [node.parent]);
|
|
330
|
+
return kind2 && node.id.type === "Identifier" && !declarationsInsideForLoop(node) ? { name: node.id.name, node, kind: kind2 } : undefined;
|
|
331
331
|
}
|
|
332
332
|
const kind = declarationsNamedKind(node, []);
|
|
333
333
|
const name = "id" in node && node.id && "name" in node.id ? node.id.name : undefined;
|
|
@@ -1075,10 +1075,10 @@ var callArrayMultiline = defineRule({
|
|
|
1075
1075
|
`;
|
|
1076
1076
|
return {
|
|
1077
1077
|
before() {
|
|
1078
|
-
const
|
|
1079
|
-
callees = new Set(
|
|
1080
|
-
minElements =
|
|
1081
|
-
indentUnit = layoutIndentUnit(
|
|
1078
|
+
const options2 = optionsFirst(context, {});
|
|
1079
|
+
callees = new Set(options2.callees ?? ["Promise.all", "Promise.allSettled"]);
|
|
1080
|
+
minElements = options2.minElements ?? 2;
|
|
1081
|
+
indentUnit = layoutIndentUnit(options2.indent);
|
|
1082
1082
|
newline = layoutNewline(context.sourceCode.text);
|
|
1083
1083
|
if (callees.size === 0)
|
|
1084
1084
|
return false;
|
|
@@ -1187,14 +1187,14 @@ var chainNewline = defineRule2({
|
|
|
1187
1187
|
let processed = new WeakSet;
|
|
1188
1188
|
return {
|
|
1189
1189
|
before() {
|
|
1190
|
-
const
|
|
1191
|
-
groups = (
|
|
1190
|
+
const options2 = optionsFirst(context, { groups: [] });
|
|
1191
|
+
groups = (options2.groups ?? []).map((group) => ({
|
|
1192
1192
|
minDepth: group.minDepth,
|
|
1193
1193
|
methods: group.methods ? new Set(group.methods) : undefined,
|
|
1194
1194
|
onlyMethods: group.onlyMethods ? new Set(group.onlyMethods) : undefined,
|
|
1195
1195
|
rootPatterns: optionsPatterns(group.rootPattern)
|
|
1196
1196
|
}));
|
|
1197
|
-
indentUnit = layoutIndentUnit(
|
|
1197
|
+
indentUnit = layoutIndentUnit(options2.indent);
|
|
1198
1198
|
newline = layoutNewline(context.sourceCode.text);
|
|
1199
1199
|
processed = new WeakSet;
|
|
1200
1200
|
if (groups.length === 0)
|
|
@@ -1404,7 +1404,7 @@ var declarationName = defineRule4({
|
|
|
1404
1404
|
}
|
|
1405
1405
|
},
|
|
1406
1406
|
createOnce(context) {
|
|
1407
|
-
let
|
|
1407
|
+
let options2 = {};
|
|
1408
1408
|
let kinds = null;
|
|
1409
1409
|
let allowed = [];
|
|
1410
1410
|
let expected = [];
|
|
@@ -1414,7 +1414,7 @@ var declarationName = defineRule4({
|
|
|
1414
1414
|
if (!item || kinds && !kinds.has(item.kind) || optionsPatternsTest(allowed, item.name)) {
|
|
1415
1415
|
return;
|
|
1416
1416
|
}
|
|
1417
|
-
const comparableName =
|
|
1417
|
+
const comparableName = options2.normalize === "none" ? item.name : item.name.replaceAll("_", "").toLowerCase();
|
|
1418
1418
|
const matches = expected.length > 0 ? optionsPatternsTest(expected, item.name) : prefixes.some((prefix) => comparableName.startsWith(prefix));
|
|
1419
1419
|
if (matches) {
|
|
1420
1420
|
return;
|
|
@@ -1424,22 +1424,22 @@ var declarationName = defineRule4({
|
|
|
1424
1424
|
messageId: expected.length > 0 ? "pattern" : "prefix",
|
|
1425
1425
|
data: expected.length > 0 ? {
|
|
1426
1426
|
name: item.name,
|
|
1427
|
-
pattern: optionsPatternLabel([
|
|
1427
|
+
pattern: optionsPatternLabel([options2.pattern ?? []].flat().filter((source) => source !== ""))
|
|
1428
1428
|
} : { name: item.name, prefix: prefixes.join(" or ") }
|
|
1429
1429
|
});
|
|
1430
1430
|
}
|
|
1431
1431
|
return {
|
|
1432
1432
|
before() {
|
|
1433
|
-
|
|
1433
|
+
options2 = optionsFirst(context, {
|
|
1434
1434
|
stem: "before-first-dot",
|
|
1435
1435
|
normalize: "remove-separators"
|
|
1436
1436
|
});
|
|
1437
|
-
kinds =
|
|
1438
|
-
allowed = optionsOptionalPatterns(
|
|
1439
|
-
expected = optionsOptionalPatterns(
|
|
1437
|
+
kinds = options2.kinds && options2.kinds.length > 0 ? new Set(options2.kinds) : null;
|
|
1438
|
+
allowed = optionsOptionalPatterns(options2.allowPattern);
|
|
1439
|
+
expected = optionsOptionalPatterns(options2.pattern, options2.flags);
|
|
1440
1440
|
const basename = namingFileBasename(context.filename).replace(/\.(tsx?|jsx?)$/, "");
|
|
1441
|
-
const stem = namingFileStem(basename,
|
|
1442
|
-
prefixes = namingFilePrefixes(stem,
|
|
1441
|
+
const stem = namingFileStem(basename, options2.stem, options2.trailingRoles, options2.roleSeparators);
|
|
1442
|
+
prefixes = namingFilePrefixes(stem, options2.normalize ?? "remove-separators", options2.singularize ?? "none");
|
|
1443
1443
|
},
|
|
1444
1444
|
FunctionDeclaration: check,
|
|
1445
1445
|
ClassDeclaration: check,
|
|
@@ -1480,28 +1480,28 @@ var exportFilePrefix = defineRule5({
|
|
|
1480
1480
|
createOnce(context) {
|
|
1481
1481
|
return {
|
|
1482
1482
|
Program(program) {
|
|
1483
|
-
const
|
|
1483
|
+
const options2 = optionsFirst(context, {
|
|
1484
1484
|
stem: "before-first-dot",
|
|
1485
1485
|
normalize: "remove-separators"
|
|
1486
1486
|
});
|
|
1487
1487
|
const basename = namingFileBasename(context.filename).replace(/\.(tsx?|jsx?)$/, "");
|
|
1488
|
-
const stem = namingFileStem(basename,
|
|
1489
|
-
const prefixes = namingFilePrefixes(stem,
|
|
1490
|
-
const allowed = optionsOptionalPatterns(
|
|
1491
|
-
const names =
|
|
1488
|
+
const stem = namingFileStem(basename, options2.stem, options2.trailingRoles, options2.roleSeparators);
|
|
1489
|
+
const prefixes = namingFilePrefixes(stem, options2.normalize ?? "remove-separators", options2.singularize ?? "none");
|
|
1490
|
+
const allowed = optionsOptionalPatterns(options2.allowPattern);
|
|
1491
|
+
const names = options2.allDeclarations ? declarationsCollectNamed(program) : exportsCollect(program).map((binding) => ({
|
|
1492
1492
|
name: binding.localName ?? binding.exportedName,
|
|
1493
1493
|
node: binding.node
|
|
1494
1494
|
}));
|
|
1495
|
-
if (
|
|
1495
|
+
if (options2.allFunctions && !options2.allDeclarations) {
|
|
1496
1496
|
const exportedNames = new Set(names.map((item) => item.name));
|
|
1497
1497
|
names.push(...declarationsCollectNamed(program).filter((item) => !exportedNames.has(item.name) && (item.node.type === "FunctionDeclaration" || item.node.type === "VariableDeclarator" && (item.node.init?.type === "ArrowFunctionExpression" || item.node.init?.type === "FunctionExpression"))));
|
|
1498
1498
|
}
|
|
1499
|
-
if (
|
|
1499
|
+
if (options2.serviceMethods)
|
|
1500
1500
|
names.push(...declarationsPublicServiceMethods(program));
|
|
1501
1501
|
const seen = new Set;
|
|
1502
1502
|
for (const item of names) {
|
|
1503
1503
|
const key = `${item.name}:${item.node.start}:${item.node.end}`;
|
|
1504
|
-
const comparableName =
|
|
1504
|
+
const comparableName = options2.normalize === "none" ? item.name : item.name.replaceAll("_", "").toLowerCase();
|
|
1505
1505
|
if (seen.has(key) || optionsPatternsTest(allowed, item.name) || prefixes.some((prefix) => comparableName.startsWith(prefix))) {
|
|
1506
1506
|
continue;
|
|
1507
1507
|
}
|
|
@@ -1791,9 +1791,9 @@ var jsxAttributesMultiline = defineRule10({
|
|
|
1791
1791
|
`;
|
|
1792
1792
|
return {
|
|
1793
1793
|
before() {
|
|
1794
|
-
const
|
|
1795
|
-
minAttributes =
|
|
1796
|
-
indentUnit = layoutIndentUnit(
|
|
1794
|
+
const options2 = optionsFirst(context, {});
|
|
1795
|
+
minAttributes = options2.minAttributes ?? 3;
|
|
1796
|
+
indentUnit = layoutIndentUnit(options2.indent);
|
|
1797
1797
|
newline = layoutNewline(context.sourceCode.text);
|
|
1798
1798
|
},
|
|
1799
1799
|
JSXOpeningElement(node) {
|
|
@@ -1928,9 +1928,9 @@ function noCommentsFollowsOpeningBrace(text, offset) {
|
|
|
1928
1928
|
}
|
|
1929
1929
|
return false;
|
|
1930
1930
|
}
|
|
1931
|
-
function noCommentsGroups(
|
|
1931
|
+
function noCommentsGroups(comments2, text) {
|
|
1932
1932
|
const groups = [];
|
|
1933
|
-
for (const comment of
|
|
1933
|
+
for (const comment of comments2) {
|
|
1934
1934
|
const current = groups.at(-1);
|
|
1935
1935
|
const previous = current?.at(-1);
|
|
1936
1936
|
if (current && previous) {
|
|
@@ -1982,21 +1982,21 @@ var noComments = defineRule12({
|
|
|
1982
1982
|
let allowed = [];
|
|
1983
1983
|
return {
|
|
1984
1984
|
before() {
|
|
1985
|
-
const
|
|
1986
|
-
allowWhy =
|
|
1987
|
-
allowJsdoc =
|
|
1988
|
-
allowed = (
|
|
1985
|
+
const options2 = optionsFirst(context, {});
|
|
1986
|
+
allowWhy = options2.allowWhy ?? true;
|
|
1987
|
+
allowJsdoc = options2.allowJsdoc ?? false;
|
|
1988
|
+
allowed = (options2.allowPatterns ?? []).map((pattern) => new RegExp(pattern));
|
|
1989
1989
|
},
|
|
1990
1990
|
Program(program) {
|
|
1991
1991
|
const source = context.sourceCode;
|
|
1992
1992
|
const text = source.text;
|
|
1993
|
-
const
|
|
1993
|
+
const comments2 = source.getAllComments().filter((comment) => comment.type !== "Shebang");
|
|
1994
1994
|
const removable = [];
|
|
1995
1995
|
const protectedTargetLines = [];
|
|
1996
1996
|
let mightContainJsxComment = false;
|
|
1997
1997
|
let whyContinuation = false;
|
|
1998
1998
|
let previousComment;
|
|
1999
|
-
for (const comment of
|
|
1999
|
+
for (const comment of comments2) {
|
|
2000
2000
|
const value = commentsNormalizedValue(comment);
|
|
2001
2001
|
if (!mightContainJsxComment && comment.type === "Block" && noCommentsFollowsOpeningBrace(text, comment.range[0])) {
|
|
2002
2002
|
mightContainJsxComment = true;
|
|
@@ -2115,20 +2115,20 @@ var noExtraExports = defineRule13({
|
|
|
2115
2115
|
createOnce(context) {
|
|
2116
2116
|
return {
|
|
2117
2117
|
Program(program) {
|
|
2118
|
-
const
|
|
2118
|
+
const options2 = optionsFirst(context);
|
|
2119
2119
|
const basename = namingFileBasename(context.filename).replace(/\.(tsx?|jsx?)$/, "");
|
|
2120
|
-
const domain = namingFileStem(basename,
|
|
2120
|
+
const domain = namingFileStem(basename, options2.domainStem, options2.trailingRoles, options2.roleSeparators);
|
|
2121
2121
|
const replacements = {
|
|
2122
2122
|
Domain: namingPascalCase(domain),
|
|
2123
2123
|
domain: namingCamelCase(domain)
|
|
2124
2124
|
};
|
|
2125
|
-
const allowed =
|
|
2126
|
-
const patterns = (
|
|
2125
|
+
const allowed = options2.names.map((template) => template.replaceAll("{Domain}", replacements.Domain).replaceAll("{domain}", replacements.domain));
|
|
2126
|
+
const patterns = (options2.patterns ?? []).map((template) => {
|
|
2127
2127
|
const source = template.replaceAll("{Domain}", replacements.Domain.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&")).replaceAll("{domain}", replacements.domain.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
2128
2128
|
return new RegExp(`^(?:${source})$`);
|
|
2129
2129
|
});
|
|
2130
2130
|
for (const binding of exportsCollect(program)) {
|
|
2131
|
-
if (
|
|
2131
|
+
if (options2.allowTypeExports && binding.typeOnly) {
|
|
2132
2132
|
continue;
|
|
2133
2133
|
}
|
|
2134
2134
|
const name = binding.localName ?? binding.exportedName;
|
|
@@ -2206,8 +2206,8 @@ var noExtraFactoryKeys = defineRule14({
|
|
|
2206
2206
|
}
|
|
2207
2207
|
return {
|
|
2208
2208
|
before() {
|
|
2209
|
-
const
|
|
2210
|
-
const { keys, factoryPattern = "^make[A-Z]", requireKeys = [], keySets: configured } =
|
|
2209
|
+
const options2 = optionsFirst(context, {});
|
|
2210
|
+
const { keys, factoryPattern = "^make[A-Z]", requireKeys = [], keySets: configured } = options2;
|
|
2211
2211
|
if (!keys && !configured) {
|
|
2212
2212
|
return false;
|
|
2213
2213
|
}
|
|
@@ -2435,14 +2435,14 @@ var noInlineSchemaElements = defineRule17({
|
|
|
2435
2435
|
if (node.callee.type !== "MemberExpression") {
|
|
2436
2436
|
return;
|
|
2437
2437
|
}
|
|
2438
|
-
const
|
|
2439
|
-
const namespaces = new Set(
|
|
2438
|
+
const options2 = optionsFirst(context);
|
|
2439
|
+
const namespaces = new Set(options2.namespaces);
|
|
2440
2440
|
const method = astStaticMemberName(node.callee);
|
|
2441
|
-
if (!schemasIsCall(node, namespaces) || !method || !
|
|
2441
|
+
if (!schemasIsCall(node, namespaces) || !method || !options2.methods.includes(method)) {
|
|
2442
2442
|
return;
|
|
2443
2443
|
}
|
|
2444
2444
|
for (const element of schemasElements(node)) {
|
|
2445
|
-
if (!schemasIsAllowedElement(element,
|
|
2445
|
+
if (!schemasIsAllowedElement(element, options2.allowZodScalars, namespaces, new Set(options2.structuralMethods))) {
|
|
2446
2446
|
context.report({
|
|
2447
2447
|
node: element,
|
|
2448
2448
|
messageId: "inline",
|
|
@@ -2517,11 +2517,11 @@ var noInlineTypes = defineRule18({
|
|
|
2517
2517
|
}
|
|
2518
2518
|
return {
|
|
2519
2519
|
before() {
|
|
2520
|
-
const
|
|
2521
|
-
checkParameters =
|
|
2522
|
-
checkReturns =
|
|
2523
|
-
checkFunctionTypes =
|
|
2524
|
-
minMembers =
|
|
2520
|
+
const options2 = optionsFirst(context, {});
|
|
2521
|
+
checkParameters = options2.parameters ?? true;
|
|
2522
|
+
checkReturns = options2.returns ?? true;
|
|
2523
|
+
checkFunctionTypes = options2.functionTypes ?? true;
|
|
2524
|
+
minMembers = options2.minMembers ?? 1;
|
|
2525
2525
|
if (!checkParameters && !checkReturns) {
|
|
2526
2526
|
return false;
|
|
2527
2527
|
}
|
|
@@ -2741,14 +2741,14 @@ var noMemberComments = defineRule21({
|
|
|
2741
2741
|
const source = context.sourceCode;
|
|
2742
2742
|
const { allowWhy = true } = optionsFirst(context, {});
|
|
2743
2743
|
const previousToken = source.getTokenBefore(node);
|
|
2744
|
-
const
|
|
2744
|
+
const comments2 = [
|
|
2745
2745
|
...source.getCommentsBefore(node).filter((comment) => !previousToken || previousToken.range[0] === parent.range[0] || previousToken.loc.end.line !== comment.loc.start.line),
|
|
2746
2746
|
...source.getCommentsAfter(node).filter((comment) => comment.loc.start.line === node.loc.end.line)
|
|
2747
2747
|
].filter((comment) => comment.range[0] > parent.range[0] && comment.range[1] < parent.range[1]);
|
|
2748
2748
|
let whyContinuation = false;
|
|
2749
2749
|
let previousLine = -1;
|
|
2750
2750
|
const removable = [];
|
|
2751
|
-
for (const comment of
|
|
2751
|
+
for (const comment of comments2) {
|
|
2752
2752
|
const value = commentsNormalizedValue(comment);
|
|
2753
2753
|
const isWhy = commentsIsWhy(value) || comment.type === "Line" && whyContinuation && comment.loc.start.line === previousLine + 1;
|
|
2754
2754
|
whyContinuation = comment.type === "Line" && isWhy;
|
|
@@ -2990,10 +2990,10 @@ var noPromiseAllMutation = defineRule23({
|
|
|
2990
2990
|
}
|
|
2991
2991
|
return {
|
|
2992
2992
|
before() {
|
|
2993
|
-
const
|
|
2994
|
-
combinators = new Set(
|
|
2995
|
-
methods = new Set(
|
|
2996
|
-
checkAssignments =
|
|
2993
|
+
const options2 = optionsFirst(context);
|
|
2994
|
+
combinators = new Set(options2.combinators);
|
|
2995
|
+
methods = new Set(options2.methods);
|
|
2996
|
+
checkAssignments = options2.checkAssignments;
|
|
2997
2997
|
references.clear();
|
|
2998
2998
|
reported.clear();
|
|
2999
2999
|
referencesReady = false;
|
|
@@ -3145,10 +3145,10 @@ var noRestrictedConstructor = defineRule25({
|
|
|
3145
3145
|
}
|
|
3146
3146
|
return {
|
|
3147
3147
|
before() {
|
|
3148
|
-
const
|
|
3149
|
-
entries = restrictedConstructorEntries(
|
|
3150
|
-
checkCalls =
|
|
3151
|
-
fallbackMessage =
|
|
3148
|
+
const options2 = optionsFirst(context);
|
|
3149
|
+
entries = restrictedConstructorEntries(options2.constructors);
|
|
3150
|
+
checkCalls = options2.checkCalls === true;
|
|
3151
|
+
fallbackMessage = options2.message;
|
|
3152
3152
|
if (entries.size === 0) {
|
|
3153
3153
|
return false;
|
|
3154
3154
|
}
|
|
@@ -3259,16 +3259,16 @@ var noRestrictedToken = defineRule27({
|
|
|
3259
3259
|
}
|
|
3260
3260
|
return {
|
|
3261
3261
|
before() {
|
|
3262
|
-
const
|
|
3262
|
+
const options2 = optionsFirst(context);
|
|
3263
3263
|
const configured = [
|
|
3264
|
-
...
|
|
3264
|
+
...options2.token ? [
|
|
3265
3265
|
{
|
|
3266
|
-
token:
|
|
3267
|
-
allowIn:
|
|
3268
|
-
allowPathPatterns:
|
|
3266
|
+
token: options2.token,
|
|
3267
|
+
allowIn: options2.allowIn,
|
|
3268
|
+
allowPathPatterns: options2.allowPathPatterns
|
|
3269
3269
|
}
|
|
3270
3270
|
] : [],
|
|
3271
|
-
...
|
|
3271
|
+
...options2.restrictions ?? []
|
|
3272
3272
|
];
|
|
3273
3273
|
const filename = namingPosixPath(context.filename);
|
|
3274
3274
|
restrictions = configured.flatMap((restriction) => {
|
|
@@ -3556,11 +3556,11 @@ var noRuntimeInTypes = defineRule28({
|
|
|
3556
3556
|
let isAmbientFile = false;
|
|
3557
3557
|
return {
|
|
3558
3558
|
before() {
|
|
3559
|
-
const
|
|
3560
|
-
allow =
|
|
3561
|
-
runtimeImports =
|
|
3562
|
-
allowedImportSources = (
|
|
3563
|
-
banReExports =
|
|
3559
|
+
const options2 = optionsFirst(context, {});
|
|
3560
|
+
allow = options2.allow ?? [];
|
|
3561
|
+
runtimeImports = options2.runtimeImports ?? "allow";
|
|
3562
|
+
allowedImportSources = (options2.allowImportSources ?? []).map((pattern) => new RegExp(pattern));
|
|
3563
|
+
banReExports = options2.banReExports === true;
|
|
3564
3564
|
isAmbientFile = runtimeInTypesIsAmbientFile(context.filename);
|
|
3565
3565
|
},
|
|
3566
3566
|
Program(program) {
|
|
@@ -3576,12 +3576,12 @@ var noRuntimeInTypes = defineRule28({
|
|
|
3576
3576
|
runtimeImportLocals.add(specifier.local.name);
|
|
3577
3577
|
}
|
|
3578
3578
|
}
|
|
3579
|
-
const
|
|
3580
|
-
if (runtimeImports === "ban" && !isAllowedSource(
|
|
3579
|
+
const source2 = String(statement.source.value);
|
|
3580
|
+
if (runtimeImports === "ban" && !isAllowedSource(source2, allowedImportSources)) {
|
|
3581
3581
|
context.report({
|
|
3582
3582
|
node: statement,
|
|
3583
3583
|
messageId: "runtimeImport",
|
|
3584
|
-
data: { source }
|
|
3584
|
+
data: { source: source2 }
|
|
3585
3585
|
});
|
|
3586
3586
|
}
|
|
3587
3587
|
continue;
|
|
@@ -3690,8 +3690,8 @@ function isDirectObjectField(identifier, ancestors, namespaces, structuralMethod
|
|
|
3690
3690
|
const method = call.callee.type === "MemberExpression" ? astStaticMemberName(call.callee) : undefined;
|
|
3691
3691
|
return Boolean(method === "object" && structuralMethods.has(method) && call.arguments.includes(object));
|
|
3692
3692
|
}
|
|
3693
|
-
function isAllowedStructuralElement(identifier, initializer, ancestors,
|
|
3694
|
-
if (!
|
|
3693
|
+
function isAllowedStructuralElement(identifier, initializer, ancestors, options2, namespaces, structuralMethods) {
|
|
3694
|
+
if (!options2.allowZodScalars || !schemasIsAllowedElement(initializer, true, namespaces, structuralMethods)) {
|
|
3695
3695
|
return false;
|
|
3696
3696
|
}
|
|
3697
3697
|
const parent = ancestors.at(-1);
|
|
@@ -3700,7 +3700,7 @@ function isAllowedStructuralElement(identifier, initializer, ancestors, options,
|
|
|
3700
3700
|
return false;
|
|
3701
3701
|
}
|
|
3702
3702
|
const method = call.callee.type === "MemberExpression" ? astStaticMemberName(call.callee) : undefined;
|
|
3703
|
-
return Boolean(method &&
|
|
3703
|
+
return Boolean(method && options2.methods.includes(method) && schemasElements(call).includes(identifier));
|
|
3704
3704
|
}
|
|
3705
3705
|
var noSingleUseScalarSchema = defineRule29({
|
|
3706
3706
|
meta: {
|
|
@@ -3754,9 +3754,9 @@ var noSingleUseScalarSchema = defineRule29({
|
|
|
3754
3754
|
}
|
|
3755
3755
|
},
|
|
3756
3756
|
"Program:exit"(program) {
|
|
3757
|
-
const
|
|
3758
|
-
const namespaces = new Set(
|
|
3759
|
-
const structuralMethods = new Set(
|
|
3757
|
+
const options2 = optionsFirst(context);
|
|
3758
|
+
const namespaces = new Set(options2.namespaces);
|
|
3759
|
+
const structuralMethods = new Set(options2.structuralMethods);
|
|
3760
3760
|
const exportedNames = new Set(exportsCollect(program).flatMap((binding) => binding.localName ? [binding.localName] : []));
|
|
3761
3761
|
for (const declarator of candidates) {
|
|
3762
3762
|
const name = declarator.id.type === "Identifier" ? declarator.id.name : undefined;
|
|
@@ -3765,14 +3765,14 @@ var noSingleUseScalarSchema = defineRule29({
|
|
|
3765
3765
|
continue;
|
|
3766
3766
|
}
|
|
3767
3767
|
const variable = context.sourceCode.getDeclaredVariables(declarator).find((candidate) => candidate.name === name);
|
|
3768
|
-
const references = variable?.references.filter((
|
|
3768
|
+
const references = variable?.references.filter((reference2) => reference2.isRead()) ?? [];
|
|
3769
3769
|
if (references.length !== 1) {
|
|
3770
3770
|
continue;
|
|
3771
3771
|
}
|
|
3772
3772
|
const reference = references[0];
|
|
3773
3773
|
const identifier = reference.identifier;
|
|
3774
3774
|
const ancestors = context.sourceCode.getAncestors(identifier);
|
|
3775
|
-
const inlineable = isDirectObjectField(identifier, ancestors, namespaces, structuralMethods) || isAllowedStructuralElement(identifier, initializer, ancestors,
|
|
3775
|
+
const inlineable = isDirectObjectField(identifier, ancestors, namespaces, structuralMethods) || isAllowedStructuralElement(identifier, initializer, ancestors, options2, namespaces, structuralMethods);
|
|
3776
3776
|
if (inlineable) {
|
|
3777
3777
|
context.report({
|
|
3778
3778
|
node: declarator.id,
|
|
@@ -3927,12 +3927,12 @@ var noTrivialFunctions = defineRule31({
|
|
|
3927
3927
|
}
|
|
3928
3928
|
return {
|
|
3929
3929
|
before() {
|
|
3930
|
-
const
|
|
3931
|
-
const { allowPattern, allowCallees: calleePatterns = [], allowAsync: asyncAllowed = false } =
|
|
3932
|
-
mode =
|
|
3933
|
-
checkServiceMethods =
|
|
3934
|
-
bannedNames = new Set(
|
|
3935
|
-
checkGenericGuards =
|
|
3930
|
+
const options2 = optionsFirst(context, {});
|
|
3931
|
+
const { allowPattern, allowCallees: calleePatterns = [], allowAsync: asyncAllowed = false } = options2;
|
|
3932
|
+
mode = options2.mode ?? "legacy";
|
|
3933
|
+
checkServiceMethods = options2.checkServiceMethods ?? false;
|
|
3934
|
+
bannedNames = new Set(options2.bannedNames ?? (mode === "precise" ? trivialBannedNames : []));
|
|
3935
|
+
checkGenericGuards = options2.checkGenericGuards ?? mode === "precise";
|
|
3936
3936
|
reported.clear();
|
|
3937
3937
|
checked.clear();
|
|
3938
3938
|
allowed = optionsOptionalPatterns(allowPattern);
|
|
@@ -3958,8 +3958,8 @@ var noTrivialFunctions = defineRule31({
|
|
|
3958
3958
|
if (reported.has(item.node.start))
|
|
3959
3959
|
continue;
|
|
3960
3960
|
const expression = trivialExpression(item.node);
|
|
3961
|
-
const
|
|
3962
|
-
if (!
|
|
3961
|
+
const trivial2 = mode === "legacy" ? declarationsIsTrivialFunction(item.node) : expression ? trivialIsForwarder(item.node, expression) : declarationsIsTrivialFunction(item.node);
|
|
3962
|
+
if (!trivial2)
|
|
3963
3963
|
continue;
|
|
3964
3964
|
const value = expression && trivialUnwrap(expression);
|
|
3965
3965
|
const call = value?.type === "CallExpression" ? value : null;
|
|
@@ -4049,14 +4049,14 @@ var noUnescapedLike = defineRule33({
|
|
|
4049
4049
|
let sanitized = new Set;
|
|
4050
4050
|
return {
|
|
4051
4051
|
Program(program) {
|
|
4052
|
-
const { sanitizers, allowSanitizedBindings = true } = optionsFirst(context);
|
|
4053
|
-
sanitized = allowSanitizedBindings ? sanitizersConfiguredBindings(program, new Set(
|
|
4052
|
+
const { sanitizers: sanitizers2, allowSanitizedBindings = true } = optionsFirst(context);
|
|
4053
|
+
sanitized = allowSanitizedBindings ? sanitizersConfiguredBindings(program, new Set(sanitizers2)) : new Set;
|
|
4054
4054
|
},
|
|
4055
4055
|
CallExpression(node) {
|
|
4056
4056
|
if (node.callee.type !== "MemberExpression") {
|
|
4057
4057
|
return;
|
|
4058
4058
|
}
|
|
4059
|
-
const { methods, sanitizers, operatorMethods = [] } = optionsFirst(context);
|
|
4059
|
+
const { methods, sanitizers: sanitizers2, operatorMethods = [] } = optionsFirst(context);
|
|
4060
4060
|
const method = astStaticMemberName(node.callee);
|
|
4061
4061
|
const operator = node.arguments[1];
|
|
4062
4062
|
const operatorCall = method && operatorMethods.includes(method) && operator?.type === "Literal" && typeof operator.value === "string" && methods.includes(operator.value);
|
|
@@ -4065,7 +4065,7 @@ var noUnescapedLike = defineRule33({
|
|
|
4065
4065
|
}
|
|
4066
4066
|
const value = node.arguments.at(-1);
|
|
4067
4067
|
const allowedIdentifier = value?.type === "Identifier" && sanitized.has(value.name);
|
|
4068
|
-
if (!sanitizersCallsConfigured(value, new Set(
|
|
4068
|
+
if (!sanitizersCallsConfigured(value, new Set(sanitizers2)) && !allowedIdentifier) {
|
|
4069
4069
|
context.report({
|
|
4070
4070
|
node: value ?? node,
|
|
4071
4071
|
messageId: "unescaped",
|
|
@@ -4143,10 +4143,10 @@ var objectMultiline = defineRule34({
|
|
|
4143
4143
|
`;
|
|
4144
4144
|
return {
|
|
4145
4145
|
before() {
|
|
4146
|
-
const
|
|
4147
|
-
minProperties =
|
|
4148
|
-
scope =
|
|
4149
|
-
indentUnit = layoutIndentUnit(
|
|
4146
|
+
const options2 = optionsFirst(context, {});
|
|
4147
|
+
minProperties = options2.minProperties ?? 3;
|
|
4148
|
+
scope = options2.scope ?? "call-args";
|
|
4149
|
+
indentUnit = layoutIndentUnit(options2.indent);
|
|
4150
4150
|
newline = layoutNewline(context.sourceCode.text);
|
|
4151
4151
|
},
|
|
4152
4152
|
ObjectExpression(node) {
|
|
@@ -4437,7 +4437,7 @@ function paddingHasBlankLine(gap) {
|
|
|
4437
4437
|
}
|
|
4438
4438
|
return false;
|
|
4439
4439
|
}
|
|
4440
|
-
function paddingBlankLineFix(sourceText,
|
|
4440
|
+
function paddingBlankLineFix(sourceText, comments2, prev, curr, newline) {
|
|
4441
4441
|
const gap = sourceText.slice(prev.range[1], curr.range[0]);
|
|
4442
4442
|
const match = /\r?\n/.exec(gap);
|
|
4443
4443
|
if (!match) {
|
|
@@ -4445,10 +4445,10 @@ function paddingBlankLineFix(sourceText, comments, prev, curr, newline) {
|
|
|
4445
4445
|
}
|
|
4446
4446
|
const newlineStart = prev.range[1] + match.index;
|
|
4447
4447
|
const newlineEnd = newlineStart + match[0].length;
|
|
4448
|
-
if (
|
|
4448
|
+
if (comments2.some((comment) => comment.range[0] < newlineEnd && comment.range[1] > newlineStart)) {
|
|
4449
4449
|
return null;
|
|
4450
4450
|
}
|
|
4451
|
-
if (
|
|
4451
|
+
if (comments2.some((comment) => comment.loc.start.line === prev.loc.end.line && /^\s*[A-Za-z][\w-]*-disable-next-line\b/.test(commentsNormalizedValue(comment)))) {
|
|
4452
4452
|
return null;
|
|
4453
4453
|
}
|
|
4454
4454
|
return { newlineEnd, newline };
|
|
@@ -4499,8 +4499,8 @@ var paddingBetweenStatements = defineRule37({
|
|
|
4499
4499
|
if (!messageId) {
|
|
4500
4500
|
continue;
|
|
4501
4501
|
}
|
|
4502
|
-
const
|
|
4503
|
-
const insert = paddingBlankLineFix(source.text,
|
|
4502
|
+
const comments2 = source.getCommentsAfter(prev).filter((comment) => comment.range[1] <= curr.range[0]);
|
|
4503
|
+
const insert = paddingBlankLineFix(source.text, comments2, prev, curr, newline);
|
|
4504
4504
|
context.report({
|
|
4505
4505
|
node: curr,
|
|
4506
4506
|
messageId,
|
|
@@ -4510,9 +4510,9 @@ var paddingBetweenStatements = defineRule37({
|
|
|
4510
4510
|
}
|
|
4511
4511
|
return {
|
|
4512
4512
|
before() {
|
|
4513
|
-
const
|
|
4514
|
-
returnMinStatements =
|
|
4515
|
-
multilineVariables =
|
|
4513
|
+
const options2 = optionsFirst(context, {});
|
|
4514
|
+
returnMinStatements = options2.returnMinStatements ?? 3;
|
|
4515
|
+
multilineVariables = options2.multilineVariables ?? false;
|
|
4516
4516
|
source = context.sourceCode;
|
|
4517
4517
|
newline = layoutNewline(source.text);
|
|
4518
4518
|
},
|
|
@@ -4596,7 +4596,7 @@ var preferNamespaceTypeImport = defineRule38({
|
|
|
4596
4596
|
}
|
|
4597
4597
|
}
|
|
4598
4598
|
const proposed = candidates.map((node) => namespaceName(node.source.value, names));
|
|
4599
|
-
const
|
|
4599
|
+
const comments2 = sourceCode.getAllComments();
|
|
4600
4600
|
const reports = [];
|
|
4601
4601
|
const edits = [];
|
|
4602
4602
|
for (const [index, node] of candidates.entries()) {
|
|
@@ -4609,7 +4609,7 @@ var preferNamespaceTypeImport = defineRule38({
|
|
|
4609
4609
|
reason = "existing namespace import from this module";
|
|
4610
4610
|
} else if (occupied.has(name) || proposed.some((other, otherIndex) => otherIndex !== index && other === name)) {
|
|
4611
4611
|
reason = "namespace name collides with a binding, reference, or another proposed namespace";
|
|
4612
|
-
} else if (
|
|
4612
|
+
} else if (comments2.some((comment) => comment.range[0] >= node.range[0] && comment.range[1] <= node.range[1])) {
|
|
4613
4613
|
reason = "comment inside import";
|
|
4614
4614
|
} else {
|
|
4615
4615
|
const variables = sourceCode.getDeclaredVariables(node);
|
|
@@ -4861,10 +4861,10 @@ var requirePairedCall = defineRule42({
|
|
|
4861
4861
|
let pairs = [];
|
|
4862
4862
|
return {
|
|
4863
4863
|
before() {
|
|
4864
|
-
const
|
|
4864
|
+
const options2 = optionsFirst(context);
|
|
4865
4865
|
const configured = [
|
|
4866
|
-
...
|
|
4867
|
-
...
|
|
4866
|
+
...options2.when && options2.require ? [{ when: options2.when, require: options2.require }] : [],
|
|
4867
|
+
...options2.pairs ?? []
|
|
4868
4868
|
];
|
|
4869
4869
|
aliases = new Map;
|
|
4870
4870
|
pairs = configured.map((pair) => ({ ...pair, firstWhen: null, sawRequired: false }));
|
|
@@ -5020,12 +5020,12 @@ var testTitlePattern = defineRule44({
|
|
|
5020
5020
|
let requiredLabel = "";
|
|
5021
5021
|
return {
|
|
5022
5022
|
before() {
|
|
5023
|
-
const
|
|
5024
|
-
callees =
|
|
5025
|
-
const flags =
|
|
5026
|
-
forbid = titlePatterns(
|
|
5027
|
-
required = titlePatterns(
|
|
5028
|
-
requiredLabel = optionsPatternLabel(
|
|
5023
|
+
const options2 = optionsFirst(context);
|
|
5024
|
+
callees = options2.callees;
|
|
5025
|
+
const flags = options2.flags ?? "";
|
|
5026
|
+
forbid = titlePatterns(options2.forbid, flags);
|
|
5027
|
+
required = titlePatterns(options2.require, flags);
|
|
5028
|
+
requiredLabel = optionsPatternLabel(options2.require);
|
|
5029
5029
|
if (forbid.length === 0 && required.length === 0) {
|
|
5030
5030
|
return false;
|
|
5031
5031
|
}
|