@ttsc/lint 0.5.0-dev.20260429
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/LICENSE +21 -0
- package/README.md +204 -0
- package/go-plugin/go.mod +38 -0
- package/go-plugin/lint/ast_helpers.go +170 -0
- package/go-plugin/lint/compile.go +393 -0
- package/go-plugin/lint/config.go +134 -0
- package/go-plugin/lint/engine.go +259 -0
- package/go-plugin/lint/host.go +190 -0
- package/go-plugin/lint/rules_arrays.go +78 -0
- package/go-plugin/lint/rules_console.go +37 -0
- package/go-plugin/lint/rules_debugger.go +29 -0
- package/go-plugin/lint/rules_dupes.go +179 -0
- package/go-plugin/lint/rules_empty.go +110 -0
- package/go-plugin/lint/rules_eval.go +57 -0
- package/go-plugin/lint/rules_finally.go +123 -0
- package/go-plugin/lint/rules_logic.go +368 -0
- package/go-plugin/lint/rules_loops.go +107 -0
- package/go-plugin/lint/rules_misc.go +69 -0
- package/go-plugin/lint/rules_problems.go +571 -0
- package/go-plugin/lint/rules_protos.go +42 -0
- package/go-plugin/lint/rules_self.go +89 -0
- package/go-plugin/lint/rules_strings.go +123 -0
- package/go-plugin/lint/rules_suggestions.go +1236 -0
- package/go-plugin/lint/rules_throw.go +31 -0
- package/go-plugin/lint/rules_ts.go +250 -0
- package/go-plugin/lint/rules_ts_extra.go +654 -0
- package/go-plugin/lint/rules_var.go +40 -0
- package/go-plugin/main.go +50 -0
- package/index.cjs +28 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jeongho Nam
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# `@ttsc/lint`
|
|
2
|
+
|
|
3
|
+

