ttsc 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.
- package/cmd/platform/main.go +9 -0
- package/cmd/ttsc/api_compile.go +122 -101
- package/cmd/ttsc/api_compile_branches_test.go +55 -57
- package/cmd/ttsc/api_transform.go +67 -49
- package/cmd/ttsc/api_transform_branches_test.go +30 -32
- package/cmd/ttsc/build.go +141 -108
- package/cmd/ttsc/build_branches_test.go +95 -97
- package/cmd/ttsc/filter.go +70 -0
- package/cmd/ttsc/filter_strips_unknown_forwarded_flag_test.go +61 -0
- package/cmd/ttsc/flags_gen.go +30 -0
- package/cmd/ttsc/helpers_test.go +39 -28
- package/cmd/ttsc/main.go +111 -104
- package/cmd/ttsc/main_alias_branches_test.go +21 -23
- package/cmd/ttscserver/main.go +96 -90
- package/cmd/ttscserver/run_lsp_prefers_tsgo_flag_test.go +22 -22
- package/cmd/ttscserver/run_lsp_reports_server_error_test.go +22 -22
- package/cmd/ttscserver/run_lsp_uses_tsgo_environment_test.go +23 -23
- package/cmd/utility-host/main.go +30 -23
- package/driver/lsp.go +53 -7
- package/driver/plugins.go +88 -72
- package/driver/program.go +464 -340
- package/driver/rewrite.go +477 -380
- package/internal/lspserver/lsp_envelope.go +64 -64
- package/internal/lspserver/lsp_frame.go +60 -60
- package/internal/lspserver/lsp_plugin.go +57 -57
- package/internal/lspserver/lsp_proxy.go +265 -251
- package/internal/lspserver/lsp_server.go +155 -144
- package/lib/TtscCompiler.d.ts +7 -0
- package/lib/TtscCompiler.js +7 -0
- package/lib/TtscCompiler.js.map +1 -1
- package/lib/compiler/internal/buildNativeCompiler.d.ts +11 -1
- package/lib/compiler/internal/buildNativeCompiler.js +23 -3
- package/lib/compiler/internal/buildNativeCompiler.js.map +1 -1
- package/lib/compiler/internal/compileProjectInMemory.d.ts +9 -0
- package/lib/compiler/internal/compileProjectInMemory.js +36 -21
- package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
- package/lib/compiler/internal/paths.d.ts +27 -0
- package/lib/compiler/internal/paths.js +70 -0
- package/lib/compiler/internal/paths.js.map +1 -0
- package/lib/compiler/internal/project/readProjectConfig.d.ts +9 -1
- package/lib/compiler/internal/project/readProjectConfig.js +80 -1
- package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
- package/lib/compiler/internal/project/resolveProjectConfig.d.ts +13 -1
- package/lib/compiler/internal/project/resolveProjectConfig.js +42 -1
- package/lib/compiler/internal/project/resolveProjectConfig.js.map +1 -1
- package/lib/compiler/internal/resolveBinary.d.ts +9 -1
- package/lib/compiler/internal/resolveBinary.js +17 -1
- package/lib/compiler/internal/resolveBinary.js.map +1 -1
- package/lib/compiler/internal/resolveEmittedJavaScript.d.ts +16 -1
- package/lib/compiler/internal/resolveEmittedJavaScript.js +42 -10
- package/lib/compiler/internal/resolveEmittedJavaScript.js.map +1 -1
- package/lib/compiler/internal/resolveTsgo.d.ts +21 -1
- package/lib/compiler/internal/resolveTsgo.js +23 -1
- package/lib/compiler/internal/resolveTsgo.js.map +1 -1
- package/lib/compiler/internal/runBuild.d.ts +24 -4
- package/lib/compiler/internal/runBuild.js +355 -93
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/runSingleFileEmit.d.ts +10 -1
- package/lib/compiler/internal/runSingleFileEmit.js +14 -1
- package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
- package/lib/compiler/internal/sharedHostHelpers.d.ts +5 -0
- package/lib/compiler/internal/sharedHostHelpers.js +6 -2
- package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
- package/lib/compiler/internal/spawnNative.d.ts +21 -0
- package/lib/compiler/internal/spawnNative.js +59 -0
- package/lib/compiler/internal/spawnNative.js.map +1 -0
- package/lib/compiler/internal/transformProjectInMemory.d.ts +15 -1
- package/lib/compiler/internal/transformProjectInMemory.js +57 -61
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/flags/parser.d.ts +63 -0
- package/lib/flags/parser.js +254 -0
- package/lib/flags/parser.js.map +1 -0
- package/lib/flags/schema.d.ts +147 -0
- package/lib/flags/schema.js +405 -0
- package/lib/flags/schema.js.map +1 -0
- package/lib/launcher/internal/getCompilerVersionText.js +7 -0
- package/lib/launcher/internal/getCompilerVersionText.js.map +1 -1
- package/lib/launcher/internal/prepareExecution.js +35 -0
- package/lib/launcher/internal/prepareExecution.js.map +1 -1
- package/lib/launcher/internal/resolveCacheDir.d.ts +9 -0
- package/lib/launcher/internal/resolveCacheDir.js +22 -0
- package/lib/launcher/internal/resolveCacheDir.js.map +1 -0
- package/lib/launcher/internal/resolveTtscserverBinary.js +2 -0
- package/lib/launcher/internal/resolveTtscserverBinary.js.map +1 -1
- package/lib/launcher/internal/runTtsc.d.ts +10 -0
- package/lib/launcher/internal/runTtsc.js +90 -153
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/launcher/internal/runTtscserver.js +10 -35
- package/lib/launcher/internal/runTtscserver.js.map +1 -1
- package/lib/launcher/internal/runTtsx.d.ts +8 -0
- package/lib/launcher/internal/runTtsx.js +137 -79
- package/lib/launcher/internal/runTtsx.js.map +1 -1
- package/lib/plugin/internal/buildSourcePlugin.d.ts +38 -0
- package/lib/plugin/internal/buildSourcePlugin.js +40 -17
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.d.ts +26 -0
- package/lib/plugin/internal/loadProjectPlugins.js +90 -41
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/structures/ITtscCompilerTransformation.d.ts +15 -2
- package/lib/structures/ITtscPlugin.d.ts +24 -0
- package/lib/structures/ITtscPluginCapabilities.d.ts +29 -0
- package/lib/structures/ITtscPluginCapabilities.js +3 -0
- package/lib/structures/ITtscPluginCapabilities.js.map +1 -0
- package/lib/structures/index.d.ts +1 -0
- package/lib/structures/index.js +1 -0
- package/lib/structures/index.js.map +1 -1
- package/lib/structures/internal/ITtscLoadedNativePlugin.d.ts +5 -0
- package/lib/structures/internal/TtscCommonOptions.d.ts +19 -0
- package/lib/structures/internal/TtscSingleFileEmitOptions.d.ts +0 -2
- package/package.json +9 -9
- package/shim/ast/shim.go +24 -0
- package/shim/checker/shim.go +35 -0
- package/shim/core/shim.go +17 -0
- package/shim/diagnosticwriter/shim.go +4 -0
- package/shim/lsp/shim.go +3 -3
- package/shim/printer/shim.go +20 -0
- package/src/TtscCompiler.ts +7 -0
- package/src/compiler/internal/buildNativeCompiler.ts +23 -3
- package/src/compiler/internal/compileProjectInMemory.ts +34 -25
- package/src/compiler/internal/paths.ts +68 -0
- package/src/compiler/internal/project/readProjectConfig.ts +86 -1
- package/src/compiler/internal/project/resolveProjectConfig.ts +44 -1
- package/src/compiler/internal/resolveBinary.ts +17 -1
- package/src/compiler/internal/resolveEmittedJavaScript.ts +43 -12
- package/src/compiler/internal/resolveTsgo.ts +29 -1
- package/src/compiler/internal/runBuild.ts +398 -112
- package/src/compiler/internal/runSingleFileEmit.ts +14 -1
- package/src/compiler/internal/sharedHostHelpers.ts +7 -7
- package/src/compiler/internal/spawnNative.ts +64 -0
- package/src/compiler/internal/transformProjectInMemory.ts +47 -67
- package/src/flags/parser.ts +367 -0
- package/src/flags/schema.ts +570 -0
- package/src/launcher/internal/getCompilerVersionText.ts +7 -0
- package/src/launcher/internal/prepareExecution.ts +35 -0
- package/src/launcher/internal/resolveCacheDir.ts +19 -0
- package/src/launcher/internal/resolveTtscserverBinary.ts +2 -0
- package/src/launcher/internal/runTtsc.ts +97 -143
- package/src/launcher/internal/runTtscserver.ts +9 -1
- package/src/launcher/internal/runTtsx.ts +149 -82
- package/src/plugin/internal/buildSourcePlugin.ts +40 -14
- package/src/plugin/internal/loadProjectPlugins.ts +116 -45
- package/src/structures/ITtscCompilerTransformation.ts +15 -2
- package/src/structures/ITtscPlugin.ts +26 -1
- package/src/structures/ITtscPluginCapabilities.ts +29 -0
- package/src/structures/index.ts +1 -0
- package/src/structures/internal/ITtscLoadedNativePlugin.ts +5 -0
- package/src/structures/internal/TtscCommonOptions.ts +19 -0
- package/src/structures/internal/TtscSingleFileEmitOptions.ts +0 -2
- package/tools/gen_shims/main.go +43 -8
- package/utility/flags_gen.go +30 -0
- package/utility/host.go +304 -245
package/driver/program.go
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
package driver
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
"io"
|
|
7
|
+
"path/filepath"
|
|
8
|
+
"strings"
|
|
9
|
+
|
|
10
|
+
"github.com/microsoft/typescript-go/shim/ast"
|
|
11
|
+
shimchecker "github.com/microsoft/typescript-go/shim/checker"
|
|
12
|
+
shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
|
|
13
|
+
"github.com/microsoft/typescript-go/shim/core"
|
|
14
|
+
shimdiagnosticwriter "github.com/microsoft/typescript-go/shim/diagnosticwriter"
|
|
15
|
+
shimscanner "github.com/microsoft/typescript-go/shim/scanner"
|
|
16
|
+
"github.com/microsoft/typescript-go/shim/tsoptions"
|
|
17
|
+
"github.com/microsoft/typescript-go/shim/tspath"
|
|
18
|
+
"github.com/microsoft/typescript-go/shim/vfs"
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
// Diagnostic is the compilation diagnostic shape ttsc passes around. Kept
|
|
@@ -27,16 +27,16 @@ import (
|
|
|
27
27
|
// `@ttsc/lint`). At most one of `raw` / `lint` is non-nil; both nil falls
|
|
28
28
|
// back to the legacy single-line form.
|
|
29
29
|
type Diagnostic struct {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
File string
|
|
31
|
+
Line int
|
|
32
|
+
Column int
|
|
33
|
+
Code int32
|
|
34
|
+
Start *int
|
|
35
|
+
Length *int
|
|
36
|
+
Message string
|
|
37
|
+
Severity Severity
|
|
38
|
+
raw *ast.Diagnostic
|
|
39
|
+
lint *shimdiagnosticwriter.LintDiagnostic
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// Severity classifies a diagnostic's blast radius. ttsc treats Error as a
|
|
@@ -44,12 +44,12 @@ type Diagnostic struct {
|
|
|
44
44
|
type Severity int
|
|
45
45
|
|
|
46
46
|
const (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
// SeverityError is the default for tsgo typecheck output and any
|
|
48
|
+
// plugin-emitted finding that should fail the build.
|
|
49
|
+
SeverityError Severity = iota
|
|
50
|
+
// SeverityWarning prints with warning coloring but keeps the build
|
|
51
|
+
// status at zero.
|
|
52
|
+
SeverityWarning
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
// IsError reports whether the diagnostic counts toward the build's error
|
|
@@ -63,60 +63,60 @@ func (d Diagnostic) IsError() bool { return d.Severity == SeverityError }
|
|
|
63
63
|
// rule's enum index). Severity controls both the rendered banner color and
|
|
64
64
|
// the exit-code outcome.
|
|
65
65
|
func NewLintDiagnostic(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
file *ast.SourceFile,
|
|
67
|
+
pos, end int,
|
|
68
|
+
code int32,
|
|
69
|
+
severity Severity,
|
|
70
|
+
message string,
|
|
71
71
|
) Diagnostic {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
72
|
+
cat := shimdiagnosticwriter.LintCategoryError
|
|
73
|
+
if severity == SeverityWarning {
|
|
74
|
+
cat = shimdiagnosticwriter.LintCategoryWarning
|
|
75
|
+
}
|
|
76
|
+
lint := shimdiagnosticwriter.NewLintDiagnostic(file, pos, end, code, cat, message)
|
|
77
|
+
d := Diagnostic{
|
|
78
|
+
Code: code,
|
|
79
|
+
Message: message,
|
|
80
|
+
Severity: severity,
|
|
81
|
+
lint: lint,
|
|
82
|
+
}
|
|
83
|
+
if file != nil {
|
|
84
|
+
d.File = file.FileName()
|
|
85
|
+
if pos >= 0 {
|
|
86
|
+
length := lint.Len()
|
|
87
|
+
d.Start = &pos
|
|
88
|
+
d.Length = &length
|
|
89
|
+
line, col := shimscanner.GetECMALineAndByteOffsetOfPosition(file, pos)
|
|
90
|
+
d.Line = line + 1
|
|
91
|
+
d.Column = col + 1
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return d
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// SourceFile returns the program source file matching filename.
|
|
98
98
|
func (p *Program) SourceFile(filename string) *ast.SourceFile {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
99
|
+
if p == nil || p.TSProgram == nil {
|
|
100
|
+
return nil
|
|
101
|
+
}
|
|
102
|
+
normalized := filepath.ToSlash(filename)
|
|
103
|
+
for _, file := range p.TSProgram.SourceFiles() {
|
|
104
|
+
if filepath.ToSlash(file.FileName()) == normalized {
|
|
105
|
+
return file
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return nil
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// String returns a `path:line:col: message` formatted string.
|
|
112
112
|
func (d Diagnostic) String() string {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
113
|
+
if d.File == "" {
|
|
114
|
+
return d.Message
|
|
115
|
+
}
|
|
116
|
+
if d.Line > 0 {
|
|
117
|
+
return fmt.Sprintf("%s:%d:%d: %s", d.File, d.Line, d.Column, d.Message)
|
|
118
|
+
}
|
|
119
|
+
return fmt.Sprintf("%s: %s", d.File, d.Message)
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
// WritePrettyDiagnostics renders diagnostics with TypeScript-style colors,
|
|
@@ -125,94 +125,105 @@ func (d Diagnostic) String() string {
|
|
|
125
125
|
// are rendered through the same color/context pipeline; entries without
|
|
126
126
|
// either anchor fall back to the legacy `path:line:col: message` form.
|
|
127
127
|
func WritePrettyDiagnostics(w io.Writer, diagnostics []Diagnostic, cwd string) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
128
|
+
if len(diagnostics) == 0 {
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
rich := make([]Diagnostic, 0, len(diagnostics))
|
|
132
|
+
plain := make([]Diagnostic, 0)
|
|
133
|
+
for _, d := range diagnostics {
|
|
134
|
+
if d.raw != nil || d.lint != nil {
|
|
135
|
+
rich = append(rich, d)
|
|
136
|
+
} else {
|
|
137
|
+
plain = append(plain, d)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if len(rich) > 0 {
|
|
141
|
+
astDiags := make([]*ast.Diagnostic, 0, len(rich))
|
|
142
|
+
lintDiags := make([]*shimdiagnosticwriter.LintDiagnostic, 0, len(rich))
|
|
143
|
+
for _, d := range rich {
|
|
144
|
+
if d.raw != nil {
|
|
145
|
+
astDiags = append(astDiags, d.raw)
|
|
146
|
+
}
|
|
147
|
+
if d.lint != nil {
|
|
148
|
+
lintDiags = append(lintDiags, d.lint)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
shimdiagnosticwriter.FormatMixedDiagnostics(w, astDiags, lintDiags, cwd)
|
|
152
|
+
}
|
|
153
|
+
for _, d := range plain {
|
|
154
|
+
fmt.Fprintln(w, " -", d.String())
|
|
155
|
+
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// CountErrors returns the number of diagnostics that should fail the build.
|
|
159
159
|
// tsgo diagnostics carry their own `Error` category; lint diagnostics carry a
|
|
160
160
|
// caller-set Severity. Anything that isn't an explicit warning counts.
|
|
161
161
|
func CountErrors(diagnostics []Diagnostic) int {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
162
|
+
n := 0
|
|
163
|
+
for _, d := range diagnostics {
|
|
164
|
+
if d.lint != nil {
|
|
165
|
+
if d.lint.IsError() {
|
|
166
|
+
n++
|
|
167
|
+
}
|
|
168
|
+
continue
|
|
169
|
+
}
|
|
170
|
+
if d.raw != nil {
|
|
171
|
+
// tsgo diagnostics use the diagnostics package category. The
|
|
172
|
+
// renderer shim already mirrors the same Error/Warning split, so
|
|
173
|
+
// re-categorize via the public IsError shortcut.
|
|
174
|
+
if d.Severity != SeverityWarning {
|
|
175
|
+
n++
|
|
176
|
+
}
|
|
177
|
+
continue
|
|
178
|
+
}
|
|
179
|
+
// Plain text diagnostics (manually assembled): treat as errors so
|
|
180
|
+
// "ttsc: tsconfig not found"-style failures still flip the exit code.
|
|
181
|
+
n++
|
|
182
|
+
}
|
|
183
|
+
return n
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
// Program is the shim-agnostic facade the rest of the engine sees.
|
|
187
187
|
type Program struct {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
188
|
+
TSProgram *shimcompiler.Program
|
|
189
|
+
ParsedConfig *tsoptions.ParsedCommandLine
|
|
190
|
+
Checker *shimchecker.Checker
|
|
191
|
+
checkerRelease func()
|
|
192
|
+
Host shimcompiler.CompilerHost
|
|
193
|
+
FS vfs.FS
|
|
194
|
+
SourcePreamble string
|
|
195
|
+
plugins linkedPluginState
|
|
196
|
+
pluginsApplied bool
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
// LoadProgramOptions controls tsconfig overrides applied before tsgo creates
|
|
200
200
|
// the program. `ForceEmit` is used by `ttsc --emit` and runtime compilation
|
|
201
201
|
// so execution still works when the project defaults to `noEmit`.
|
|
202
202
|
type LoadProgramOptions struct {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
203
|
+
ForceEmit bool
|
|
204
|
+
ForceNoEmit bool
|
|
205
|
+
OutDir string
|
|
206
|
+
SourcePreamble string
|
|
207
|
+
// SingleThreaded forces TypeScript-Go's single-threaded mode (one checker,
|
|
208
|
+
// serial parse/check/emit), mirroring `tsgo --singleThreaded`.
|
|
209
|
+
SingleThreaded bool
|
|
210
|
+
// Checkers overrides the type-checker pool size, mirroring `tsgo --checkers`.
|
|
211
|
+
// Zero leaves TypeScript-Go's default; ignored when SingleThreaded is set.
|
|
212
|
+
Checkers int
|
|
213
|
+
// TsgoArgs carries tsgo CLI flags the `ttsc` launcher did not recognize as
|
|
214
|
+
// its own (`--strict`, `--target es2020`, …). They are parsed through
|
|
215
|
+
// TypeScript-Go's own command-line parser into a CompilerOptions overlay
|
|
216
|
+
// that wins over the tsconfig, exactly as `tsgo`'s CLI merges them.
|
|
217
|
+
TsgoArgs []string
|
|
207
218
|
}
|
|
208
219
|
|
|
209
220
|
// Close releases the checker pool lease acquired by LoadProgram.
|
|
210
221
|
func (p *Program) Close() error {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
222
|
+
if p.checkerRelease != nil {
|
|
223
|
+
p.checkerRelease()
|
|
224
|
+
p.checkerRelease = nil
|
|
225
|
+
}
|
|
226
|
+
return nil
|
|
216
227
|
}
|
|
217
228
|
|
|
218
229
|
// ParseTSConfig parses a tsconfig.json file via tsgo's native JSONC parser.
|
|
@@ -221,32 +232,91 @@ func (p *Program) Close() error {
|
|
|
221
232
|
// The absolute path is resolved against cwd before any VFS lookups because
|
|
222
233
|
// tsgo's filesystem APIs require absolute paths — mirrors what tsc does when
|
|
223
234
|
// you pass a relative `--project` flag.
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
+
//
|
|
236
|
+
// cliOptions is a CompilerOptions overlay (from forwarded `tsgo` CLI flags);
|
|
237
|
+
// TypeScript-Go merges its non-zero fields over the tsconfig so the CLI wins,
|
|
238
|
+
// the same precedence tsgo's own command line uses. Pass nil for none.
|
|
239
|
+
func ParseTSConfig(fs vfs.FS, cwd, tsconfigPath string, host shimcompiler.CompilerHost, cliOptions *core.CompilerOptions) (*tsoptions.ParsedCommandLine, []Diagnostic, error) {
|
|
240
|
+
resolved := tspath.ResolvePath(cwd, tsconfigPath)
|
|
241
|
+
if !fs.FileExists(resolved) {
|
|
242
|
+
return nil, nil, fmt.Errorf("tsconfig not found: %s", resolved)
|
|
243
|
+
}
|
|
244
|
+
if cliOptions == nil {
|
|
245
|
+
cliOptions = &core.CompilerOptions{}
|
|
246
|
+
}
|
|
247
|
+
parsed, diags := tsoptions.GetParsedCommandLineOfConfigFile(resolved, cliOptions, nil, host, nil)
|
|
248
|
+
allDiags := append(diags, parsed.Errors...)
|
|
249
|
+
if len(allDiags) > 0 {
|
|
250
|
+
return nil, convertDiagnostics(allDiags), nil
|
|
251
|
+
}
|
|
252
|
+
return parsed, nil, nil
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// parseTsgoArgs runs forwarded tsgo CLI flags through TypeScript-Go's own
|
|
256
|
+
// command-line parser, yielding a CompilerOptions overlay ParseTSConfig merges
|
|
257
|
+
// over the tsconfig. This is how a plugin build — which constructs its Program
|
|
258
|
+
// in-process rather than shelling out to `tsgo` — still honors flags like
|
|
259
|
+
// `ttsc --strict`. Returns (nil, nil, nil) when there are no forwarded flags.
|
|
260
|
+
func parseTsgoArgs(args []string, host shimcompiler.CompilerHost) (*core.CompilerOptions, []Diagnostic, error) {
|
|
261
|
+
if len(args) == 0 {
|
|
262
|
+
return nil, nil, nil
|
|
263
|
+
}
|
|
264
|
+
cli := tsoptions.ParseCommandLine(args, host)
|
|
265
|
+
if cli == nil {
|
|
266
|
+
return nil, nil, fmt.Errorf("driver: tsgo argument parser returned nil")
|
|
267
|
+
}
|
|
268
|
+
if len(cli.Errors) > 0 {
|
|
269
|
+
return nil, convertDiagnostics(cli.Errors), nil
|
|
270
|
+
}
|
|
271
|
+
return cli.CompilerOptions(), nil, nil
|
|
235
272
|
}
|
|
236
273
|
|
|
237
274
|
// CreateProgramFromConfig builds a tsgo Program from the parsed config.
|
|
275
|
+
//
|
|
276
|
+
// SingleThreaded is intentionally left unset so the program keeps
|
|
277
|
+
// TypeScript-Go's parallel source parsing and parallel emit. The checker
|
|
278
|
+
// pool, however, is pinned to a single checker (see forceSingleChecker):
|
|
279
|
+
// every phase ttsc layers on top — plugin transforms and the output
|
|
280
|
+
// rewriter — walks the program serially against the one checker returned by
|
|
281
|
+
// Program.GetTypeChecker, and then asks that checker to resolve types in
|
|
282
|
+
// nodes drawn from *every* source file. TypeScript-Go's multi-checker pool
|
|
283
|
+
// affinitizes each file to a different checker and forbids mixing types
|
|
284
|
+
// across them; a circular type whose declarations span files on different
|
|
285
|
+
// checkers resolves to `any` on the borrowed checker. Pinning the pool to
|
|
286
|
+
// one checker keeps prog.Checker consistent with how every file was checked
|
|
287
|
+
// while leaving parse and emit parallel. Both EmitAll and EmitAllRaw
|
|
288
|
+
// serialize the WriteFile callback under a mutex so the emit-stage rewriter
|
|
289
|
+
// never observes the parallel emit either.
|
|
238
290
|
func CreateProgramFromConfig(parsed *tsoptions.ParsedCommandLine, host shimcompiler.CompilerHost) (*shimcompiler.Program, []Diagnostic, error) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
291
|
+
if parsed == nil {
|
|
292
|
+
return nil, nil, fmt.Errorf("driver: nil parsed command line")
|
|
293
|
+
}
|
|
294
|
+
forceSingleChecker(parsed)
|
|
295
|
+
opts := shimcompiler.ProgramOptions{
|
|
296
|
+
Config: parsed,
|
|
297
|
+
Host: host,
|
|
298
|
+
UseSourceOfProjectReference: true,
|
|
299
|
+
}
|
|
300
|
+
p := shimcompiler.NewProgram(opts)
|
|
301
|
+
return p, nil, nil
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// forceSingleChecker pins the TypeScript-Go checker pool to a single checker.
|
|
305
|
+
//
|
|
306
|
+
// ttsc's transform and rewrite phases run serially and obtain types through
|
|
307
|
+
// the single checker that Program.GetTypeChecker hands back. Those phases
|
|
308
|
+
// query types on nodes from arbitrary source files, so the checker must be
|
|
309
|
+
// the same one that checked every file. A pool of size > 1 affinitizes files
|
|
310
|
+
// to distinct checkers; resolving a type whose declarations cross that
|
|
311
|
+
// boundary (e.g. a circular indexed-access alias) yields `any`. Parallel
|
|
312
|
+
// parsing and emit are unaffected — they do not consult the checker count.
|
|
313
|
+
func forceSingleChecker(parsed *tsoptions.ParsedCommandLine) {
|
|
314
|
+
options := parsed.ParsedConfig.CompilerOptions
|
|
315
|
+
if options.SingleThreaded == core.TSTrue {
|
|
316
|
+
return
|
|
317
|
+
}
|
|
318
|
+
one := 1
|
|
319
|
+
options.Checkers = &one
|
|
250
320
|
}
|
|
251
321
|
|
|
252
322
|
// LoadProgram is the one-shot convenience used by `ttsc`.
|
|
@@ -255,230 +325,284 @@ func CreateProgramFromConfig(parsed *tsoptions.ParsedCommandLine, host shimcompi
|
|
|
255
325
|
//
|
|
256
326
|
// cwd must be absolute; tsconfigPath may be relative to cwd.
|
|
257
327
|
func LoadProgram(cwd, tsconfigPath string, options LoadProgramOptions) (*Program, []Diagnostic, error) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
328
|
+
if !filepath.IsAbs(cwd) {
|
|
329
|
+
if abs, err := filepath.Abs(cwd); err == nil {
|
|
330
|
+
cwd = abs
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
cwd = tspath.ResolvePath(cwd)
|
|
334
|
+
pluginState, err := loadLinkedPluginState(cwd, tsconfigPath)
|
|
335
|
+
if err != nil {
|
|
336
|
+
return nil, nil, err
|
|
337
|
+
}
|
|
338
|
+
preamble, err := pluginState.sourcePreamble()
|
|
339
|
+
if err != nil {
|
|
340
|
+
return nil, nil, err
|
|
341
|
+
}
|
|
342
|
+
if preamble != "" {
|
|
343
|
+
options.SourcePreamble += preamble
|
|
344
|
+
}
|
|
345
|
+
fs := DefaultFS()
|
|
346
|
+
if options.SourcePreamble != "" {
|
|
347
|
+
fs = sourcePreambleFS{
|
|
348
|
+
FS: fs,
|
|
349
|
+
preamble: options.SourcePreamble,
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
host := DefaultHost(cwd, fs)
|
|
353
|
+
|
|
354
|
+
cliOptions, cliDiags, err := parseTsgoArgs(options.TsgoArgs, host)
|
|
355
|
+
if err != nil {
|
|
356
|
+
return nil, nil, err
|
|
357
|
+
}
|
|
358
|
+
if len(cliDiags) > 0 {
|
|
359
|
+
return nil, cliDiags, nil
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
parsed, diags, err := ParseTSConfig(fs, cwd, tsconfigPath, host, cliOptions)
|
|
363
|
+
if err != nil {
|
|
364
|
+
return nil, nil, err
|
|
365
|
+
}
|
|
366
|
+
if len(diags) > 0 {
|
|
367
|
+
return nil, diags, nil
|
|
368
|
+
}
|
|
369
|
+
if options.ForceNoEmit {
|
|
370
|
+
forceNoEmit(parsed)
|
|
371
|
+
}
|
|
372
|
+
if options.ForceEmit {
|
|
373
|
+
forceEmit(parsed)
|
|
374
|
+
}
|
|
375
|
+
if options.OutDir != "" {
|
|
376
|
+
overrideOutDir(cwd, parsed, options.OutDir)
|
|
377
|
+
}
|
|
378
|
+
applyThreadingOptions(parsed, options.SingleThreaded, options.Checkers)
|
|
379
|
+
|
|
380
|
+
tsProgram, _, _ := CreateProgramFromConfig(parsed, host)
|
|
381
|
+
|
|
382
|
+
checker, done := tsProgram.GetTypeChecker(context.Background())
|
|
383
|
+
prog := &Program{
|
|
384
|
+
TSProgram: tsProgram,
|
|
385
|
+
ParsedConfig: parsed,
|
|
386
|
+
Checker: checker,
|
|
387
|
+
checkerRelease: done,
|
|
388
|
+
Host: host,
|
|
389
|
+
FS: fs,
|
|
390
|
+
SourcePreamble: options.SourcePreamble,
|
|
391
|
+
}
|
|
392
|
+
prog.plugins = pluginState
|
|
393
|
+
return prog, nil, nil
|
|
315
394
|
}
|
|
316
395
|
|
|
396
|
+
// forceEmit clears noEmit and emitDeclarationOnly so the program always
|
|
397
|
+
// produces JavaScript output regardless of the tsconfig settings.
|
|
317
398
|
func forceEmit(parsed *tsoptions.ParsedCommandLine) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
399
|
+
options := parsed.ParsedConfig.CompilerOptions
|
|
400
|
+
options.NoEmit = core.TSFalse
|
|
401
|
+
options.EmitDeclarationOnly = core.TSFalse
|
|
321
402
|
}
|
|
322
403
|
|
|
404
|
+
// forceNoEmit sets noEmit so the program type-checks without writing files.
|
|
323
405
|
func forceNoEmit(parsed *tsoptions.ParsedCommandLine) {
|
|
324
|
-
|
|
406
|
+
parsed.ParsedConfig.CompilerOptions.NoEmit = core.TSTrue
|
|
325
407
|
}
|
|
326
408
|
|
|
409
|
+
// overrideOutDir resolves outDir against cwd and applies it to the parsed
|
|
410
|
+
// config, replacing any outDir already set in tsconfig.json.
|
|
327
411
|
func overrideOutDir(cwd string, parsed *tsoptions.ParsedCommandLine, outDir string) {
|
|
328
|
-
|
|
412
|
+
parsed.ParsedConfig.CompilerOptions.OutDir = tspath.ResolvePath(cwd, outDir)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// applyThreadingOptions forwards the CLI threading knobs onto the parsed
|
|
416
|
+
// compiler options. ttsc mirrors tsgo here: `--singleThreaded` / `--checkers`
|
|
417
|
+
// land in CompilerOptions, and both Program.SingleThreaded() and the checker
|
|
418
|
+
// pool read them from there — ProgramOptions is left untouched, exactly as
|
|
419
|
+
// tsgo's own CLI does. SingleThreaded wins over Checkers, matching the pool's
|
|
420
|
+
// own precedence.
|
|
421
|
+
//
|
|
422
|
+
// Note that CreateProgramFromConfig calls forceSingleChecker afterwards, so a
|
|
423
|
+
// `--checkers N` greater than 1 is recorded here but then clamped back to a
|
|
424
|
+
// single checker: ttsc's serial transform/rewrite phases require one checker
|
|
425
|
+
// (see forceSingleChecker). `--singleThreaded` still takes full effect.
|
|
426
|
+
func applyThreadingOptions(parsed *tsoptions.ParsedCommandLine, singleThreaded bool, checkers int) {
|
|
427
|
+
options := parsed.ParsedConfig.CompilerOptions
|
|
428
|
+
if singleThreaded {
|
|
429
|
+
options.SingleThreaded = core.TSTrue
|
|
430
|
+
}
|
|
431
|
+
if checkers > 0 {
|
|
432
|
+
n := checkers
|
|
433
|
+
options.Checkers = &n
|
|
434
|
+
}
|
|
329
435
|
}
|
|
330
436
|
|
|
437
|
+
// sourcePreambleFS wraps a vfs.FS and prepends the preamble string to every
|
|
438
|
+
// source file read by tsgo's parser. Declaration files (.d.ts etc.) are
|
|
439
|
+
// excluded so injected code never appears in type definitions.
|
|
331
440
|
type sourcePreambleFS struct {
|
|
332
|
-
|
|
333
|
-
|
|
441
|
+
vfs.FS
|
|
442
|
+
preamble string
|
|
334
443
|
}
|
|
335
444
|
|
|
336
445
|
func (fs sourcePreambleFS) ReadFile(filePath string) (string, bool) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
446
|
+
contents, ok := fs.FS.ReadFile(filePath)
|
|
447
|
+
if !ok || !isSourcePreambleTarget(filePath) {
|
|
448
|
+
return contents, ok
|
|
449
|
+
}
|
|
450
|
+
return ApplySourcePreamble(contents, fs.preamble), true
|
|
342
451
|
}
|
|
343
452
|
|
|
453
|
+
// isSourcePreambleTarget reports whether the preamble should be injected into
|
|
454
|
+
// the file at filePath. Declaration files are excluded; all other TypeScript
|
|
455
|
+
// and JavaScript source extensions qualify.
|
|
344
456
|
func isSourcePreambleTarget(filePath string) bool {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
457
|
+
lower := strings.ToLower(filepath.ToSlash(filePath))
|
|
458
|
+
for _, suffix := range []string{".d.ts", ".d.mts", ".d.cts"} {
|
|
459
|
+
if strings.HasSuffix(lower, suffix) {
|
|
460
|
+
return false
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
for _, suffix := range []string{".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"} {
|
|
464
|
+
if strings.HasSuffix(lower, suffix) {
|
|
465
|
+
return true
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return false
|
|
357
469
|
}
|
|
358
470
|
|
|
359
471
|
// ApplySourcePreamble inserts a generated source preamble without moving the
|
|
360
472
|
// file's BOM or hashbang away from the first bytes of the physical output.
|
|
361
473
|
func ApplySourcePreamble(text string, preamble string) string {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
474
|
+
if preamble == "" {
|
|
475
|
+
return text
|
|
476
|
+
}
|
|
477
|
+
bom := ""
|
|
478
|
+
rest := text
|
|
479
|
+
if strings.HasPrefix(rest, "\ufeff") {
|
|
480
|
+
bom = "\ufeff"
|
|
481
|
+
rest = strings.TrimPrefix(rest, "\ufeff")
|
|
482
|
+
}
|
|
483
|
+
if strings.HasPrefix(rest, "#!") {
|
|
484
|
+
end := strings.IndexByte(rest, '\n')
|
|
485
|
+
if end < 0 {
|
|
486
|
+
return bom + rest + "\n" + preamble
|
|
487
|
+
}
|
|
488
|
+
return bom + rest[:end+1] + preamble + rest[end+1:]
|
|
489
|
+
}
|
|
490
|
+
return bom + preamble + rest
|
|
379
491
|
}
|
|
380
492
|
|
|
381
493
|
// SourceFiles exposes the program's user-authored source files (declaration
|
|
382
494
|
// files filtered out).
|
|
383
495
|
func (p *Program) SourceFiles() []*ast.SourceFile {
|
|
384
|
-
|
|
385
|
-
|
|
496
|
+
_ = p.ApplyLinkedPlugins()
|
|
497
|
+
return p.sourceFilesRaw()
|
|
386
498
|
}
|
|
387
499
|
|
|
500
|
+
// sourceFilesRaw returns the program's non-declaration source files without
|
|
501
|
+
// running ApplyLinkedPlugins. Used internally to avoid a re-entrant apply.
|
|
388
502
|
func (p *Program) sourceFilesRaw() []*ast.SourceFile {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
503
|
+
out := make([]*ast.SourceFile, 0)
|
|
504
|
+
if p == nil || p.TSProgram == nil {
|
|
505
|
+
return out
|
|
506
|
+
}
|
|
507
|
+
for _, f := range p.TSProgram.SourceFiles() {
|
|
508
|
+
if f.IsDeclarationFile {
|
|
509
|
+
continue
|
|
510
|
+
}
|
|
511
|
+
out = append(out, f)
|
|
512
|
+
}
|
|
513
|
+
return out
|
|
400
514
|
}
|
|
401
515
|
|
|
402
516
|
// ApplyLinkedPlugins runs registered linked ProgramPlugin hooks exactly once.
|
|
403
517
|
func (p *Program) ApplyLinkedPlugins() error {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
518
|
+
if p == nil || p.pluginsApplied {
|
|
519
|
+
return nil
|
|
520
|
+
}
|
|
521
|
+
p.pluginsApplied = true
|
|
522
|
+
return p.plugins.apply(p)
|
|
409
523
|
}
|
|
410
524
|
|
|
411
525
|
// Diagnostics returns project diagnostics that must block compilation or
|
|
412
526
|
// runtime execution before any JavaScript is emitted or evaluated.
|
|
413
527
|
func (p *Program) Diagnostics() []Diagnostic {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
528
|
+
if p == nil || p.TSProgram == nil {
|
|
529
|
+
return []Diagnostic{{Message: "driver: nil program"}}
|
|
530
|
+
}
|
|
531
|
+
ctx := context.Background()
|
|
532
|
+
raw := shimcompiler.GetDiagnosticsOfAnyProgram(
|
|
533
|
+
ctx,
|
|
534
|
+
p.TSProgram,
|
|
535
|
+
nil,
|
|
536
|
+
false,
|
|
537
|
+
p.TSProgram.GetBindDiagnostics,
|
|
538
|
+
p.TSProgram.GetSemanticDiagnostics,
|
|
539
|
+
)
|
|
540
|
+
raw = filterDiagnostics(raw)
|
|
541
|
+
return convertDiagnostics(shimcompiler.SortAndDeduplicateDiagnostics(raw))
|
|
428
542
|
}
|
|
429
543
|
|
|
544
|
+
// filterDiagnostics removes diagnostics that are false positives in ttsc's
|
|
545
|
+
// compilation model. Currently it suppresses unused type-parameter warnings
|
|
546
|
+
// on overload signatures that have no body (see isUnusedOverloadSignatureTypeParameterDiagnostic).
|
|
430
547
|
func filterDiagnostics(in []*ast.Diagnostic) []*ast.Diagnostic {
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
548
|
+
out := in[:0]
|
|
549
|
+
for _, d := range in {
|
|
550
|
+
if isUnusedOverloadSignatureTypeParameterDiagnostic(d) {
|
|
551
|
+
continue
|
|
552
|
+
}
|
|
553
|
+
out = append(out, d)
|
|
554
|
+
}
|
|
555
|
+
return out
|
|
439
556
|
}
|
|
440
557
|
|
|
558
|
+
// isUnusedOverloadSignatureTypeParameterDiagnostic reports true when the
|
|
559
|
+
// diagnostic is TS6196 ("unused declaration") or TS6205 ("all type parameters
|
|
560
|
+
// are unused") on a function declaration that has no body — i.e., an overload
|
|
561
|
+
// signature. tsgo fires these on overloads whose type parameters are used only
|
|
562
|
+
// in the implementation signature, which is a false positive: the overload
|
|
563
|
+
// signatures are required for narrowing and their type parameters are
|
|
564
|
+
// effectively forwarded to the implementation.
|
|
441
565
|
func isUnusedOverloadSignatureTypeParameterDiagnostic(d *ast.Diagnostic) bool {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
566
|
+
if d == nil || d.File() == nil {
|
|
567
|
+
return false
|
|
568
|
+
}
|
|
569
|
+
switch d.Code() {
|
|
570
|
+
case 6196, 6205: // unused declaration / all type parameters are unused
|
|
571
|
+
default:
|
|
572
|
+
return false
|
|
573
|
+
}
|
|
574
|
+
node := ast.GetNodeAtPosition(d.File(), d.Pos(), false)
|
|
575
|
+
for node != nil {
|
|
576
|
+
if node.Kind == ast.KindFunctionDeclaration {
|
|
577
|
+
return node.Body() == nil
|
|
578
|
+
}
|
|
579
|
+
node = node.Parent
|
|
580
|
+
}
|
|
581
|
+
return false
|
|
458
582
|
}
|
|
459
583
|
|
|
460
584
|
// convertDiagnostics translates shim-specific diagnostics into the plain
|
|
461
585
|
// Diagnostic struct with line/column populated via tsgo's ECMALineMap (the
|
|
462
586
|
// same helper tsc uses for its "file:line:col: message" banner).
|
|
463
587
|
func convertDiagnostics(in []*ast.Diagnostic) []Diagnostic {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
588
|
+
out := make([]Diagnostic, 0, len(in))
|
|
589
|
+
for _, d := range in {
|
|
590
|
+
if d == nil {
|
|
591
|
+
continue
|
|
592
|
+
}
|
|
593
|
+
diag := Diagnostic{Code: d.Code(), Message: d.String(), raw: d}
|
|
594
|
+
if file := d.File(); file != nil {
|
|
595
|
+
diag.File = file.FileName()
|
|
596
|
+
if pos := d.Pos(); pos >= 0 {
|
|
597
|
+
length := d.Len()
|
|
598
|
+
diag.Start = &pos
|
|
599
|
+
diag.Length = &length
|
|
600
|
+
line, col := shimscanner.GetECMALineAndByteOffsetOfPosition(file, pos)
|
|
601
|
+
diag.Line = line + 1
|
|
602
|
+
diag.Column = col + 1
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
out = append(out, diag)
|
|
606
|
+
}
|
|
607
|
+
return out
|
|
484
608
|
}
|