@ttsc/lint 0.5.0-dev.20260429-5 → 0.6.0-dev.20250430
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 +66 -8
- package/go.mod +1 -1
- package/lib/index.d.ts +10 -0
- package/lib/index.js +40 -0
- package/lib/index.js.map +1 -0
- package/lib/structures/ITtscLintConfig.d.ts +5 -0
- package/lib/structures/ITtscLintConfig.js +3 -0
- package/lib/structures/ITtscLintConfig.js.map +1 -0
- package/lib/structures/ITtscLintRule.d.ts +1 -0
- package/lib/structures/ITtscLintRule.js +3 -0
- package/lib/structures/ITtscLintRule.js.map +1 -0
- package/lib/structures/ITtscLintSeverity.d.ts +1 -0
- package/lib/structures/ITtscLintSeverity.js +3 -0
- package/lib/structures/ITtscLintSeverity.js.map +1 -0
- package/package.json +18 -9
- package/plugin/ast_helpers.go +56 -0
- package/plugin/compile.go +4 -4
- package/plugin/config.go +359 -5
- package/plugin/rules_gap.go +341 -0
- package/plugin/rules_logic.go +14 -1
- package/plugin/rules_var.go +87 -0
- package/src/index.ts +35 -0
- package/src/structures/ITtscLintConfig.ts +6 -0
- package/src/structures/ITtscLintRule.ts +131 -0
- package/src/structures/ITtscLintSeverity.ts +1 -0
- package/tsconfig.json +10 -0
- package/src/index.cjs +0 -29
package/README.md
CHANGED
|
@@ -27,8 +27,9 @@ Open your project's `tsconfig.json`, then add this entry under `compilerOptions.
|
|
|
27
27
|
"plugins": [
|
|
28
28
|
{
|
|
29
29
|
"transform": "@ttsc/lint",
|
|
30
|
-
"
|
|
30
|
+
"config": {
|
|
31
31
|
"no-var": "error",
|
|
32
|
+
"prefer-const": "error",
|
|
32
33
|
"no-explicit-any": "warning",
|
|
33
34
|
"no-console": "off"
|
|
34
35
|
}
|
|
@@ -47,6 +48,50 @@ npx ttsx src/index.ts
|
|
|
47
48
|
|
|
48
49
|
Lint errors fail the command. With `ttsx`, lint errors stop the program before your entrypoint runs. Lint warnings are printed without changing the exit code.
|
|
49
50
|
|
|
51
|
+
You can also keep the lint rules in a standalone config file and leave only the file reference in `tsconfig.json`:
|
|
52
|
+
|
|
53
|
+
```jsonc
|
|
54
|
+
{
|
|
55
|
+
"compilerOptions": {
|
|
56
|
+
"plugins": [
|
|
57
|
+
{
|
|
58
|
+
"transform": "@ttsc/lint",
|
|
59
|
+
"config": "./ttsc-lint.config.ts"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
// ttsc-lint.config.ts
|
|
68
|
+
export default {
|
|
69
|
+
"no-var": "error",
|
|
70
|
+
"prefer-const": "error",
|
|
71
|
+
"no-explicit-any": "warning",
|
|
72
|
+
"no-console": "off"
|
|
73
|
+
};
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`config` accepts either a config object or a path to `.json`, `.js`, `.cjs`, `.mjs`, `.ts`, `.cts`, or `.mts`. JavaScript and TypeScript config files may export the object directly, as `default`, as `config`, or as a function that returns the object. Relative paths are resolved from the owning tsconfig directory.
|
|
77
|
+
|
|
78
|
+
Inline `config` is also accepted:
|
|
79
|
+
|
|
80
|
+
```jsonc
|
|
81
|
+
{
|
|
82
|
+
"compilerOptions": {
|
|
83
|
+
"plugins": [
|
|
84
|
+
{
|
|
85
|
+
"transform": "@ttsc/lint",
|
|
86
|
+
"config": {
|
|
87
|
+
"no-var": "error"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
50
95
|
## Notes
|
|
51
96
|
|
|
52
97
|
`@ttsc/lint` must be the first active plugin entry because it reports on the source code you wrote. Output plugins such as `@ttsc/banner`, `@ttsc/paths`, and `@ttsc/strip` can come after it.
|
|
@@ -56,7 +101,7 @@ Lint errors fail the command. With `ttsx`, lint errors stop the program before y
|
|
|
56
101
|
"compilerOptions": {
|
|
57
102
|
"plugins": [
|
|
58
103
|
// Keep lint first.
|
|
59
|
-
{ "transform": "@ttsc/lint", "
|
|
104
|
+
{ "transform": "@ttsc/lint", "config": { "no-var": "error", "prefer-const": "error" } },
|
|
60
105
|
|
|
61
106
|
// Output plugins run after emit, in order.
|
|
62
107
|
{ "transform": "@ttsc/banner", "banner": "/*! @license MIT */" },
|
|
@@ -75,12 +120,10 @@ Rules are off until you enable them:
|
|
|
75
120
|
|
|
76
121
|
```jsonc
|
|
77
122
|
{
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"no-non-null-assertion": "off"
|
|
83
|
-
}
|
|
123
|
+
"no-var": "error",
|
|
124
|
+
"eqeqeq": "error",
|
|
125
|
+
"prefer-template": "warning",
|
|
126
|
+
"no-non-null-assertion": "off"
|
|
84
127
|
}
|
|
85
128
|
```
|
|
86
129
|
|
|
@@ -93,7 +136,10 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
|
|
|
93
136
|
- [`ban-ts-comment`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/ban-ts-comment.ts): rejects TypeScript suppression comments such as `@ts-ignore`.
|
|
94
137
|
- [`ban-tslint-comment`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/ban-tslint-comment.ts): rejects obsolete `tslint:` comments.
|
|
95
138
|
- [`consistent-indexed-object-style`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/consistent-indexed-object-style.ts): prefers `Record` for single index-signature object types.
|
|
139
|
+
- [`consistent-type-assertions`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/consistent-type-assertions.ts): prefers `as` type assertions over angle-bracket assertions.
|
|
140
|
+
- [`consistent-type-definitions`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/consistent-type-definitions.ts): prefers interfaces for object-shaped type definitions.
|
|
96
141
|
- [`consistent-type-imports`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/consistent-type-imports/violation.ts): uses `import type` when imported names are type-only.
|
|
142
|
+
- [`dot-notation`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/dot-notation.ts): prefers dot property access when a string-literal key is a valid identifier.
|
|
97
143
|
- [`eqeqeq`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/eqeqeq.ts): requires strict equality operators.
|
|
98
144
|
- [`for-direction`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/for-direction.ts): catches loop counters updated in the wrong direction.
|
|
99
145
|
- [`no-alert`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-alert.ts): rejects `alert`, `confirm`, and `prompt`.
|
|
@@ -118,12 +164,14 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
|
|
|
118
164
|
- [`no-dupe-keys`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-dupe-keys.ts): rejects duplicate object keys.
|
|
119
165
|
- [`no-duplicate-case`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-duplicate-case.ts): rejects duplicate `switch` case labels.
|
|
120
166
|
- [`no-duplicate-enum-values`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-duplicate-enum-values.ts): rejects duplicate enum member values.
|
|
167
|
+
- [`no-dynamic-delete`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-dynamic-delete.ts): rejects `delete` on dynamically computed property keys.
|
|
121
168
|
- [`no-empty`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty.ts): rejects empty blocks.
|
|
122
169
|
- [`no-empty-character-class`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-character-class.ts): rejects empty regex character classes.
|
|
123
170
|
- [`no-empty-function`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-function.ts): rejects empty functions.
|
|
124
171
|
- [`no-empty-interface`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-interface.ts): rejects empty interfaces.
|
|
125
172
|
- [`no-empty-object-type`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-object-type.ts): rejects empty object type literals.
|
|
126
173
|
- [`no-empty-pattern`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-pattern.ts): rejects empty destructuring patterns.
|
|
174
|
+
- [`no-empty-static-block`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-static-block.ts): rejects empty class static blocks.
|
|
127
175
|
- [`no-eq-null`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-eq-null.ts): rejects loose null comparisons.
|
|
128
176
|
- [`no-eval`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-eval.ts): rejects `eval`.
|
|
129
177
|
- [`no-ex-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-ex-assign.ts): rejects reassignment of caught exceptions.
|
|
@@ -151,6 +199,7 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
|
|
|
151
199
|
- [`no-new`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-new.ts): rejects `new` expressions used only for side effects.
|
|
152
200
|
- [`no-new-func`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-new-func.ts): rejects `Function` constructors.
|
|
153
201
|
- [`no-new-wrappers`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-new-wrappers.ts): rejects primitive wrapper constructors.
|
|
202
|
+
- [`no-non-null-asserted-nullish-coalescing`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-non-null-asserted-nullish-coalescing.ts): rejects non-null assertions next to `??`.
|
|
154
203
|
- [`no-non-null-asserted-optional-chain`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-non-null-asserted-optional-chain.ts): rejects non-null assertions on optional chains.
|
|
155
204
|
- [`no-non-null-assertion`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-non-null-assertion.ts): rejects postfix non-null assertions.
|
|
156
205
|
- [`no-obj-calls`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-obj-calls.ts): rejects calling global objects as functions.
|
|
@@ -168,6 +217,7 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
|
|
|
168
217
|
- [`no-self-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-self-assign.ts): rejects assignments to the same value.
|
|
169
218
|
- [`no-self-compare`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-self-compare.ts): rejects comparing a value to itself.
|
|
170
219
|
- [`no-sequences`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-sequences.ts): rejects comma expressions.
|
|
220
|
+
- [`no-setter-return`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-setter-return.ts): rejects returned values from setters.
|
|
171
221
|
- [`no-shadow-restricted-names`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-shadow-restricted-names.ts): rejects shadowing restricted globals.
|
|
172
222
|
- [`no-sparse-arrays`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-sparse-arrays.ts): rejects sparse arrays.
|
|
173
223
|
- [`no-template-curly-in-string`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-template-curly-in-string.ts): rejects `${...}` text inside normal strings.
|
|
@@ -175,24 +225,32 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
|
|
|
175
225
|
- [`no-throw-literal`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-throw-literal.ts): rejects throwing literals.
|
|
176
226
|
- [`no-undef-init`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-undef-init.ts): rejects initializing to `undefined`.
|
|
177
227
|
- [`no-undefined`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-undefined.ts): rejects the global `undefined` identifier.
|
|
228
|
+
- [`no-unnecessary-type-constraint`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unnecessary-type-constraint.ts): rejects redundant `extends any` and `extends unknown` constraints.
|
|
178
229
|
- [`no-unneeded-ternary`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unneeded-ternary.ts): rejects redundant ternary expressions.
|
|
230
|
+
- [`no-unsafe-declaration-merging`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-declaration-merging.ts): rejects unsafe class/interface declaration merging.
|
|
179
231
|
- [`no-unsafe-finally`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-finally.ts): rejects control flow from `finally`.
|
|
232
|
+
- [`no-unsafe-function-type`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-function-type.ts): rejects the unsafe `Function` type.
|
|
180
233
|
- [`no-unsafe-negation`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-negation.ts): rejects unsafe negation before relational checks.
|
|
181
234
|
- [`no-unused-expressions`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unused-expressions.ts): rejects expression statements with no effect.
|
|
235
|
+
- [`no-unused-labels`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unused-labels.ts): rejects labels that no `break` or `continue` targets.
|
|
182
236
|
- [`no-useless-call`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-call.ts): rejects unnecessary `.call()` and `.apply()`.
|
|
183
237
|
- [`no-useless-catch`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-catch.ts): rejects catch blocks that only rethrow.
|
|
184
238
|
- [`no-useless-computed-key`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-computed-key.ts): rejects unnecessary computed property keys.
|
|
185
239
|
- [`no-useless-concat`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-concat.ts): rejects unnecessary string concatenation.
|
|
240
|
+
- [`no-useless-constructor`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-constructor.ts): rejects empty constructors with no parameters.
|
|
186
241
|
- [`no-useless-rename`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-rename.ts): rejects import/export/destructure renames to the same name.
|
|
187
242
|
- [`no-var`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-var.ts): rejects `var`.
|
|
188
243
|
- [`no-with`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-with.ts): rejects `with` statements.
|
|
244
|
+
- [`no-wrapper-object-types`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-wrapper-object-types.ts): rejects boxed object type names such as `String` and `Boolean`.
|
|
189
245
|
- [`object-shorthand`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/object-shorthand.ts): requires object property shorthand where possible.
|
|
190
246
|
- [`operator-assignment`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/operator-assignment.ts): prefers compound assignment operators.
|
|
191
247
|
- [`prefer-as-const`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-as-const.ts): prefers `as const` for literal assertions.
|
|
248
|
+
- [`prefer-const`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-const.ts): prefers `const` for `let` bindings that are never reassigned.
|
|
192
249
|
- [`prefer-enum-initializers`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-enum-initializers.ts): requires explicit enum member initializers.
|
|
193
250
|
- [`prefer-exponentiation-operator`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-exponentiation-operator.ts): prefers `**` over `Math.pow`.
|
|
194
251
|
- [`prefer-for-of`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-for-of.ts): prefers `for...of` for simple array iteration.
|
|
195
252
|
- [`prefer-function-type`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-function-type.ts): prefers function type aliases over single-call interfaces.
|
|
253
|
+
- [`prefer-literal-enum-member`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-literal-enum-member.ts): prefers literal enum member initializers over computed expressions.
|
|
196
254
|
- [`prefer-namespace-keyword`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-namespace-keyword.ts): prefers `namespace` over TypeScript's legacy `module` keyword.
|
|
197
255
|
- [`prefer-spread`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-spread.ts): prefers spread arguments over `.apply`.
|
|
198
256
|
- [`prefer-template`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-template.ts): prefers template literals over string concatenation.
|
package/go.mod
CHANGED
|
@@ -30,7 +30,7 @@ require (
|
|
|
30
30
|
require (
|
|
31
31
|
github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
|
|
32
32
|
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
|
33
|
-
github.com/microsoft/typescript-go v0.0.0-
|
|
33
|
+
github.com/microsoft/typescript-go v0.0.0-20260429010842-56ab4af42157 // indirect
|
|
34
34
|
github.com/zeebo/xxh3 v1.1.0 // indirect
|
|
35
35
|
golang.org/x/sync v0.20.0 // indirect
|
|
36
36
|
golang.org/x/sys v0.42.0 // indirect
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ITtscProjectPluginConfig, ITtscPlugin, ITtscPluginFactoryContext } from "ttsc";
|
|
2
|
+
import type { ITtscLintConfig } from "./structures/ITtscLintConfig";
|
|
3
|
+
export * from "./structures/ITtscLintConfig";
|
|
4
|
+
export * from "./structures/ITtscLintRule";
|
|
5
|
+
export * from "./structures/ITtscLintSeverity";
|
|
6
|
+
export type ITtscLintPluginConfig = ITtscProjectPluginConfig & {
|
|
7
|
+
config?: string | ITtscLintConfig;
|
|
8
|
+
};
|
|
9
|
+
export declare function createTtscPlugin(_context: ITtscPluginFactoryContext<ITtscLintPluginConfig>): ITtscPlugin;
|
|
10
|
+
export default createTtscPlugin;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.createTtscPlugin = createTtscPlugin;
|
|
21
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
22
|
+
__exportStar(require("./structures/ITtscLintConfig"), exports);
|
|
23
|
+
__exportStar(require("./structures/ITtscLintRule"), exports);
|
|
24
|
+
__exportStar(require("./structures/ITtscLintSeverity"), exports);
|
|
25
|
+
function createTtscPlugin(_context) {
|
|
26
|
+
return {
|
|
27
|
+
name: "@ttsc/lint",
|
|
28
|
+
native: {
|
|
29
|
+
mode: "ttsc-lint",
|
|
30
|
+
source: {
|
|
31
|
+
dir: node_path_1.default.resolve(__dirname, ".."),
|
|
32
|
+
entry: "./plugin",
|
|
33
|
+
},
|
|
34
|
+
contractVersion: 1,
|
|
35
|
+
capabilities: ["check"],
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
exports.default = createTtscPlugin;
|
|
40
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,0DAA6B;AAS7B,+DAA6C;AAC7C,6DAA2C;AAC3C,iEAA+C;AAM/C,0BACE,QAA0D;IAE1D,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE;YACN,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE;gBACN,GAAG,EAAE,mBAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC;gBAClC,KAAK,EAAE,UAAU;aAClB;YACD,eAAe,EAAE,CAAC;YAClB,YAAY,EAAE,CAAC,OAAO,CAAC;SACxB;KACF,CAAC;AACJ,CAAC;kBAEc,gBAAgB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITtscLintConfig.js","sourceRoot":"","sources":["../../src/structures/ITtscLintConfig.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ITtscLintRule = "adjacent-overload-signatures" | "array-type" | "ban-ts-comment" | "ban-tslint-comment" | "consistent-indexed-object-style" | "consistent-type-assertions" | "consistent-type-definitions" | "consistent-type-imports" | "dot-notation" | "eqeqeq" | "for-direction" | "no-alert" | "no-array-constructor" | "no-array-delete" | "no-async-promise-executor" | "no-bitwise" | "no-caller" | "no-case-declarations" | "no-class-assign" | "no-compare-neg-zero" | "no-cond-assign" | "no-confusing-non-null-assertion" | "no-console" | "no-constant-condition" | "no-continue" | "no-control-regex" | "no-debugger" | "no-delete-var" | "no-dupe-args" | "no-dupe-else-if" | "no-dupe-keys" | "no-duplicate-case" | "no-duplicate-enum-values" | "no-dynamic-delete" | "no-empty" | "no-empty-character-class" | "no-empty-function" | "no-empty-interface" | "no-empty-object-type" | "no-empty-pattern" | "no-empty-static-block" | "no-eq-null" | "no-eval" | "no-ex-assign" | "no-explicit-any" | "no-extra-bind" | "no-extra-boolean-cast" | "no-extra-non-null-assertion" | "no-fallthrough" | "no-func-assign" | "no-inferrable-types" | "no-inner-declarations" | "no-irregular-whitespace" | "no-iterator" | "no-labels" | "no-lone-blocks" | "no-lonely-if" | "no-loss-of-precision" | "no-misleading-character-class" | "no-misused-new" | "no-multi-assign" | "no-multi-str" | "no-namespace" | "no-negated-condition" | "no-nested-ternary" | "no-new" | "no-new-func" | "no-new-wrappers" | "no-non-null-asserted-nullish-coalescing" | "no-non-null-asserted-optional-chain" | "no-non-null-assertion" | "no-obj-calls" | "no-object-constructor" | "no-octal" | "no-octal-escape" | "no-plusplus" | "no-promise-executor-return" | "no-proto" | "no-prototype-builtins" | "no-regex-spaces" | "no-require-imports" | "no-return-assign" | "no-script-url" | "no-self-assign" | "no-self-compare" | "no-sequences" | "no-setter-return" | "no-shadow-restricted-names" | "no-sparse-arrays" | "no-template-curly-in-string" | "no-this-alias" | "no-throw-literal" | "no-undef-init" | "no-undefined" | "no-unnecessary-type-constraint" | "no-unneeded-ternary" | "no-unsafe-declaration-merging" | "no-unsafe-finally" | "no-unsafe-function-type" | "no-unsafe-negation" | "no-unused-expressions" | "no-unused-labels" | "no-useless-call" | "no-useless-catch" | "no-useless-computed-key" | "no-useless-concat" | "no-useless-constructor" | "no-useless-rename" | "no-var" | "no-with" | "no-wrapper-object-types" | "object-shorthand" | "operator-assignment" | "prefer-as-const" | "prefer-const" | "prefer-enum-initializers" | "prefer-exponentiation-operator" | "prefer-for-of" | "prefer-function-type" | "prefer-literal-enum-member" | "prefer-namespace-keyword" | "prefer-spread" | "prefer-template" | "radix" | "require-yield" | "triple-slash-reference" | "use-isnan" | "valid-typeof" | "vars-on-top" | "yoda";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITtscLintRule.js","sourceRoot":"","sources":["../../src/structures/ITtscLintRule.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ITtscLintSeverity = "off" | "warning" | "warn" | "error" | 0 | 1 | 2;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITtscLintSeverity.js","sourceRoot":"","sources":["../../src/structures/ITtscLintSeverity.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttsc/lint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-dev.20250430",
|
|
4
4
|
"description": "Reference ttsc plugin: ESLint-style lint rules hosted in the same Program/Checker as the type-check pass.",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
6
7
|
"exports": {
|
|
7
|
-
".":
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./lib/index.d.ts",
|
|
10
|
+
"default": "./lib/index.js"
|
|
11
|
+
},
|
|
8
12
|
"./package.json": "./package.json"
|
|
9
13
|
},
|
|
10
14
|
"keywords": [
|
|
@@ -16,10 +20,18 @@
|
|
|
16
20
|
],
|
|
17
21
|
"files": [
|
|
18
22
|
"README.md",
|
|
19
|
-
"
|
|
23
|
+
"lib",
|
|
24
|
+
"src",
|
|
25
|
+
"tsconfig.json",
|
|
20
26
|
"go.mod",
|
|
21
27
|
"plugin"
|
|
22
28
|
],
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@typescript/native-preview": "7.0.0-dev.20260429.1",
|
|
31
|
+
"@types/node": "^25.3.0",
|
|
32
|
+
"rimraf": "^6.1.2",
|
|
33
|
+
"ttsc": "0.6.0-dev.20250430"
|
|
34
|
+
},
|
|
23
35
|
"repository": {
|
|
24
36
|
"type": "git",
|
|
25
37
|
"url": "https://github.com/samchon/ttsc"
|
|
@@ -30,11 +42,8 @@
|
|
|
30
42
|
"url": "https://github.com/samchon/ttsc/issues"
|
|
31
43
|
},
|
|
32
44
|
"homepage": "https://github.com/samchon/ttsc/tree/master/packages/lint#readme",
|
|
33
|
-
"deprecation": {
|
|
34
|
-
"preferred": "@typescript-eslint/eslint-plugin",
|
|
35
|
-
"rationale": "@ttsc/lint is a curated reference implementation. The strongly preferred outcome is for eslint / @typescript-eslint maintainers to take ownership of the host slot. If they do, this package will be deprecated and re-pointed at theirs."
|
|
36
|
-
},
|
|
37
45
|
"scripts": {
|
|
38
|
-
"
|
|
46
|
+
"build": "rimraf lib && tsgo -p tsconfig.json",
|
|
47
|
+
"test": "pnpm run build && pnpm --dir ../../tests/lint start"
|
|
39
48
|
}
|
|
40
49
|
}
|
package/plugin/ast_helpers.go
CHANGED
|
@@ -168,3 +168,59 @@ func stringLiteralText(node *shimast.Node) string {
|
|
|
168
168
|
}
|
|
169
169
|
return ""
|
|
170
170
|
}
|
|
171
|
+
|
|
172
|
+
// walkDescendants visits node and every child below it, depth-first.
|
|
173
|
+
func walkDescendants(node *shimast.Node, visit func(*shimast.Node)) {
|
|
174
|
+
if node == nil {
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
visit(node)
|
|
178
|
+
node.ForEachChild(func(child *shimast.Node) bool {
|
|
179
|
+
walkDescendants(child, visit)
|
|
180
|
+
return false
|
|
181
|
+
})
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
func bindingIdentifierNames(node *shimast.Node) []string {
|
|
185
|
+
if node == nil {
|
|
186
|
+
return nil
|
|
187
|
+
}
|
|
188
|
+
if name := identifierText(node); name != "" {
|
|
189
|
+
return []string{name}
|
|
190
|
+
}
|
|
191
|
+
if node.Kind != shimast.KindObjectBindingPattern && node.Kind != shimast.KindArrayBindingPattern {
|
|
192
|
+
return nil
|
|
193
|
+
}
|
|
194
|
+
var names []string
|
|
195
|
+
walkDescendants(node, func(child *shimast.Node) {
|
|
196
|
+
if child == node {
|
|
197
|
+
return
|
|
198
|
+
}
|
|
199
|
+
if name := identifierText(child); name != "" {
|
|
200
|
+
names = append(names, name)
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
return names
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
func isLiteralLike(node *shimast.Node) bool {
|
|
207
|
+
node = stripParens(node)
|
|
208
|
+
if node == nil {
|
|
209
|
+
return false
|
|
210
|
+
}
|
|
211
|
+
if isLiteralExpression(node) {
|
|
212
|
+
return true
|
|
213
|
+
}
|
|
214
|
+
if node.Kind == shimast.KindPrefixUnaryExpression {
|
|
215
|
+
prefix := node.AsPrefixUnaryExpression()
|
|
216
|
+
if prefix == nil {
|
|
217
|
+
return false
|
|
218
|
+
}
|
|
219
|
+
switch prefix.Operator {
|
|
220
|
+
case shimast.KindPlusToken, shimast.KindMinusToken:
|
|
221
|
+
return prefix.Operand != nil &&
|
|
222
|
+
(prefix.Operand.Kind == shimast.KindNumericLiteral || prefix.Operand.Kind == shimast.KindBigIntLiteral)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return false
|
|
226
|
+
}
|
package/plugin/compile.go
CHANGED
|
@@ -93,7 +93,7 @@ func RunTransform(args []string) int {
|
|
|
93
93
|
}
|
|
94
94
|
defer prog.close()
|
|
95
95
|
|
|
96
|
-
rules, err := loadRules(*pluginsJSON)
|
|
96
|
+
rules, err := loadRules(*pluginsJSON, resolvedCwd, *tsconfig)
|
|
97
97
|
if err != nil {
|
|
98
98
|
fmt.Fprintln(os.Stderr, err)
|
|
99
99
|
return 2
|
|
@@ -227,7 +227,7 @@ func runProject(opts *subcommandOpts) int {
|
|
|
227
227
|
}
|
|
228
228
|
defer prog.close()
|
|
229
229
|
|
|
230
|
-
rules, err := loadRules(opts.pluginsJSON)
|
|
230
|
+
rules, err := loadRules(opts.pluginsJSON, opts.cwd, opts.tsconfig)
|
|
231
231
|
if err != nil {
|
|
232
232
|
fmt.Fprintln(os.Stderr, err)
|
|
233
233
|
return 2
|
|
@@ -268,7 +268,7 @@ func runProject(opts *subcommandOpts) int {
|
|
|
268
268
|
return 0
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
func loadRules(pluginsJSON string) (RuleConfig, error) {
|
|
271
|
+
func loadRules(pluginsJSON, cwd, tsconfigPath string) (RuleConfig, error) {
|
|
272
272
|
entries, err := ParsePlugins(pluginsJSON)
|
|
273
273
|
if err != nil {
|
|
274
274
|
return nil, err
|
|
@@ -280,7 +280,7 @@ func loadRules(pluginsJSON string) (RuleConfig, error) {
|
|
|
280
280
|
if entry == nil {
|
|
281
281
|
return RuleConfig{}, nil
|
|
282
282
|
}
|
|
283
|
-
return
|
|
283
|
+
return LoadRuleConfig(entry, cwd, tsconfigPath)
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
func warnUnknownRules(w io.Writer, unknown []string) {
|