@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 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
+ ![banner of @ttsc/lint](https://raw.githubusercontent.com/samchon/ttsc/refs/heads/master/assets/og.jpg)
4
+
5
+ [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/samchon/ttsc/blob/master/LICENSE)
6
+ [![NPM Version](https://img.shields.io/npm/v/@ttsc/lint.svg)](https://www.npmjs.com/package/@ttsc/lint)
7
+ [![NPM Downloads](https://img.shields.io/npm/dm/@ttsc/lint.svg)](https://www.npmjs.com/package/@ttsc/lint)
8
+ [![Build Status](https://github.com/samchon/ttsc/workflows/test/badge.svg)](https://github.com/samchon/ttsc/actions?query=workflow%3Atest)
9
+ [![Discord Badge](https://img.shields.io/badge/discord-samchon-d91965?style=flat&labelColor=5866f2&logo=discord&logoColor=white&link=https://discord.gg/E94XhzrUCZ)](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.
@@ -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
+ }