@ttsc/lint 0.12.3 → 0.13.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.
Files changed (74) hide show
  1. package/lib/defaultFormat.d.ts +10 -11
  2. package/lib/defaultFormat.js +10 -11
  3. package/lib/defaultFormat.js.map +1 -1
  4. package/lib/index.js +233 -135
  5. package/lib/index.js.map +1 -1
  6. package/lib/structures/ITtscLintConfig.d.ts +2 -2
  7. package/lib/structures/ITtscLintFormatConfig.d.ts +53 -55
  8. package/lib/structures/ITtscLintPluginConfig.d.ts +10 -77
  9. package/lib/structures/ITtscLintPluginMeta.d.ts +9 -1
  10. package/lib/structures/TtscLintRule.d.ts +10 -1
  11. package/lib/structures/TtscLintRuleMap.d.ts +2 -2
  12. package/lib/structures/TtscLintRuleOptions.d.ts +14 -0
  13. package/linthost/ast_helpers.go +80 -11
  14. package/linthost/compile.go +116 -112
  15. package/linthost/config.go +647 -687
  16. package/linthost/config_format.go +272 -247
  17. package/linthost/contrib_adapter.go +7 -0
  18. package/linthost/directives.go +116 -0
  19. package/linthost/dispatch.go +33 -33
  20. package/linthost/engine.go +156 -43
  21. package/linthost/fix.go +47 -27
  22. package/linthost/flags_gen.go +31 -0
  23. package/linthost/format.go +119 -3
  24. package/linthost/host.go +115 -5
  25. package/linthost/print_dispatch.go +128 -28
  26. package/linthost/print_doc.go +23 -0
  27. package/linthost/print_engine.go +168 -4
  28. package/linthost/print_nodes_array.go +17 -7
  29. package/linthost/print_nodes_call.go +138 -20
  30. package/linthost/print_nodes_function.go +353 -0
  31. package/linthost/print_nodes_imports.go +46 -29
  32. package/linthost/print_nodes_list.go +86 -5
  33. package/linthost/print_nodes_object.go +56 -11
  34. package/linthost/rules_arrays.go +5 -2
  35. package/linthost/rules_debugger.go +3 -2
  36. package/linthost/rules_dupes.go +7 -4
  37. package/linthost/rules_empty.go +3 -2
  38. package/linthost/rules_escape.go +35 -3
  39. package/linthost/rules_eval.go +3 -0
  40. package/linthost/rules_finally.go +11 -0
  41. package/linthost/rules_format_jsdoc.go +7 -0
  42. package/linthost/rules_format_print_width.go +270 -15
  43. package/linthost/rules_format_quotes.go +3 -0
  44. package/linthost/rules_format_sort_imports.go +4 -0
  45. package/linthost/rules_gap.go +75 -3
  46. package/linthost/rules_imports.go +5 -7
  47. package/linthost/rules_logic.go +75 -5
  48. package/linthost/rules_loops.go +4 -0
  49. package/linthost/rules_misc.go +4 -2
  50. package/linthost/rules_params.go +7 -11
  51. package/linthost/rules_problems.go +89 -22
  52. package/linthost/rules_promise.go +15 -0
  53. package/linthost/rules_protos.go +3 -2
  54. package/linthost/rules_self.go +6 -0
  55. package/linthost/rules_strings.go +10 -0
  56. package/linthost/rules_suggestions.go +174 -9
  57. package/linthost/rules_throw.go +2 -0
  58. package/linthost/rules_ts.go +13 -0
  59. package/linthost/rules_ts_extra.go +25 -8
  60. package/linthost/rules_var.go +15 -2
  61. package/package.json +3 -3
  62. package/plugin/main.go +4 -4
  63. package/rule/astutil/astutil.go +12 -0
  64. package/rule/rule.go +123 -123
  65. package/src/defaultFormat.ts +10 -11
  66. package/src/index.ts +257 -168
  67. package/src/structures/ITtscLintConfig.ts +2 -2
  68. package/src/structures/ITtscLintFormatConfig.ts +53 -55
  69. package/src/structures/ITtscLintPluginConfig.ts +10 -83
  70. package/src/structures/ITtscLintPluginMeta.ts +9 -1
  71. package/src/structures/TtscLintRule.ts +10 -1
  72. package/src/structures/TtscLintRuleMap.ts +17 -18
  73. package/src/structures/TtscLintRuleOptions.ts +15 -0
  74. package/linthost/eslint_runtime.go +0 -320
