@timmo001/oxlint-rules 0.6.2 → 0.6.3
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/README.md +3 -2
- package/dist/cli.js +22 -3
- package/dist/configs/recommended-effect.js +22 -3
- package/dist/configs/recommended.js +22 -3
- package/dist/upstream/anti-slop.js +22 -3
- package/package.json +5 -5
- package/vendor/anti-slop/src/rules/require-readable-spacing.ts +63 -30
- package/vendor/anti-slop/src/vendor/eslint-stylistic/UPSTREAM.md +1 -1
- package/vendor/anti-slop/src/vendor/eslint-stylistic/padding-line-between-statements.ts +32 -9
package/README.md
CHANGED
|
@@ -139,8 +139,9 @@ they only run when the consumer enables `typeAware`.
|
|
|
139
139
|
a `yield* Gh` binding from `@timmo001/effect-gh`, `Api.raw` from that package,
|
|
140
140
|
and calls that launch gh: `"gh"` followed by its arguments, such as
|
|
141
141
|
`executor.run("gh", ...)`, or an argument array starting with `"gh"` passed
|
|
142
|
-
to a spawn, exec, run or command function, such as `Bun.spawn(["gh", ...])`.
|
|
143
|
-
package's typed operations, and add one to effect-gh when a command
|
|
142
|
+
to a spawn, exec, run or command function, such as `Bun.spawn(["gh", ...])`.
|
|
143
|
+
Use the package's typed operations, and add one to effect-gh when a command
|
|
144
|
+
has none.
|
|
144
145
|
effect-gh's own relative imports are not reported.
|
|
145
146
|
- `no-try-catch-in-effect-generators`: diagnoses synchronous `try/catch` owned
|
|
146
147
|
by generators passed directly to `Effect.gen` or the curried `Effect.fn`
|
package/dist/cli.js
CHANGED
|
@@ -2172,7 +2172,8 @@ var StatementTypes = {
|
|
|
2172
2172
|
]
|
|
2173
2173
|
]))
|
|
2174
2174
|
};
|
|
2175
|
-
function createPaddingLineRule(options) {
|
|
2175
|
+
function createPaddingLineRule(options, statementTypes) {
|
|
2176
|
+
const customStatementTypes = statementTypes ?? {};
|
|
2176
2177
|
return {
|
|
2177
2178
|
meta: {
|
|
2178
2179
|
type: "layout",
|
|
@@ -2288,7 +2289,7 @@ function createPaddingLineRule(options) {
|
|
|
2288
2289
|
return !isSingleLine(innerStatementNode);
|
|
2289
2290
|
return true;
|
|
2290
2291
|
} else {
|
|
2291
|
-
const statementType = StatementTypes[type];
|
|
2292
|
+
const statementType = customStatementTypes[type] ?? StatementTypes[type];
|
|
2292
2293
|
if (statementType === undefined)
|
|
2293
2294
|
throw new Error(`Padding rule invariant: unsupported statement type ${type}`);
|
|
2294
2295
|
return statementType.test(innerStatementNode, sourceCode);
|
|
@@ -2387,6 +2388,20 @@ function createPaddingLineRule(options) {
|
|
|
2387
2388
|
}
|
|
2388
2389
|
|
|
2389
2390
|
// vendor/anti-slop/src/rules/require-readable-spacing.ts
|
|
2391
|
+
function isSinglelineBinding(node) {
|
|
2392
|
+
const declaration = node.type === "ExportNamedDeclaration" ? node.declaration : node;
|
|
2393
|
+
return declaration?.type === "VariableDeclaration" && node.loc.start.line === node.loc.end.line;
|
|
2394
|
+
}
|
|
2395
|
+
function hasLeadingComment(node, sourceCode) {
|
|
2396
|
+
const previousLine = sourceCode.getTokenBefore(node)?.loc.end.line;
|
|
2397
|
+
return sourceCode.getCommentsBefore(node).some((comment) => comment.loc.start.line !== previousLine);
|
|
2398
|
+
}
|
|
2399
|
+
var singlelineBinding = {
|
|
2400
|
+
test: (node) => isSinglelineBinding(node)
|
|
2401
|
+
};
|
|
2402
|
+
var undocumentedSinglelineBinding = {
|
|
2403
|
+
test: (node, sourceCode) => isSinglelineBinding(node) && !hasLeadingComment(node, sourceCode)
|
|
2404
|
+
};
|
|
2390
2405
|
var paddingRule = createPaddingLineRule([
|
|
2391
2406
|
{ blankLine: "always", prev: "import", next: "*" },
|
|
2392
2407
|
{ blankLine: "always", prev: "*", next: { selector: "Program > :not(ImportDeclaration)" } },
|
|
@@ -2406,6 +2421,7 @@ var paddingRule = createPaddingLineRule([
|
|
|
2406
2421
|
{ blankLine: "always", prev: "*", next: ["return", "if", "switch", "try", "for", "while", "do"] },
|
|
2407
2422
|
{ blankLine: "always", prev: "block-like", next: "*" },
|
|
2408
2423
|
{ blankLine: "any", prev: "import", next: "import" },
|
|
2424
|
+
{ blankLine: "any", prev: "singleline-binding", next: "undocumented-singleline-binding" },
|
|
2409
2425
|
{
|
|
2410
2426
|
blankLine: "any",
|
|
2411
2427
|
prev: {
|
|
@@ -2415,7 +2431,10 @@ var paddingRule = createPaddingLineRule([
|
|
|
2415
2431
|
selector: ':matches(TSDeclareFunction, FunctionDeclaration, ExportNamedDeclaration[declaration.type="TSDeclareFunction"], ExportNamedDeclaration[declaration.type="FunctionDeclaration"])'
|
|
2416
2432
|
}
|
|
2417
2433
|
}
|
|
2418
|
-
]
|
|
2434
|
+
], {
|
|
2435
|
+
"singleline-binding": singlelineBinding,
|
|
2436
|
+
"undocumented-singleline-binding": undocumentedSinglelineBinding
|
|
2437
|
+
});
|
|
2419
2438
|
var requireReadableSpacingRule = {
|
|
2420
2439
|
...paddingRule,
|
|
2421
2440
|
meta: {
|
|
@@ -2669,7 +2669,8 @@ var StatementTypes = {
|
|
|
2669
2669
|
]
|
|
2670
2670
|
]))
|
|
2671
2671
|
};
|
|
2672
|
-
function createPaddingLineRule(options) {
|
|
2672
|
+
function createPaddingLineRule(options, statementTypes) {
|
|
2673
|
+
const customStatementTypes = statementTypes ?? {};
|
|
2673
2674
|
return {
|
|
2674
2675
|
meta: {
|
|
2675
2676
|
type: "layout",
|
|
@@ -2785,7 +2786,7 @@ function createPaddingLineRule(options) {
|
|
|
2785
2786
|
return !isSingleLine(innerStatementNode);
|
|
2786
2787
|
return true;
|
|
2787
2788
|
} else {
|
|
2788
|
-
const statementType = StatementTypes[type];
|
|
2789
|
+
const statementType = customStatementTypes[type] ?? StatementTypes[type];
|
|
2789
2790
|
if (statementType === undefined)
|
|
2790
2791
|
throw new Error(`Padding rule invariant: unsupported statement type ${type}`);
|
|
2791
2792
|
return statementType.test(innerStatementNode, sourceCode);
|
|
@@ -2884,6 +2885,20 @@ function createPaddingLineRule(options) {
|
|
|
2884
2885
|
}
|
|
2885
2886
|
|
|
2886
2887
|
// vendor/anti-slop/src/rules/require-readable-spacing.ts
|
|
2888
|
+
function isSinglelineBinding(node) {
|
|
2889
|
+
const declaration = node.type === "ExportNamedDeclaration" ? node.declaration : node;
|
|
2890
|
+
return declaration?.type === "VariableDeclaration" && node.loc.start.line === node.loc.end.line;
|
|
2891
|
+
}
|
|
2892
|
+
function hasLeadingComment(node, sourceCode) {
|
|
2893
|
+
const previousLine = sourceCode.getTokenBefore(node)?.loc.end.line;
|
|
2894
|
+
return sourceCode.getCommentsBefore(node).some((comment) => comment.loc.start.line !== previousLine);
|
|
2895
|
+
}
|
|
2896
|
+
var singlelineBinding = {
|
|
2897
|
+
test: (node) => isSinglelineBinding(node)
|
|
2898
|
+
};
|
|
2899
|
+
var undocumentedSinglelineBinding = {
|
|
2900
|
+
test: (node, sourceCode) => isSinglelineBinding(node) && !hasLeadingComment(node, sourceCode)
|
|
2901
|
+
};
|
|
2887
2902
|
var paddingRule = createPaddingLineRule([
|
|
2888
2903
|
{ blankLine: "always", prev: "import", next: "*" },
|
|
2889
2904
|
{ blankLine: "always", prev: "*", next: { selector: "Program > :not(ImportDeclaration)" } },
|
|
@@ -2903,6 +2918,7 @@ var paddingRule = createPaddingLineRule([
|
|
|
2903
2918
|
{ blankLine: "always", prev: "*", next: ["return", "if", "switch", "try", "for", "while", "do"] },
|
|
2904
2919
|
{ blankLine: "always", prev: "block-like", next: "*" },
|
|
2905
2920
|
{ blankLine: "any", prev: "import", next: "import" },
|
|
2921
|
+
{ blankLine: "any", prev: "singleline-binding", next: "undocumented-singleline-binding" },
|
|
2906
2922
|
{
|
|
2907
2923
|
blankLine: "any",
|
|
2908
2924
|
prev: {
|
|
@@ -2912,7 +2928,10 @@ var paddingRule = createPaddingLineRule([
|
|
|
2912
2928
|
selector: ':matches(TSDeclareFunction, FunctionDeclaration, ExportNamedDeclaration[declaration.type="TSDeclareFunction"], ExportNamedDeclaration[declaration.type="FunctionDeclaration"])'
|
|
2913
2929
|
}
|
|
2914
2930
|
}
|
|
2915
|
-
]
|
|
2931
|
+
], {
|
|
2932
|
+
"singleline-binding": singlelineBinding,
|
|
2933
|
+
"undocumented-singleline-binding": undocumentedSinglelineBinding
|
|
2934
|
+
});
|
|
2916
2935
|
var requireReadableSpacingRule = {
|
|
2917
2936
|
...paddingRule,
|
|
2918
2937
|
meta: {
|
|
@@ -2167,7 +2167,8 @@ var StatementTypes = {
|
|
|
2167
2167
|
]
|
|
2168
2168
|
]))
|
|
2169
2169
|
};
|
|
2170
|
-
function createPaddingLineRule(options) {
|
|
2170
|
+
function createPaddingLineRule(options, statementTypes) {
|
|
2171
|
+
const customStatementTypes = statementTypes ?? {};
|
|
2171
2172
|
return {
|
|
2172
2173
|
meta: {
|
|
2173
2174
|
type: "layout",
|
|
@@ -2283,7 +2284,7 @@ function createPaddingLineRule(options) {
|
|
|
2283
2284
|
return !isSingleLine(innerStatementNode);
|
|
2284
2285
|
return true;
|
|
2285
2286
|
} else {
|
|
2286
|
-
const statementType = StatementTypes[type];
|
|
2287
|
+
const statementType = customStatementTypes[type] ?? StatementTypes[type];
|
|
2287
2288
|
if (statementType === undefined)
|
|
2288
2289
|
throw new Error(`Padding rule invariant: unsupported statement type ${type}`);
|
|
2289
2290
|
return statementType.test(innerStatementNode, sourceCode);
|
|
@@ -2382,6 +2383,20 @@ function createPaddingLineRule(options) {
|
|
|
2382
2383
|
}
|
|
2383
2384
|
|
|
2384
2385
|
// vendor/anti-slop/src/rules/require-readable-spacing.ts
|
|
2386
|
+
function isSinglelineBinding(node) {
|
|
2387
|
+
const declaration = node.type === "ExportNamedDeclaration" ? node.declaration : node;
|
|
2388
|
+
return declaration?.type === "VariableDeclaration" && node.loc.start.line === node.loc.end.line;
|
|
2389
|
+
}
|
|
2390
|
+
function hasLeadingComment(node, sourceCode) {
|
|
2391
|
+
const previousLine = sourceCode.getTokenBefore(node)?.loc.end.line;
|
|
2392
|
+
return sourceCode.getCommentsBefore(node).some((comment) => comment.loc.start.line !== previousLine);
|
|
2393
|
+
}
|
|
2394
|
+
var singlelineBinding = {
|
|
2395
|
+
test: (node) => isSinglelineBinding(node)
|
|
2396
|
+
};
|
|
2397
|
+
var undocumentedSinglelineBinding = {
|
|
2398
|
+
test: (node, sourceCode) => isSinglelineBinding(node) && !hasLeadingComment(node, sourceCode)
|
|
2399
|
+
};
|
|
2385
2400
|
var paddingRule = createPaddingLineRule([
|
|
2386
2401
|
{ blankLine: "always", prev: "import", next: "*" },
|
|
2387
2402
|
{ blankLine: "always", prev: "*", next: { selector: "Program > :not(ImportDeclaration)" } },
|
|
@@ -2401,6 +2416,7 @@ var paddingRule = createPaddingLineRule([
|
|
|
2401
2416
|
{ blankLine: "always", prev: "*", next: ["return", "if", "switch", "try", "for", "while", "do"] },
|
|
2402
2417
|
{ blankLine: "always", prev: "block-like", next: "*" },
|
|
2403
2418
|
{ blankLine: "any", prev: "import", next: "import" },
|
|
2419
|
+
{ blankLine: "any", prev: "singleline-binding", next: "undocumented-singleline-binding" },
|
|
2404
2420
|
{
|
|
2405
2421
|
blankLine: "any",
|
|
2406
2422
|
prev: {
|
|
@@ -2410,7 +2426,10 @@ var paddingRule = createPaddingLineRule([
|
|
|
2410
2426
|
selector: ':matches(TSDeclareFunction, FunctionDeclaration, ExportNamedDeclaration[declaration.type="TSDeclareFunction"], ExportNamedDeclaration[declaration.type="FunctionDeclaration"])'
|
|
2411
2427
|
}
|
|
2412
2428
|
}
|
|
2413
|
-
]
|
|
2429
|
+
], {
|
|
2430
|
+
"singleline-binding": singlelineBinding,
|
|
2431
|
+
"undocumented-singleline-binding": undocumentedSinglelineBinding
|
|
2432
|
+
});
|
|
2414
2433
|
var requireReadableSpacingRule = {
|
|
2415
2434
|
...paddingRule,
|
|
2416
2435
|
meta: {
|
|
@@ -2162,7 +2162,8 @@ var StatementTypes = {
|
|
|
2162
2162
|
]
|
|
2163
2163
|
]))
|
|
2164
2164
|
};
|
|
2165
|
-
function createPaddingLineRule(options) {
|
|
2165
|
+
function createPaddingLineRule(options, statementTypes) {
|
|
2166
|
+
const customStatementTypes = statementTypes ?? {};
|
|
2166
2167
|
return {
|
|
2167
2168
|
meta: {
|
|
2168
2169
|
type: "layout",
|
|
@@ -2278,7 +2279,7 @@ function createPaddingLineRule(options) {
|
|
|
2278
2279
|
return !isSingleLine(innerStatementNode);
|
|
2279
2280
|
return true;
|
|
2280
2281
|
} else {
|
|
2281
|
-
const statementType = StatementTypes[type];
|
|
2282
|
+
const statementType = customStatementTypes[type] ?? StatementTypes[type];
|
|
2282
2283
|
if (statementType === undefined)
|
|
2283
2284
|
throw new Error(`Padding rule invariant: unsupported statement type ${type}`);
|
|
2284
2285
|
return statementType.test(innerStatementNode, sourceCode);
|
|
@@ -2377,6 +2378,20 @@ function createPaddingLineRule(options) {
|
|
|
2377
2378
|
}
|
|
2378
2379
|
|
|
2379
2380
|
// vendor/anti-slop/src/rules/require-readable-spacing.ts
|
|
2381
|
+
function isSinglelineBinding(node) {
|
|
2382
|
+
const declaration = node.type === "ExportNamedDeclaration" ? node.declaration : node;
|
|
2383
|
+
return declaration?.type === "VariableDeclaration" && node.loc.start.line === node.loc.end.line;
|
|
2384
|
+
}
|
|
2385
|
+
function hasLeadingComment(node, sourceCode) {
|
|
2386
|
+
const previousLine = sourceCode.getTokenBefore(node)?.loc.end.line;
|
|
2387
|
+
return sourceCode.getCommentsBefore(node).some((comment) => comment.loc.start.line !== previousLine);
|
|
2388
|
+
}
|
|
2389
|
+
var singlelineBinding = {
|
|
2390
|
+
test: (node) => isSinglelineBinding(node)
|
|
2391
|
+
};
|
|
2392
|
+
var undocumentedSinglelineBinding = {
|
|
2393
|
+
test: (node, sourceCode) => isSinglelineBinding(node) && !hasLeadingComment(node, sourceCode)
|
|
2394
|
+
};
|
|
2380
2395
|
var paddingRule = createPaddingLineRule([
|
|
2381
2396
|
{ blankLine: "always", prev: "import", next: "*" },
|
|
2382
2397
|
{ blankLine: "always", prev: "*", next: { selector: "Program > :not(ImportDeclaration)" } },
|
|
@@ -2396,6 +2411,7 @@ var paddingRule = createPaddingLineRule([
|
|
|
2396
2411
|
{ blankLine: "always", prev: "*", next: ["return", "if", "switch", "try", "for", "while", "do"] },
|
|
2397
2412
|
{ blankLine: "always", prev: "block-like", next: "*" },
|
|
2398
2413
|
{ blankLine: "any", prev: "import", next: "import" },
|
|
2414
|
+
{ blankLine: "any", prev: "singleline-binding", next: "undocumented-singleline-binding" },
|
|
2399
2415
|
{
|
|
2400
2416
|
blankLine: "any",
|
|
2401
2417
|
prev: {
|
|
@@ -2405,7 +2421,10 @@ var paddingRule = createPaddingLineRule([
|
|
|
2405
2421
|
selector: ':matches(TSDeclareFunction, FunctionDeclaration, ExportNamedDeclaration[declaration.type="TSDeclareFunction"], ExportNamedDeclaration[declaration.type="FunctionDeclaration"])'
|
|
2406
2422
|
}
|
|
2407
2423
|
}
|
|
2408
|
-
]
|
|
2424
|
+
], {
|
|
2425
|
+
"singleline-binding": singlelineBinding,
|
|
2426
|
+
"undocumented-singleline-binding": undocumentedSinglelineBinding
|
|
2427
|
+
});
|
|
2409
2428
|
var requireReadableSpacingRule = {
|
|
2410
2429
|
...paddingRule,
|
|
2411
2430
|
meta: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timmo001/oxlint-rules",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "Shared Oxlint plugins and configs with optional Effect rules.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
"typecheck": "tsc --noEmit"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@oxlint/plugins": "1.
|
|
53
|
-
"oxlint": "1.
|
|
52
|
+
"@oxlint/plugins": "1.88.0",
|
|
53
|
+
"oxlint": "1.88.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@oxlint/plugins": "1.
|
|
56
|
+
"@oxlint/plugins": "1.88.0",
|
|
57
57
|
"@types/bun": "^1.3.14",
|
|
58
|
-
"oxlint": "1.
|
|
58
|
+
"oxlint": "1.88.0",
|
|
59
59
|
"oxlint-tsgolint": "7.0.2004",
|
|
60
60
|
"prettier": "^3.9.5",
|
|
61
61
|
"skills-ref": "0.1.5",
|
|
@@ -1,40 +1,73 @@
|
|
|
1
|
-
import type { CreateRule } from "@oxlint/plugins";
|
|
1
|
+
import type { CreateRule, ESTree, SourceCode } from "@oxlint/plugins";
|
|
2
2
|
|
|
3
3
|
import createPaddingLineRule from "../vendor/eslint-stylistic/padding-line-between-statements.ts";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
5
|
+
import type { NodeTestObject } from "../vendor/eslint-stylistic/padding-line-between-statements.ts";
|
|
6
|
+
|
|
7
|
+
/** A `const`/`let`/`var`/`using` declaration, optionally exported, written on one line. */
|
|
8
|
+
function isSinglelineBinding(node: ESTree.Node): boolean {
|
|
9
|
+
const declaration = node.type === "ExportNamedDeclaration" ? node.declaration : node;
|
|
10
|
+
return declaration?.type === "VariableDeclaration" && node.loc.start.line === node.loc.end.line;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Comments above a statement belong to it; a comment trailing the previous line does not. */
|
|
14
|
+
function hasLeadingComment(node: ESTree.Node, sourceCode: SourceCode): boolean {
|
|
15
|
+
const previousLine = sourceCode.getTokenBefore(node)?.loc.end.line;
|
|
16
|
+
return sourceCode
|
|
17
|
+
.getCommentsBefore(node)
|
|
18
|
+
.some((comment) => comment.loc.start.line !== previousLine);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const singlelineBinding: NodeTestObject = {
|
|
22
|
+
test: (node) => isSinglelineBinding(node),
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const undocumentedSinglelineBinding: NodeTestObject = {
|
|
26
|
+
test: (node, sourceCode) => isSinglelineBinding(node) && !hasLeadingComment(node, sourceCode),
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const paddingRule = createPaddingLineRule(
|
|
30
|
+
[
|
|
31
|
+
{ blankLine: "always", prev: "import", next: "*" },
|
|
32
|
+
{ blankLine: "always", prev: "*", next: { selector: "Program > :not(ImportDeclaration)" } },
|
|
33
|
+
{ blankLine: "always", prev: { selector: "Program > :not(ImportDeclaration)" }, next: "*" },
|
|
34
|
+
{ blankLine: "always", prev: "*", next: ["function", "class", "interface", "type"] },
|
|
35
|
+
{ blankLine: "always", prev: ["function", "class", "interface", "type"], next: "*" },
|
|
36
|
+
{
|
|
37
|
+
blankLine: "always",
|
|
38
|
+
prev: "*",
|
|
39
|
+
next: ["multiline-const", "multiline-let", "multiline-var", "multiline-using"],
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
blankLine: "always",
|
|
43
|
+
prev: ["multiline-const", "multiline-let", "multiline-var", "multiline-using"],
|
|
44
|
+
next: "*",
|
|
29
45
|
},
|
|
30
|
-
next:
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
{ blankLine: "always", prev: "*", next: ["return", "if", "switch", "try", "for", "while", "do"] },
|
|
47
|
+
{ blankLine: "always", prev: "block-like", next: "*" },
|
|
48
|
+
{ blankLine: "any", prev: "import", next: "import" },
|
|
49
|
+
// Consecutive single-line bindings form one group at any scope, including
|
|
50
|
+
// module scope. A binding with its own leading comment starts a new group.
|
|
51
|
+
{ blankLine: "any", prev: "singleline-binding", next: "undocumented-singleline-binding" },
|
|
52
|
+
{
|
|
53
|
+
blankLine: "any",
|
|
54
|
+
prev: {
|
|
55
|
+
selector:
|
|
56
|
+
':matches(TSDeclareFunction, ExportNamedDeclaration[declaration.type="TSDeclareFunction"])',
|
|
57
|
+
},
|
|
58
|
+
next: {
|
|
59
|
+
selector:
|
|
60
|
+
':matches(TSDeclareFunction, FunctionDeclaration, ExportNamedDeclaration[declaration.type="TSDeclareFunction"], ExportNamedDeclaration[declaration.type="FunctionDeclaration"])',
|
|
61
|
+
},
|
|
33
62
|
},
|
|
63
|
+
],
|
|
64
|
+
{
|
|
65
|
+
"singleline-binding": singlelineBinding,
|
|
66
|
+
"undocumented-singleline-binding": undocumentedSinglelineBinding,
|
|
34
67
|
},
|
|
35
|
-
|
|
68
|
+
);
|
|
36
69
|
|
|
37
|
-
/** Restore structural blank lines with whitespace-only fixes; keep
|
|
70
|
+
/** Restore structural blank lines with whitespace-only fixes; keep single-line binding groups and overloads grouped. */
|
|
38
71
|
export const requireReadableSpacingRule: CreateRule = {
|
|
39
72
|
...paddingRule,
|
|
40
73
|
meta: {
|
|
@@ -15,7 +15,7 @@ The rule is MIT-licensed. Keep `LICENSE` with every redistributed copy, includin
|
|
|
15
15
|
- Replace upstream type aliases with Oxlint's ESTree, context, token/comment, and rule types. Upstream's token type includes comments; Oxlint exposes those separately.
|
|
16
16
|
- Replace `AST_NODE_TYPES` enum members with identical string literals.
|
|
17
17
|
- Guard indexed reads for consuming repositories with `noUncheckedIndexedAccess`. Impossible missing AST/configuration entries raise explicit invariant errors rather than introducing new non-null assertions.
|
|
18
|
-
- Replace the repository-specific `createRule` factory with `createPaddingLineRule(options)`. The anti-slop wrapper supplies typed options directly; it exposes no user configuration options.
|
|
18
|
+
- Replace the repository-specific `createRule` factory with `createPaddingLineRule(options, statementTypes?)`. The anti-slop wrapper supplies typed options directly; it exposes no user configuration options. The optional second argument registers caller-defined statement types, consulted before the upstream table, so a policy can match syntax the upstream matchers do not distinguish (exported bindings, comment ownership) without editing the vendored tables.
|
|
19
19
|
- Implement the small required AST helper surface in `padding-line-ast.ts` using Oxlint's public source-code/token API. `isParenthesized` only needs the one-pair check used to exclude parenthesized directive strings, not the upstream general-purpose overloads.
|
|
20
20
|
- Retain the upstream statement matchers, scope tracking, comment-aware insertion/removal, selector support, and diagnostic text. Upstream naming and non-null assumptions remain localized here to keep future diffs reviewable; the file is not a model for new application code.
|
|
21
21
|
|
|
@@ -3,9 +3,9 @@ import type { ESTree, Context as RuleContext, SourceCode, Token as SyntaxToken,
|
|
|
3
3
|
type ASTNode = ESTree.Node
|
|
4
4
|
type Token = SyntaxToken | Comment
|
|
5
5
|
import type {
|
|
6
|
-
|
|
6
|
+
PaddingType,
|
|
7
7
|
SelectorOption,
|
|
8
|
-
|
|
8
|
+
StatementMatcher,
|
|
9
9
|
} from './padding-line-options.d.ts'
|
|
10
10
|
import {
|
|
11
11
|
isClosingBraceToken,
|
|
@@ -42,17 +42,32 @@ type NodeTest = (
|
|
|
42
42
|
sourceCode: SourceCode,
|
|
43
43
|
) => boolean
|
|
44
44
|
|
|
45
|
-
interface NodeTestObject {
|
|
45
|
+
export interface NodeTestObject {
|
|
46
46
|
test: NodeTest
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* A policy entry may name a caller-defined statement type (registered through
|
|
51
|
+
* `createPaddingLineRule`) anywhere the upstream statement types are accepted.
|
|
52
|
+
*/
|
|
53
|
+
export type PolicyStatementOption<Extra extends string = never> =
|
|
54
|
+
| StatementMatcher
|
|
55
|
+
| Extra
|
|
56
|
+
| [StatementMatcher | Extra, ...(StatementMatcher | Extra)[]]
|
|
57
|
+
|
|
58
|
+
export type PolicyOptions<Extra extends string = never> = {
|
|
59
|
+
blankLine: PaddingType
|
|
60
|
+
prev: PolicyStatementOption<Extra>
|
|
61
|
+
next: PolicyStatementOption<Extra>
|
|
62
|
+
}[]
|
|
63
|
+
|
|
49
64
|
const LT = `[${Array.from(LINEBREAKS).join('')}]`
|
|
50
65
|
const PADDING_LINE_SEQUENCE = new RegExp(
|
|
51
66
|
String.raw`^(\s*?${LT})\s*${LT}(\s*;?)$`,
|
|
52
67
|
'u',
|
|
53
68
|
)
|
|
54
69
|
|
|
55
|
-
function isSelectorOption(option:
|
|
70
|
+
function isSelectorOption(option: PolicyStatementOption<string>): option is SelectorOption {
|
|
56
71
|
return typeof option === 'object' && !Array.isArray(option)
|
|
57
72
|
}
|
|
58
73
|
|
|
@@ -589,8 +604,16 @@ const StatementTypes: Record<string, NodeTestObject> = {
|
|
|
589
604
|
),
|
|
590
605
|
}
|
|
591
606
|
|
|
592
|
-
/**
|
|
593
|
-
|
|
607
|
+
/**
|
|
608
|
+
* Build the vendored padding rule with caller-owned, typed policy options.
|
|
609
|
+
* `statementTypes` registers caller-defined statement types, looked up before
|
|
610
|
+
* the upstream table, for syntax the upstream matchers do not distinguish.
|
|
611
|
+
*/
|
|
612
|
+
export default function createPaddingLineRule<Extra extends string = never>(
|
|
613
|
+
options: PolicyOptions<NoInfer<Extra>>,
|
|
614
|
+
statementTypes?: Record<Extra, NodeTestObject>,
|
|
615
|
+
): CreateRule {
|
|
616
|
+
const customStatementTypes: Partial<Record<string, NodeTestObject>> = statementTypes ?? {}
|
|
594
617
|
return {
|
|
595
618
|
meta: {
|
|
596
619
|
type: 'layout',
|
|
@@ -667,7 +690,7 @@ return {
|
|
|
667
690
|
const selectorMatchedNodes = new Map<string, Set<ASTNode>>()
|
|
668
691
|
const pendingPairs: { prevNode: ASTNode, nextNode: ASTNode }[] = []
|
|
669
692
|
|
|
670
|
-
function collectSelectorOption(option:
|
|
693
|
+
function collectSelectorOption(option: PolicyStatementOption<Extra>): void {
|
|
671
694
|
if (Array.isArray(option)) {
|
|
672
695
|
for (const item of option)
|
|
673
696
|
collectSelectorOption(item)
|
|
@@ -722,7 +745,7 @@ return {
|
|
|
722
745
|
* @returns `true` if the statement node matched the type.
|
|
723
746
|
* @private
|
|
724
747
|
*/
|
|
725
|
-
function match(node: ASTNode, type:
|
|
748
|
+
function match(node: ASTNode, type: PolicyStatementOption<Extra>): boolean {
|
|
726
749
|
let innerStatementNode = node
|
|
727
750
|
|
|
728
751
|
while (innerStatementNode.type === 'LabeledStatement')
|
|
@@ -746,7 +769,7 @@ return {
|
|
|
746
769
|
return true
|
|
747
770
|
}
|
|
748
771
|
else {
|
|
749
|
-
const statementType = StatementTypes[type]
|
|
772
|
+
const statementType = customStatementTypes[type] ?? StatementTypes[type]
|
|
750
773
|
if (statementType === undefined)
|
|
751
774
|
throw new Error(`Padding rule invariant: unsupported statement type ${type}`)
|
|
752
775
|
return statementType.test(innerStatementNode, sourceCode)
|