@ttsc/lint 0.14.0-dev.20260528.1 → 0.14.0-dev.20260529.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/README.md +69 -76
- package/linthost/lsp.go +149 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,14 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
[](https://github.com/samchon/ttsc/blob/master/LICENSE)
|
|
6
|
-
[](https://www.npmjs.com/package/@ttsc/lint)
|
|
7
|
-
[](https://www.npmjs.com/package/@ttsc/lint)
|
|
8
|
-
[](https://github.com/samchon/ttsc/actions?query=workflow%3Atest)
|
|
9
|
-
[](https://ttsc.dev/docs)
|
|
10
|
-
[](https://discord.gg/E94XhzrUCZ)
|
|
5
|
+
[](https://github.com/samchon/ttsc/blob/master/LICENSE) [](https://www.npmjs.com/package/@ttsc/lint) [](https://www.npmjs.com/package/@ttsc/lint) [](https://github.com/samchon/ttsc/actions?query=workflow%3Atest) [](https://ttsc.dev/docs) [](https://discord.gg/E94XhzrUCZ)
|
|
11
6
|
|
|
12
|
-
A linter and formatter. Co-protagonist of the [`ttsc`](https://ttsc.dev) toolchain
|
|
7
|
+
A linter and formatter. Co-protagonist of the [`ttsc`](https://ttsc.dev) toolchain, paired with `ttsc`, it replaces `eslint` and `prettier`.
|
|
13
8
|
|
|
14
9
|
720+ rules across 21 families. Lint violations surface as `error TSxxxxx` from a single compile pass; the formatter applies via `ttsc format`.
|
|
15
10
|
|
|
@@ -86,7 +81,7 @@ npx ttsx src/index.ts
|
|
|
86
81
|
|
|
87
82
|
Errors fail the command; warnings print without affecting the exit code. Under `ttsx`, errors stop the program before your entrypoint runs.
|
|
88
83
|
|
|
89
|
-
`ttsc fix` applies every autofix the enabled rules offer
|
|
84
|
+
`ttsc fix` applies every autofix the enabled rules offer, lint and format together. Writes results back to disk, then re-runs type-check + lint. `ttsc format` runs the format rule set through the same dataflow.
|
|
90
85
|
|
|
91
86
|
```bash
|
|
92
87
|
npx ttsc fix
|
|
@@ -97,7 +92,7 @@ npx ttsc format
|
|
|
97
92
|
|
|
98
93
|
## Format
|
|
99
94
|
|
|
100
|
-
Configure the formatter through the `format` block in `lint.config.ts`. Keys mirror `.prettierrc`; the presence of the block
|
|
95
|
+
Configure the formatter through the `format` block in `lint.config.ts`. Keys mirror `.prettierrc`; the presence of the block, even empty `format: {}`, enables the always-on format rules at Prettier defaults so `ttsc format` rewrites your source to match.
|
|
101
96
|
|
|
102
97
|
```ts
|
|
103
98
|
// lint.config.ts
|
|
@@ -115,13 +110,13 @@ export default {
|
|
|
115
110
|
} satisfies ITtscLintConfig;
|
|
116
111
|
```
|
|
117
112
|
|
|
118
|
-
`ttsc check` does **not** fail on formatting by default
|
|
113
|
+
`ttsc check` does **not** fail on formatting by default. It surfaces format diagnostics only when you opt in with `format.severity`. `ttsc format` runs the active format rules across the project and writes results to disk regardless of `severity`.
|
|
119
114
|
|
|
120
115
|
Each `format` config key activates one rule:
|
|
121
116
|
|
|
122
117
|
| Config key | Rule | Effect |
|
|
123
118
|
| --- | --- | --- |
|
|
124
|
-
| `severity` (default `"off"`) | applies to every format rule | Sets the check-time diagnostic level. Does not gate `ttsc format
|
|
119
|
+
| `severity` (default `"off"`) | applies to every format rule | Sets the check-time diagnostic level. Does not gate `ttsc format`. That runs all active rules. |
|
|
125
120
|
| `semi` | `format/semi` | Insert trailing semicolons on ASI-terminated statements. |
|
|
126
121
|
| `singleQuote` | `format/quotes` | Convert quoted strings to the preferred quote style. |
|
|
127
122
|
| `trailingComma` | `format/trailing-comma` | Add trailing commas to multi-line lists. |
|
|
@@ -129,9 +124,9 @@ Each `format` config key activates one rule:
|
|
|
129
124
|
| `importOrder` (opt-in) | `format/sort-imports` | Group external/relative imports and alphabetize each group + its specifiers. |
|
|
130
125
|
| `jsdoc` (opt-in) | `format/jsdoc` | Normalize JSDoc blocks toward [prettier-plugin-jsdoc](https://github.com/hosseinmd/prettier-plugin-jsdoc). |
|
|
131
126
|
|
|
132
|
-
`format/sort-imports` and `format/jsdoc` are **opt-in
|
|
127
|
+
`format/sort-imports` and `format/jsdoc` are **opt-in**. They only activate when you set `importOrder` or `jsdoc`. Every other format rule turns on automatically as soon as the `format` block is present.
|
|
133
128
|
|
|
134
|
-
To override a single format rule, drop a sibling `rules` entry
|
|
129
|
+
To override a single format rule, drop a sibling `rules` entry, `rules` wins on conflict:
|
|
135
130
|
|
|
136
131
|
```ts
|
|
137
132
|
export default {
|
|
@@ -156,21 +151,21 @@ export default {
|
|
|
156
151
|
} satisfies ITtscLintConfig;
|
|
157
152
|
```
|
|
158
153
|
|
|
159
|
-
Rule IDs use ESLint-style kebab-case and slash namespaces
|
|
154
|
+
Rule IDs use ESLint-style kebab-case and slash namespaces, `no-var`, `react/jsx-key`, `testing-library/prefer-screen-queries`. The exported `ITtscLintRules` type is the intersection of family-specific interfaces such as `ITtscLintCoreRules`, `ITtscLintTypeScriptRules`, `ITtscLintReactRules`, and `ITtscLintVitestRules`, so users can type a whole config or a narrower family-shaped object.
|
|
160
155
|
|
|
161
156
|
Each rule below links to its TypeScript fixture under [`tests/test-lint/src/cases/`](https://github.com/samchon/ttsc/tree/master/tests/test-lint/src/cases).
|
|
162
157
|
|
|
163
158
|
<!--
|
|
164
|
-
AGENT INSTRUCTIONS
|
|
159
|
+
AGENT INSTRUCTIONS, adding a new rule family or a new rule.
|
|
165
160
|
|
|
166
161
|
Family section shape (one `### <Family display name>` heading per family, alphabetical
|
|
167
162
|
by display name):
|
|
168
163
|
|
|
169
164
|
### <Family display name>
|
|
170
165
|
|
|
171
|
-
<One-sentence summary of what this family covers
|
|
166
|
+
<One-sentence summary of what this family covers, the "what".>
|
|
172
167
|
|
|
173
|
-
<One short paragraph elaborating
|
|
168
|
+
<One short paragraph elaborating, the "why" / scope notes / known limits.>
|
|
174
169
|
|
|
175
170
|
Source: [`<upstream-package>`](https://github.com/<org>/<repo>), [optional second source](https://…).
|
|
176
171
|
|
|
@@ -178,7 +173,7 @@ by display name):
|
|
|
178
173
|
|
|
179
174
|
Rules:
|
|
180
175
|
|
|
181
|
-
- Bullet shape is `- [\`<rule-id>\`](url): description
|
|
176
|
+
- Bullet shape is `- [\`<rule-id>\`](url): description.`: colon as separator, lowercase
|
|
182
177
|
description, ending in a period. No em-dash separator. Bullets sort alphabetically
|
|
183
178
|
by rule id within the family.
|
|
184
179
|
- The fixture path is `tests/test-lint/src/cases/<rule-id>.ts` for core rules,
|
|
@@ -196,17 +191,16 @@ Rules:
|
|
|
196
191
|
joined the family list.
|
|
197
192
|
-->
|
|
198
193
|
|
|
199
|
-
|
|
200
194
|
### ESLint core
|
|
201
195
|
|
|
202
|
-
Generic ESLint-compatible rules that apply to both JavaScript and TypeScript source. Every rule listed here corresponds 1-to-1 with an ESLint core rule of the same kebab-case id, so projects migrating from ESLint can paste their rule severities into `lint.config.ts` without renaming anything. TypeScript-only rules and `@typescript-eslint` extensions live under `typescript/*` in [TypeScript](#typescript)
|
|
196
|
+
Generic ESLint-compatible rules that apply to both JavaScript and TypeScript source. Every rule listed here corresponds 1-to-1 with an ESLint core rule of the same kebab-case id, so projects migrating from ESLint can paste their rule severities into `lint.config.ts` without renaming anything. TypeScript-only rules and `@typescript-eslint` extensions live under `typescript/*` in [TypeScript](#typescript), `@ttsc/lint` does not accept legacy bare names or `@typescript-eslint/*` aliases for those.
|
|
203
197
|
|
|
204
198
|
Source: [ESLint core rules](https://eslint.org/docs/latest/rules/).
|
|
205
199
|
|
|
206
|
-
- [`camelcase`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/camelcase.ts): reject identifier declarations that aren't camelCase or PascalCase
|
|
200
|
+
- [`camelcase`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/camelcase.ts): reject identifier declarations that aren't camelCase or PascalCase, snake_case bindings are flagged.
|
|
207
201
|
- [`complexity`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/complexity.ts): reject function bodies whose cyclomatic complexity exceeds twenty (default ESLint threshold).
|
|
208
202
|
- [`consistent-return`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/consistent-return.ts): reject functions where some `return` statements return a value and others fall through without one.
|
|
209
|
-
- [`curly`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/curly.ts): require block statements for every `if`, `else`, `while`, `for`, and `do` body
|
|
203
|
+
- [`curly`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/curly.ts): require block statements for every `if`, `else`, `while`, `for`, and `do` body. Reject the single-statement shorthand.
|
|
210
204
|
- [`default-case`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/default-case.ts): require `switch` statements to include a `default` clause.
|
|
211
205
|
- [`default-case-last`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/default-case-last.ts): require the `default` clause of a `switch` statement to appear last.
|
|
212
206
|
- [`default-param-last`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/default-param-last.ts): keeps parameters with default values at the end of the list.
|
|
@@ -313,7 +307,7 @@ Source: [ESLint core rules](https://eslint.org/docs/latest/rules/).
|
|
|
313
307
|
- [`no-undef-init`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-undef-init.ts): rejects initializing to `undefined`.
|
|
314
308
|
- [`no-undefined`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-undefined.ts): rejects the global `undefined` identifier.
|
|
315
309
|
- [`no-unneeded-ternary`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unneeded-ternary.ts): rejects redundant ternary expressions.
|
|
316
|
-
- [`no-unreachable`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unreachable.ts): reject statements that follow an unconditional `return`, `throw`, `break`, or `continue` in the same block
|
|
310
|
+
- [`no-unreachable`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unreachable.ts): reject statements that follow an unconditional `return`, `throw`, `break`, or `continue` in the same block, control flow has already left the block, so any later statement is dead code.
|
|
317
311
|
- [`no-unsafe-finally`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unsafe-finally.ts): rejects control flow from `finally`.
|
|
318
312
|
- [`no-unsafe-negation`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unsafe-negation.ts): rejects unsafe negation before relational checks.
|
|
319
313
|
- [`no-unsafe-optional-chaining`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unsafe-optional-chaining.ts): reject member access or call expressions that chain off an optional chain without continuing the chain.
|
|
@@ -332,16 +326,16 @@ Source: [ESLint core rules](https://eslint.org/docs/latest/rules/).
|
|
|
332
326
|
- [`no-with`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-with.ts): rejects `with` statements.
|
|
333
327
|
- [`object-shorthand`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/object-shorthand.ts): requires object property shorthand where possible.
|
|
334
328
|
- [`operator-assignment`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/operator-assignment.ts): prefers compound assignment operators.
|
|
335
|
-
- [`prefer-arrow-callback`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-arrow-callback.ts): reject `function() { ... }` expressions passed as callback arguments
|
|
329
|
+
- [`prefer-arrow-callback`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-arrow-callback.ts): reject `function() { ... }` expressions passed as callback arguments. Prefer the arrow form.
|
|
336
330
|
- [`prefer-const`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-const.ts): prefers `const` for `let` bindings that are never reassigned.
|
|
337
331
|
- [`prefer-destructuring`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-destructuring.ts): reject single-property and single-index variable declarations (`const a = obj.a`, `const x = arr[0]`) that destructuring would replace verbatim.
|
|
338
332
|
- [`prefer-exponentiation-operator`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-exponentiation-operator.ts): prefers `**` over `Math.pow`.
|
|
339
333
|
- [`prefer-for-of`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-for-of.ts): prefers `for...of` for simple array iteration.
|
|
340
|
-
- [`prefer-named-capture-group`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-named-capture-group.ts): reject regex literals with unnamed capturing groups `(...)
|
|
334
|
+
- [`prefer-named-capture-group`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-named-capture-group.ts): reject regex literals with unnamed capturing groups `(...)`. Prefer named groups `(?<name>...)`.
|
|
341
335
|
- [`prefer-numeric-literals`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-numeric-literals.ts): prefer ES2015+ numeric literal forms (`0b…`, `0o…`, `0x…`) over `parseInt(string, 2 | 8 | 16)`.
|
|
342
336
|
- [`prefer-object-has-own`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-object-has-own.ts): prefer `Object.hasOwn(obj, key)` over `Object.prototype.hasOwnProperty.call(obj, key)`.
|
|
343
337
|
- [`prefer-object-spread`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-object-spread.ts): prefer object-spread `{ ...a, ...b }` over `Object.assign({}, a, b)`.
|
|
344
|
-
- [`prefer-rest-params`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-rest-params.ts): reject reading from `arguments` in a non-arrow function body
|
|
338
|
+
- [`prefer-rest-params`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-rest-params.ts): reject reading from `arguments` in a non-arrow function body. Prefer the ES2015 rest-parameter form `(...args)`.
|
|
345
339
|
- [`prefer-spread`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-spread.ts): prefers spread arguments over `.apply`.
|
|
346
340
|
- [`prefer-template`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-template.ts): prefers template literals over string concatenation.
|
|
347
341
|
- [`radix`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/radix.ts): requires a radix argument for `parseInt`.
|
|
@@ -378,7 +372,7 @@ Source: [`typescript-eslint`](https://github.com/typescript-eslint/typescript-es
|
|
|
378
372
|
- [`typescript/no-array-for-each`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-array-for-each.ts): prefer `for ... of` over `Array.prototype.forEach()`.
|
|
379
373
|
- [`typescript/no-base-to-string`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-base-to-string.ts): rejects string coercion of values whose `toString` resolves to the default `Object.prototype.toString` (type-aware).
|
|
380
374
|
- [`typescript/no-confusing-non-null-assertion`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-confusing-non-null-assertion.ts): rejects confusing non-null assertions next to equality checks.
|
|
381
|
-
- [`typescript/no-confusing-void-expression`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-confusing-void-expression.ts): reject `void X` expressions used in any position where the surrounding context expects a value
|
|
375
|
+
- [`typescript/no-confusing-void-expression`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-confusing-void-expression.ts): reject `void X` expressions used in any position where the surrounding context expects a value, initializer, call argument, `return` operand, conditional, binary, or ternary subexpression.
|
|
382
376
|
- [`typescript/no-deprecated`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-deprecated.ts): reject references to declarations annotated `@deprecated` in their JSDoc, with the deprecation comment surfaced at the reference site (type-aware).
|
|
383
377
|
- [`typescript/no-duplicate-enum-values`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-duplicate-enum-values.ts): rejects duplicate enum member values.
|
|
384
378
|
- [`typescript/no-dynamic-delete`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-dynamic-delete.ts): rejects `delete` on dynamically computed property keys.
|
|
@@ -387,13 +381,13 @@ Source: [`typescript-eslint`](https://github.com/typescript-eslint/typescript-es
|
|
|
387
381
|
- [`typescript/no-explicit-any`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-explicit-any.ts): rejects explicit `any`.
|
|
388
382
|
- [`typescript/no-extra-non-null-assertion`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-extra-non-null-assertion.ts): rejects repeated non-null assertions.
|
|
389
383
|
- [`typescript/no-extraneous-class`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-extraneous-class.ts): reject classes that exist purely as a namespace for static members or that are entirely empty.
|
|
390
|
-
- [`typescript/no-floating-promises`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-floating-promises.ts): reject Promise-typed expressions whose result is discarded
|
|
384
|
+
- [`typescript/no-floating-promises`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-floating-promises.ts): reject Promise-typed expressions whose result is discarded, most often a bare `getPromise();` expression statement.
|
|
391
385
|
- [`typescript/no-for-in-array`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-for-in-array.ts): reject `for (const k in arr)` where `arr` is statically typed as an array or tuple.
|
|
392
386
|
- [`typescript/no-import-type-side-effects`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-import-type-side-effects/violation.ts): hoists inline `type` modifiers into a single `import type` declaration.
|
|
393
387
|
- [`typescript/no-inferrable-types`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-inferrable-types.ts): rejects type annotations TypeScript can infer.
|
|
394
388
|
- [`typescript/no-invalid-void-type`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-invalid-void-type.ts): reject `void` used as anything other than a function return type.
|
|
395
389
|
- [`typescript/no-magic-numbers`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-magic-numbers.ts): typeScript-aware extension of `no-magic-numbers` that additionally ignores enum member values.
|
|
396
|
-
- [`typescript/no-meaningless-void-operator`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-meaningless-void-operator.ts): reject `void X` where `X` is already statically typed `void
|
|
390
|
+
- [`typescript/no-meaningless-void-operator`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-meaningless-void-operator.ts): reject `void X` where `X` is already statically typed `void`, the operator adds nothing because the operand already evaluates to `undefined` (type-aware).
|
|
397
391
|
- [`typescript/no-misused-new`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-misused-new.ts): rejects constructor-like signatures in interfaces.
|
|
398
392
|
- [`typescript/no-misused-promises`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-misused-promises.ts): reject Promise values supplied where a non-Promise was expected.
|
|
399
393
|
- [`typescript/no-misused-spread`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-misused-spread.ts): reject spread expressions whose operand is syntactically wrong for the surrounding context.
|
|
@@ -402,33 +396,33 @@ Source: [`typescript-eslint`](https://github.com/typescript-eslint/typescript-es
|
|
|
402
396
|
- [`typescript/no-non-null-asserted-nullish-coalescing`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-non-null-asserted-nullish-coalescing.ts): rejects non-null assertions next to `??`.
|
|
403
397
|
- [`typescript/no-non-null-asserted-optional-chain`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-non-null-asserted-optional-chain.ts): rejects non-null assertions on optional chains.
|
|
404
398
|
- [`typescript/no-non-null-assertion`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-non-null-assertion.ts): rejects postfix non-null assertions.
|
|
405
|
-
- [`typescript/no-redundant-type-constituents`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-redundant-type-constituents.ts): reject union and intersection type constituents that the type system absorbs anyway
|
|
399
|
+
- [`typescript/no-redundant-type-constituents`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-redundant-type-constituents.ts): reject union and intersection type constituents that the type system absorbs anyway, `string | any` collapses to `any`, `T & never` collapses to `never`, `T & unknown` collapses to `T`, and repeated constituents add nothing.
|
|
406
400
|
- [`typescript/no-require-imports`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-require-imports.ts): rejects CommonJS `require` imports.
|
|
407
|
-
- [`typescript/no-restricted-types`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-restricted-types.ts): reject specific type-reference names that are almost always a mistake
|
|
401
|
+
- [`typescript/no-restricted-types`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-restricted-types.ts): reject specific type-reference names that are almost always a mistake, by default the global wrapper types `Object`, `Function`, `Number`, `String`, and `Boolean`.
|
|
408
402
|
- [`typescript/no-this-alias`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-this-alias.ts): rejects aliasing `this` to locals.
|
|
409
|
-
- [`typescript/no-unnecessary-boolean-literal-compare`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-boolean-literal-compare.ts): reject direct comparison of a boolean-typed value with `true` / `false` literals
|
|
410
|
-
- [`typescript/no-unnecessary-condition`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-condition.ts): reject conditions whose static type proves the runtime truthiness is fixed
|
|
403
|
+
- [`typescript/no-unnecessary-boolean-literal-compare`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-boolean-literal-compare.ts): reject direct comparison of a boolean-typed value with `true` / `false` literals, `x === true` is just `x`, `x !== false` is just `x`.
|
|
404
|
+
- [`typescript/no-unnecessary-condition`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-condition.ts): reject conditions whose static type proves the runtime truthiness is fixed, `if ({})`, `if (null)`, `while ("")`, `0 && f()` (type-aware).
|
|
411
405
|
- [`typescript/no-unnecessary-parameter-property-assignment`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unnecessary-parameter-property-assignment.ts): rejects constructor assignments already handled by parameter properties.
|
|
412
406
|
- [`typescript/no-unnecessary-qualifier`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-qualifier.ts): reject namespace/enum qualifiers that the surrounding scope makes unnecessary (type-aware).
|
|
413
|
-
- [`typescript/no-unnecessary-template-expression`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-template-expression.ts): reject template literals that collapse to a regular string
|
|
414
|
-
- [`typescript/no-unnecessary-type-arguments`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-type-arguments.ts): reject `Foo<DefaultT>` calls where the supplied generic argument is the same as the parameter's default
|
|
415
|
-
- [`typescript/no-unnecessary-type-assertion`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-type-assertion.ts): reject `x as T`, `<T>x`, and `x!` assertions whose target type is the same as `x`'s already-known static type
|
|
407
|
+
- [`typescript/no-unnecessary-template-expression`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-template-expression.ts): reject template literals that collapse to a regular string, `` `${"abc"}` ``, `` `${name}` `` around a string-typed value, or a plain `` `abc` `` with no escaped backticks (type-aware).
|
|
408
|
+
- [`typescript/no-unnecessary-type-arguments`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-type-arguments.ts): reject `Foo<DefaultT>` calls where the supplied generic argument is the same as the parameter's default, the argument adds nothing (type-aware).
|
|
409
|
+
- [`typescript/no-unnecessary-type-assertion`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unnecessary-type-assertion.ts): reject `x as T`, `<T>x`, and `x!` assertions whose target type is the same as `x`'s already-known static type, the assertion adds nothing (type-aware).
|
|
416
410
|
- [`typescript/no-unnecessary-type-constraint`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unnecessary-type-constraint.ts): rejects redundant `extends any` and `extends unknown` constraints.
|
|
417
411
|
- [`typescript/no-unsafe-argument`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-argument.ts): reject passing an `any`-typed value to a parameter whose declared type is concrete (type-aware).
|
|
418
412
|
- [`typescript/no-unsafe-assignment`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-assignment.ts): reject assigning an `any`-typed value to a variable, parameter, or property whose declared type is concrete (type-aware).
|
|
419
413
|
- [`typescript/no-unsafe-call`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-call.ts): reject calling a value whose static type is `any` (type-aware).
|
|
420
414
|
- [`typescript/no-unsafe-declaration-merging`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unsafe-declaration-merging.ts): rejects unsafe class/interface declaration merging.
|
|
421
|
-
- [`typescript/no-unsafe-enum-comparison`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-enum-comparison.ts): reject `==` / `===` / `!=` / `!==` comparisons between an enum-typed value and a plain `number` or `string` of the same widened primitive
|
|
415
|
+
- [`typescript/no-unsafe-enum-comparison`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-enum-comparison.ts): reject `==` / `===` / `!=` / `!==` comparisons between an enum-typed value and a plain `number` or `string` of the same widened primitive, the comparison silently accepts unrelated enums and raw literals that happen to share the underlying primitive (type-aware).
|
|
422
416
|
- [`typescript/no-unsafe-function-type`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-unsafe-function-type.ts): rejects the unsafe `Function` type.
|
|
423
417
|
- [`typescript/no-unsafe-member-access`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-member-access.ts): reject member access on a value whose static type is `any` (type-aware).
|
|
424
|
-
- [`typescript/no-unsafe-return`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-return.ts): reject a `return` expression whose static type is `any` from a function whose declared return type is a concrete (non-`any` / non-`unknown` / non-`void`) shape
|
|
425
|
-
- [`typescript/no-unsafe-unary-minus`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-unary-minus.ts): reject the unary `-` operator applied to an operand whose static type is not number-like or bigint-like
|
|
418
|
+
- [`typescript/no-unsafe-return`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-return.ts): reject a `return` expression whose static type is `any` from a function whose declared return type is a concrete (non-`any` / non-`unknown` / non-`void`) shape, the `any` leaks past the type boundary and disables every downstream check on the returned value (type-aware).
|
|
419
|
+
- [`typescript/no-unsafe-unary-minus`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-unsafe-unary-minus.ts): reject the unary `-` operator applied to an operand whose static type is not number-like or bigint-like, `-x` silently coerces strings, objects, and other shapes via `Number(x)` and almost always indicates a bug (type-aware).
|
|
426
420
|
- [`typescript/no-useless-constructor`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-no-useless-constructor.ts): typeScript-aware extension of `no-useless-constructor` that tolerates a constructor existing solely to expose parameter properties.
|
|
427
421
|
- [`typescript/no-useless-empty-export`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-useless-empty-export.ts): rejects redundant empty `export {}` declarations in module files.
|
|
428
422
|
- [`typescript/no-wrapper-object-types`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/no-wrapper-object-types.ts): rejects boxed object type names such as `String` and `Boolean`.
|
|
429
|
-
- [`typescript/non-nullable-type-assertion-style`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/non-nullable-type-assertion-style.ts): reject `x as Foo` assertions whose target type is the non-nullable version of `x`'s static type
|
|
430
|
-
- [`typescript/only-throw-error`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/only-throw-error.ts): reject `throw X` where `X` is statically known not to derive from `Error
|
|
431
|
-
- [`typescript/parameter-properties`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-parameter-properties.ts): reject TypeScript parameter-property constructors (`constructor(public foo: T)`)
|
|
423
|
+
- [`typescript/non-nullable-type-assertion-style`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/non-nullable-type-assertion-style.ts): reject `x as Foo` assertions whose target type is the non-nullable version of `x`'s static type. Replace with the shorter `x!` non-null assertion.
|
|
424
|
+
- [`typescript/only-throw-error`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/only-throw-error.ts): reject `throw X` where `X` is statically known not to derive from `Error`, string literals, numbers, plain object literals, and the like.
|
|
425
|
+
- [`typescript/parameter-properties`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-parameter-properties.ts): reject TypeScript parameter-property constructors (`constructor(public foo: T)`). Prefer plain field declarations so the class shape is visible from the member list instead of buried inside the constructor parameter list.
|
|
432
426
|
- [`typescript/prefer-as-const`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-as-const.ts): prefers `as const` for literal assertions.
|
|
433
427
|
- [`typescript/prefer-enum-initializers`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-enum-initializers.ts): requires explicit enum member initializers.
|
|
434
428
|
- [`typescript/prefer-find`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-find.ts): prefer `array.find(predicate)` over `array.filter(predicate)[0]` / `.shift()` when only the first match is needed.
|
|
@@ -438,18 +432,18 @@ Source: [`typescript-eslint`](https://github.com/typescript-eslint/typescript-es
|
|
|
438
432
|
- [`typescript/prefer-namespace-keyword`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/prefer-namespace-keyword.ts): prefers `namespace` over TypeScript's legacy `module` keyword.
|
|
439
433
|
- [`typescript/prefer-nullish-coalescing`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-nullish-coalescing.ts): prefer `??` over `||` (and `??=` over `||=`, and `??` over the ternary `x ? x : y`) when the intent is to default `null` / `undefined`.
|
|
440
434
|
- [`typescript/prefer-optional-chain`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-optional-chain.ts): prefer an optional chain (`a?.b?.c`) over chained boolean guards such as `a && a.b && a.b.c` or `a != null && a.b`.
|
|
441
|
-
- [`typescript/prefer-promise-reject-errors`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-promise-reject-errors.ts): reject `Promise.reject(value)` where `value` is statically known not to derive from `Error
|
|
435
|
+
- [`typescript/prefer-promise-reject-errors`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-promise-reject-errors.ts): reject `Promise.reject(value)` where `value` is statically known not to derive from `Error`, type-aware analog of `only-throw-error` for the rejection side of the promise contract.
|
|
442
436
|
- [`typescript/prefer-readonly`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-readonly.ts): reject private class fields that could carry `readonly`.
|
|
443
437
|
- [`typescript/prefer-reduce-type-parameter`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-reduce-type-parameter.ts): prefer `arr.reduce<T>(..., initial)` over `arr.reduce(..., initial as T)` so the accumulator type is set on the call site instead of widened away inside the assertion (type-aware).
|
|
444
|
-
- [`typescript/prefer-regexp-exec`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-regexp-exec.ts): prefer `regex.exec(str)` over `str.match(regex)` when the regex carries the `g` flag
|
|
438
|
+
- [`typescript/prefer-regexp-exec`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-regexp-exec.ts): prefer `regex.exec(str)` over `str.match(regex)` when the regex carries the `g` flag, `.match` returns only the matched substrings and discards capture groups.
|
|
445
439
|
- [`typescript/prefer-return-this-type`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-return-this-type.ts): prefer the explicit `this` return type for chainable methods so fluent subclasses preserve their concrete `this` instead of widening to the base.
|
|
446
440
|
- [`typescript/prefer-string-starts-ends-with`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-prefer-string-starts-ends-with.ts): prefer `str.startsWith(p)` / `str.endsWith(p)` over `str.indexOf(p) === 0`, `str.indexOf(p, str.length - p.length) !== -1`, `str.lastIndexOf(p) === str.length - p.length`, and the anchored-regex `/^p/.test(str)` / `/p$/.test(str)` idioms (type-aware).
|
|
447
441
|
- [`typescript/promise-function-async`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-promise-function-async.ts): require functions whose return type is `Promise<T>` to be declared with the `async` keyword so synchronous throws surface as a rejected Promise (type-aware).
|
|
448
|
-
- [`typescript/related-getter-setter-pairs`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-related-getter-setter-pairs.ts): reject a `get` accessor whose declared return type does not match the parameter type of its companion `set` accessor on the same class
|
|
442
|
+
- [`typescript/related-getter-setter-pairs`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-related-getter-setter-pairs.ts): reject a `get` accessor whose declared return type does not match the parameter type of its companion `set` accessor on the same class, readers should not observe a type the writer cannot accept (type-aware).
|
|
449
443
|
- [`typescript/require-array-sort-compare`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-require-array-sort-compare.ts): require `arr.sort()` and `arr.toSorted()` calls to pass an explicit `compareFunction`.
|
|
450
444
|
- [`typescript/require-await`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/require-await.ts): reject `async` functions whose body contains no `await` expression.
|
|
451
445
|
- [`typescript/restrict-plus-operands`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-restrict-plus-operands.ts): rejects `+` expressions whose operands are not both `number`, both `string`, or both `bigint` (type-aware).
|
|
452
|
-
- [`typescript/restrict-template-expressions`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-restrict-template-expressions.ts): reject template-literal interpolations whose expression carries a type that does not stringify cleanly
|
|
446
|
+
- [`typescript/restrict-template-expressions`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-restrict-template-expressions.ts): reject template-literal interpolations whose expression carries a type that does not stringify cleanly, `${obj}` prints `"[object Object]"`, `${null}` prints `"null"`, and so on.
|
|
453
447
|
- [`typescript/return-await`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/return-await.ts): reject `return promise` inside `try`, `catch`, or `finally`; require `return await promise`.
|
|
454
448
|
- [`typescript/sort-type-constituents`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-sort-type-constituents.ts): sort the members of union (`A | B | C`) and intersection (`A & B & C`) types into a canonical order so reorderings don't show up as diffs.
|
|
455
449
|
- [`typescript/strict-boolean-expressions`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/typescript-strict-boolean-expressions.ts): rejects non-boolean values used in a boolean context such as `if`, `&&`, `||`, or `!` (type-aware).
|
|
@@ -460,13 +454,13 @@ Source: [`typescript-eslint`](https://github.com/typescript-eslint/typescript-es
|
|
|
460
454
|
|
|
461
455
|
### React
|
|
462
456
|
|
|
463
|
-
React TSX rules
|
|
457
|
+
React TSX rules, Hooks correctness, JSX safety, the React Compiler subset, and Fast Refresh export shape. Bundles rules from three upstream plugins under one `react/*` namespace, matching Oxlint's layout. Performance-only rules live in [React performance](#react-performance) because they are opt-in toggles rather than correctness checks.
|
|
464
458
|
|
|
465
459
|
Source: [`eslint-plugin-react`](https://github.com/jsx-eslint/eslint-plugin-react), [`eslint-plugin-react-hooks`](https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks), [`eslint-plugin-react-refresh`](https://github.com/ArnaudBarre/eslint-plugin-react-refresh).
|
|
466
460
|
|
|
467
461
|
- [`react/button-has-type`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-button-has-type.tsx): requires explicit valid `type` values on JSX `button` elements.
|
|
468
462
|
- [`react/component-hook-factories`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-component-hook-factories.tsx): rejects nested component or Hook factories that call Hooks.
|
|
469
|
-
- [`react/display-name`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-display-name.tsx): require components wrapped in `React.memo(...)` or `React.forwardRef(...)` to be named
|
|
463
|
+
- [`react/display-name`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-display-name.tsx): require components wrapped in `React.memo(...)` or `React.forwardRef(...)` to be named, either by passing a named function, assigning the call to a named binding, or setting an explicit `displayName`.
|
|
470
464
|
- [`react/exhaustive-deps`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-exhaustive-deps.tsx): reports high-confidence missing identifier dependencies in `useEffect`, `useLayoutEffect`, `useInsertionEffect`, `useMemo`, and `useCallback`.
|
|
471
465
|
- [`react/iframe-missing-sandbox`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-iframe-missing-sandbox.tsx): requires JSX `iframe` elements to include a sandbox attribute.
|
|
472
466
|
- [`react/immutability`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-immutability.tsx): rejects local prop mutation inside components and Hooks.
|
|
@@ -475,7 +469,7 @@ Source: [`eslint-plugin-react`](https://github.com/jsx-eslint/eslint-plugin-reac
|
|
|
475
469
|
- [`react/jsx-no-script-url`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-jsx-no-script-url.tsx): rejects `javascript:` URLs in JSX URL-like props.
|
|
476
470
|
- [`react/jsx-no-target-blank`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-jsx-no-target-blank.tsx): reject `<a target="_blank">` (or any JSX element with `target="_blank"`) that does not also carry `rel="noreferrer"` (or `rel="noopener noreferrer"`).
|
|
477
471
|
- [`react/jsx-no-undef`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-jsx-no-undef.tsx): reject JSX elements whose tag is an uppercase identifier with no value-level declaration anywhere in the source file.
|
|
478
|
-
- [`react/jsx-no-useless-fragment`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-jsx-no-useless-fragment.tsx): reject JSX fragments that wrap exactly one element child or have no meaningful content
|
|
472
|
+
- [`react/jsx-no-useless-fragment`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-jsx-no-useless-fragment.tsx): reject JSX fragments that wrap exactly one element child or have no meaningful content. The child (or nothing) can be returned directly.
|
|
479
473
|
- [`react/no-array-index-key`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-no-array-index-key.tsx): rejects array map index parameters as JSX keys.
|
|
480
474
|
- [`react/no-children-prop`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-no-children-prop.tsx): rejects passing children through a JSX `children` prop.
|
|
481
475
|
- [`react/no-danger`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/react-no-danger.tsx): rejects `dangerouslySetInnerHTML`.
|
|
@@ -496,7 +490,7 @@ Source: [`eslint-plugin-react`](https://github.com/jsx-eslint/eslint-plugin-reac
|
|
|
496
490
|
|
|
497
491
|
### React performance
|
|
498
492
|
|
|
499
|
-
Detects freshly-allocated reference values (arrays, objects, functions, JSX elements) passed as JSX props. A new reference invalidates `React.memo` / `useMemo` shallow checks on every render. Useful for performance-critical render paths; usually unnecessary for top-level pages. Diagnostics only fire on `.tsx` source files
|
|
493
|
+
Detects freshly-allocated reference values (arrays, objects, functions, JSX elements) passed as JSX props. A new reference invalidates `React.memo` / `useMemo` shallow checks on every render. Useful for performance-critical render paths; usually unnecessary for top-level pages. Diagnostics only fire on `.tsx` source files, JSX heuristics rely on the file extension, so `.ts` files are skipped even when they contain JSX-like syntax.
|
|
500
494
|
|
|
501
495
|
Source: [`eslint-plugin-react-perf`](https://github.com/cvazac/eslint-plugin-react-perf).
|
|
502
496
|
|
|
@@ -507,7 +501,7 @@ Source: [`eslint-plugin-react-perf`](https://github.com/cvazac/eslint-plugin-rea
|
|
|
507
501
|
|
|
508
502
|
### JSX accessibility
|
|
509
503
|
|
|
510
|
-
JSX accessibility rules applied to TSX (and JSX-in-TS) sources. Checks the static structure of JSX elements against WAI-ARIA authoring guidance
|
|
504
|
+
JSX accessibility rules applied to TSX (and JSX-in-TS) sources. Checks the static structure of JSX elements against WAI-ARIA authoring guidance, interactive controls should be focusable, labels should reference a control, ARIA properties should match the element role, and so on. Runtime accessibility issues require live audits; this family catches the statically-decidable subset. Component alias settings, router-specific anchor settings, and autofixes are deferred.
|
|
511
505
|
|
|
512
506
|
Source: [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y).
|
|
513
507
|
|
|
@@ -526,7 +520,7 @@ Source: [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-j
|
|
|
526
520
|
- [`jsx-a11y/heading-has-content`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/jsx-a11y-heading-has-content.tsx): rejects empty JSX headings.
|
|
527
521
|
- [`jsx-a11y/html-has-lang`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/jsx-a11y-html-has-lang.tsx): requires `<html>` JSX elements to declare a non-empty `lang` attribute.
|
|
528
522
|
- [`jsx-a11y/iframe-has-title`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/jsx-a11y-iframe-has-title.tsx): requires every `<iframe>` JSX element to declare a non-empty, unique `title`.
|
|
529
|
-
- [`jsx-a11y/img-redundant-alt`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/jsx-a11y-img-redundant-alt.tsx): rejects redundant words such as
|
|
523
|
+
- [`jsx-a11y/img-redundant-alt`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/jsx-a11y-img-redundant-alt.tsx): rejects redundant words such as _image_, _photo_, or _picture_ inside the `alt` attribute of an `<img>`.
|
|
530
524
|
- [`jsx-a11y/interactive-supports-focus`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/jsx-a11y-interactive-supports-focus.tsx): requires elements with interactive ARIA roles to be focusable.
|
|
531
525
|
- [`jsx-a11y/label-has-associated-control`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/jsx-a11y-label-has-associated-control.tsx): requires `<label>` elements to wrap a form control or reference one via `htmlFor`.
|
|
532
526
|
- [`jsx-a11y/label-has-for`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/jsx-a11y-label-has-for.tsx): deprecated predecessor of `label-has-associated-control` that checks the same nesting / `htmlFor` association requirement.
|
|
@@ -551,7 +545,7 @@ Source: [`eslint-plugin-jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-j
|
|
|
551
545
|
|
|
552
546
|
### Next.js
|
|
553
547
|
|
|
554
|
-
Next.js framework rules applied to TypeScript and TSX sources inside Next.js apps. Cover static TS/TSX Next.js source patterns the framework's runtime treats as load-bearing
|
|
548
|
+
Next.js framework rules applied to TypeScript and TSX sources inside Next.js apps. Cover static TS/TSX Next.js source patterns the framework's runtime treats as load-bearing, pages/app routing, `<Head>` placement, font and script loading, image and link components, and common data export typos. Rules that need non-TypeScript files or runtime filesystem route discovery are intentionally conservative.
|
|
555
549
|
|
|
556
550
|
Source: [`@next/eslint-plugin-next`](https://github.com/vercel/next.js/tree/canary/packages/eslint-plugin-next).
|
|
557
551
|
|
|
@@ -603,11 +597,11 @@ Source: [`eslint-plugin-solid`](https://github.com/solidjs-community/eslint-plug
|
|
|
603
597
|
- [`solid/reactivity`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/solid-reactivity.tsx): flag bare signal accessors that break fine-grained reactivity tracking.
|
|
604
598
|
- [`solid/self-closing-comp`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/solid-self-closing-comp.tsx): require empty JSX components to use the self-closing form.
|
|
605
599
|
- [`solid/style-prop`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/solid-style-prop.tsx): reject camelCased CSS keys in JSX `style` object literals.
|
|
606
|
-
- [`solid/validate-jsx-nesting`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/solid-validate-jsx-nesting.tsx): reject JSX nestings that the HTML parser would silently restructure at runtime
|
|
600
|
+
- [`solid/validate-jsx-nesting`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/solid-validate-jsx-nesting.tsx): reject JSX nestings that the HTML parser would silently restructure at runtime, `<p>` cannot contain block-level children, `<a>` cannot contain another `<a>`, and `<button>` cannot contain other interactive elements.
|
|
607
601
|
|
|
608
602
|
### Jest
|
|
609
603
|
|
|
610
|
-
Jest test source rules. Apply to TypeScript test files that use the Jest runner (`describe`, `test`/`it`, `expect`, lifecycle hooks). Guard test-quality patterns the type system cannot detect
|
|
604
|
+
Jest test source rules. Apply to TypeScript test files that use the Jest runner (`describe`, `test`/`it`, `expect`, lifecycle hooks). Guard test-quality patterns the type system cannot detect, unended assertions, focused tests left behind, duplicate hook calls.
|
|
611
605
|
|
|
612
606
|
Source: [`eslint-plugin-jest`](https://github.com/jest-community/eslint-plugin-jest).
|
|
613
607
|
|
|
@@ -633,7 +627,7 @@ Source: [`eslint-plugin-jest`](https://github.com/jest-community/eslint-plugin-j
|
|
|
633
627
|
|
|
634
628
|
### Vitest
|
|
635
629
|
|
|
636
|
-
Vitest test source rules. Vitest reuses much of Jest's testing surface but ships its own runner and configuration. These rules mirror the ergonomic subset of `eslint-plugin-jest` adapted for Vitest semantics
|
|
630
|
+
Vitest test source rules. Vitest reuses much of Jest's testing surface but ships its own runner and configuration. These rules mirror the ergonomic subset of `eslint-plugin-jest` adapted for Vitest semantics, focused or disabled tests, duplicate titles, missing or conditional assertions, standalone `expect` calls, done callbacks, invalid `expect` chains, invalid titles, returned test values, and `.length` assertions that should use `toHaveLength`.
|
|
637
631
|
|
|
638
632
|
Source: [`@vitest/eslint-plugin`](https://github.com/vitest-dev/eslint-plugin-vitest).
|
|
639
633
|
|
|
@@ -689,7 +683,7 @@ Source: [`eslint-plugin-testing-library`](https://github.com/testing-library/esl
|
|
|
689
683
|
|
|
690
684
|
### Playwright
|
|
691
685
|
|
|
692
|
-
Playwright end-to-end test rules applied to TypeScript test files driven by the `@playwright/test` runner. Guard Playwright-specific patterns
|
|
686
|
+
Playwright end-to-end test rules applied to TypeScript test files driven by the `@playwright/test` runner. Guard Playwright-specific patterns, locator usage, web-first assertions, focused/slowed tests. That would otherwise compile and run silently.
|
|
693
687
|
|
|
694
688
|
Source: [`eslint-plugin-playwright`](https://github.com/playwright-community/eslint-plugin-playwright).
|
|
695
689
|
|
|
@@ -785,7 +779,7 @@ Source: [`@tanstack/eslint-plugin-query`](https://github.com/TanStack/query/tree
|
|
|
785
779
|
|
|
786
780
|
### Promise
|
|
787
781
|
|
|
788
|
-
Promise correctness and style rules. Check the chain shape of Promise-using code: every chain ends with `catch`, no callback inside a `then`, no nested `.then().then()`, and so on. AST-local only
|
|
782
|
+
Promise correctness and style rules. Check the chain shape of Promise-using code: every chain ends with `catch`, no callback inside a `then`, no nested `.then().then()`, and so on. AST-local only, type-aware Promise checks belong with `typescript/*` checker rules.
|
|
789
783
|
|
|
790
784
|
Source: [`eslint-plugin-promise`](https://github.com/eslint-community/eslint-plugin-promise).
|
|
791
785
|
|
|
@@ -831,7 +825,7 @@ Source: [`eslint-plugin-unicorn`](https://github.com/sindresorhus/eslint-plugin-
|
|
|
831
825
|
- [`unicorn/filename-case`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-filename-case.ts): enforce a single case style (kebab/camel/snake/pascal) for source filenames.
|
|
832
826
|
- [`unicorn/import-style`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-import-style.ts): restrict each module's allowed import styles (named only, default only, namespace only).
|
|
833
827
|
- [`unicorn/isolated-functions`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-isolated-functions.ts): reject references to outer-scope variables inside functions marked as isolated (e.g., the body of a web worker).
|
|
834
|
-
- [`unicorn/new-for-builtins`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-new-for-builtins.ts): require `new` when calling builtin constructors like `Error`, `Map`, `Set`, `Date
|
|
828
|
+
- [`unicorn/new-for-builtins`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-new-for-builtins.ts): require `new` when calling builtin constructors like `Error`, `Map`, `Set`, `Date`, and forbid `new` on primitive wrappers like `String`, `Number`, `Boolean`.
|
|
835
829
|
- [`unicorn/no-abusive-eslint-disable`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-abusive-eslint-disable.ts): require every `eslint-disable*` directive to name the rules it disables.
|
|
836
830
|
- [`unicorn/no-accessor-recursion`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-accessor-recursion.ts): reject recursive reads on `this.<prop>` inside the getter / setter for `<prop>`.
|
|
837
831
|
- [`unicorn/no-anonymous-default-export`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-anonymous-default-export.ts): require a name on every default-exported function, class, or object.
|
|
@@ -842,14 +836,14 @@ Source: [`eslint-plugin-unicorn`](https://github.com/sindresorhus/eslint-plugin-
|
|
|
842
836
|
- [`unicorn/no-array-reverse`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-array-reverse.ts): prefer `Array#toReversed` over the mutating `Array#reverse`.
|
|
843
837
|
- [`unicorn/no-array-sort`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-array-sort.ts): prefer `Array#toSorted` over the mutating `Array#sort`.
|
|
844
838
|
- [`unicorn/no-await-expression-member`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-await-expression-member.ts): reject member access on an `await` expression without parens; require `(await x).y`.
|
|
845
|
-
- [`unicorn/no-await-in-promise-methods`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-await-in-promise-methods.ts): reject `await` inside arrays passed to `Promise.all`/`Promise.allSettled`/`Promise.race`/`Promise.any
|
|
846
|
-
- [`unicorn/no-console-spaces`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-console-spaces.ts): reject leading or trailing spaces in arguments to `console.log` and friends
|
|
839
|
+
- [`unicorn/no-await-in-promise-methods`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-await-in-promise-methods.ts): reject `await` inside arrays passed to `Promise.all`/`Promise.allSettled`/`Promise.race`/`Promise.any`. The awaits serialize the calls.
|
|
840
|
+
- [`unicorn/no-console-spaces`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-console-spaces.ts): reject leading or trailing spaces in arguments to `console.log` and friends, `console` already inserts spaces between arguments.
|
|
847
841
|
- [`unicorn/no-document-cookie`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-document-cookie.ts): reject direct reads or assignments to `document.cookie`; use the Cookie Store API or a wrapper.
|
|
848
842
|
- [`unicorn/no-empty-file`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-empty-file.ts): reject source files whose only content is whitespace and/or comments.
|
|
849
843
|
- [`unicorn/no-for-loop`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-for-loop.ts): prefer `for...of` over index-based `for` loops over arrays.
|
|
850
844
|
- [`unicorn/no-hex-escape`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-hex-escape.ts): prefer Unicode escape (`©`) over hexadecimal escape (`\xA9`).
|
|
851
845
|
- [`unicorn/no-immediate-mutation`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-immediate-mutation.ts): reject mutating a value on the same expression that produces it (`[...x].push(y)`); separate the construction and the mutation.
|
|
852
|
-
- [`unicorn/no-instanceof-builtins`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-instanceof-builtins.ts): reject `instanceof Array`, `instanceof Error`, `instanceof Map`, etc
|
|
846
|
+
- [`unicorn/no-instanceof-builtins`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-instanceof-builtins.ts): reject `instanceof Array`, `instanceof Error`, `instanceof Map`, etc.. They fail across realms and for subclasses.
|
|
853
847
|
- [`unicorn/no-invalid-fetch-options`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-invalid-fetch-options.ts): reject GET / HEAD `fetch()` calls that also set a request `body`, which throws at runtime.
|
|
854
848
|
- [`unicorn/no-invalid-remove-event-listener`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-invalid-remove-event-listener.ts): reject `removeEventListener` calls whose handler argument is a fresh function reference and therefore matches no registered listener.
|
|
855
849
|
- [`unicorn/no-keyword-prefix`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-keyword-prefix.ts): reject identifiers that start with a reserved word (`newFoo`, `classBar`).
|
|
@@ -866,7 +860,7 @@ Source: [`eslint-plugin-unicorn`](https://github.com/sindresorhus/eslint-plugin-
|
|
|
866
860
|
- [`unicorn/no-process-exit`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-process-exit.ts): reject `process.exit()`; throw or return a non-zero status instead.
|
|
867
861
|
- [`unicorn/no-single-promise-in-promise-methods`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-single-promise-in-promise-methods.ts): reject `Promise.all`/`Promise.race`/etc. called with a single-element array; the wrapper is redundant.
|
|
868
862
|
- [`unicorn/no-static-only-class`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-static-only-class.ts): reject classes whose every member is `static`; use a plain module-level namespace instead.
|
|
869
|
-
- [`unicorn/no-thenable`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-thenable.ts): reject defining a property named `then` on objects, modules, or classes
|
|
863
|
+
- [`unicorn/no-thenable`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-thenable.ts): reject defining a property named `then` on objects, modules, or classes, `await` and Promise resolution accidentally invoke it.
|
|
870
864
|
- [`unicorn/no-this-assignment`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-this-assignment.ts): reject `const self = this` and similar aliases; capture via arrow functions instead.
|
|
871
865
|
- [`unicorn/no-typeof-undefined`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-typeof-undefined.ts): reject `typeof x === "undefined"`; compare against `undefined` directly.
|
|
872
866
|
- [`unicorn/no-unnecessary-array-flat-depth`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-unnecessary-array-flat-depth.ts): reject `1` as the explicit depth argument of `Array#flat`; the default is already `1`.
|
|
@@ -882,7 +876,7 @@ Source: [`eslint-plugin-unicorn`](https://github.com/sindresorhus/eslint-plugin-
|
|
|
882
876
|
- [`unicorn/no-useless-fallback-in-spread`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-useless-fallback-in-spread.ts): reject `...(x ?? {})` and similar fallbacks when spreading; the spread of `null`/`undefined` is already a no-op.
|
|
883
877
|
- [`unicorn/no-useless-iterator-to-array`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-useless-iterator-to-array.ts): reject `[...iterator]` / `Array.from(iterator)` when the iterator can be consumed directly (e.g., inside `for...of`).
|
|
884
878
|
- [`unicorn/no-useless-length-check`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-useless-length-check.ts): reject `arr.length` checks that the iteration method itself already handles.
|
|
885
|
-
- [`unicorn/no-useless-promise-resolve-reject`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-useless-promise-resolve-reject.ts): reject `return Promise.resolve(x)` / `return Promise.reject(e)` inside `async` functions
|
|
879
|
+
- [`unicorn/no-useless-promise-resolve-reject`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-useless-promise-resolve-reject.ts): reject `return Promise.resolve(x)` / `return Promise.reject(e)` inside `async` functions, `return x` and `throw e` work identically.
|
|
886
880
|
- [`unicorn/no-useless-spread`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-useless-spread.ts): reject spreading a single iterable into a new collection of the same kind (`[...arr]`, `{...obj}`) when the original would suffice.
|
|
887
881
|
- [`unicorn/no-useless-switch-case`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-useless-switch-case.ts): reject `case` clauses with an empty body that immediately precede a `default` whose body executes for them.
|
|
888
882
|
- [`unicorn/no-useless-undefined`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-no-useless-undefined.ts): reject explicit `undefined` returns, default initializers, and arguments where the omission has the same meaning.
|
|
@@ -957,12 +951,12 @@ Source: [`eslint-plugin-unicorn`](https://github.com/sindresorhus/eslint-plugin-
|
|
|
957
951
|
- [`unicorn/switch-case-braces`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-switch-case-braces.ts): enforce a consistent presence/absence of `{}` braces around `case` clauses inside `switch`.
|
|
958
952
|
- [`unicorn/switch-case-break-position`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-switch-case-break-position.ts): enforce a consistent position for `break` (or `return` / `throw`) inside `case` clauses.
|
|
959
953
|
- [`unicorn/template-indent`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-template-indent.ts): re-indent the body of tagged template literals (`html`, `gql`, `sql`) to the indentation of the opening backtick.
|
|
960
|
-
- [`unicorn/text-encoding-identifier-case`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-text-encoding-identifier-case.ts): enforce a canonical case for text-encoding identifiers
|
|
954
|
+
- [`unicorn/text-encoding-identifier-case`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-text-encoding-identifier-case.ts): enforce a canonical case for text-encoding identifiers, `"utf-8"` (not `"UTF-8"` / `"utf8"`).
|
|
961
955
|
- [`unicorn/throw-new-error`](https://github.com/samchon/ttsc/blob/master/tests/test-lint/src/cases/unicorn-throw-new-error.ts): require `throw new Error(...)` over `throw Error(...)`.
|
|
962
956
|
|
|
963
957
|
### Regular expressions
|
|
964
958
|
|
|
965
|
-
Regex-shape rules. Check the structure of regex literals
|
|
959
|
+
Regex-shape rules. Check the structure of regex literals, emptiness, uselessness, flag ordering, shorthand classes, Unicode support. Some rules supersede the regex-related rules in [ESLint core](#eslint-core); both ids exist so projects can keep the legacy ESLint names alongside the regexp-plugin variants.
|
|
966
960
|
|
|
967
961
|
Source: [`eslint-plugin-regexp`](https://github.com/ota-meshi/eslint-plugin-regexp).
|
|
968
962
|
|
|
@@ -991,7 +985,7 @@ Source: [`eslint-plugin-regexp`](https://github.com/ota-meshi/eslint-plugin-rege
|
|
|
991
985
|
|
|
992
986
|
### Security
|
|
993
987
|
|
|
994
|
-
Security-focused TypeScript source rules. Report likely security smells
|
|
988
|
+
Security-focused TypeScript source rules. Report likely security smells, non-literal sinks for eval, file I/O, regex construction, child-process spawning, cryptographic primitives. That warrant human review even if no exploit is statically provable. Treat findings as _hints_, not proofs.
|
|
995
989
|
|
|
996
990
|
Source: [`eslint-plugin-security@4.0.0`](https://github.com/eslint-community/eslint-plugin-security).
|
|
997
991
|
|
|
@@ -1012,7 +1006,7 @@ Source: [`eslint-plugin-security@4.0.0`](https://github.com/eslint-community/esl
|
|
|
1012
1006
|
|
|
1013
1007
|
### JSDoc
|
|
1014
1008
|
|
|
1015
|
-
Documentation-comment validation rules. Bundles `eslint-plugin-jsdoc` content checks (tag names, parameter coverage, descriptions) with the lone `eslint-plugin-tsdoc` syntax check (`jsdoc/tsdoc-syntax`)
|
|
1009
|
+
Documentation-comment validation rules. Bundles `eslint-plugin-jsdoc` content checks (tag names, parameter coverage, descriptions) with the lone `eslint-plugin-tsdoc` syntax check (`jsdoc/tsdoc-syntax`). Both target `/** ... */` comments. Formatting concerns (alignment, indentation) are configured through the top-level [`format`](#format) block, not here.
|
|
1016
1010
|
|
|
1017
1011
|
Source: [`eslint-plugin-jsdoc`](https://github.com/gajus/eslint-plugin-jsdoc), [`eslint-plugin-tsdoc`](https://github.com/microsoft/tsdoc).
|
|
1018
1012
|
|
|
@@ -1032,7 +1026,7 @@ Source: [`eslint-plugin-jsdoc`](https://github.com/gajus/eslint-plugin-jsdoc), [
|
|
|
1032
1026
|
|
|
1033
1027
|
### Functional
|
|
1034
1028
|
|
|
1035
|
-
Functional-programming policy rules. Push code toward immutability, side-effect-free expressions, and expression-style control flow. Most rules are useful in pieces
|
|
1029
|
+
Functional-programming policy rules. Push code toward immutability, side-effect-free expressions, and expression-style control flow. Most rules are useful in pieces, projects rarely enable the whole family at `"error"`. Enabling the whole set together expresses a strict functional-core / imperative-shell discipline. Diagnostic-only: `ttsc fix` does not rewrite mutation, classes, exceptions, loops, or branching into a functional design.
|
|
1036
1030
|
|
|
1037
1031
|
Source: [`eslint-plugin-functional`](https://github.com/eslint-functional/eslint-plugin-functional).
|
|
1038
1032
|
|
|
@@ -1080,7 +1074,7 @@ export default {
|
|
|
1080
1074
|
|
|
1081
1075
|
### Architecture boundaries
|
|
1082
1076
|
|
|
1083
|
-
Architecture-boundary rules enforce import direction and module visibility between configured source-path
|
|
1077
|
+
Architecture-boundary rules enforce import direction and module visibility between configured source-path _elements_ (layers, features, apps in a monorepo). Every rule operates on the _resolved source file_ of an import, relative imports are followed to the real `.ts`/`.tsx`/`.d.ts` file before classification. Boundary diagnostics do not offer autofixes, a violation usually needs an API or architecture decision, not a mechanical import rewrite.
|
|
1084
1078
|
|
|
1085
1079
|
Source: ported from [`eslint-plugin-boundaries`](https://github.com/javierbrea/eslint-plugin-boundaries).
|
|
1086
1080
|
|
|
@@ -1138,7 +1132,7 @@ export default {
|
|
|
1138
1132
|
|
|
1139
1133
|
`ttsc` copies each declared contributor's Go source into a sub-package of `@ttsc/lint`'s module at build time, so the resulting binary has both built-in and contributor rules registered before `main`. Authoring instructions and the public Go API live in the [`@ttsc/lint` walkthrough → How a contributor package ships](https://ttsc.dev/docs/development/walkthroughs/lint#how-a-contributor-package-ships).
|
|
1140
1134
|
|
|
1141
|
-
Contributor rules emit autofixes the same way built-ins do
|
|
1135
|
+
Contributor rules emit autofixes the same way built-ins do, call `ctx.ReportFix(node, message, edits...)` or `ctx.ReportRangeFix(pos, end, message, edits...)`. The `rule/astutil` package re-exports the byte-range helpers built-ins use (`NodeText`, `KeywordStart`, `FindKeyword`, `TokenRange`). See the [contributor autofix path](https://ttsc.dev/docs/development/walkthroughs/lint#the-contributor-autofix-path) section for the full contract and an example.
|
|
1142
1136
|
|
|
1143
1137
|
## Sponsors
|
|
1144
1138
|
|
|
@@ -1151,7 +1145,7 @@ Your [donation](https://github.com/sponsors/samchon) encourages `ttsc` developme
|
|
|
1151
1145
|
## References
|
|
1152
1146
|
|
|
1153
1147
|
<!--
|
|
1154
|
-
AGENT INSTRUCTIONS
|
|
1148
|
+
AGENT INSTRUCTIONS, adding a new upstream reference.
|
|
1155
1149
|
|
|
1156
1150
|
When you add a new rule family to [Rules](#rules), do all of:
|
|
1157
1151
|
|
|
@@ -1164,7 +1158,7 @@ When you add a new rule family to [Rules](#rules), do all of:
|
|
|
1164
1158
|
that single upstream, mention the namespace in `### Claim ownership` so the
|
|
1165
1159
|
maintainers know the port belongs to their family. The paragraph already lists
|
|
1166
1160
|
`react/*, jest/*, playwright/*, tanstack-query/*, promise/*, and the other family
|
|
1167
|
-
namespaces
|
|
1161
|
+
namespaces`, extend that list naturally; do not start a new sentence per family.
|
|
1168
1162
|
3. Do NOT put license parentheticals (`(MIT)`, `(BSD-3-Clause)`, etc.) after the
|
|
1169
1163
|
link. Reader clicks through if they need the license.
|
|
1170
1164
|
4. Order is roughly the same as the family ordering in [Rules](#rules); insert at
|
|
@@ -1199,9 +1193,8 @@ When you add a new rule family to [Rules](#rules), do all of:
|
|
|
1199
1193
|
|
|
1200
1194
|
### Claim ownership
|
|
1201
1195
|
|
|
1202
|
-
To the maintainers of every plugin listed above: the rule semantics under `react/*`, `jest/*`, `playwright/*`, `tanstack-query/*`, `promise/*`, and the other family namespaces inside `@ttsc/lint` are a Go re-implementation of your work for the TypeScript-Go Checker. The intent is convenience
|
|
1196
|
+
To the maintainers of every plugin listed above: the rule semantics under `react/*`, `jest/*`, `playwright/*`, `tanstack-query/*`, `promise/*`, and the other family namespaces inside `@ttsc/lint` are a Go re-implementation of your work for the TypeScript-Go Checker. The intent is convenience, projects on `ttsc` get your rules without standing up a separate ESLint process, not ownership.
|
|
1203
1197
|
|
|
1204
|
-
If you would prefer to publish a first-party `@ttsc/lint` plugin for your family yourself, you are welcome to take the Go sources under [`packages/lint/linthost/rules_*.go`](https://github.com/samchon/ttsc/tree/master/packages/lint/linthost) and the fixtures under [`tests/test-lint/src/cases/`](https://github.com/samchon/ttsc/tree/master/tests/test-lint/src/cases) and ship them as your own contributor plugin. Open an issue at [samchon/ttsc](https://github.com/samchon/ttsc/issues) when the upstream package is ready, and I will retire the in-tree port and add a redirect line under [Rules](#rules) pointing at your package. Same offer for partial coverage
|
|
1198
|
+
If you would prefer to publish a first-party `@ttsc/lint` plugin for your family yourself, you are welcome to take the Go sources under [`packages/lint/linthost/rules_*.go`](https://github.com/samchon/ttsc/tree/master/packages/lint/linthost) and the fixtures under [`tests/test-lint/src/cases/`](https://github.com/samchon/ttsc/tree/master/tests/test-lint/src/cases) and ship them as your own contributor plugin. Open an issue at [samchon/ttsc](https://github.com/samchon/ttsc/issues) when the upstream package is ready, and I will retire the in-tree port and add a redirect line under [Rules](#rules) pointing at your package. Same offer for partial coverage. Name a subset and I will remove just those rules.
|
|
1205
1199
|
|
|
1206
1200
|
The contributor-plugin walkthrough is the [`@ttsc/lint` development guide](https://ttsc.dev/docs/development/walkthroughs/lint).
|
|
1207
|
-
|
package/linthost/lsp.go
CHANGED
|
@@ -5,6 +5,7 @@ import (
|
|
|
5
5
|
"errors"
|
|
6
6
|
"flag"
|
|
7
7
|
"fmt"
|
|
8
|
+
"io"
|
|
8
9
|
"io/fs"
|
|
9
10
|
"net/url"
|
|
10
11
|
"os"
|
|
@@ -12,6 +13,10 @@ import (
|
|
|
12
13
|
"strings"
|
|
13
14
|
"unicode/utf16"
|
|
14
15
|
"unicode/utf8"
|
|
16
|
+
|
|
17
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
18
|
+
shimcore "github.com/microsoft/typescript-go/shim/core"
|
|
19
|
+
shimparser "github.com/microsoft/typescript-go/shim/parser"
|
|
15
20
|
)
|
|
16
21
|
|
|
17
22
|
const (
|
|
@@ -67,8 +72,13 @@ type lspCommandOptions struct {
|
|
|
67
72
|
argumentsJSON string
|
|
68
73
|
command string
|
|
69
74
|
contextJSON string
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
// contentStdin reports whether the caller passed --content-stdin. When
|
|
76
|
+
// set, RunLSPExecuteCommand reads the FULL document buffer from os.Stdin
|
|
77
|
+
// (to EOF) and formats that text in memory instead of reading the target
|
|
78
|
+
// file from disk. See lspFormatBuffer.
|
|
79
|
+
contentStdin bool
|
|
80
|
+
cwd string
|
|
81
|
+
pluginsJSON string
|
|
72
82
|
// rangeJSON is accepted from the ttsc LSP server
|
|
73
83
|
// (`internal/lspserver/lsp_native_plugin_source.go`) for forward
|
|
74
84
|
// compatibility, but no current code path consumes it — code actions
|
|
@@ -180,6 +190,24 @@ func RunLSPExecuteCommand(args []string) int {
|
|
|
180
190
|
return 2
|
|
181
191
|
}
|
|
182
192
|
opts.uri = uri
|
|
193
|
+
// --content-stdin selects the lightweight in-memory format path: the full
|
|
194
|
+
// document buffer is read from stdin and formatted with AST+source rules
|
|
195
|
+
// only, with no temp-workspace copy and no tsgo Program. It applies to
|
|
196
|
+
// ttsc.format.document; ttsc.lint.fixAll under --content-stdin is out of
|
|
197
|
+
// scope (lint-class fixes can require a type checker), so it falls back to
|
|
198
|
+
// the disk-based path below.
|
|
199
|
+
if opts.contentStdin && opts.command == commandFormatDocument {
|
|
200
|
+
content, err := io.ReadAll(os.Stdin)
|
|
201
|
+
if err != nil {
|
|
202
|
+
fmt.Fprintf(os.Stderr, "@ttsc/lint lsp-execute-command: read --content-stdin: %v\n", err)
|
|
203
|
+
return 2
|
|
204
|
+
}
|
|
205
|
+
edit, code := lspFormatBuffer(string(content), opts)
|
|
206
|
+
if code != 0 {
|
|
207
|
+
return code
|
|
208
|
+
}
|
|
209
|
+
return writeJSON(edit)
|
|
210
|
+
}
|
|
183
211
|
edit, code := lspWorkspaceEditForCommand(opts)
|
|
184
212
|
if code != 0 {
|
|
185
213
|
return code
|
|
@@ -198,6 +226,7 @@ func parseLSPCommandOptions(name string, args []string) (*lspCommandOptions, boo
|
|
|
198
226
|
contextJSON := fs.String("context-json", "", "")
|
|
199
227
|
command := fs.String("command", "", "")
|
|
200
228
|
argumentsJSON := fs.String("arguments-json", "", "")
|
|
229
|
+
contentStdin := fs.Bool("content-stdin", false, "")
|
|
201
230
|
if err := fs.Parse(args); err != nil {
|
|
202
231
|
return nil, false
|
|
203
232
|
}
|
|
@@ -210,6 +239,7 @@ func parseLSPCommandOptions(name string, args []string) (*lspCommandOptions, boo
|
|
|
210
239
|
argumentsJSON: *argumentsJSON,
|
|
211
240
|
command: *command,
|
|
212
241
|
contextJSON: *contextJSON,
|
|
242
|
+
contentStdin: *contentStdin,
|
|
213
243
|
cwd: resolvedCwd,
|
|
214
244
|
pluginsJSON: *pluginsJSON,
|
|
215
245
|
rangeJSON: *rangeJSON,
|
|
@@ -421,6 +451,123 @@ func lspWorkspaceEditForCommand(opts *lspCommandOptions) (*lspWorkspaceEdit, int
|
|
|
421
451
|
return workspaceEditForFullDocument(opts.uri, string(original), string(next)), 0
|
|
422
452
|
}
|
|
423
453
|
|
|
454
|
+
// lspFormatBuffer formats an in-memory document buffer using only the
|
|
455
|
+
// format-class rules, with no tsgo Program and no temp-workspace copy. It is
|
|
456
|
+
// the lightweight path behind --content-stdin for ttsc.format.document.
|
|
457
|
+
//
|
|
458
|
+
// Format rules are AST+source only (`IsFormat() == true`); none implement
|
|
459
|
+
// typeAwareRule, so the engine runs them with a nil checker. The document
|
|
460
|
+
// content comes entirely from `content` — the file on disk at opts.uri is
|
|
461
|
+
// never read — so an editor can format an unsaved buffer without paying the
|
|
462
|
+
// disk-copy + full-program-load cost of lspWorkspaceEditForCommand.
|
|
463
|
+
//
|
|
464
|
+
// Returns the same WorkspaceEdit shape as the disk path, or (nil, 0) on a
|
|
465
|
+
// no-op (no fixable findings, or text unchanged after convergence).
|
|
466
|
+
func lspFormatBuffer(content string, opts *lspCommandOptions) (*lspWorkspaceEdit, int) {
|
|
467
|
+
target, err := filePathFromURI(opts.uri)
|
|
468
|
+
if err != nil {
|
|
469
|
+
fmt.Fprintln(os.Stderr, err)
|
|
470
|
+
return nil, 2
|
|
471
|
+
}
|
|
472
|
+
// Guard rails mirror lspWorkspaceEditForCommand: skip targets outside the
|
|
473
|
+
// project root or inside node_modules.
|
|
474
|
+
if _, ok := projectRelativePath(opts.cwd, target); !ok {
|
|
475
|
+
fmt.Fprintf(os.Stderr, "@ttsc/lint: LSP command target %s is outside cwd %s\n", target, opts.cwd)
|
|
476
|
+
return nil, 2
|
|
477
|
+
}
|
|
478
|
+
if projectPathHasSegment(opts.cwd, target, "node_modules") {
|
|
479
|
+
return nil, 0
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
rules, err := loadRules(opts.pluginsJSON, opts.cwd, opts.tsconfig)
|
|
483
|
+
if err != nil {
|
|
484
|
+
fmt.Fprintln(os.Stderr, err)
|
|
485
|
+
return nil, 2
|
|
486
|
+
}
|
|
487
|
+
rules = formatCommandResolver{inner: rules}
|
|
488
|
+
engine := NewEngineWithResolver(rules)
|
|
489
|
+
if engine.NeedsTypeChecker() {
|
|
490
|
+
// A format-class contributor rule (formatContributorAdapter) needs the type
|
|
491
|
+
// checker, which the single-file in-memory parse can't supply. Fall back to
|
|
492
|
+
// the disk path, which builds a full program with a checker, so the result
|
|
493
|
+
// matches `ttsc format`; the dirty buffer can't be honored for these rules.
|
|
494
|
+
// Built-in format rules are AST-only, so they keep the fast in-memory path.
|
|
495
|
+
return lspWorkspaceEditForCommand(opts)
|
|
496
|
+
}
|
|
497
|
+
scriptKind := scriptKindForPath(target)
|
|
498
|
+
|
|
499
|
+
text := content
|
|
500
|
+
converged := false
|
|
501
|
+
for pass := 0; pass < maxFormatPasses; pass++ {
|
|
502
|
+
file := shimparser.ParseSourceFile(shimast.SourceFileParseOptions{FileName: target}, text, scriptKind)
|
|
503
|
+
if file == nil {
|
|
504
|
+
// Match the disk path: a buffer we can't parse is a benign no-op, not a
|
|
505
|
+
// hard error — don't fight the editor's own diagnostics on a dirty buffer.
|
|
506
|
+
return nil, 0
|
|
507
|
+
}
|
|
508
|
+
findings := filterFormatFindings(engine.Run([]*shimast.SourceFile{file}, nil))
|
|
509
|
+
next, applied := applyFindingFixesToText(text, findings)
|
|
510
|
+
if applied == 0 {
|
|
511
|
+
converged = true
|
|
512
|
+
break
|
|
513
|
+
}
|
|
514
|
+
text = next
|
|
515
|
+
}
|
|
516
|
+
if !converged {
|
|
517
|
+
fmt.Fprintf(os.Stderr,
|
|
518
|
+
"@ttsc/lint: LSP %s cascade did not converge after %d passes\n",
|
|
519
|
+
opts.command, maxFormatPasses)
|
|
520
|
+
return nil, 2
|
|
521
|
+
}
|
|
522
|
+
return workspaceEditForFullDocument(opts.uri, content, text), 0
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// scriptKindForPath maps a file extension to the tsgo ScriptKind the parser
|
|
526
|
+
// needs so TS/JSX-only syntax is recognized. Mirrors the test helpers'
|
|
527
|
+
// ScriptKind selection (helpers_test.go parseTSFile/parseTSXFile).
|
|
528
|
+
func scriptKindForPath(path string) shimcore.ScriptKind {
|
|
529
|
+
switch strings.ToLower(filepath.Ext(path)) {
|
|
530
|
+
case ".tsx":
|
|
531
|
+
return shimcore.ScriptKindTSX
|
|
532
|
+
case ".jsx":
|
|
533
|
+
return shimcore.ScriptKindJSX
|
|
534
|
+
case ".js", ".cjs", ".mjs":
|
|
535
|
+
return shimcore.ScriptKindJS
|
|
536
|
+
default:
|
|
537
|
+
return shimcore.ScriptKindTS
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// applyFindingFixesToText is the in-memory counterpart of
|
|
542
|
+
// applyFindingFixes/applyTextEditsToFile (fix.go): it collects every fixable
|
|
543
|
+
// finding's TextEdit, selects a non-overlapping set with the same
|
|
544
|
+
// selectTextEdits logic, applies them right-to-left to `text`, and returns the
|
|
545
|
+
// new string plus the number of edits applied. It never writes to disk and
|
|
546
|
+
// never reloads a Program. Findings carry byte offsets into the same `text`
|
|
547
|
+
// that was just parsed, so no per-file grouping is needed.
|
|
548
|
+
func applyFindingFixesToText(text string, findings []*Finding) (string, int) {
|
|
549
|
+
edits := make([]TextEdit, 0, len(findings))
|
|
550
|
+
for _, finding := range findings {
|
|
551
|
+
if finding == nil || len(finding.Fix) == 0 {
|
|
552
|
+
continue
|
|
553
|
+
}
|
|
554
|
+
edits = append(edits, finding.Fix...)
|
|
555
|
+
}
|
|
556
|
+
selected := selectTextEdits(len(text), edits)
|
|
557
|
+
if len(selected) == 0 {
|
|
558
|
+
return text, 0
|
|
559
|
+
}
|
|
560
|
+
next := text
|
|
561
|
+
for i := len(selected) - 1; i >= 0; i-- {
|
|
562
|
+
edit := selected[i]
|
|
563
|
+
next = next[:edit.Pos] + edit.Text + next[edit.End:]
|
|
564
|
+
}
|
|
565
|
+
if next == text {
|
|
566
|
+
return text, 0
|
|
567
|
+
}
|
|
568
|
+
return next, len(selected)
|
|
569
|
+
}
|
|
570
|
+
|
|
424
571
|
func workspaceEditForFullDocument(uri string, original string, next string) *lspWorkspaceEdit {
|
|
425
572
|
if original == next {
|
|
426
573
|
return nil
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttsc/lint",
|
|
3
|
-
"version": "0.14.0-dev.
|
|
3
|
+
"version": "0.14.0-dev.20260529.2",
|
|
4
4
|
"description": "Reference ttsc plugin: ESLint-style lint rules hosted in the same Program/Checker as the type-check pass.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@typescript/native-preview": "7.0.0-dev.20260527.2",
|
|
37
37
|
"@types/node": "^25.3.0",
|
|
38
38
|
"rimraf": "^6.1.2",
|
|
39
|
-
"ttsc": "0.14.0-dev.
|
|
39
|
+
"ttsc": "0.14.0-dev.20260529.2"
|
|
40
40
|
},
|
|
41
41
|
"repository": {
|
|
42
42
|
"type": "git",
|