@sister.software/oxlint-config 9.3.0 → 10.0.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/README.md +102 -10
- package/out/constant-doc-plugin.d.ts +26 -0
- package/out/constant-doc-plugin.d.ts.map +1 -0
- package/out/constant-doc-plugin.js +87 -0
- package/out/constant-doc-plugin.js.map +1 -0
- package/out/headers-plugin.js +1 -1
- package/out/headers-plugin.js.map +1 -1
- package/out/index.d.ts +70 -1
- package/out/index.d.ts.map +1 -1
- package/out/index.js +280 -6
- package/out/index.js.map +1 -1
- package/out/length-truthiness-plugin.d.ts +18 -0
- package/out/length-truthiness-plugin.d.ts.map +1 -0
- package/out/length-truthiness-plugin.js +113 -0
- package/out/length-truthiness-plugin.js.map +1 -0
- package/out/plugin-types.d.ts +23 -0
- package/out/plugin-types.d.ts.map +1 -1
- package/out/plugin.d.ts.map +1 -1
- package/out/plugin.js +6 -0
- package/out/plugin.js.map +1 -1
- package/out/threshold-plugin.d.ts +21 -0
- package/out/threshold-plugin.d.ts.map +1 -0
- package/out/threshold-plugin.js +72 -0
- package/out/threshold-plugin.js.map +1 -0
- package/package.json +2 -2
- package/src/constant-doc-plugin.ts +114 -0
- package/src/headers-plugin.ts +1 -1
- package/src/index.ts +341 -5
- package/src/length-truthiness-plugin.ts +132 -0
- package/src/plugin-types.ts +23 -0
- package/src/plugin.ts +6 -0
- package/src/threshold-plugin.ts +93 -0
package/out/index.js
CHANGED
|
@@ -6,7 +6,54 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { createRuntimeOverrides } from "./restrictions.js";
|
|
8
8
|
export * from "./restrictions.js";
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Calibrated against the mailwoman corpus (1,048 non-test source files). Each value sits just past the knee in that
|
|
11
|
+
* repo's distribution, so considered human code stays silent and runaway generation does not. See the design spec for
|
|
12
|
+
* the full sweep.
|
|
13
|
+
*
|
|
14
|
+
* The four SIZE ceilings are deliberately looser than the knee. Adopting v10 surfaced 172 pre-existing violations, and
|
|
15
|
+
* splitting that many functions across a parser — with no accuracy gate available to verify the result — is a larger
|
|
16
|
+
* risk than the legibility it buys. They are set at the p90 of the measured overage instead, so the worst decile had to
|
|
17
|
+
* be fixed at adoption while the body was grandfathered:
|
|
18
|
+
*
|
|
19
|
+
* max-statements n=88 median= 73 p90= 115 max= 272
|
|
20
|
+
* complexity n=32 median= 49 p90= 84 max= 173
|
|
21
|
+
* max-lines-per-function n=26 median=283 p90= 829 max=1329
|
|
22
|
+
* max-params n=15 median= 7 p90= 8 max= 10
|
|
23
|
+
*
|
|
24
|
+
* RATCHET THESE DOWN as the grandfathered functions are split. They exist to stop new code drifting, and every step
|
|
25
|
+
* toward the knee makes them do more of that job.
|
|
26
|
+
*/
|
|
27
|
+
export const DefaultLimits = {
|
|
28
|
+
maxDepth: 5,
|
|
29
|
+
maxParams: 8,
|
|
30
|
+
maxStatements: 115,
|
|
31
|
+
maxLinesPerFunction: 830,
|
|
32
|
+
maxLines: 750,
|
|
33
|
+
maxNestedCallbacks: 4,
|
|
34
|
+
maxNestedCalls: 4,
|
|
35
|
+
complexity: 85,
|
|
36
|
+
};
|
|
37
|
+
/** Globs treated as test files, where the size and named-constant rules are switched off. */
|
|
38
|
+
export const DefaultTestFilePatterns = [
|
|
39
|
+
"**/*.test.ts",
|
|
40
|
+
"**/*.test.tsx",
|
|
41
|
+
"**/test/**",
|
|
42
|
+
"**/fixtures/**",
|
|
43
|
+
"**/*.bench.ts",
|
|
44
|
+
// Storybook stories are fixtures in the same sense: each export is a rendered case, and its NAME is
|
|
45
|
+
// the label shown in the sidebar. A JSDoc block on `export const Default: Story = {}` says nothing
|
|
46
|
+
// the name does not.
|
|
47
|
+
"**/*.stories.ts",
|
|
48
|
+
"**/*.stories.tsx",
|
|
49
|
+
];
|
|
50
|
+
/**
|
|
51
|
+
* Globs whose contents are emitted by a generator, not written by hand. The size ceilings are meaningless there — the
|
|
52
|
+
* file is as long as its input is wide, and no reviewer reads it top to bottom — but every correctness rule still
|
|
53
|
+
* applies, because generated code ships.
|
|
54
|
+
*/
|
|
55
|
+
export const DefaultGeneratedFilePatterns = ["**/*.gen.ts", "**/*.gen.tsx", "**/*.generated.ts", "**/generated/**"];
|
|
56
|
+
/** Default ignore patterns for generated/build output and vendored tooling. */
|
|
10
57
|
export const DefaultIgnorePatterns = [
|
|
11
58
|
"**/out",
|
|
12
59
|
"**/dist",
|
|
@@ -14,6 +61,9 @@ export const DefaultIgnorePatterns = [
|
|
|
14
61
|
"**/node_modules",
|
|
15
62
|
"**/coverage",
|
|
16
63
|
"**/storybook-static",
|
|
64
|
+
// Yarn 4 vendors its own release bundle and plugin code here. It is third-party, minified, and
|
|
65
|
+
// not ours to lint — Tier 2's `no-abusive-eslint-disable` fires on it otherwise.
|
|
66
|
+
"**/.yarn/**",
|
|
17
67
|
];
|
|
18
68
|
/**
|
|
19
69
|
* Builds the complete oxlint configuration for a Sister Software package.
|
|
@@ -30,14 +80,14 @@ export const DefaultIgnorePatterns = [
|
|
|
30
80
|
* @returns A complete oxlint config object (no `extends` required).
|
|
31
81
|
*/
|
|
32
82
|
export function createOxlintConfig(options = {}) {
|
|
33
|
-
const { packageNamespace = "@sister.software", copyrightHolder = "Sister Software", spdxLicenseIdentifier = "UNLICENSED", author = "Teffen Ellis, et al.", react = false, headers = true, padding = true, braces = true, restrictProcessGlobals = false, ignorePatterns = DefaultIgnorePatterns, overrides = {}, } = options;
|
|
34
|
-
const
|
|
83
|
+
const { packageNamespace = "@sister.software", copyrightHolder = "Sister Software", spdxLicenseIdentifier = "UNLICENSED", author = "Teffen Ellis, et al.", react = false, headers = true, padding = true, braces = true, restrictProcessGlobals = false, unnamedThresholds = false, constantDocs = false, lengthTruthiness = true, limits: limitOverrides = {}, testFilePatterns = DefaultTestFilePatterns, generatedFilePatterns = DefaultGeneratedFilePatterns, ignorePatterns = DefaultIgnorePatterns, overrides = {}, } = options;
|
|
84
|
+
const limits = { ...DefaultLimits, ...limitOverrides };
|
|
85
|
+
const plugins = ["typescript", "unicorn", "oxc", "import", "promise", "vitest", ...(react ? ["react"] : [])];
|
|
35
86
|
const rules = {
|
|
36
87
|
// JavaScript
|
|
37
88
|
eqeqeq: ["error", "always", { null: "ignore" }],
|
|
38
89
|
"prefer-const": "warn",
|
|
39
90
|
"object-shorthand": ["warn", "always"],
|
|
40
|
-
"no-shadow": "off",
|
|
41
91
|
"no-undef": "off",
|
|
42
92
|
"no-unused-vars": [
|
|
43
93
|
"warn",
|
|
@@ -62,7 +112,186 @@ export function createOxlintConfig(options = {}) {
|
|
|
62
112
|
"typescript/no-non-null-assertion": "off",
|
|
63
113
|
"typescript/no-var-requires": "off",
|
|
64
114
|
"typescript/no-require-imports": "off",
|
|
115
|
+
// Tier 1 — legibility guardrails. Thresholds are ceilings past the knee of the calibration
|
|
116
|
+
// corpus's distribution: they stay silent on considered code and fire on runaway generation.
|
|
117
|
+
"max-depth": ["error", { max: limits.maxDepth }],
|
|
118
|
+
"max-params": ["error", { max: limits.maxParams }],
|
|
119
|
+
"max-statements": ["error", { max: limits.maxStatements }],
|
|
120
|
+
"max-lines-per-function": ["error", { max: limits.maxLinesPerFunction, skipBlankLines: true, skipComments: true }],
|
|
121
|
+
"max-lines": ["error", { max: limits.maxLines, skipBlankLines: true, skipComments: true }],
|
|
122
|
+
"max-nested-callbacks": ["error", { max: limits.maxNestedCallbacks }],
|
|
123
|
+
"unicorn/max-nested-calls": ["error", { max: limits.maxNestedCalls }],
|
|
124
|
+
complexity: ["error", limits.complexity],
|
|
125
|
+
"unicorn/no-array-reduce": "error",
|
|
126
|
+
"unicorn/no-unreadable-array-destructuring": "error",
|
|
127
|
+
// Tier 2 — defect classes that `correctness` does not cover. Every rule here corresponds to a
|
|
128
|
+
// way working-looking code is wrong at runtime.
|
|
129
|
+
"no-shadow": "error",
|
|
130
|
+
"no-promise-executor-return": "error",
|
|
131
|
+
"no-useless-assignment": "error",
|
|
132
|
+
"no-unreachable-loop": "error",
|
|
133
|
+
"no-unmodified-loop-condition": "error",
|
|
134
|
+
"no-loop-func": "error",
|
|
135
|
+
// `.sort()` and `.reverse()` mutate in place; on a shared or cached array that is a bug at a
|
|
136
|
+
// distance. The fixes are `toSorted()` / `toReversed()`.
|
|
137
|
+
"unicorn/no-array-sort": "error",
|
|
138
|
+
"unicorn/no-array-reverse": "error",
|
|
139
|
+
"unicorn/no-immediate-mutation": "error",
|
|
140
|
+
"unicorn/no-array-method-this-argument": "error",
|
|
141
|
+
"unicorn/no-typeof-undefined": "error",
|
|
142
|
+
"unicorn/no-useless-promise-resolve-reject": "error",
|
|
143
|
+
"unicorn/prefer-type-error": "error",
|
|
144
|
+
// Global `isNaN` coerces its argument; `Number.isNaN` does not.
|
|
145
|
+
"unicorn/prefer-number-properties": "error",
|
|
146
|
+
"unicorn/no-abusive-eslint-disable": "error",
|
|
147
|
+
// Off despite the name: it fires on `.map(x => ({ ...x, field }))`, which is O(n·k) overall and the
|
|
148
|
+
// ordinary way to add a field. The quadratic accumulation worth catching is `acc = { ...acc, x }`
|
|
149
|
+
// inside a reduce, which this does not distinguish. 14 sites, 14 false positives.
|
|
150
|
+
"oxc/no-map-spread": "off",
|
|
151
|
+
"oxc/bad-bitwise-operator": "error",
|
|
152
|
+
"oxc/branches-sharing-code": "error",
|
|
153
|
+
"typescript/no-dynamic-delete": "error",
|
|
154
|
+
"typescript/prefer-ts-expect-error": "error",
|
|
155
|
+
// A cycle here is not a style issue: it leaves bindings unevaluated at import time, which
|
|
156
|
+
// surfaces as a base class that is `undefined` at class-definition time.
|
|
157
|
+
"import/no-cycle": "error",
|
|
158
|
+
// `ignoreLastCallback` keeps the rule pointed at CHAINS, where a missing return silently feeds
|
|
159
|
+
// undefined to the next link. A terminal `.then(…)` doing side effects has nothing downstream
|
|
160
|
+
// to starve, and rewriting those adds a return whose value no one reads.
|
|
161
|
+
"promise/always-return": ["error", { ignoreLastCallback: true }],
|
|
162
|
+
// Off: it cannot see that a ternary settles exactly once. `cb((err) => (err ? reject(err) : resolve()))`
|
|
163
|
+
// is the standard way to bridge a node-style callback to a promise, and the rule flagged every
|
|
164
|
+
// instance of it on the calibration corpus — 6 sites, 6 false positives, no real double-settle.
|
|
165
|
+
"promise/no-multiple-resolved": "off",
|
|
166
|
+
// Tier 3 — test discipline. `expect-expect` is the one that matters most: it catches a test
|
|
167
|
+
// that runs, passes, and asserts nothing.
|
|
168
|
+
"vitest/expect-expect": "error",
|
|
169
|
+
// vitest's `expect(value, message)` takes an optional assertion message as a second argument —
|
|
170
|
+
// the rule's default of one would flag the API's own signature.
|
|
171
|
+
"vitest/valid-expect": ["error", { maxArgs: 2 }],
|
|
172
|
+
"vitest/valid-title": "error",
|
|
173
|
+
"vitest/valid-describe-callback": "error",
|
|
174
|
+
// Off: the dominant shape it flags is a parameterized assertion helper, where the conditional IS
|
|
175
|
+
// the contract — `expectProposal(out, { kind, body, minConfidence? })` asserts only what the
|
|
176
|
+
// caller specified. 33 sites on the calibration corpus, none a hidden never-running assertion.
|
|
177
|
+
"vitest/no-conditional-expect": "off",
|
|
178
|
+
"vitest/no-conditional-tests": "error",
|
|
179
|
+
"vitest/no-disabled-tests": "error",
|
|
180
|
+
"vitest/no-commented-out-tests": "error",
|
|
181
|
+
"vitest/no-alias-methods": "error",
|
|
182
|
+
"vitest/prefer-to-be": "error",
|
|
183
|
+
"vitest/prefer-to-have-length": "error",
|
|
184
|
+
"vitest/prefer-to-contain": "error",
|
|
185
|
+
"vitest/require-to-throw-message": "error",
|
|
186
|
+
// Playwright names its e2e specs `*.spec.ts`; vitest unit tests are `*.test.ts`. A repo running
|
|
187
|
+
// both has two legitimate conventions, so the rule is scoped to the vitest ones.
|
|
188
|
+
"vitest/consistent-test-filename": ["error", { allTestPattern: String.raw `.*\.test\.[tj]sx?$` }],
|
|
189
|
+
// Enabling a plugin also activates its `correctness`-category rules, so a rule this tier turned
|
|
190
|
+
// down must be switched off explicitly rather than merely left out of the list above.
|
|
191
|
+
"vitest/require-mock-type-parameters": "off",
|
|
192
|
+
"vitest/no-conditional-in-test": "off",
|
|
193
|
+
// Tier 4 — mechanical hygiene. All autofixable, none requiring judgment.
|
|
194
|
+
// Literal form.
|
|
195
|
+
"unicorn/numeric-separators-style": "error",
|
|
196
|
+
"unicorn/no-zero-fractions": "error",
|
|
197
|
+
"unicorn/text-encoding-identifier-case": "error",
|
|
198
|
+
"unicorn/escape-case": "error",
|
|
199
|
+
"unicorn/no-hex-escape": "error",
|
|
200
|
+
// Import discipline.
|
|
201
|
+
// `disallowTypeAnnotations: false` keeps the valuable half — a type-only import must be written
|
|
202
|
+
// `import type` — while allowing `typeof import("…")` in an annotation. That form is how a
|
|
203
|
+
// guarded dynamic import is typed: the module is optional and loaded at runtime, and the inline
|
|
204
|
+
// annotation is what says so. `import type` would erase to nothing and read as a hard dep.
|
|
205
|
+
"typescript/consistent-type-imports": ["error", { disallowTypeAnnotations: false }],
|
|
206
|
+
"typescript/no-import-type-side-effects": "error",
|
|
207
|
+
"unicorn/prefer-export-from": "error",
|
|
208
|
+
"import/no-duplicates": "error",
|
|
209
|
+
"import/first": "error",
|
|
210
|
+
"import/newline-after-import": "error",
|
|
211
|
+
// Modern API preference.
|
|
212
|
+
"unicorn/prefer-string-replace-all": "error",
|
|
213
|
+
// `caught` is permitted alongside `error`: when a catch sits inside a scope that already binds
|
|
214
|
+
// `error` (a React component's error state, say), no-shadow requires a different name and this
|
|
215
|
+
// rule would otherwise demand the shadowing one. The two rules are in direct conflict without it.
|
|
216
|
+
"unicorn/catch-error-name": ["error", { ignore: ["caught"] }],
|
|
217
|
+
"unicorn/prefer-at": "error",
|
|
218
|
+
"unicorn/prefer-global-this": "error",
|
|
219
|
+
"unicorn/consistent-existence-index-check": "error",
|
|
220
|
+
"unicorn/new-for-builtins": "error",
|
|
221
|
+
"unicorn/prefer-array-find": "error",
|
|
222
|
+
"unicorn/prefer-structured-clone": "error",
|
|
223
|
+
"unicorn/prefer-negative-index": "error",
|
|
224
|
+
"unicorn/prefer-math-min-max": "error",
|
|
225
|
+
"unicorn/no-useless-collection-argument": "error",
|
|
226
|
+
"unicorn/throw-new-error": "error",
|
|
227
|
+
// Two rules that look mechanical but are not type-safe, so they stay off:
|
|
228
|
+
//
|
|
229
|
+
// `unicorn/prefer-code-point` rewrites `charCodeAt` to `codePointAt`, which returns
|
|
230
|
+
// `number | undefined`. It exists for surrogate-pair correctness, but on the ASCII arithmetic
|
|
231
|
+
// where it usually fires it buys nothing and forces an undefined branch at every site.
|
|
232
|
+
//
|
|
233
|
+
// `unicorn/no-useless-undefined` drops an explicitly-passed `undefined` argument. oxlint has no
|
|
234
|
+
// type information, so it cannot tell an optional parameter from a required one and will
|
|
235
|
+
// silently turn `f(a, undefined)` into a call that no longer type-checks.
|
|
236
|
+
//
|
|
237
|
+
// `unicorn/prefer-string-raw` rewrites a string literal to a String.raw template. That is
|
|
238
|
+
// runtime-identical but not type-identical: the literal type is lost, so any template-literal
|
|
239
|
+
// type built from the value collapses. It widens types silently, which is worse than the
|
|
240
|
+
// escaped backslashes it removes.
|
|
241
|
+
"unicorn/prefer-code-point": "off",
|
|
242
|
+
"unicorn/no-useless-undefined": "off",
|
|
243
|
+
"unicorn/prefer-string-raw": "off",
|
|
244
|
+
//
|
|
245
|
+
// `unicorn/prefer-math-trunc` is the one that is not merely type-unsafe but semantically wrong.
|
|
246
|
+
// `x | 0` and `x >>> 0` are int32/uint32 coercion, and the wrapping is the point — every site on
|
|
247
|
+
// the calibration corpus was a hash function, a PRNG, or a seeded evaluation harness.
|
|
248
|
+
// `Math.trunc` does not wrap, so taking its suggestion silently changes what those produce.
|
|
249
|
+
"unicorn/prefer-math-trunc": "off",
|
|
250
|
+
//
|
|
251
|
+
// `unicorn/prefer-number-coercion` rewrites `Number.parseInt(x, 10)` to
|
|
252
|
+
// `Math.trunc(Number(x))`. parseInt parses a numeric PREFIX; Number is strict, so
|
|
253
|
+
// `parseInt("12px", 10)` is 12 where `Number("12px")` is NaN. On the calibration corpus the
|
|
254
|
+
// inputs included CLI options and an HTTP status of uncertain type — exactly where the
|
|
255
|
+
// difference bites. It also reintroduces Math.trunc, disabled just above.
|
|
256
|
+
"unicorn/prefer-number-coercion": "off",
|
|
257
|
+
//
|
|
258
|
+
// These two are not unsafe — they are unsatisfiable. oxfmt reverts both fixes on its next run:
|
|
259
|
+
// it lowercases hex digits, and it strips the parentheses unicorn/no-nested-ternary adds. Lint
|
|
260
|
+
// and format are both CI gates, so a rule the formatter undoes can never go green. Neither
|
|
261
|
+
// behaviour is configurable in oxfmt today.
|
|
262
|
+
"unicorn/number-literal-case": "off",
|
|
263
|
+
"unicorn/no-nested-ternary": "off",
|
|
264
|
+
//
|
|
265
|
+
// `unicorn/explicit-length-check` enforces `x.length > 0`, the opposite of the house
|
|
266
|
+
// convention. `sister-software/prefer-length-truthiness` enforces ours.
|
|
267
|
+
"unicorn/explicit-length-check": "off",
|
|
268
|
+
//
|
|
269
|
+
// Core `no-duplicate-imports` is not TypeScript-aware: it counts a value import and an
|
|
270
|
+
// `import type` from the same module as a duplicate, which is the split
|
|
271
|
+
// `typescript/consistent-type-imports` exists to create. On the calibration corpus it reported
|
|
272
|
+
// 71 sites where the TS-aware `import/no-duplicates` reported 1, and that 1 was real.
|
|
273
|
+
"no-duplicate-imports": "off",
|
|
274
|
+
// TS style.
|
|
275
|
+
"typescript/consistent-type-definitions": "error",
|
|
276
|
+
"typescript/consistent-indexed-object-style": "error",
|
|
277
|
+
"typescript/prefer-for-of": "error",
|
|
278
|
+
"typescript/no-inferrable-types": "error",
|
|
279
|
+
// Small structural.
|
|
280
|
+
"unicorn/prefer-ternary": "error",
|
|
281
|
+
"unicorn/prefer-logical-operator-over-ternary": "error",
|
|
282
|
+
"unicorn/no-lonely-if": "error",
|
|
283
|
+
"unicorn/no-console-spaces": "error",
|
|
284
|
+
"unicorn/no-static-only-class": "error",
|
|
285
|
+
"no-useless-return": "error",
|
|
65
286
|
};
|
|
287
|
+
if (react) {
|
|
288
|
+
rules["react-hooks/rules-of-hooks"] = "error";
|
|
289
|
+
rules["react/no-unstable-nested-components"] = "error";
|
|
290
|
+
rules["react/no-object-type-as-default-prop"] = "error";
|
|
291
|
+
rules["react/jsx-no-constructed-context-values"] = "error";
|
|
292
|
+
// The automatic JSX runtime made this obsolete; the rule predates it.
|
|
293
|
+
rules["react/react-in-jsx-scope"] = "off";
|
|
294
|
+
}
|
|
66
295
|
if (headers) {
|
|
67
296
|
// Error severity: missing headers should fail `oxlint` (a real CI gate) and surface as an
|
|
68
297
|
// editor error. The rule is auto-fixable, so `oxlint --fix` keeps the friction low.
|
|
@@ -80,15 +309,60 @@ export function createOxlintConfig(options = {}) {
|
|
|
80
309
|
// Error severity: a governance gate — direct env/argv access should fail the lint.
|
|
81
310
|
rules["sister-software/no-process-globals"] = "error";
|
|
82
311
|
}
|
|
312
|
+
if (unnamedThresholds) {
|
|
313
|
+
// Error severity: an unnamed threshold is a legibility defect, not a style preference.
|
|
314
|
+
rules["sister-software/no-unnamed-threshold"] = [
|
|
315
|
+
"error",
|
|
316
|
+
typeof unnamedThresholds === "object" ? unnamedThresholds : {},
|
|
317
|
+
];
|
|
318
|
+
}
|
|
319
|
+
if (constantDocs) {
|
|
320
|
+
// Error severity: an undocumented public constant or tuning knob is a legibility defect.
|
|
321
|
+
rules["sister-software/require-constant-doc"] = ["error", typeof constantDocs === "object" ? constantDocs : {}];
|
|
322
|
+
}
|
|
323
|
+
if (lengthTruthiness) {
|
|
324
|
+
rules["sister-software/prefer-length-truthiness"] = "error";
|
|
325
|
+
}
|
|
326
|
+
// Rules switched off inside test files. Table-driven test bodies are legitimately long, and
|
|
327
|
+
// expected values are legitimately unnamed numbers. oxlint validates override entries against the
|
|
328
|
+
// registered rule set, so an entry may only name a rule this config actually turned on.
|
|
329
|
+
const testFileRules = {
|
|
330
|
+
"max-lines-per-function": "off",
|
|
331
|
+
"max-statements": "off",
|
|
332
|
+
"max-lines": "off",
|
|
333
|
+
};
|
|
334
|
+
if (react) {
|
|
335
|
+
// A Storybook `render` IS a component — React calls it as one — but it is not NAMED like one, so
|
|
336
|
+
// the hook rules read it as a plain function. Test files that render hooks go through a
|
|
337
|
+
// testing-library wrapper for the same reason.
|
|
338
|
+
testFileRules["react-hooks/rules-of-hooks"] = "off";
|
|
339
|
+
}
|
|
340
|
+
if (unnamedThresholds) {
|
|
341
|
+
testFileRules["sister-software/no-unnamed-threshold"] = "off";
|
|
342
|
+
}
|
|
343
|
+
if (constantDocs) {
|
|
344
|
+
testFileRules["sister-software/require-constant-doc"] = "off";
|
|
345
|
+
}
|
|
346
|
+
/** Generated files: size ceilings only. Everything else still applies — generated code ships. */
|
|
347
|
+
const generatedFileRules = {
|
|
348
|
+
"max-lines": "off",
|
|
349
|
+
"max-lines-per-function": "off",
|
|
350
|
+
"max-statements": "off",
|
|
351
|
+
complexity: "off",
|
|
352
|
+
};
|
|
83
353
|
return {
|
|
84
354
|
plugins,
|
|
85
|
-
...(headers || padding || braces || restrictProcessGlobals
|
|
355
|
+
...(headers || padding || braces || restrictProcessGlobals || unnamedThresholds || constantDocs || lengthTruthiness
|
|
86
356
|
? { jsPlugins: ["@sister.software/oxlint-config/plugin"] }
|
|
87
357
|
: {}),
|
|
88
358
|
categories: { correctness: "error" },
|
|
89
359
|
ignorePatterns,
|
|
90
360
|
rules,
|
|
91
|
-
overrides:
|
|
361
|
+
overrides: [
|
|
362
|
+
...createRuntimeOverrides(packageNamespace),
|
|
363
|
+
{ files: testFilePatterns, rules: testFileRules },
|
|
364
|
+
{ files: generatedFilePatterns, rules: generatedFileRules },
|
|
365
|
+
],
|
|
92
366
|
...overrides,
|
|
93
367
|
};
|
|
94
368
|
}
|
package/out/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,cAAc,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file A prefer-length-truthiness rule, authored as an oxlint JS plugin (ESLint v9-compatible API).
|
|
6
|
+
* It is the house counterpart to `unicorn/explicit-length-check`, which enforces the opposite
|
|
7
|
+
* convention and is therefore off: `if (items.length)` reads better here than
|
|
8
|
+
* `if (items.length > 0)`.
|
|
9
|
+
*
|
|
10
|
+
* The rule only fires where the value is ALREADY coerced to a boolean — a condition, a ternary
|
|
11
|
+
* test, or the operand of `!` — including through `&&`/`||` nested inside one. Outside those
|
|
12
|
+
* positions the comparison is the value itself, and rewriting `const hasItems = items.length > 0`
|
|
13
|
+
* would silently change its type from boolean to number.
|
|
14
|
+
*/
|
|
15
|
+
import type { Rule } from "./plugin-types.js";
|
|
16
|
+
export declare const preferLengthTruthinessRule: Rule;
|
|
17
|
+
export default preferLengthTruthinessRule;
|
|
18
|
+
//# sourceMappingURL=length-truthiness-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"length-truthiness-plugin.d.ts","sourceRoot":"","sources":["../src/length-truthiness-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAkB,IAAI,EAAe,MAAM,mBAAmB,CAAA;AA2C1E,eAAO,MAAM,0BAA0B,EAAE,IAuExC,CAAA;AAED,eAAe,0BAA0B,CAAA"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file A prefer-length-truthiness rule, authored as an oxlint JS plugin (ESLint v9-compatible API).
|
|
6
|
+
* It is the house counterpart to `unicorn/explicit-length-check`, which enforces the opposite
|
|
7
|
+
* convention and is therefore off: `if (items.length)` reads better here than
|
|
8
|
+
* `if (items.length > 0)`.
|
|
9
|
+
*
|
|
10
|
+
* The rule only fires where the value is ALREADY coerced to a boolean — a condition, a ternary
|
|
11
|
+
* test, or the operand of `!` — including through `&&`/`||` nested inside one. Outside those
|
|
12
|
+
* positions the comparison is the value itself, and rewriting `const hasItems = items.length > 0`
|
|
13
|
+
* would silently change its type from boolean to number.
|
|
14
|
+
*/
|
|
15
|
+
/** Comparisons meaning "non-empty", which become the bare length. */
|
|
16
|
+
const TRUTHY_FORMS = new Set(["> 0", "!== 0", "!= 0", ">= 1"]);
|
|
17
|
+
/** Comparisons meaning "empty", which become a negated length. */
|
|
18
|
+
const FALSY_FORMS = new Set(["=== 0", "== 0", "< 1"]);
|
|
19
|
+
/** Members whose length-ness the rule understands. */
|
|
20
|
+
const LENGTH_PROPERTIES = new Set(["length", "size"]);
|
|
21
|
+
/** The comparison rendered as `<operator> <literal>`, or null when it is not a length comparison. */
|
|
22
|
+
function classify(node) {
|
|
23
|
+
if (node.type !== "BinaryExpression" || !node.operator || !node.left || !node.right)
|
|
24
|
+
return null;
|
|
25
|
+
// Accept both `x.length > 0` and the flipped `0 < x.length`.
|
|
26
|
+
const flipped = { "<": ">", ">": "<", "<=": ">=", ">=": "<=" };
|
|
27
|
+
let { left, right, operator } = { left: node.left, right: node.right, operator: node.operator };
|
|
28
|
+
if (left.type === "Literal" || left.type === "NumericLiteral") {
|
|
29
|
+
;
|
|
30
|
+
[left, right] = [right, left];
|
|
31
|
+
operator = flipped[operator] ?? operator;
|
|
32
|
+
}
|
|
33
|
+
if (left.type !== "MemberExpression" && left.type !== "StaticMemberExpression")
|
|
34
|
+
return null;
|
|
35
|
+
const property = left.property;
|
|
36
|
+
if (!property || property.type !== "Identifier" || !LENGTH_PROPERTIES.has(property.name ?? ""))
|
|
37
|
+
return null;
|
|
38
|
+
if (right.type !== "Literal" && right.type !== "NumericLiteral")
|
|
39
|
+
return null;
|
|
40
|
+
if (typeof right.value !== "number")
|
|
41
|
+
return null;
|
|
42
|
+
const form = `${operator} ${right.value}`;
|
|
43
|
+
if (TRUTHY_FORMS.has(form))
|
|
44
|
+
return { member: left, negate: false };
|
|
45
|
+
if (FALSY_FORMS.has(form))
|
|
46
|
+
return { member: left, negate: true };
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
export const preferLengthTruthinessRule = {
|
|
50
|
+
meta: {
|
|
51
|
+
name: "prefer-length-truthiness",
|
|
52
|
+
type: "suggestion",
|
|
53
|
+
fixable: "code",
|
|
54
|
+
schema: [{ type: "object", additionalProperties: true }],
|
|
55
|
+
},
|
|
56
|
+
create(context) {
|
|
57
|
+
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
58
|
+
const text = sourceCode.getText();
|
|
59
|
+
function report(node) {
|
|
60
|
+
const hit = classify(node);
|
|
61
|
+
if (!hit)
|
|
62
|
+
return;
|
|
63
|
+
const member = text.slice(hit.member.range[0], hit.member.range[1]);
|
|
64
|
+
const replacement = hit.negate ? `!${member}` : member;
|
|
65
|
+
context.report({
|
|
66
|
+
node,
|
|
67
|
+
message: `Prefer \`${replacement}\` over an explicit length comparison — the house convention is truthiness.`,
|
|
68
|
+
fix(fixer) {
|
|
69
|
+
return fixer.replaceTextRange(node.range, replacement);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** Walk into a boolean context: logical operands and `!` arguments stay boolean. */
|
|
74
|
+
function visitCondition(node) {
|
|
75
|
+
if (!node)
|
|
76
|
+
return;
|
|
77
|
+
if (node.type === "LogicalExpression") {
|
|
78
|
+
visitCondition(node.left);
|
|
79
|
+
visitCondition(node.right);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (node.type === "UnaryExpression" && node.operator === "!") {
|
|
83
|
+
visitCondition(node.argument);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
report(node);
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
IfStatement(node) {
|
|
90
|
+
visitCondition(node.test);
|
|
91
|
+
},
|
|
92
|
+
WhileStatement(node) {
|
|
93
|
+
visitCondition(node.test);
|
|
94
|
+
},
|
|
95
|
+
DoWhileStatement(node) {
|
|
96
|
+
visitCondition(node.test);
|
|
97
|
+
},
|
|
98
|
+
ForStatement(node) {
|
|
99
|
+
visitCondition(node.test);
|
|
100
|
+
},
|
|
101
|
+
ConditionalExpression(node) {
|
|
102
|
+
visitCondition(node.test);
|
|
103
|
+
},
|
|
104
|
+
UnaryExpression(node) {
|
|
105
|
+
if (node.operator === "!") {
|
|
106
|
+
visitCondition(node.argument);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
export default preferLengthTruthinessRule;
|
|
113
|
+
//# sourceMappingURL=length-truthiness-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"length-truthiness-plugin.js","sourceRoot":"","sources":["../src/length-truthiness-plugin.ts"],"names":[],"mappings":"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"}
|
package/out/plugin-types.d.ts
CHANGED
|
@@ -20,6 +20,29 @@ export interface AstNode {
|
|
|
20
20
|
/** `if`/`else` branches, for the require-braces rule. */
|
|
21
21
|
consequent?: AstNode;
|
|
22
22
|
alternate?: AstNode | null;
|
|
23
|
+
/** Binary/unary operator text, for the threshold rule. */
|
|
24
|
+
operator?: string;
|
|
25
|
+
/** Binary-expression operands. */
|
|
26
|
+
left?: AstNode;
|
|
27
|
+
right?: AstNode;
|
|
28
|
+
/** Unary-expression operand. */
|
|
29
|
+
argument?: AstNode;
|
|
30
|
+
/** A literal's value, and its verbatim source text (`raw` preserves a `0x` prefix). */
|
|
31
|
+
value?: unknown;
|
|
32
|
+
raw?: string;
|
|
33
|
+
/** `const` / `let` / `var`, for the constant-doc rule. */
|
|
34
|
+
kind?: string;
|
|
35
|
+
/** Declarators of a variable declaration. */
|
|
36
|
+
declarations?: AstNode[];
|
|
37
|
+
/** A declarator's binding identifier and initializer. */
|
|
38
|
+
id?: AstNode;
|
|
39
|
+
init?: AstNode | null;
|
|
40
|
+
/** An identifier's name. */
|
|
41
|
+
name?: string;
|
|
42
|
+
/** The condition of an `if`/`while`/`for`/ternary, for the length-truthiness rule. */
|
|
43
|
+
test?: AstNode | null;
|
|
44
|
+
/** A member expression's accessed property. */
|
|
45
|
+
property?: AstNode;
|
|
23
46
|
}
|
|
24
47
|
export interface SourceCode {
|
|
25
48
|
getText(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-types.d.ts","sourceRoot":"","sources":["../src/plugin-types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACvB;AAED,yEAAyE;AACzE,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,4FAA4F;IAC5F,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IAC1B,yDAAyD;IACzD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin-types.d.ts","sourceRoot":"","sources":["../src/plugin-types.ts"],"names":[],"mappings":"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"}
|
package/out/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAI/C,QAAA,MAAM,oBAAoB,EAAE,MAW3B,CAAA;AAED,eAAe,oBAAoB,CAAA"}
|
package/out/plugin.js
CHANGED
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
* names) exposing all of Sister Software's custom rules under the `sister-software/` namespace.
|
|
7
7
|
*/
|
|
8
8
|
import { bracesRule } from "./braces-plugin.js";
|
|
9
|
+
import { requireConstantDocRule } from "./constant-doc-plugin.js";
|
|
9
10
|
import { headerRule } from "./headers-plugin.js";
|
|
11
|
+
import { preferLengthTruthinessRule } from "./length-truthiness-plugin.js";
|
|
10
12
|
import { paddingRule } from "./padding-plugin.js";
|
|
11
13
|
import { noProcessGlobalsRule } from "./process-globals-plugin.js";
|
|
14
|
+
import { noUnnamedThresholdRule } from "./threshold-plugin.js";
|
|
12
15
|
const sisterSoftwarePlugin = {
|
|
13
16
|
meta: { name: "sister-software" },
|
|
14
17
|
rules: {
|
|
@@ -16,6 +19,9 @@ const sisterSoftwarePlugin = {
|
|
|
16
19
|
"padding-lines": paddingRule,
|
|
17
20
|
"require-braces": bracesRule,
|
|
18
21
|
"no-process-globals": noProcessGlobalsRule,
|
|
22
|
+
"no-unnamed-threshold": noUnnamedThresholdRule,
|
|
23
|
+
"require-constant-doc": requireConstantDocRule,
|
|
24
|
+
"prefer-length-truthiness": preferLengthTruthinessRule,
|
|
19
25
|
},
|
|
20
26
|
};
|
|
21
27
|
export default sisterSoftwarePlugin;
|
package/out/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAA;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAE9D,MAAM,oBAAoB,GAAW;IACpC,IAAI,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE;IACjC,KAAK,EAAE;QACN,qBAAqB,EAAE,UAAU;QACjC,eAAe,EAAE,WAAW;QAC5B,gBAAgB,EAAE,UAAU;QAC5B,oBAAoB,EAAE,oBAAoB;QAC1C,sBAAsB,EAAE,sBAAsB;QAC9C,sBAAsB,EAAE,sBAAsB;QAC9C,0BAA0B,EAAE,0BAA0B;KACtD;CACD,CAAA;AAED,eAAe,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file A no-unnamed-threshold rule, authored as an oxlint JS plugin (ESLint v9-compatible API). It
|
|
6
|
+
* flags a numeric literal used as a threshold — an operand of a comparison — and nothing else.
|
|
7
|
+
* Numbers inside array and object literals are left alone, because a bounding box or a codepoint
|
|
8
|
+
* table is data rather than a tuning knob. That distinction is why this exists instead of
|
|
9
|
+
* `no-magic-numbers`, which cannot express it.
|
|
10
|
+
*/
|
|
11
|
+
import type { Rule } from "./plugin-types.js";
|
|
12
|
+
/** Options accepted by {@link noUnnamedThresholdRule}. */
|
|
13
|
+
export interface ThresholdOptions {
|
|
14
|
+
/** Values that may appear unnamed. Replaces the default list rather than extending it. */
|
|
15
|
+
ignore?: number[];
|
|
16
|
+
/** Exempt radix-prefixed literals, which already read as codepoints or bit masks. */
|
|
17
|
+
allowHex?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare const noUnnamedThresholdRule: Rule;
|
|
20
|
+
export default noUnnamedThresholdRule;
|
|
21
|
+
//# sourceMappingURL=threshold-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threshold-plugin.d.ts","sourceRoot":"","sources":["../src/threshold-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAWtD,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAChC,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,eAAO,MAAM,sBAAsB,EAAE,IA4DpC,CAAA;AAED,eAAe,sBAAsB,CAAA"}
|