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/utility/host.go
CHANGED
|
@@ -1,308 +1,367 @@
|
|
|
1
1
|
package utility
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"flag"
|
|
6
|
+
"fmt"
|
|
7
|
+
"os"
|
|
8
|
+
"path/filepath"
|
|
9
|
+
"strings"
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
|
|
12
|
+
shimprinter "github.com/microsoft/typescript-go/shim/printer"
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
+
// hostOptions is the parsed form of the flags accepted by all three
|
|
18
|
+
// subcommands (check, build, transform).
|
|
17
19
|
type hostOptions struct {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
cwd string
|
|
21
|
+
emit bool
|
|
22
|
+
noEmit bool
|
|
23
|
+
outDir string
|
|
24
|
+
pluginsJSON string
|
|
25
|
+
quiet bool
|
|
26
|
+
tsconfig string
|
|
27
|
+
verbose bool
|
|
28
|
+
singleThreaded bool
|
|
29
|
+
checkers int
|
|
30
|
+
tsgoArgs []string
|
|
26
31
|
}
|
|
27
32
|
|
|
33
|
+
// transformResult is the JSON envelope written to stdout by RunTransform.
|
|
34
|
+
// TypeScript maps relative output key → printer output; Diagnostics is
|
|
35
|
+
// reserved for future plugin diagnostics (currently always empty/omitted).
|
|
28
36
|
type transformResult struct {
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
Diagnostics []any `json:"diagnostics,omitempty"`
|
|
38
|
+
TypeScript map[string]string `json:"typescript"`
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
// RunCheck validates the project and linked plugin configuration without
|
|
34
42
|
// emitting output.
|
|
35
43
|
func RunCheck(args []string) int {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
opts, ok := parseHostOptions("check", args)
|
|
45
|
+
if !ok {
|
|
46
|
+
return 2
|
|
47
|
+
}
|
|
48
|
+
opts.noEmit = true
|
|
49
|
+
prog, _, ok := loadUtilityProgram(opts)
|
|
50
|
+
if !ok {
|
|
51
|
+
return 2
|
|
52
|
+
}
|
|
53
|
+
defer prog.Close()
|
|
54
|
+
if err := prog.ApplyLinkedPlugins(); err != nil {
|
|
55
|
+
fmt.Fprintln(os.Stderr, err)
|
|
56
|
+
return 2
|
|
57
|
+
}
|
|
58
|
+
return 0
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
// RunBuild hosts linked transform packages inside one compiler emit.
|
|
54
62
|
func RunBuild(args []string) int {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
63
|
+
opts, ok := parseHostOptions("build", args)
|
|
64
|
+
if !ok {
|
|
65
|
+
return 2
|
|
66
|
+
}
|
|
67
|
+
prog, entries, ok := loadUtilityProgram(opts)
|
|
68
|
+
if !ok {
|
|
69
|
+
return 2
|
|
70
|
+
}
|
|
71
|
+
defer prog.Close()
|
|
72
|
+
if opts.noEmit {
|
|
73
|
+
return 0
|
|
74
|
+
}
|
|
75
|
+
if opts.verbose {
|
|
76
|
+
opts.quiet = false // --verbose overrides the default --quiet=true
|
|
77
|
+
}
|
|
78
|
+
if !opts.quiet {
|
|
79
|
+
fmt.Fprintf(os.Stdout, "// ttsc utility: plugins=%d emit=%v\n", len(entries), !opts.noEmit)
|
|
80
|
+
}
|
|
81
|
+
res, eDiags, err := prog.EmitAllRaw(makeSourcePreambleWriteFile(prog))
|
|
82
|
+
if err != nil {
|
|
83
|
+
fmt.Fprintf(os.Stderr, "ttsc utility: emit failed: %v\n", err)
|
|
84
|
+
return 3
|
|
85
|
+
}
|
|
86
|
+
for _, d := range eDiags {
|
|
87
|
+
fmt.Fprintln(os.Stderr, " -", d.String())
|
|
88
|
+
}
|
|
89
|
+
if driver.CountErrors(eDiags) > 0 {
|
|
90
|
+
return 2
|
|
91
|
+
}
|
|
92
|
+
if res != nil && !opts.quiet {
|
|
93
|
+
fmt.Fprintf(os.Stdout, "// ttsc utility: emitted=%d files\n", len(res.EmittedFiles))
|
|
94
|
+
}
|
|
95
|
+
return 0
|
|
88
96
|
}
|
|
89
97
|
|
|
90
98
|
// RunTransform returns the project TypeScript text after linked source
|
|
91
99
|
// mutations.
|
|
92
100
|
func RunTransform(args []string) int {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
101
|
+
opts, ok := parseHostOptions("transform", args)
|
|
102
|
+
if !ok {
|
|
103
|
+
return 2
|
|
104
|
+
}
|
|
105
|
+
prog, _, ok := loadUtilityProgram(opts)
|
|
106
|
+
if !ok {
|
|
107
|
+
return 2
|
|
108
|
+
}
|
|
109
|
+
defer prog.Close()
|
|
110
|
+
if err := prog.ApplyLinkedPlugins(); err != nil {
|
|
111
|
+
fmt.Fprintln(os.Stderr, err)
|
|
112
|
+
return 2
|
|
113
|
+
}
|
|
114
|
+
printer := shimprinter.NewPrinter(shimprinter.PrinterOptions{}, shimprinter.PrintHandlers{}, nil)
|
|
115
|
+
out := transformResult{TypeScript: map[string]string{}}
|
|
116
|
+
for _, file := range prog.SourceFiles() {
|
|
117
|
+
text := shimprinter.EmitSourceFile(printer, file)
|
|
118
|
+
out.TypeScript[apiOutputKey(opts.cwd, file.FileName())] = text
|
|
119
|
+
}
|
|
120
|
+
data, _ := json.Marshal(out)
|
|
121
|
+
fmt.Fprintln(os.Stdout, string(data))
|
|
122
|
+
return 0
|
|
115
123
|
}
|
|
116
124
|
|
|
125
|
+
// parseHostOptions parses the standard flag set for the given subcommand name.
|
|
126
|
+
// Unknown flags forwarded from the JS launcher are stripped by filterHostArgs
|
|
127
|
+
// before flag.FlagSet sees them, so spurious "flag provided but not defined"
|
|
128
|
+
// errors are avoided. Returns (zero, false) on any parse or validation error.
|
|
117
129
|
func parseHostOptions(command string, args []string) (hostOptions, bool) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
130
|
+
fs := flag.NewFlagSet(command, flag.ContinueOnError)
|
|
131
|
+
fs.SetOutput(os.Stderr)
|
|
132
|
+
cwd := fs.String("cwd", "", "project directory")
|
|
133
|
+
emit := fs.Bool("emit", false, "force emit")
|
|
134
|
+
noEmit := fs.Bool("noEmit", false, "force no emit")
|
|
135
|
+
outDir := fs.String("outDir", "", "emit directory override")
|
|
136
|
+
pluginsJSON := fs.String("plugins-json", "", "ttsc plugin manifest JSON")
|
|
137
|
+
quiet := fs.Bool("quiet", true, "suppress summary")
|
|
138
|
+
tsconfig := fs.String("tsconfig", "tsconfig.json", "project tsconfig")
|
|
139
|
+
verbose := fs.Bool("verbose", false, "print summary")
|
|
140
|
+
singleThreaded := fs.Bool("singleThreaded", false, "run TypeScript-Go single-threaded")
|
|
141
|
+
checkers := fs.Int("checkers", 0, "type-checker pool size (0 = TypeScript-Go default)")
|
|
142
|
+
tsgoArgsRaw := fs.String("tsgo-args", "", "JSON array of forwarded tsgo CLI flags")
|
|
143
|
+
if err := fs.Parse(filterHostArgs(args)); err != nil {
|
|
144
|
+
return hostOptions{}, false
|
|
145
|
+
}
|
|
146
|
+
var tsgoArgs []string
|
|
147
|
+
if *tsgoArgsRaw != "" {
|
|
148
|
+
if err := json.Unmarshal([]byte(*tsgoArgsRaw), &tsgoArgs); err != nil {
|
|
149
|
+
fmt.Fprintf(os.Stderr, "ttsc utility: invalid --tsgo-args: %v\n", err)
|
|
150
|
+
return hostOptions{}, false
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if *emit && *noEmit {
|
|
154
|
+
fmt.Fprintln(os.Stderr, "ttsc utility: --emit and --noEmit are mutually exclusive")
|
|
155
|
+
return hostOptions{}, false
|
|
156
|
+
}
|
|
157
|
+
resolvedCwd := *cwd
|
|
158
|
+
if resolvedCwd == "" {
|
|
159
|
+
var err error
|
|
160
|
+
resolvedCwd, err = os.Getwd()
|
|
161
|
+
if err != nil {
|
|
162
|
+
fmt.Fprintf(os.Stderr, "ttsc utility: cwd: %v\n", err)
|
|
163
|
+
return hostOptions{}, false
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if !filepath.IsAbs(resolvedCwd) {
|
|
167
|
+
abs, err := filepath.Abs(resolvedCwd)
|
|
168
|
+
if err != nil {
|
|
169
|
+
fmt.Fprintf(os.Stderr, "ttsc utility: cwd: %v\n", err)
|
|
170
|
+
return hostOptions{}, false
|
|
171
|
+
}
|
|
172
|
+
resolvedCwd = abs
|
|
173
|
+
}
|
|
174
|
+
return hostOptions{
|
|
175
|
+
cwd: filepath.Clean(resolvedCwd),
|
|
176
|
+
emit: *emit,
|
|
177
|
+
noEmit: *noEmit,
|
|
178
|
+
outDir: *outDir,
|
|
179
|
+
pluginsJSON: *pluginsJSON,
|
|
180
|
+
quiet: *quiet,
|
|
181
|
+
tsconfig: *tsconfig,
|
|
182
|
+
verbose: *verbose,
|
|
183
|
+
singleThreaded: *singleThreaded,
|
|
184
|
+
checkers: *checkers,
|
|
185
|
+
tsgoArgs: tsgoArgs,
|
|
186
|
+
}, true
|
|
162
187
|
}
|
|
163
188
|
|
|
189
|
+
// filterHostArgs strips flags that the Go flag set does not declare so that
|
|
190
|
+
// flags forwarded from the JS launcher (e.g. tsgo-specific options) do not
|
|
191
|
+
// cause flag.FlagSet to error. Flags not in the known set are consumed together
|
|
192
|
+
// with their value argument when they clearly take one (no inline "=" and the
|
|
193
|
+
// next token does not start with "-").
|
|
194
|
+
//
|
|
195
|
+
// The allow-list itself is generated from packages/ttsc/src/flags/schema.ts
|
|
196
|
+
// (see flags_gen.go); editing it means editing the schema and re-running
|
|
197
|
+
// `pnpm format`, not patching this file.
|
|
164
198
|
func filterHostArgs(args []string) []string {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
i++
|
|
191
|
-
filtered = append(filtered, args[i])
|
|
192
|
-
}
|
|
193
|
-
continue
|
|
194
|
-
}
|
|
195
|
-
if !hasInlineValue && i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
|
|
196
|
-
i++
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return filtered
|
|
199
|
+
filtered := make([]string, 0, len(args))
|
|
200
|
+
for i := 0; i < len(args); i++ {
|
|
201
|
+
current := args[i]
|
|
202
|
+
if current == "--" {
|
|
203
|
+
break
|
|
204
|
+
}
|
|
205
|
+
if !strings.HasPrefix(current, "--") {
|
|
206
|
+
filtered = append(filtered, current)
|
|
207
|
+
continue
|
|
208
|
+
}
|
|
209
|
+
name, hasInlineValue := flagName(current)
|
|
210
|
+
takesValue, ok := HostFlagAllowList[name]
|
|
211
|
+
if ok {
|
|
212
|
+
filtered = append(filtered, current)
|
|
213
|
+
if takesValue && !hasInlineValue && i+1 < len(args) {
|
|
214
|
+
i++
|
|
215
|
+
filtered = append(filtered, args[i])
|
|
216
|
+
}
|
|
217
|
+
continue
|
|
218
|
+
}
|
|
219
|
+
if !hasInlineValue && i+1 < len(args) && !strings.HasPrefix(args[i+1], "-") {
|
|
220
|
+
i++
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return filtered
|
|
200
224
|
}
|
|
201
225
|
|
|
226
|
+
// flagName strips the leading "--" from a flag argument and reports whether
|
|
227
|
+
// the flag carries an inline value (i.e. the argument contains "=").
|
|
202
228
|
func flagName(arg string) (string, bool) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
229
|
+
name := strings.TrimPrefix(arg, "--")
|
|
230
|
+
before, _, found := strings.Cut(name, "=")
|
|
231
|
+
return before, found
|
|
206
232
|
}
|
|
207
233
|
|
|
234
|
+
// loadUtilityProgram parses plugins JSON, sets the linked-plugin environment
|
|
235
|
+
// variable for the duration of LoadProgram, and returns a fully initialized
|
|
236
|
+
// Program along with the decoded plugin entries. Returns (nil, nil, false) and
|
|
237
|
+
// prints diagnostics to stderr on any error.
|
|
208
238
|
func loadUtilityProgram(opts hostOptions) (*driver.Program, []driver.PluginEntry, bool) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
239
|
+
entries, err := parsePluginEntries(opts.pluginsJSON)
|
|
240
|
+
if err != nil {
|
|
241
|
+
fmt.Fprintln(os.Stderr, err)
|
|
242
|
+
return nil, nil, false
|
|
243
|
+
}
|
|
244
|
+
restoreEnv := setLinkedPluginManifest(opts.pluginsJSON)
|
|
245
|
+
defer restoreEnv()
|
|
216
246
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
247
|
+
prog, diags, err := driver.LoadProgram(opts.cwd, opts.tsconfig, driver.LoadProgramOptions{
|
|
248
|
+
ForceEmit: opts.emit,
|
|
249
|
+
ForceNoEmit: opts.noEmit,
|
|
250
|
+
OutDir: opts.outDir,
|
|
251
|
+
SingleThreaded: opts.singleThreaded,
|
|
252
|
+
Checkers: opts.checkers,
|
|
253
|
+
TsgoArgs: opts.tsgoArgs,
|
|
254
|
+
})
|
|
255
|
+
if err != nil {
|
|
256
|
+
fmt.Fprintf(os.Stderr, "ttsc utility: %v\n", err)
|
|
257
|
+
return nil, nil, false
|
|
258
|
+
}
|
|
259
|
+
if len(diags) > 0 {
|
|
260
|
+
driver.WritePrettyDiagnostics(os.Stderr, diags, opts.cwd)
|
|
261
|
+
return nil, nil, false
|
|
262
|
+
}
|
|
263
|
+
if diags := prog.Diagnostics(); len(diags) > 0 {
|
|
264
|
+
driver.WritePrettyDiagnostics(os.Stderr, diags, opts.cwd)
|
|
265
|
+
_ = prog.Close()
|
|
266
|
+
return nil, nil, false
|
|
267
|
+
}
|
|
268
|
+
return prog, entries, true
|
|
236
269
|
}
|
|
237
270
|
|
|
271
|
+
// parsePluginEntries decodes the --plugins-json flag value into a slice of
|
|
272
|
+
// PluginEntry. An empty or whitespace-only string is treated as "no plugins"
|
|
273
|
+
// (returns nil, nil) rather than a JSON error.
|
|
238
274
|
func parsePluginEntries(input string) ([]driver.PluginEntry, error) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
275
|
+
if strings.TrimSpace(input) == "" {
|
|
276
|
+
return nil, nil
|
|
277
|
+
}
|
|
278
|
+
var entries []driver.PluginEntry
|
|
279
|
+
if err := json.Unmarshal([]byte(input), &entries); err != nil {
|
|
280
|
+
return nil, fmt.Errorf("ttsc utility: invalid --plugins-json: %w", err)
|
|
281
|
+
}
|
|
282
|
+
return entries, nil
|
|
247
283
|
}
|
|
248
284
|
|
|
285
|
+
// setLinkedPluginManifest writes input into the LinkedPluginsEnv environment
|
|
286
|
+
// variable (or clears it when input is blank) and returns a restore function
|
|
287
|
+
// that puts the variable back to its previous state. The restore function is
|
|
288
|
+
// intended to be called via defer immediately after setLinkedPluginManifest.
|
|
249
289
|
func setLinkedPluginManifest(input string) func() {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
290
|
+
previous, existed := os.LookupEnv(driver.LinkedPluginsEnv)
|
|
291
|
+
if strings.TrimSpace(input) == "" {
|
|
292
|
+
_ = os.Unsetenv(driver.LinkedPluginsEnv)
|
|
293
|
+
} else {
|
|
294
|
+
_ = os.Setenv(driver.LinkedPluginsEnv, input)
|
|
295
|
+
}
|
|
296
|
+
return func() {
|
|
297
|
+
if existed {
|
|
298
|
+
_ = os.Setenv(driver.LinkedPluginsEnv, previous)
|
|
299
|
+
} else {
|
|
300
|
+
_ = os.Unsetenv(driver.LinkedPluginsEnv)
|
|
301
|
+
}
|
|
302
|
+
}
|
|
263
303
|
}
|
|
264
304
|
|
|
305
|
+
// makeSourcePreambleWriteFile returns a WriteFile callback that injects
|
|
306
|
+
// prog.SourcePreamble at the top of every emitted output file that supports
|
|
307
|
+
// it. Returns nil when no preamble is needed (empty preamble, nil program, or
|
|
308
|
+
// RemoveComments enabled), which tells the caller to use the default writer.
|
|
265
309
|
func makeSourcePreambleWriteFile(prog *driver.Program) shimcompiler.WriteFile {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
310
|
+
if prog == nil || prog.SourcePreamble == "" || shouldRemoveComments(prog) {
|
|
311
|
+
return nil
|
|
312
|
+
}
|
|
313
|
+
return func(fileName, text string, _ *shimcompiler.WriteFileData) error {
|
|
314
|
+
if shouldEnsureSourcePreamble(fileName, text, prog.SourcePreamble) {
|
|
315
|
+
text = driver.ApplySourcePreamble(text, prog.SourcePreamble)
|
|
316
|
+
}
|
|
317
|
+
return driver.DefaultWriteFile(fileName, text)
|
|
318
|
+
}
|
|
275
319
|
}
|
|
276
320
|
|
|
321
|
+
// shouldRemoveComments reports whether the compiler options ask tsgo to strip
|
|
322
|
+
// comments. When true the source preamble (which is itself a comment block) must
|
|
323
|
+
// not be injected because tsgo would then strip it, resulting in a no-op.
|
|
277
324
|
func shouldRemoveComments(prog *driver.Program) bool {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
325
|
+
if prog == nil || prog.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig == nil || prog.ParsedConfig.ParsedConfig.CompilerOptions == nil {
|
|
326
|
+
return false
|
|
327
|
+
}
|
|
328
|
+
return prog.ParsedConfig.ParsedConfig.CompilerOptions.RemoveComments.IsTrue()
|
|
282
329
|
}
|
|
283
330
|
|
|
331
|
+
// shouldEnsureSourcePreamble reports whether the preamble still needs to be
|
|
332
|
+
// injected into the output file. The idempotency check (strings.Contains)
|
|
333
|
+
// prevents double-injection on watch-mode rebuilds.
|
|
284
334
|
func shouldEnsureSourcePreamble(fileName, text, sourcePreamble string) bool {
|
|
285
|
-
|
|
335
|
+
return isSourcePreambleOutputTarget(fileName) && !strings.Contains(text, sourcePreamble)
|
|
286
336
|
}
|
|
287
337
|
|
|
338
|
+
// isSourcePreambleOutputTarget reports whether fileName is a JS or declaration
|
|
339
|
+
// output file that should receive the source preamble. Declaration files
|
|
340
|
+
// (.d.ts/.d.mts/.d.cts) are included because plugins like @ttsc/banner inject
|
|
341
|
+
// a copyright header that must appear there as well.
|
|
288
342
|
func isSourcePreambleOutputTarget(fileName string) bool {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
343
|
+
lower := strings.ToLower(filepath.ToSlash(fileName))
|
|
344
|
+
for _, suffix := range []string{".d.ts", ".d.mts", ".d.cts", ".js", ".jsx", ".mjs", ".cjs"} {
|
|
345
|
+
if strings.HasSuffix(lower, suffix) {
|
|
346
|
+
return true
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return false
|
|
296
350
|
}
|
|
297
351
|
|
|
352
|
+
// apiOutputKey converts an absolute fileName to a path relative to cwd for use
|
|
353
|
+
// as the JSON key in RunTransform output. Falls back to the slash-normalized
|
|
354
|
+
// absolute path when the file lives outside the project root.
|
|
298
355
|
func apiOutputKey(cwd, fileName string) string {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
356
|
+
rel, err := filepath.Rel(cwd, fileName)
|
|
357
|
+
if err != nil || isOutsideRelativePath(rel) {
|
|
358
|
+
return filepath.ToSlash(fileName)
|
|
359
|
+
}
|
|
360
|
+
return filepath.ToSlash(rel)
|
|
304
361
|
}
|
|
305
362
|
|
|
363
|
+
// isOutsideRelativePath reports whether rel escapes the project root (starts
|
|
364
|
+
// with ".." or is exactly "..").
|
|
306
365
|
func isOutsideRelativePath(rel string) bool {
|
|
307
|
-
|
|
366
|
+
return rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator))
|
|
308
367
|
}
|