lintcn 0.0.1 → 0.2.0
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/CHANGELOG.md +31 -0
- package/LICENSE +21 -0
- package/README.md +157 -5
- package/dist/cache.d.ts +9 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +88 -0
- package/dist/cli.js +71 -3
- package/dist/codegen.d.ts +18 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +607 -0
- package/dist/commands/add.d.ts +2 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +101 -0
- package/dist/commands/lint.d.ts +10 -0
- package/dist/commands/lint.d.ts.map +1 -0
- package/dist/commands/lint.js +78 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +24 -0
- package/dist/commands/remove.d.ts +2 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +31 -0
- package/dist/discover.d.ts +16 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +44 -0
- package/dist/exec.d.ts +10 -0
- package/dist/exec.d.ts.map +1 -0
- package/dist/exec.js +34 -0
- package/dist/hash.d.ts +5 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +33 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/paths.d.ts +2 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +5 -0
- package/package.json +12 -9
- package/src/cache.ts +106 -0
- package/src/cli.ts +80 -2
- package/src/codegen.ts +640 -0
- package/src/commands/add.ts +118 -0
- package/src/commands/lint.ts +110 -0
- package/src/commands/list.ts +33 -0
- package/src/commands/remove.ts +41 -0
- package/src/discover.ts +69 -0
- package/src/exec.ts +50 -0
- package/src/hash.ts +45 -0
- package/src/index.ts +7 -1
- package/src/paths.ts +7 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
## 0.2.0
|
|
2
|
+
|
|
3
|
+
1. **Pinned tsgolint version** — each lintcn release bundles a specific tsgolint version (`v0.9.2`). Builds are now reproducible: everyone on the same lintcn version compiles against the same tsgolint API. Previously used `main` branch which was non-deterministic.
|
|
4
|
+
|
|
5
|
+
2. **`--tsgolint-version` flag** — override the pinned version for testing unreleased tsgolint:
|
|
6
|
+
```bash
|
|
7
|
+
npx lintcn lint --tsgolint-version v0.10.0
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
3. **Version pinning docs** — README now explains why you should pin lintcn in `package.json` (no `^` or `~`) and how to update safely.
|
|
11
|
+
|
|
12
|
+
## 0.1.0
|
|
13
|
+
|
|
14
|
+
1. **Initial release** — CLI for adding type-aware TypeScript lint rules as Go files to your project:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx lintcn add https://github.com/user/repo/blob/main/rules/no_unhandled_error.go
|
|
18
|
+
npx lintcn lint
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
2. **`lintcn add <url>`** — fetch a `.go` rule file by URL into `.lintcn/`. Normalizes GitHub blob URLs to raw URLs automatically. Also fetches the matching `_test.go` if present. Rewrites the package declaration to `package lintcn` and injects a `// lintcn:source` comment.
|
|
22
|
+
|
|
23
|
+
3. **`lintcn lint`** — builds a custom tsgolint binary (all 50+ built-in rules + your custom rules) and runs it against the project. Binary is cached by SHA-256 content hash — rebuilds only when rules change.
|
|
24
|
+
|
|
25
|
+
4. **`lintcn build`** — build the custom binary without running it. Prints the binary path.
|
|
26
|
+
|
|
27
|
+
5. **`lintcn list`** — list installed rules with descriptions parsed from `// lintcn:` metadata comments.
|
|
28
|
+
|
|
29
|
+
6. **`lintcn remove <name>`** — delete a rule and its test file from `.lintcn/`.
|
|
30
|
+
|
|
31
|
+
7. **Editor/LSP support** — generates `go.work` and `go.mod` inside `.lintcn/` so gopls provides full autocomplete, go-to-definition, and type checking on tsgolint APIs while writing rules.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kimaki
|
|
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
CHANGED
|
@@ -1,12 +1,164 @@
|
|
|
1
1
|
# lintcn
|
|
2
2
|
|
|
3
|
-
The [shadcn](https://ui.shadcn.com) for type-aware TypeScript lint rules.
|
|
3
|
+
The [shadcn](https://ui.shadcn.com) for type-aware TypeScript lint rules. Powered by [tsgolint](https://github.com/oxc-project/tsgolint).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Add rules by URL, own the source, customize freely. Rules are Go files that use the TypeScript type checker for deep analysis — things ESLint can't do.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
11
|
-
npx lintcn add no-unused-result
|
|
10
|
+
npm install -D lintcn
|
|
12
11
|
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Add a rule by URL
|
|
17
|
+
npx lintcn add https://github.com/user/repo/blob/main/rules/no_unhandled_error.go
|
|
18
|
+
|
|
19
|
+
# Lint your project
|
|
20
|
+
npx lintcn lint
|
|
21
|
+
|
|
22
|
+
# Lint with a specific tsconfig
|
|
23
|
+
npx lintcn lint --tsconfig tsconfig.build.json
|
|
24
|
+
|
|
25
|
+
# List installed rules
|
|
26
|
+
npx lintcn list
|
|
27
|
+
|
|
28
|
+
# Remove a rule
|
|
29
|
+
npx lintcn remove no-unhandled-error
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## How it works
|
|
33
|
+
|
|
34
|
+
Rules live as `.go` files in `.lintcn/` at your project root. You own the source — edit, customize, delete.
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
my-project/
|
|
38
|
+
├── .lintcn/
|
|
39
|
+
│ ├── .gitignore ← ignores generated Go files
|
|
40
|
+
│ ├── no_unhandled_error.go ← your rule (committed)
|
|
41
|
+
│ └── no_unhandled_error_test.go ← its tests (committed)
|
|
42
|
+
├── src/
|
|
43
|
+
│ ├── index.ts
|
|
44
|
+
│ └── ...
|
|
45
|
+
├── tsconfig.json
|
|
46
|
+
└── package.json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
When you run `npx lintcn lint`, the CLI:
|
|
50
|
+
|
|
51
|
+
1. Scans `.lintcn/*.go` for rule definitions
|
|
52
|
+
2. Generates a Go workspace with all 50+ built-in tsgolint rules + your custom rules
|
|
53
|
+
3. Compiles a custom binary (cached — rebuilds only when rules change)
|
|
54
|
+
4. Runs the binary against your project
|
|
55
|
+
|
|
56
|
+
## Writing a rule
|
|
57
|
+
|
|
58
|
+
Every rule is a Go file with `package lintcn` that exports a `rule.Rule` variable.
|
|
59
|
+
|
|
60
|
+
Here's a rule that errors when you discard the return value of a function that returns `Error | T` — enforcing the [errore](https://errore.org) pattern:
|
|
61
|
+
|
|
62
|
+
```go
|
|
63
|
+
// lintcn:name no-unhandled-error
|
|
64
|
+
// lintcn:description Disallow discarding Error-typed return values
|
|
65
|
+
|
|
66
|
+
package lintcn
|
|
67
|
+
|
|
68
|
+
import (
|
|
69
|
+
"github.com/microsoft/typescript-go/shim/ast"
|
|
70
|
+
"github.com/microsoft/typescript-go/shim/checker"
|
|
71
|
+
"github.com/typescript-eslint/tsgolint/internal/rule"
|
|
72
|
+
"github.com/typescript-eslint/tsgolint/internal/utils"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
var NoUnhandledErrorRule = rule.Rule{
|
|
76
|
+
Name: "no-unhandled-error",
|
|
77
|
+
Run: func(ctx rule.RuleContext, options any) rule.RuleListeners {
|
|
78
|
+
return rule.RuleListeners{
|
|
79
|
+
ast.KindExpressionStatement: func(node *ast.Node) {
|
|
80
|
+
expression := ast.SkipParentheses(node.AsExpressionStatement().Expression)
|
|
81
|
+
|
|
82
|
+
if ast.IsVoidExpression(expression) {
|
|
83
|
+
return // void = intentional discard
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
innerExpr := expression
|
|
87
|
+
if ast.IsAwaitExpression(innerExpr) {
|
|
88
|
+
innerExpr = ast.SkipParentheses(innerExpr.Expression())
|
|
89
|
+
}
|
|
90
|
+
if !ast.IsCallExpression(innerExpr) {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
t := ctx.TypeChecker.GetTypeAtLocation(expression)
|
|
95
|
+
|
|
96
|
+
if utils.IsTypeFlagSet(t, checker.TypeFlagsVoid|checker.TypeFlagsUndefined|checker.TypeFlagsNever) {
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for _, part := range utils.UnionTypeParts(t) {
|
|
101
|
+
if utils.IsErrorLike(ctx.Program, ctx.TypeChecker, part) {
|
|
102
|
+
ctx.ReportNode(node, rule.RuleMessage{
|
|
103
|
+
Id: "noUnhandledError",
|
|
104
|
+
Description: "Error-typed return value is not handled.",
|
|
105
|
+
})
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
This catches code like:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// error — result discarded, Error not handled
|
|
119
|
+
getUser("id") // returns Error | User
|
|
120
|
+
await fetchData("/api") // returns Promise<Error | Data>
|
|
121
|
+
|
|
122
|
+
// ok — result is checked
|
|
123
|
+
const user = getUser("id")
|
|
124
|
+
if (user instanceof Error) return user
|
|
125
|
+
|
|
126
|
+
// ok — explicitly discarded
|
|
127
|
+
void getUser("id")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Version pinning
|
|
131
|
+
|
|
132
|
+
**Pin lintcn in your `package.json`** — do not use `^` or `~`:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"devDependencies": {
|
|
137
|
+
"lintcn": "0.1.0"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Each lintcn release bundles a specific tsgolint version. Updating lintcn can change the underlying tsgolint API, which may cause your rules to no longer compile. Always update consciously:
|
|
143
|
+
|
|
144
|
+
1. Check the [changelog](./CHANGELOG.md) for tsgolint version changes
|
|
145
|
+
2. Run `npx lintcn build` after updating to verify your rules still compile
|
|
146
|
+
3. Fix any compilation errors before committing
|
|
147
|
+
|
|
148
|
+
You can test against an unreleased tsgolint version without updating lintcn:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npx lintcn lint --tsgolint-version v0.10.0
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Prerequisites
|
|
155
|
+
|
|
156
|
+
- **Node.js** — for the CLI
|
|
157
|
+
- **Go 1.26+** — for compiling rules (`go.dev/dl`)
|
|
158
|
+
- **Git** — for cloning tsgolint source on first build
|
|
159
|
+
|
|
160
|
+
Go is only needed for `lintcn lint` / `lintcn build`. Adding and listing rules works without Go.
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
MIT
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const DEFAULT_TSGOLINT_VERSION = "v0.9.2";
|
|
2
|
+
export declare function getCacheDir(): string;
|
|
3
|
+
export declare function getTsgolintSourceDir(version: string): string;
|
|
4
|
+
export declare function getBinDir(): string;
|
|
5
|
+
export declare function getBinaryPath(contentHash: string): string;
|
|
6
|
+
export declare function getBuildDir(): string;
|
|
7
|
+
export declare function ensureTsgolintSource(version: string): Promise<string>;
|
|
8
|
+
export declare function cachedBinaryExists(contentHash: string): boolean;
|
|
9
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,wBAAwB,WAAW,CAAA;AAEhD,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA2D3E;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAQ/D"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Manage cached tsgolint source clone and compiled binaries.
|
|
2
|
+
// Cache lives in ~/.cache/lintcn/ with structure:
|
|
3
|
+
// tsgolint/<version>/ — cloned tsgolint source (read-only)
|
|
4
|
+
// bin/<content-hash> — compiled binaries
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { execAsync } from "./exec.js";
|
|
9
|
+
// Pinned tsgolint version — updated with each lintcn release.
|
|
10
|
+
// This ensures reproducible builds: every user on the same lintcn version
|
|
11
|
+
// compiles rules against the same tsgolint API. Changing this is a conscious
|
|
12
|
+
// decision — tsgolint API changes can break user rules.
|
|
13
|
+
export const DEFAULT_TSGOLINT_VERSION = 'v0.9.2';
|
|
14
|
+
export function getCacheDir() {
|
|
15
|
+
return path.join(os.homedir(), '.cache', 'lintcn');
|
|
16
|
+
}
|
|
17
|
+
export function getTsgolintSourceDir(version) {
|
|
18
|
+
return path.join(getCacheDir(), 'tsgolint', version);
|
|
19
|
+
}
|
|
20
|
+
export function getBinDir() {
|
|
21
|
+
return path.join(getCacheDir(), 'bin');
|
|
22
|
+
}
|
|
23
|
+
export function getBinaryPath(contentHash) {
|
|
24
|
+
return path.join(getBinDir(), contentHash);
|
|
25
|
+
}
|
|
26
|
+
export function getBuildDir() {
|
|
27
|
+
return path.join(getCacheDir(), 'build');
|
|
28
|
+
}
|
|
29
|
+
export async function ensureTsgolintSource(version) {
|
|
30
|
+
const sourceDir = getTsgolintSourceDir(version);
|
|
31
|
+
const readyMarker = path.join(sourceDir, '.lintcn-ready');
|
|
32
|
+
if (fs.existsSync(readyMarker)) {
|
|
33
|
+
return sourceDir;
|
|
34
|
+
}
|
|
35
|
+
console.log(`Cloning tsgolint@${version}...`);
|
|
36
|
+
fs.mkdirSync(sourceDir, { recursive: true });
|
|
37
|
+
// clone with depth 1 for speed — --branch works with tags and branches
|
|
38
|
+
const cloneArgs = [
|
|
39
|
+
'clone', '--depth', '1',
|
|
40
|
+
'--branch', version,
|
|
41
|
+
'--recurse-submodules', '--shallow-submodules',
|
|
42
|
+
'https://github.com/oxc-project/tsgolint.git', sourceDir,
|
|
43
|
+
];
|
|
44
|
+
await execAsync('git', cloneArgs);
|
|
45
|
+
// apply patches if they exist
|
|
46
|
+
const patchesDir = path.join(sourceDir, 'patches');
|
|
47
|
+
if (fs.existsSync(patchesDir)) {
|
|
48
|
+
const patches = fs.readdirSync(patchesDir).filter((f) => {
|
|
49
|
+
return f.endsWith('.patch');
|
|
50
|
+
}).sort();
|
|
51
|
+
if (patches.length > 0) {
|
|
52
|
+
console.log(`Applying ${patches.length} patches...`);
|
|
53
|
+
const patchPaths = patches.map((p) => {
|
|
54
|
+
return path.join('..', 'patches', p);
|
|
55
|
+
});
|
|
56
|
+
await execAsync('git', ['am', '--3way', '--no-gpg-sign', ...patchPaths], {
|
|
57
|
+
cwd: path.join(sourceDir, 'typescript-go'),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// copy internal/collections from typescript-go (required by tsgolint, done by `just init`)
|
|
62
|
+
const collectionsDir = path.join(sourceDir, 'internal', 'collections');
|
|
63
|
+
const tsGoCollections = path.join(sourceDir, 'typescript-go', 'internal', 'collections');
|
|
64
|
+
if (!fs.existsSync(collectionsDir) && fs.existsSync(tsGoCollections)) {
|
|
65
|
+
fs.mkdirSync(collectionsDir, { recursive: true });
|
|
66
|
+
const files = fs.readdirSync(tsGoCollections).filter((f) => {
|
|
67
|
+
return f.endsWith('.go') && !f.endsWith('_test.go');
|
|
68
|
+
});
|
|
69
|
+
for (const file of files) {
|
|
70
|
+
fs.copyFileSync(path.join(tsGoCollections, file), path.join(collectionsDir, file));
|
|
71
|
+
}
|
|
72
|
+
console.log(`Copied ${files.length} collection files`);
|
|
73
|
+
}
|
|
74
|
+
// write ready marker
|
|
75
|
+
fs.writeFileSync(readyMarker, new Date().toISOString());
|
|
76
|
+
console.log('tsgolint source ready');
|
|
77
|
+
return sourceDir;
|
|
78
|
+
}
|
|
79
|
+
export function cachedBinaryExists(contentHash) {
|
|
80
|
+
const binPath = getBinaryPath(contentHash);
|
|
81
|
+
try {
|
|
82
|
+
fs.accessSync(binPath, fs.constants.X_OK);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,72 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
// lintcn — the shadcn for type-aware TypeScript lint rules.
|
|
3
|
+
// Add rules by URL, compile, and run them via tsgolint.
|
|
4
|
+
import { goke } from 'goke';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import { addRule } from "./commands/add.js";
|
|
7
|
+
import { lint, buildBinary } from "./commands/lint.js";
|
|
8
|
+
import { listRules } from "./commands/list.js";
|
|
9
|
+
import { removeRule } from "./commands/remove.js";
|
|
10
|
+
import { DEFAULT_TSGOLINT_VERSION } from "./cache.js";
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
const packageJson = require('../package.json');
|
|
13
|
+
const cli = goke('lintcn');
|
|
14
|
+
cli
|
|
15
|
+
.command('add <url>', 'Add a rule by URL. Fetches the .go file and copies it into .lintcn/')
|
|
16
|
+
.example('# Add a rule from GitHub')
|
|
17
|
+
.example('lintcn add https://github.com/user/repo/blob/main/rules/no_floating_promises.go')
|
|
18
|
+
.example('# Add from raw URL')
|
|
19
|
+
.example('lintcn add https://raw.githubusercontent.com/user/repo/main/rules/no_unused_result.go')
|
|
20
|
+
.action(async (url) => {
|
|
21
|
+
await addRule(url);
|
|
22
|
+
});
|
|
23
|
+
cli
|
|
24
|
+
.command('remove <name>', 'Remove an installed rule from .lintcn/')
|
|
25
|
+
.example('lintcn remove no-floating-promises')
|
|
26
|
+
.action((name) => {
|
|
27
|
+
removeRule(name);
|
|
28
|
+
});
|
|
29
|
+
cli
|
|
30
|
+
.command('list', 'List all installed rules')
|
|
31
|
+
.action(() => {
|
|
32
|
+
listRules();
|
|
33
|
+
});
|
|
34
|
+
cli
|
|
35
|
+
.command('lint', 'Build custom tsgolint binary and run it against the project')
|
|
36
|
+
.option('--rebuild', 'Force rebuild even if cached binary exists')
|
|
37
|
+
.option('--tsconfig <path>', 'Path to tsconfig.json')
|
|
38
|
+
.option('--list-files', 'List matched files')
|
|
39
|
+
.option('--tsgolint-version [version]', 'Override the pinned tsgolint version (tag or commit). For testing unreleased tsgolint versions.')
|
|
40
|
+
.action(async (options) => {
|
|
41
|
+
const tsgolintVersion = options.tsgolintVersion || DEFAULT_TSGOLINT_VERSION;
|
|
42
|
+
const passthroughArgs = [];
|
|
43
|
+
if (options.tsconfig) {
|
|
44
|
+
passthroughArgs.push('--tsconfig', options.tsconfig);
|
|
45
|
+
}
|
|
46
|
+
if (options.listFiles) {
|
|
47
|
+
passthroughArgs.push('--list-files');
|
|
48
|
+
}
|
|
49
|
+
// pass through anything after --
|
|
50
|
+
const doubleDash = options['--'];
|
|
51
|
+
if (doubleDash && Array.isArray(doubleDash)) {
|
|
52
|
+
passthroughArgs.push(...doubleDash);
|
|
53
|
+
}
|
|
54
|
+
const exitCode = await lint({
|
|
55
|
+
rebuild: !!options.rebuild,
|
|
56
|
+
tsgolintVersion,
|
|
57
|
+
passthroughArgs,
|
|
58
|
+
});
|
|
59
|
+
process.exit(exitCode);
|
|
60
|
+
});
|
|
61
|
+
cli
|
|
62
|
+
.command('build', 'Build the custom tsgolint binary without running it')
|
|
63
|
+
.option('--rebuild', 'Force rebuild even if cached binary exists')
|
|
64
|
+
.option('--tsgolint-version [version]', 'Override the pinned tsgolint version (tag or commit). For testing unreleased tsgolint versions.')
|
|
65
|
+
.action(async (options) => {
|
|
66
|
+
const tsgolintVersion = options.tsgolintVersion || DEFAULT_TSGOLINT_VERSION;
|
|
67
|
+
const binaryPath = await buildBinary({ rebuild: !!options.rebuild, tsgolintVersion });
|
|
68
|
+
console.log(binaryPath);
|
|
69
|
+
});
|
|
70
|
+
cli.help();
|
|
71
|
+
cli.version(packageJson.version);
|
|
72
|
+
cli.parse();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RuleMetadata } from './discover.ts';
|
|
2
|
+
/** Generate .lintcn/go.work and .lintcn/go.mod for editor/gopls support.
|
|
3
|
+
*
|
|
4
|
+
* Key learnings from testing:
|
|
5
|
+
* - Module name MUST be a child path of github.com/typescript-eslint/tsgolint
|
|
6
|
+
* so Go allows importing internal/ packages across the module boundary.
|
|
7
|
+
* - go.work must `use` both .tsgolint AND .tsgolint/typescript-go since
|
|
8
|
+
* tsgolint's own go.work (which does this) is ignored by the outer workspace.
|
|
9
|
+
* - go.mod should be minimal (no requires) — the workspace resolves everything. */
|
|
10
|
+
export declare function generateEditorGoFiles(lintcnDir: string): void;
|
|
11
|
+
/** Generate build workspace in cache dir for compiling the custom binary */
|
|
12
|
+
export declare function generateBuildWorkspace({ buildDir, tsgolintDir, lintcnDir, rules, }: {
|
|
13
|
+
buildDir: string;
|
|
14
|
+
tsgolintDir: string;
|
|
15
|
+
lintcnDir: string;
|
|
16
|
+
rules: RuleMetadata[];
|
|
17
|
+
}): void;
|
|
18
|
+
//# sourceMappingURL=codegen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAiGjD;;;;;;;oFAOoF;AACpF,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAiC7D;AAED,4EAA4E;AAC5E,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,WAAW,EACX,SAAS,EACT,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB,GAAG,IAAI,CAgDP"}
|