|
|
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://discord.gg/E94XhzrUCZ)
|
|
10
|
+
|
|
11
|
+
`@ttsc/lint` reports ESLint-style diagnostics from the same TypeScript-Go type-check pass that `ttsc` already runs.
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
Install `ttsc`, TypeScript-Go, and the lint plugin:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -D ttsc @typescript/native-preview @ttsc/lint
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Open your project's `tsconfig.json`, then add this entry under `compilerOptions.plugins`. If the file already has `compilerOptions`, merge this into the existing object and keep `@ttsc/lint` as the first active plugin:
|
|
22
|
+
|
|
23
|
+
```jsonc
|
|
24
|
+
{
|
|
25
|
+
"compilerOptions": {
|
|
26
|
+
"plugins": [
|
|
27
|
+
{
|
|
28
|
+
"transform": "@ttsc/lint",
|
|
29
|
+
"rules": {
|
|
30
|
+
"no-var": "error",
|
|
31
|
+
"no-explicit-any": "warning",
|
|
32
|
+
"no-console": "off"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Run your normal `ttsc` or `ttsx` command:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx ttsc
|
|
44
|
+
npx ttsx src/index.ts
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
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.
|
|
48
|
+
|
|
49
|
+
## Notes
|
|
50
|
+
|
|
51
|
+
`@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.
|
|
52
|
+
|
|
53
|
+
```jsonc
|
|
54
|
+
{
|
|
55
|
+
"compilerOptions": {
|
|
56
|
+
"plugins": [
|
|
57
|
+
// Keep lint first.
|
|
58
|
+
{ "transform": "@ttsc/lint", "rules": { "no-var": "error" } },
|
|
59
|
+
|
|
60
|
+
// Output plugins run after emit, in order.
|
|
61
|
+
{ "transform": "@ttsc/banner", "banner": "/*! @license MIT */" },
|
|
62
|
+
{ "transform": "@ttsc/paths" },
|
|
63
|
+
{ "transform": "@ttsc/strip", "calls": ["console.log"] }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This package is diagnostic-only today: no autofix, no recommended preset, no custom rule loading, and no cross-file lint rules.
|
|
70
|
+
|
|
71
|
+
## Rules
|
|
72
|
+
|
|
73
|
+
Rules are off until you enable them:
|
|
74
|
+
|
|
75
|
+
```jsonc
|
|
76
|
+
{
|
|
77
|
+
"rules": {
|
|
78
|
+
"no-var": "error",
|
|
79
|
+
"eqeqeq": "error",
|
|
80
|
+
"prefer-template": "warning",
|
|
81
|
+
"no-non-null-assertion": "off"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Rule severities are `"error"`, `"warning"`, and `"off"`.
|
|
87
|
+
|
|
88
|
+
The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to check the exact patterns currently covered. Each rule below links to its tested fixture:
|
|
89
|
+
|
|
90
|
+
- [`adjacent-overload-signatures`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/adjacent-overload-signatures.ts): keeps overload declarations for the same member adjacent.
|
|
91
|
+
- [`array-type`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/array-type.ts): prefers `T[]` and `readonly T[]` over array helper types.
|
|
92
|
+
- [`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`.
|
|
93
|
+
- [`ban-tslint-comment`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/ban-tslint-comment.ts): rejects obsolete `tslint:` comments.
|
|
94
|
+
- [`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.
|
|
95
|
+
- [`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.
|
|
96
|
+
- [`eqeqeq`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/eqeqeq.ts): requires strict equality operators.
|
|
97
|
+
- [`for-direction`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/for-direction.ts): catches loop counters updated in the wrong direction.
|
|
98
|
+
- [`no-alert`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-alert.ts): rejects `alert`, `confirm`, and `prompt`.
|
|
99
|
+
- [`no-array-constructor`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-array-constructor.ts): rejects `Array` constructor calls.
|
|
100
|
+
- [`no-array-delete`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-array-delete.ts): rejects `delete` on array elements.
|
|
101
|
+
- [`no-async-promise-executor`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-async-promise-executor.ts): rejects async Promise executors.
|
|
102
|
+
- [`no-bitwise`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-bitwise.ts): rejects bitwise operators.
|
|
103
|
+
- [`no-caller`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-caller.ts): rejects `arguments.caller` and `arguments.callee`.
|
|
104
|
+
- [`no-case-declarations`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-case-declarations.ts): rejects lexical declarations directly inside `case` clauses.
|
|
105
|
+
- [`no-class-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-class-assign.ts): rejects reassignment of class declarations.
|
|
106
|
+
- [`no-compare-neg-zero`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-compare-neg-zero.ts): rejects comparisons against `-0`.
|
|
107
|
+
- [`no-cond-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-cond-assign.ts): rejects assignments inside conditions.
|
|
108
|
+
- [`no-confusing-non-null-assertion`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-confusing-non-null-assertion.ts): rejects confusing non-null assertions next to equality checks.
|
|
109
|
+
- [`no-console`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-console.ts): rejects `console` calls.
|
|
110
|
+
- [`no-constant-condition`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-constant-condition.ts): rejects constant conditions.
|
|
111
|
+
- [`no-continue`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-continue.ts): rejects `continue` statements.
|
|
112
|
+
- [`no-control-regex`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-control-regex.ts): rejects control characters in regular expressions.
|
|
113
|
+
- [`no-debugger`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-debugger.ts): rejects `debugger` statements.
|
|
114
|
+
- [`no-delete-var`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-delete-var.ts): rejects deleting variables.
|
|
115
|
+
- [`no-dupe-args`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-dupe-args.ts): rejects duplicate function parameters.
|
|
116
|
+
- [`no-dupe-else-if`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-dupe-else-if.ts): rejects repeated `else if` conditions.
|
|
117
|
+
- [`no-dupe-keys`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-dupe-keys.ts): rejects duplicate object keys.
|
|
118
|
+
- [`no-duplicate-case`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-duplicate-case.ts): rejects duplicate `switch` case labels.
|
|
119
|
+
- [`no-duplicate-enum-values`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-duplicate-enum-values.ts): rejects duplicate enum member values.
|
|
120
|
+
- [`no-empty`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty.ts): rejects empty blocks.
|
|
121
|
+
- [`no-empty-character-class`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-character-class.ts): rejects empty regex character classes.
|
|
122
|
+
- [`no-empty-function`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-function.ts): rejects empty functions.
|
|
123
|
+
- [`no-empty-interface`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-interface.ts): rejects empty interfaces.
|
|
124
|
+
- [`no-empty-object-type`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-object-type.ts): rejects empty object type literals.
|
|
125
|
+
- [`no-empty-pattern`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-pattern.ts): rejects empty destructuring patterns.
|
|
126
|
+
- [`no-eq-null`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-eq-null.ts): rejects loose null comparisons.
|
|
127
|
+
- [`no-eval`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-eval.ts): rejects `eval`.
|
|
128
|
+
- [`no-ex-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-ex-assign.ts): rejects reassignment of caught exceptions.
|
|
129
|
+
- [`no-explicit-any`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-explicit-any.ts): rejects explicit `any`.
|
|
130
|
+
- [`no-extra-bind`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-extra-bind.ts): rejects unnecessary `.bind()` calls.
|
|
131
|
+
- [`no-extra-boolean-cast`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-extra-boolean-cast.ts): rejects redundant boolean casts.
|
|
132
|
+
- [`no-extra-non-null-assertion`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-extra-non-null-assertion.ts): rejects repeated non-null assertions.
|
|
133
|
+
- [`no-fallthrough`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-fallthrough.ts): rejects unmarked `switch` fallthrough.
|
|
134
|
+
- [`no-func-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-func-assign.ts): rejects reassignment of function declarations.
|
|
135
|
+
- [`no-inferrable-types`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-inferrable-types.ts): rejects type annotations TypeScript can infer.
|
|
136
|
+
- [`no-inner-declarations`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-inner-declarations.ts): rejects function declarations nested in blocks.
|
|
137
|
+
- [`no-irregular-whitespace`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-irregular-whitespace.ts): rejects irregular whitespace.
|
|
138
|
+
- [`no-iterator`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-iterator.ts): rejects `__iterator__`.
|
|
139
|
+
- [`no-labels`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-labels.ts): rejects labels.
|
|
140
|
+
- [`no-lone-blocks`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-lone-blocks.ts): rejects unnecessary standalone blocks.
|
|
141
|
+
- [`no-lonely-if`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-lonely-if.ts): rejects `if` as the only statement in an `else`.
|
|
142
|
+
- [`no-loss-of-precision`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-loss-of-precision.ts): rejects number literals that lose precision.
|
|
143
|
+
- [`no-misleading-character-class`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-misleading-character-class.ts): rejects misleading regex character classes.
|
|
144
|
+
- [`no-misused-new`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-misused-new.ts): rejects constructor-like signatures in interfaces.
|
|
145
|
+
- [`no-multi-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-multi-assign.ts): rejects chained assignments.
|
|
146
|
+
- [`no-multi-str`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-multi-str.ts): rejects multiline string escapes.
|
|
147
|
+
- [`no-namespace`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-namespace.ts): rejects non-ambient namespaces.
|
|
148
|
+
- [`no-negated-condition`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-negated-condition.ts): rejects negated conditions with an `else`.
|
|
149
|
+
- [`no-nested-ternary`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-nested-ternary.ts): rejects nested ternary expressions.
|
|
150
|
+
- [`no-new`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-new.ts): rejects `new` expressions used only for side effects.
|
|
151
|
+
- [`no-new-func`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-new-func.ts): rejects `Function` constructors.
|
|
152
|
+
- [`no-new-wrappers`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-new-wrappers.ts): rejects primitive wrapper constructors.
|
|
153
|
+
- [`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.
|
|
154
|
+
- [`no-non-null-assertion`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-non-null-assertion.ts): rejects postfix non-null assertions.
|
|
155
|
+
- [`no-obj-calls`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-obj-calls.ts): rejects calling global objects as functions.
|
|
156
|
+
- [`no-object-constructor`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-object-constructor.ts): rejects `new Object()`.
|
|
157
|
+
- [`no-octal`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-octal.ts): rejects legacy octal literals.
|
|
158
|
+
- [`no-octal-escape`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-octal-escape.ts): rejects octal escape sequences.
|
|
159
|
+
- [`no-plusplus`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-plusplus.ts): rejects `++` and `--`.
|
|
160
|
+
- [`no-promise-executor-return`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-promise-executor-return.ts): rejects returned values from Promise executors.
|
|
161
|
+
- [`no-proto`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-proto.ts): rejects `__proto__`.
|
|
162
|
+
- [`no-prototype-builtins`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-prototype-builtins.ts): rejects direct `Object.prototype` method calls.
|
|
163
|
+
- [`no-regex-spaces`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-regex-spaces.ts): rejects repeated literal spaces in regexes.
|
|
164
|
+
- [`no-require-imports`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-require-imports.ts): rejects CommonJS `require` imports.
|
|
165
|
+
- [`no-return-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-return-assign.ts): rejects assignments in `return`.
|
|
166
|
+
- [`no-script-url`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-script-url.ts): rejects `javascript:` URLs.
|
|
167
|
+
- [`no-self-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-self-assign.ts): rejects assignments to the same value.
|
|
168
|
+
- [`no-self-compare`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-self-compare.ts): rejects comparing a value to itself.
|
|
169
|
+
- [`no-sequences`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-sequences.ts): rejects comma expressions.
|
|
170
|
+
- [`no-shadow-restricted-names`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-shadow-restricted-names.ts): rejects shadowing restricted globals.
|
|
171
|
+
- [`no-sparse-arrays`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-sparse-arrays.ts): rejects sparse arrays.
|
|
172
|
+
- [`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.
|
|
173
|
+
- [`no-this-alias`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-this-alias.ts): rejects aliasing `this` to locals.
|
|
174
|
+
- [`no-throw-literal`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-throw-literal.ts): rejects throwing literals.
|
|
175
|
+
- [`no-undef-init`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-undef-init.ts): rejects initializing to `undefined`.
|
|
176
|
+
- [`no-undefined`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-undefined.ts): rejects the global `undefined` identifier.
|
|
177
|
+
- [`no-unneeded-ternary`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unneeded-ternary.ts): rejects redundant ternary expressions.
|
|
178
|
+
- [`no-unsafe-finally`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-finally.ts): rejects control flow from `finally`.
|
|
179
|
+
- [`no-unsafe-negation`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-negation.ts): rejects unsafe negation before relational checks.
|
|
180
|
+
- [`no-unused-expressions`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unused-expressions.ts): rejects expression statements with no effect.
|
|
181
|
+
- [`no-useless-call`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-call.ts): rejects unnecessary `.call()` and `.apply()`.
|
|
182
|
+
- [`no-useless-catch`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-catch.ts): rejects catch blocks that only rethrow.
|
|
183
|
+
- [`no-useless-computed-key`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-computed-key.ts): rejects unnecessary computed property keys.
|
|
184
|
+
- [`no-useless-concat`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-concat.ts): rejects unnecessary string concatenation.
|
|
185
|
+
- [`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.
|
|
186
|
+
- [`no-var`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-var.ts): rejects `var`.
|
|
187
|
+
- [`no-with`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-with.ts): rejects `with` statements.
|
|
188
|
+
- [`object-shorthand`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/object-shorthand.ts): requires object property shorthand where possible.
|
|
189
|
+
- [`operator-assignment`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/operator-assignment.ts): prefers compound assignment operators.
|
|
190
|
+
- [`prefer-as-const`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-as-const.ts): prefers `as const` for literal assertions.
|
|
191
|
+
- [`prefer-enum-initializers`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-enum-initializers.ts): requires explicit enum member initializers.
|
|
192
|
+
- [`prefer-exponentiation-operator`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-exponentiation-operator.ts): prefers `**` over `Math.pow`.
|
|
193
|
+
- [`prefer-for-of`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-for-of.ts): prefers `for...of` for simple array iteration.
|
|
194
|
+
- [`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.
|
|
195
|
+
- [`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.
|
|
196
|
+
- [`prefer-spread`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-spread.ts): prefers spread arguments over `.apply`.
|
|
197
|
+
- [`prefer-template`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-template.ts): prefers template literals over string concatenation.
|
|
198
|
+
- [`radix`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/radix.ts): requires a radix argument for `parseInt`.
|
|
199
|
+
- [`require-yield`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/require-yield.ts): requires generator functions to contain `yield`.
|
|
200
|
+
- [`triple-slash-reference`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/triple-slash-reference/violation.ts): rejects triple-slash reference directives.
|
|
201
|
+
- [`use-isnan`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/use-isnan.ts): requires `Number.isNaN`/`isNaN` for `NaN` checks.
|
|
202
|
+
- [`valid-typeof`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/valid-typeof.ts): restricts `typeof` comparisons to valid strings.
|
|
203
|
+
- [`vars-on-top`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/vars-on-top.ts): requires `var` declarations at the top of their scope.
|
|
204
|
+
- [`yoda`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/yoda.ts): rejects literal-first comparisons.
|
package/go-plugin/go.mod
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module github.com/samchon/ttsc/packages/lint/go-plugin
|
|
2
|
+
|
|
3
|
+
go 1.26
|
|
4
|
+
|
|
5
|
+
// The plugin depends only on the `microsoft/typescript-go/shim/*`
|
|
6
|
+
// modules so that `go mod tidy` works against the public proxy. The
|
|
7
|
+
// bootstrap glue (Program creation, diagnostic rendering, emit) is
|
|
8
|
+
// inlined under ./lint/host.go to avoid a transitive dependency on the
|
|
9
|
+
// in-tree `github.com/samchon/ttsc/packages/ttsc` module — that module
|
|
10
|
+
// has no public version tag and would only resolve through ttsc's
|
|
11
|
+
// scratch-dir go.work overlay, which conflicts with go.mod-level
|
|
12
|
+
// replace directives.
|
|
13
|
+
|
|
14
|
+
require (
|
|
15
|
+
github.com/microsoft/typescript-go/shim/ast v0.0.0
|
|
16
|
+
github.com/microsoft/typescript-go/shim/bundled v0.0.0
|
|
17
|
+
github.com/microsoft/typescript-go/shim/checker v0.0.0
|
|
18
|
+
github.com/microsoft/typescript-go/shim/compiler v0.0.0
|
|
19
|
+
github.com/microsoft/typescript-go/shim/core v0.0.0
|
|
20
|
+
github.com/microsoft/typescript-go/shim/diagnosticwriter v0.0.0
|
|
21
|
+
github.com/microsoft/typescript-go/shim/parser v0.0.0
|
|
22
|
+
github.com/microsoft/typescript-go/shim/scanner v0.0.0
|
|
23
|
+
github.com/microsoft/typescript-go/shim/tsoptions v0.0.0
|
|
24
|
+
github.com/microsoft/typescript-go/shim/tspath v0.0.0
|
|
25
|
+
github.com/microsoft/typescript-go/shim/vfs v0.0.0
|
|
26
|
+
github.com/microsoft/typescript-go/shim/vfs/cachedvfs v0.0.0
|
|
27
|
+
github.com/microsoft/typescript-go/shim/vfs/osvfs v0.0.0
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
require (
|
|
31
|
+
github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
|
|
32
|
+
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
|
33
|
+
github.com/microsoft/typescript-go v0.0.0-20260424234512-515d036f927a // indirect
|
|
34
|
+
github.com/zeebo/xxh3 v1.1.0 // indirect
|
|
35
|
+
golang.org/x/sync v0.20.0 // indirect
|
|
36
|
+
golang.org/x/sys v0.42.0 // indirect
|
|
37
|
+
golang.org/x/text v0.35.0 // indirect
|
|
38
|
+
)
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
package lint
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"strings"
|
|
5
|
+
|
|
6
|
+
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
7
|
+
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// nodeText returns the source text under a node with all leading
|
|
11
|
+
// trivia stripped — both whitespace AND comments. Used by rules that
|
|
12
|
+
// compare textual identity (e.g. `no-self-assign`, `no-self-compare`,
|
|
13
|
+
// `operator-assignment`); naively reading `src[node.Pos():node.End()]`
|
|
14
|
+
// would include any preceding comment because tsgo's Pos points at
|
|
15
|
+
// the start of leading trivia, not the actual token.
|
|
16
|
+
func nodeText(file *shimast.SourceFile, node *shimast.Node) string {
|
|
17
|
+
if file == nil || node == nil {
|
|
18
|
+
return ""
|
|
19
|
+
}
|
|
20
|
+
src := file.Text()
|
|
21
|
+
end := node.End()
|
|
22
|
+
pos := shimscanner.SkipTrivia(src, node.Pos())
|
|
23
|
+
if pos < 0 || end > len(src) || pos >= end {
|
|
24
|
+
return ""
|
|
25
|
+
}
|
|
26
|
+
return strings.TrimRight(src[pos:end], " \t\r\n")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// identifierText returns the lexical name of an Identifier node, or "" if
|
|
30
|
+
// the node isn't an Identifier.
|
|
31
|
+
func identifierText(node *shimast.Node) string {
|
|
32
|
+
if node == nil || node.Kind != shimast.KindIdentifier {
|
|
33
|
+
return ""
|
|
34
|
+
}
|
|
35
|
+
id := node.AsIdentifier()
|
|
36
|
+
if id == nil {
|
|
37
|
+
return ""
|
|
38
|
+
}
|
|
39
|
+
return id.Text
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// stripParens descends through ParenthesizedExpression nodes and returns
|
|
43
|
+
// the first non-parenthesized child. ESLint rules typically operate on
|
|
44
|
+
// the canonical form.
|
|
45
|
+
func stripParens(node *shimast.Node) *shimast.Node {
|
|
46
|
+
for node != nil && node.Kind == shimast.KindParenthesizedExpression {
|
|
47
|
+
next := node.AsParenthesizedExpression()
|
|
48
|
+
if next == nil || next.Expression == nil {
|
|
49
|
+
return node
|
|
50
|
+
}
|
|
51
|
+
node = next.Expression
|
|
52
|
+
}
|
|
53
|
+
return node
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// isMatchingPropertyAccess reports whether `node` reads the chain
|
|
57
|
+
// `head.tail[0].tail[1]…`. Useful for detecting `obj.__proto__` or
|
|
58
|
+
// `console.log` shapes regardless of nesting.
|
|
59
|
+
func isMatchingPropertyAccess(node *shimast.Node, head string, tail ...string) bool {
|
|
60
|
+
if node == nil || node.Kind != shimast.KindPropertyAccessExpression {
|
|
61
|
+
return false
|
|
62
|
+
}
|
|
63
|
+
chain := []*shimast.Node{}
|
|
64
|
+
cur := node
|
|
65
|
+
for cur != nil && cur.Kind == shimast.KindPropertyAccessExpression {
|
|
66
|
+
access := cur.AsPropertyAccessExpression()
|
|
67
|
+
if access == nil {
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
chain = append([]*shimast.Node{access.Name()}, chain...)
|
|
71
|
+
cur = access.Expression
|
|
72
|
+
}
|
|
73
|
+
if cur == nil || identifierText(cur) != head {
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
if len(chain) != len(tail) {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
for i, want := range tail {
|
|
80
|
+
if identifierText(chain[i]) != want {
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// isLiteralBoolean returns the boolean value (and ok=true) for a
|
|
88
|
+
// `KindTrueKeyword` / `KindFalseKeyword` literal. Other nodes return
|
|
89
|
+
// (false, false).
|
|
90
|
+
func isLiteralBoolean(node *shimast.Node) (bool, bool) {
|
|
91
|
+
if node == nil {
|
|
92
|
+
return false, false
|
|
93
|
+
}
|
|
94
|
+
switch node.Kind {
|
|
95
|
+
case shimast.KindTrueKeyword:
|
|
96
|
+
return true, true
|
|
97
|
+
case shimast.KindFalseKeyword:
|
|
98
|
+
return false, true
|
|
99
|
+
}
|
|
100
|
+
return false, false
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// isLiteralExpression returns true for nodes whose value is intrinsically
|
|
104
|
+
// truthy / falsy at parse time — these flag `no-constant-condition` etc.
|
|
105
|
+
func isLiteralExpression(node *shimast.Node) bool {
|
|
106
|
+
if node == nil {
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
109
|
+
switch node.Kind {
|
|
110
|
+
case
|
|
111
|
+
shimast.KindStringLiteral,
|
|
112
|
+
shimast.KindNumericLiteral,
|
|
113
|
+
shimast.KindBigIntLiteral,
|
|
114
|
+
shimast.KindNoSubstitutionTemplateLiteral,
|
|
115
|
+
shimast.KindRegularExpressionLiteral,
|
|
116
|
+
shimast.KindTrueKeyword,
|
|
117
|
+
shimast.KindFalseKeyword,
|
|
118
|
+
shimast.KindNullKeyword:
|
|
119
|
+
return true
|
|
120
|
+
}
|
|
121
|
+
return false
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// callCalleeName returns the simple-identifier callee of a CallExpression
|
|
125
|
+
// (e.g. `eval` from `eval("...")`). Returns "" when the callee is more
|
|
126
|
+
// complex than a bare identifier.
|
|
127
|
+
func callCalleeName(call *shimast.CallExpression) string {
|
|
128
|
+
if call == nil || call.Expression == nil {
|
|
129
|
+
return ""
|
|
130
|
+
}
|
|
131
|
+
return identifierText(call.Expression)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// numericLiteralText returns the literal text of a numeric / bigint
|
|
135
|
+
// literal, normalized for the comparisons rules need (`-0`, `0xFF`).
|
|
136
|
+
func numericLiteralText(node *shimast.Node) string {
|
|
137
|
+
if node == nil {
|
|
138
|
+
return ""
|
|
139
|
+
}
|
|
140
|
+
switch node.Kind {
|
|
141
|
+
case shimast.KindNumericLiteral:
|
|
142
|
+
if lit := node.AsNumericLiteral(); lit != nil {
|
|
143
|
+
return lit.Text
|
|
144
|
+
}
|
|
145
|
+
case shimast.KindBigIntLiteral:
|
|
146
|
+
if lit := node.AsBigIntLiteral(); lit != nil {
|
|
147
|
+
return lit.Text
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return ""
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// stringLiteralText returns the value of a string-shaped literal:
|
|
154
|
+
// StringLiteral or NoSubstitutionTemplateLiteral.
|
|
155
|
+
func stringLiteralText(node *shimast.Node) string {
|
|
156
|
+
if node == nil {
|
|
157
|
+
return ""
|
|
158
|
+
}
|
|
159
|
+
switch node.Kind {
|
|
160
|
+
case shimast.KindStringLiteral:
|
|
161
|
+
if lit := node.AsStringLiteral(); lit != nil {
|
|
162
|
+
return lit.Text
|
|
163
|
+
}
|
|
164
|
+
case shimast.KindNoSubstitutionTemplateLiteral:
|
|
165
|
+
if lit := node.AsNoSubstitutionTemplateLiteral(); lit != nil {
|
|
166
|
+
return lit.Text
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return ""
|
|
170
|
+
}
|