-
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy path.oxlintrc.json
More file actions
409 lines (363 loc) · 17.4 KB
/
Copy path.oxlintrc.json
File metadata and controls
409 lines (363 loc) · 17.4 KB
1
2
3
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
{
"jsPlugins": ["./.oxlint/oxlint-plugin-no-showmessage.mjs"],
"categories": {
"correctness": "error",
"suspicious": "error",
"pedantic": "error",
"perf": "error",
"style": "error"
},
"rules": {
// `== null` / `!= null` is the idiomatic null-or-undefined check
// and is used throughout the codebase. Keep `eqeqeq` on for every
// other comparison.
"eqeqeq": ["error", "always", { "null": "ignore" }],
// Domain: codebase parses binary formats (Fallout .pro/.map, bit offsets,
// PID constants). Numeric literals ARE the spec - extracting them hurts
// readability instead of helping.
"no-magic-numbers": "off",
// Object-key order carries meaning here: tree-sitter node orderings,
// grammar rules, snippet stanzas, and data tables are grouped by
// feature. Alphabetizing destroys that grouping.
"sort-keys": "off",
// Arbitrary numeric caps - block-count, file length, param count,
// identifier length, call-nesting depth. No evidence any instance is
// actually a problem; the cap is the problem.
"max-statements": "off",
"max-lines-per-function": "off",
"max-lines": "off",
"max-params": "off",
"id-length": "off",
"unicorn/max-nested-calls": "off",
// Pure style preference; no correctness value.
"func-style": "off",
"no-ternary": "off",
"capitalized-comments": "off",
"no-inline-comments": "off",
"prefer-destructuring": "off",
"no-continue": "off",
"init-declarations": "off",
"unicorn/switch-case-braces": "off",
// Forcing fixed-length digit groups on hex literals harms readability
// for values that read naturally as words (`0xdeadbeef`) or as a
// single 32-bit constant. Authors can still apply the project's
// 2-digit byte grouping where it helps; mandating it everywhere is
// noise.
"unicorn/numeric-separators-style": "off",
// The codec-meta module bundles tightly-coupled typed-binary Schema
// subclasses (u24, i24, future bit-packed codecs) for a single
// registration table. Splitting each into its own file would scatter
// the registration across N files for no readability gain.
"max-classes-per-file": "off",
// `filename-case` would force a repo-wide rename without an
// established convention - out of scope for a lint upgrade.
"unicorn/filename-case": "off",
// `null` is required by surfaces we interoperate with (JSON payloads,
// LSP protocol, some tree-sitter APIs). Blanket ban doesn't fit.
"unicorn/no-null": "off",
// Member-order churn with no autofix in oxlint. Imports are grouped
// by origin (external -> internal -> types), not alphabetized within
// braces.
"sort-imports": "off",
// Project style: bare-statement `if`/`else`/`for` bodies are used
// deliberately. Forcing braces across hundreds of call sites is
// churn, not safety.
"curly": "off",
// Template-vs-concat is a preference, not a correctness concern.
// The codebase uses both intentionally.
"prefer-template": "off",
// Arbitrary nesting cap with no bug rationale; parsers and tree
// walkers legitimately nest deep.
"max-depth": "off",
// `utf8` vs `utf-8` cosmetic; both are recognized by Node and the
// DOM. Not worth the churn.
"unicorn/text-encoding-identifier-case": "off",
// oxfmt normalizes hex literals to lowercase (`0xFF` -> `0xff`) and
// has no option to configure case. The rule would fight the formatter
// on every run.
"unicorn/number-literal-case": "off",
// Rule pushes `.toSorted()` (ES2023) in places where the project's
// TS lib target predates it. Re-enable when lib is bumped.
"unicorn/no-array-sort": "off",
// Sequential-condition ternaries (`a ? X : b ? Y : Z`) are used
// idiomatically in the codebase for short classification chains
// (enum-like lookups, type-narrowing fallbacks). Forbidding them
// outright is churn; the equivalent if/else-chain is less compact
// without being clearer.
"no-nested-ternary": "off",
"unicorn/no-nested-ternary": "off",
// `.at(-1)` is modern but slower than `arr[arr.length - 1]` in hot
// parser paths; keep both idioms legal.
"unicorn/prefer-at": "off",
// `String.raw` rewrite is cosmetic.
"unicorn/prefer-string-raw": "off",
// `.slice` vs `.substring` - both are fine; no correctness value.
"unicorn/prefer-string-slice": "off",
// Readability preference; `if (!x)` is idiomatic in this codebase.
"no-negated-condition": "off",
// `async` without `await` is used deliberately to make interfaces
// uniformly Promise-returning (e.g., provider methods where some
// impls are sync).
"require-await": "off",
// Inline `import("module").Type` annotations are used in places where
// hoisting to a top-level import would create a circular import or
// expand the import block for a one-off type reference. Keep the
// top-level `import { X }` -> `import type { X }` enforcement active
// (controlled by `prefer: "type-imports"`) but allow the inline form.
"typescript/consistent-type-imports": ["error", { "disallowTypeAnnotations": false }],
// `T[]` and `Array<T>` are both idiomatic; forcing one is churn.
"typescript/array-type": "off",
// Auto-numbered enums are intentional in tree-sitter wrappers and
// flag sets; explicit initializers would add noise without value.
"typescript/prefer-enum-initializers": "off",
// Explicit annotations are often deliberate self-documentation,
// especially on public APIs.
"typescript/no-inferrable-types": "off",
// Flattening `if/else` to `?:` is a style preference.
"unicorn/prefer-ternary": "off",
// False positives with closures that intentionally capture scope.
"unicorn/consistent-function-scoping": "off",
// Collapsing `else { if ... }` is style churn.
"unicorn/no-lonely-if": "off",
"no-lonely-if": "off",
// `const x: Map<K, V> = new Map()` vs `const x = new Map<K, V>()`
// both have legitimate uses.
"typescript/consistent-generic-constructors": "off",
// `{}` is used deliberately in generic bounds and duck-typed
// positions; blanket ban doesn't fit.
"typescript/ban-types": "off",
// `if (arr.length)` is idiomatic and unambiguous in this codebase.
"unicorn/explicit-length-check": "off",
// Early-return vs. else-branch is a readability preference.
"no-else-return": "off",
// Brace-vs-expression body is a style preference.
"arrow-body-style": "off",
// `x = x + 1` vs `x += 1` is style churn.
"operator-assignment": "off",
// `{ foo: foo }` vs `{ foo }` is style churn.
"object-shorthand": "off",
// Empty interfaces are used as markers and for declaration merging.
"typescript/no-empty-interface": "off",
// Rule bans TODO/FIXME comments; these are useful tracking markers.
"no-warning-comments": "off",
// Parameter ordering is sometimes dictated by external APIs or
// readability (required before optional).
"default-param-last": "off",
// `type` vs `interface` is a style preference.
"typescript/consistent-type-definitions": "off",
// Anonymous function expressions are used deliberately in callbacks
// and factories.
"func-names": "off",
// Rule pushes away from `.map(x => ({ ...x, extra }))` for perf, but
// the alternatives either mutate the input (usually wrong) or have
// equivalent perf (`Object.assign`). Spreading to produce a fresh
// object is the idiomatic copy-on-write pattern here.
"oxc/no-map-spread": "off",
// Same readability rationale as `no-negated-condition` above; the
// `unicorn/` variant is a duplicate.
"unicorn/no-negated-condition": "off",
// Adding the `/u` flag changes regex semantics (Unicode mode is
// stricter on escape parsing and treats surrogate pairs as one
// code point). The codebase parses ASCII-only formats (Fallout SSL,
// WeiDU, binary headers) where the flag adds no correctness value
// and risks behavior changes on patterns with literal backslashes.
"require-unicode-regexp": "off",
// Newly enabled by oxlint 1.68. The codebase's regexes parse ASCII
// formats (Fallout SSL, WeiDU, binary headers) and address capture
// groups positionally; naming every group is churn across parser and
// grammar regexes with no correctness value. Same "out of scope for a
// lint upgrade" rationale as `unicorn/filename-case` above.
"prefer-named-capture-group": "off",
// Also newly enabled by oxlint 1.68. Method-signature vs
// property-signature (`foo(): T` vs `foo: () => T`) in interfaces is a
// style preference with no correctness value; the codebase uses method
// signatures idiomatically. Converting the call sites is churn out of
// scope for a lint upgrade, same as the other `typescript/` style
// rules disabled above (`array-type`, `consistent-type-definitions`).
"typescript/method-signature-style": "off",
// Newly enabled by oxlint 1.73. `parseInt(x, 10)` and
// `Math.trunc(Number(x))` are NOT behaviorally equivalent: parseInt
// parses the longest valid numeric prefix and ignores trailing junk
// ("3abc" -> 3), while Number() is strict and yields NaN for the same
// input. Call sites here parse WeiDU/sslc diagnostic output, tree-sitter
// node text, and an env var (BGFORGE_LSP_SLOW_MS) - swapping to the
// stricter form at 30+ sites is a behavior change out of scope for a
// lint-tool upgrade, same rationale as `prefer-named-capture-group`.
"unicorn/prefer-number-coercion": "off"
},
"overrides": [
{
"files": ["grammars/**/*.js"],
"globals": {
"grammar": "readonly",
"seq": "readonly",
"choice": "readonly",
"repeat": "readonly",
"repeat1": "readonly",
"optional": "readonly",
"prec": "readonly",
"token": "readonly",
"field": "readonly",
"alias": "readonly",
"LANGUAGE": "readonly",
"LRULE": "readonly"
},
"rules": {
"no-undef": "error",
"no-unused-vars": "off",
"no-useless-escape": "off",
// Tree-sitter convention: hidden grammar rules are prefixed
// with `_` (e.g. `_statement`, `_expression`). The names are
// part of the grammar's public ABI.
"no-underscore-dangle": "off"
}
},
{
"files": ["server/src/**/*.ts"],
"rules": {
"bgforge-mls/no-showmessage": "error"
}
},
{
// VS Code idiom: a private `_onDidX` EventEmitter exposes its
// public `.event` as `onDidX`. The pattern is used by `vscode.d.ts`
// itself; renaming would diverge from the host API style.
"files": [
"client/src/editors/binaryEditor*.ts",
"client/src/binary-editor/**/*.ts",
"client/src/image-editor/**/*.ts"
],
"rules": {
"no-underscore-dangle": "off"
}
},
{
// The filesystem providers follow the same VS Code editor idioms: `_onDidX` EventEmitters, and
// `vscode.FileSystemError.FileNotFound(...)` factory calls (uppercase names called without `new`).
"files": ["client/src/ie-resources/**/*.ts", "client/src/int-editor/**/*.ts"],
"rules": {
"no-underscore-dangle": "off",
"new-cap": "off"
}
},
{
// `document.getElementById` is clearer and faster than
// `.querySelector('#id')`; the rule's premise doesn't hold.
// Webview scripts are the only DOM consumers in the codebase.
"files": ["client/src/**/*-webview*.ts", "client/src/dialog-editor/webview/**"],
"rules": {
"unicorn/prefer-query-selector": "off"
}
},
{
// Svelte 5 runes require `let`: `let x = $state(...)` and
// `let { ... } = $props()` are reassigned by the compiler's reactivity,
// which oxlint cannot see - it reports them as never-reassigned. `sort-vars`
// likewise fights the rune/prop declaration order. Scope: the dialog editor's
// Svelte webview components.
"files": ["client/src/dialog-editor/webview/**/*.svelte"],
"rules": {
"prefer-const": "off",
"sort-vars": "off"
}
},
{
// VS Code's `webview.postMessage()` (extension side),
// `acquireVsCodeApi().postMessage()` (webview side), and
// `worker_threads` `parentPort.postMessage()` are not the browser's
// `window.postMessage`; none take a `targetOrigin`.
"files": [
"client/src/editors/**",
"client/src/webview-utils.ts",
"client/src/binary-editor/**",
"client/src/dialog-editor/**",
"client/src/image-editor/**"
],
"rules": {
"unicorn/require-post-message-target-origin": "off"
}
},
{
// SSL-compiler tests mock Node `child_process` (EventEmitter-based);
// converting the mock to EventTarget would break the surface they
// stand in for.
"files": ["server/test/**"],
"rules": {
"unicorn/prefer-event-target": "off"
}
},
{
// CLI entrypoints catch errors at the top level and translate them
// to exit codes; top-level await would force a module-shape change
// that breaks that pattern.
"files": ["**/src/cli.ts", "client/src/test/runTest.ts"],
"rules": {
"unicorn/prefer-top-level-await": "off"
}
},
{
// `x | 0` (32-bit truncation) and `x >>> 0` (unsigned 32-bit coercion) are
// deliberate binary-codec idioms; `Math.trunc` is not equivalent at the bytecode
// level. Applies inside `binary/` and `image/` (the FRM/BAM parsers and the
// hand-rolled PNG codec) and the editor's binary-formatting helper.
"files": ["binary/**", "image/**", "client/src/editors/binaryEditor-formatting.ts"],
"rules": {
"unicorn/prefer-math-trunc": "off"
}
},
{
// Tests intentionally compare against the literal string `"${x}"`
// (snippet output, esbuild template fixtures); the rule's
// "forgotten backticks" heuristic does not apply.
"files": ["**/test/**", "**/*.test.ts"],
"rules": {
"no-template-curly-in-string": "off"
}
},
{
// Test mocks like `vi.fn().mockResolvedValue(undefined)` pass
// `undefined` to satisfy a typed signature that requires the
// argument; the rule's "useless undefined" heuristic doesn't
// distinguish that case from a genuinely-redundant pass.
"files": ["**/test/**", "**/*.test.ts"],
"rules": {
"unicorn/no-useless-undefined": "off"
}
},
{
// bits-ui is an accessible headless component primitive library.
// All imports must go through webview/components/primitives/ wrappers
// so the dependency has one swap point if it is ever replaced.
"files": ["client/src/binary-editor/webview/**"],
"rules": {
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "bits-ui",
"message": "Import bits-ui only via webview/components/primitives wrappers."
}
]
}
]
}
},
{
// The primitives wrapper directory is the designated single import
// point for bits-ui; the restriction above does not apply here.
"files": ["client/src/binary-editor/webview/components/primitives/**"],
"rules": {
"no-restricted-imports": "off"
}
}
],
"ignorePatterns": [
"**/node_modules/**",
"**/out/**",
"**/*.d.ts",
"server/src/user-messages.ts",
"binary-editor/test/harness/**",
"client/src/dialog-editor/test/harness/**"
]
}