@@ -1,320 +0,0 @@
1
- package linthost
2
-
3
- import (
4
- "encoding/json"
5
- "fmt"
6
- "os"
7
- "os/exec"
8
- "path/filepath"
9
- "strings"
10
- "unicode/utf8"
11
-
12
- shimast "github.com/microsoft/typescript-go/shim/ast"
13
- shimdw "github.com/microsoft/typescript-go/shim/diagnosticwriter"
14
- )
15
-
16
- type eslintRuntimeProvider interface {
17
- ExternalConfigPath() string
18
- WantsESLintRuntime() bool
19
- RequiresESLintRuntime() bool
20
- }
21
-
22
- type eslintRuntimeOutput struct {
23
- Missing bool `json:"missing"`
24
- Fixed int `json:"fixed"`
25
- Results []eslintRuntimeFile `json:"results"`
26
- }
27
-
28
- type eslintRuntimeFile struct {
29
- FilePath string `json:"filePath"`
30
- Messages []eslintRuntimeMessage `json:"messages"`
31
- }
32
-
33
- type eslintRuntimeMessage struct {
34
- RuleID string `json:"ruleId"`
35
- Severity int `json:"severity"`
36
- Message string `json:"message"`
37
- Line int `json:"line"`
38
- Column int `json:"column"`
39
- EndLine int `json:"endLine"`
40
- EndColumn int `json:"endColumn"`
41
- }
42
-
43
- func runExternalESLintDiagnostics(
44
- resolver RuleResolver,
45
- cwd string,
46
- files []*shimast.SourceFile,
47
- ) ([]*shimdw.LintDiagnostic, bool, error) {
48
- provider, ok := resolver.(eslintRuntimeProvider)
49
- if !ok || !provider.WantsESLintRuntime() {
50
- return nil, false, nil
51
- }
52
- configPath := provider.ExternalConfigPath()
53
- if configPath == "" {
54
- return nil, false, nil
55
- }
56
-
57
- fileNames := make([]string, 0, len(files))
58
- byPath := make(map[string]*shimast.SourceFile, len(files))
59
- for _, file := range files {
60
- if file == nil || file.IsDeclarationFile {
61
- continue
62
- }
63
- name := file.FileName()
64
- if !filepath.IsAbs(name) {
65
- name = filepath.Join(cwd, name)
66
- }
67
- if abs, err := filepath.Abs(name); err == nil {
68
- name = abs
69
- }
70
- fileNames = append(fileNames, name)
71
- byPath[filepath.ToSlash(name)] = file
72
- }
73
- if len(fileNames) == 0 {
74
- return nil, true, nil
75
- }
76
-
77
- payload, err := json.Marshal(fileNames)
78
- if err != nil {
79
- return nil, false, fmt.Errorf("@ttsc/lint: encode ESLint file list: %w", err)
80
- }
81
-
82
- output, err := runExternalESLint(cwd, configPath, string(payload))
83
- if err != nil {
84
- return nil, false, err
85
- }
86
- if output.Missing {
87
- if provider.RequiresESLintRuntime() {
88
- return nil, false, fmt.Errorf("@ttsc/lint: ESLint runtime is required by %s; install eslint in the project or replace runtime-only config features", configPath)
89
- }
90
- return nil, false, nil
91
- }
92
-
93
- diagnostics := make([]*shimdw.LintDiagnostic, 0)
94
- for _, result := range output.Results {
95
- file := byPath[filepath.ToSlash(result.FilePath)]
96
- if file == nil {
97
- continue
98
- }
99
- for _, msg := range result.Messages {
100
- if msg.Severity == 0 {
101
- continue
102
- }
103
- ruleID := strings.TrimSpace(msg.RuleID)
104
- if ruleID == "" {
105
- ruleID = "eslint"
106
- }
107
- category := shimdw.LintCategoryWarning
108
- if msg.Severity >= 2 {
109
- category = shimdw.LintCategoryError
110
- }
111
- pos := positionOfESLintLocation(file.Text(), msg.Line, msg.Column)
112
- end := positionOfESLintLocation(file.Text(), msg.EndLine, msg.EndColumn)
113
- if end <= pos {
114
- end = pos + 1
115
- }
116
- diagnostics = append(diagnostics, shimdw.NewLintDiagnostic(
117
- file,
118
- pos,
119
- end,
120
- ruleCode(ruleID),
121
- category,
122
- fmt.Sprintf("[%s] %s", ruleID, msg.Message),
123
- ))
124
- }
125
- }
126
- return diagnostics, true, nil
127
- }
128
-
129
- func runExternalESLint(cwd, configPath, fileListJSON string) (*eslintRuntimeOutput, error) {
130
- return runExternalESLintWithMode(cwd, configPath, fileListJSON, false)
131
- }
132
-
133
- func runExternalESLintFixes(
134
- resolver RuleResolver,
135
- cwd string,
136
- files []*shimast.SourceFile,
137
- ) (int, error) {
138
- provider, ok := resolver.(eslintRuntimeProvider)
139
- if !ok || !provider.WantsESLintRuntime() {
140
- return 0, nil
141
- }
142
- configPath := provider.ExternalConfigPath()
143
- if configPath == "" {
144
- return 0, nil
145
- }
146
-
147
- fileNames := make([]string, 0, len(files))
148
- for _, file := range files {
149
- if file == nil || file.IsDeclarationFile {
150
- continue
151
- }
152
- name := file.FileName()
153
- if !filepath.IsAbs(name) {
154
- name = filepath.Join(cwd, name)
155
- }
156
- if abs, err := filepath.Abs(name); err == nil {
157
- name = abs
158
- }
159
- fileNames = append(fileNames, name)
160
- }
161
- if len(fileNames) == 0 {
162
- return 0, nil
163
- }
164
-
165
- payload, err := json.Marshal(fileNames)
166
- if err != nil {
167
- return 0, fmt.Errorf("@ttsc/lint: encode ESLint file list: %w", err)
168
- }
169
-
170
- output, err := runExternalESLintWithMode(cwd, configPath, string(payload), true)
171
- if err != nil {
172
- return 0, err
173
- }
174
- if output.Missing {
175
- if provider.RequiresESLintRuntime() {
176
- return 0, fmt.Errorf("@ttsc/lint: ESLint runtime is required by %s; install eslint in the project or replace runtime-only config features", configPath)
177
- }
178
- return 0, nil
179
- }
180
- return output.Fixed, nil
181
- }
182
-
183
- func runExternalESLintWithMode(cwd, configPath, fileListJSON string, fix bool) (*eslintRuntimeOutput, error) {
184
- node := os.Getenv("TTSC_NODE_BINARY")
185
- if node == "" {
186
- node = "node"
187
- }
188
- mode := "check"
189
- if fix {
190
- mode = "fix"
191
- }
192
- cmd := exec.Command(node, "-e", externalESLintRunnerScript, cwd, configPath, fileListJSON, mode)
193
- cmd.Env = nodeConfigLoaderEnv(configPath)
194
- cmd.Dir = cwd
195
- raw, err := cmd.Output()
196
- if err != nil {
197
- stderr := ""
198
- if exit, ok := err.(*exec.ExitError); ok {
199
- stderr = strings.TrimSpace(string(exit.Stderr))
200
- }
201
- if stderr != "" {
202
- return nil, fmt.Errorf("@ttsc/lint: run ESLint config %s: %s", configPath, stderr)
203
- }
204
- return nil, fmt.Errorf("@ttsc/lint: run ESLint config %s: %w", configPath, err)
205
- }
206
- var output eslintRuntimeOutput
207
- if err := json.Unmarshal(raw, &output); err != nil {
208
- return nil, fmt.Errorf("@ttsc/lint: parse ESLint output for %s: %w", configPath, err)
209
- }
210
- return &output, nil
211
- }
212
-
213
- func positionOfESLintLocation(text string, line, column int) int {
214
- if line <= 0 {
215
- line = 1
216
- }
217
- if column <= 0 {
218
- column = 1
219
- }
220
- lineStart := 0
221
- currentLine := 1
222
- for i := 0; i < len(text) && currentLine < line; {
223
- r, size := utf8.DecodeRuneInString(text[i:])
224
- if r == '\n' {
225
- currentLine++
226
- lineStart = i + size
227
- }
228
- i += size
229
- }
230
- targetUTF16 := column - 1
231
- seenUTF16 := 0
232
- for i := lineStart; i < len(text); {
233
- if seenUTF16 >= targetUTF16 {
234
- return i
235
- }
236
- r, size := utf8.DecodeRuneInString(text[i:])
237
- if r == '\n' || r == '\r' {
238
- return i
239
- }
240
- if r > 0xFFFF {
241
- seenUTF16 += 2
242
- } else {
243
- seenUTF16++
244
- }
245
- i += size
246
- }
247
- return len(text)
248
- }
249
-
250
- const externalESLintRunnerScript = `
251
- const { createRequire } = require("node:module");
252
- const path = require("node:path");
253
-
254
- (async () => {
255
- const cwd = process.argv[1];
256
- const configPath = process.argv[2];
257
- const files = JSON.parse(process.argv[3]);
258
- const shouldFix = process.argv[4] === "fix";
259
- const requireFromProject = createRequire(path.join(cwd, "package.json"));
260
- let eslintPath;
261
- try {
262
- eslintPath = requireFromProject.resolve("eslint");
263
- } catch (error) {
264
- if (error && error.code === "MODULE_NOT_FOUND") {
265
- process.stdout.write(JSON.stringify({ missing: true, results: [] }));
266
- return;
267
- }
268
- throw error;
269
- }
270
- const eslintModule = requireFromProject(eslintPath);
271
-
272
- const ESLintCtor = typeof eslintModule.loadESLint === "function"
273
- ? await eslintModule.loadESLint({ useFlatConfig: true })
274
- : eslintModule.ESLint ?? eslintModule.default?.ESLint ?? eslintModule.default;
275
-
276
- if (typeof ESLintCtor !== "function") {
277
- throw new Error("installed eslint package does not export ESLint or loadESLint");
278
- }
279
-
280
- const eslint = new ESLintCtor({
281
- cwd,
282
- overrideConfigFile: configPath,
283
- fix: shouldFix,
284
- ignore: true,
285
- warnIgnored: false,
286
- });
287
- const results = await eslint.lintFiles(files);
288
- if (shouldFix) {
289
- const outputFixes =
290
- ESLintCtor.outputFixes ||
291
- eslintModule.ESLint?.outputFixes ||
292
- eslintModule.default?.ESLint?.outputFixes;
293
- if (typeof outputFixes !== "function") {
294
- throw new Error("installed eslint package does not expose ESLint.outputFixes");
295
- }
296
- await outputFixes.call(ESLintCtor, results);
297
- }
298
- process.stdout.write(JSON.stringify({
299
- missing: false,
300
- fixed: shouldFix
301
- ? results.filter((result) => typeof result.output === "string").length
302
- : 0,
303
- results: results.map((result) => ({
304
- filePath: result.filePath,
305
- messages: result.messages.map((message) => ({
306
- ruleId: message.ruleId || "eslint",
307
- severity: message.severity,
308
- message: message.message,
309
- line: message.line || 1,
310
- column: message.column || 1,
311
- endLine: message.endLine || message.line || 1,
312
- endColumn: message.endColumn || message.column || 1,
313
- })),
314
- })),
315
- }));
316
- })().catch((error) => {
317
- process.stderr.write(error && error.stack ? error.stack : String(error));
318
- process.exit(1);
319
- });
320
- `