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.
Files changed (151) hide show
  1. package/cmd/platform/main.go +9 -0
  2. package/cmd/ttsc/api_compile.go +122 -101
  3. package/cmd/ttsc/api_compile_branches_test.go +55 -57
  4. package/cmd/ttsc/api_transform.go +67 -49
  5. package/cmd/ttsc/api_transform_branches_test.go +30 -32
  6. package/cmd/ttsc/build.go +141 -108
  7. package/cmd/ttsc/build_branches_test.go +95 -97
  8. package/cmd/ttsc/filter.go +70 -0
  9. package/cmd/ttsc/filter_strips_unknown_forwarded_flag_test.go +61 -0
  10. package/cmd/ttsc/flags_gen.go +30 -0
  11. package/cmd/ttsc/helpers_test.go +39 -28
  12. package/cmd/ttsc/main.go +111 -104
  13. package/cmd/ttsc/main_alias_branches_test.go +21 -23
  14. package/cmd/ttscserver/main.go +96 -90
  15. package/cmd/ttscserver/run_lsp_prefers_tsgo_flag_test.go +22 -22
  16. package/cmd/ttscserver/run_lsp_reports_server_error_test.go +22 -22
  17. package/cmd/ttscserver/run_lsp_uses_tsgo_environment_test.go +23 -23
  18. package/cmd/utility-host/main.go +30 -23
  19. package/driver/lsp.go +53 -7
  20. package/driver/plugins.go +88 -72
  21. package/driver/program.go +464 -340
  22. package/driver/rewrite.go +477 -380
  23. package/internal/lspserver/lsp_envelope.go +64 -64
  24. package/internal/lspserver/lsp_frame.go +60 -60
  25. package/internal/lspserver/lsp_plugin.go +57 -57
  26. package/internal/lspserver/lsp_proxy.go +265 -251
  27. package/internal/lspserver/lsp_server.go +155 -144
  28. package/lib/TtscCompiler.d.ts +7 -0
  29. package/lib/TtscCompiler.js +7 -0
  30. package/lib/TtscCompiler.js.map +1 -1
  31. package/lib/compiler/internal/buildNativeCompiler.d.ts +11 -1
  32. package/lib/compiler/internal/buildNativeCompiler.js +23 -3
  33. package/lib/compiler/internal/buildNativeCompiler.js.map +1 -1
  34. package/lib/compiler/internal/compileProjectInMemory.d.ts +9 -0
  35. package/lib/compiler/internal/compileProjectInMemory.js +36 -21
  36. package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
  37. package/lib/compiler/internal/paths.d.ts +27 -0
  38. package/lib/compiler/internal/paths.js +70 -0
  39. package/lib/compiler/internal/paths.js.map +1 -0
  40. package/lib/compiler/internal/project/readProjectConfig.d.ts +9 -1
  41. package/lib/compiler/internal/project/readProjectConfig.js +80 -1
  42. package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
  43. package/lib/compiler/internal/project/resolveProjectConfig.d.ts +13 -1
  44. package/lib/compiler/internal/project/resolveProjectConfig.js +42 -1
  45. package/lib/compiler/internal/project/resolveProjectConfig.js.map +1 -1
  46. package/lib/compiler/internal/resolveBinary.d.ts +9 -1
  47. package/lib/compiler/internal/resolveBinary.js +17 -1
  48. package/lib/compiler/internal/resolveBinary.js.map +1 -1
  49. package/lib/compiler/internal/resolveEmittedJavaScript.d.ts +16 -1
  50. package/lib/compiler/internal/resolveEmittedJavaScript.js +42 -10
  51. package/lib/compiler/internal/resolveEmittedJavaScript.js.map +1 -1
  52. package/lib/compiler/internal/resolveTsgo.d.ts +21 -1
  53. package/lib/compiler/internal/resolveTsgo.js +23 -1
  54. package/lib/compiler/internal/resolveTsgo.js.map +1 -1
  55. package/lib/compiler/internal/runBuild.d.ts +24 -4
  56. package/lib/compiler/internal/runBuild.js +355 -93
  57. package/lib/compiler/internal/runBuild.js.map +1 -1
  58. package/lib/compiler/internal/runSingleFileEmit.d.ts +10 -1
  59. package/lib/compiler/internal/runSingleFileEmit.js +14 -1
  60. package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
  61. package/lib/compiler/internal/sharedHostHelpers.d.ts +5 -0
  62. package/lib/compiler/internal/sharedHostHelpers.js +6 -2
  63. package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
  64. package/lib/compiler/internal/spawnNative.d.ts +21 -0
  65. package/lib/compiler/internal/spawnNative.js +59 -0
  66. package/lib/compiler/internal/spawnNative.js.map +1 -0
  67. package/lib/compiler/internal/transformProjectInMemory.d.ts +15 -1
  68. package/lib/compiler/internal/transformProjectInMemory.js +57 -61
  69. package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
  70. package/lib/flags/parser.d.ts +63 -0
  71. package/lib/flags/parser.js +254 -0
  72. package/lib/flags/parser.js.map +1 -0
  73. package/lib/flags/schema.d.ts +147 -0
  74. package/lib/flags/schema.js +405 -0
  75. package/lib/flags/schema.js.map +1 -0
  76. package/lib/launcher/internal/getCompilerVersionText.js +7 -0
  77. package/lib/launcher/internal/getCompilerVersionText.js.map +1 -1
  78. package/lib/launcher/internal/prepareExecution.js +35 -0
  79. package/lib/launcher/internal/prepareExecution.js.map +1 -1
  80. package/lib/launcher/internal/resolveCacheDir.d.ts +9 -0
  81. package/lib/launcher/internal/resolveCacheDir.js +22 -0
  82. package/lib/launcher/internal/resolveCacheDir.js.map +1 -0
  83. package/lib/launcher/internal/resolveTtscserverBinary.js +2 -0
  84. package/lib/launcher/internal/resolveTtscserverBinary.js.map +1 -1
  85. package/lib/launcher/internal/runTtsc.d.ts +10 -0
  86. package/lib/launcher/internal/runTtsc.js +90 -153
  87. package/lib/launcher/internal/runTtsc.js.map +1 -1
  88. package/lib/launcher/internal/runTtscserver.js +10 -35
  89. package/lib/launcher/internal/runTtscserver.js.map +1 -1
  90. package/lib/launcher/internal/runTtsx.d.ts +8 -0
  91. package/lib/launcher/internal/runTtsx.js +137 -79
  92. package/lib/launcher/internal/runTtsx.js.map +1 -1
  93. package/lib/plugin/internal/buildSourcePlugin.d.ts +38 -0
  94. package/lib/plugin/internal/buildSourcePlugin.js +40 -17
  95. package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
  96. package/lib/plugin/internal/loadProjectPlugins.d.ts +26 -0
  97. package/lib/plugin/internal/loadProjectPlugins.js +90 -41
  98. package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
  99. package/lib/structures/ITtscCompilerTransformation.d.ts +15 -2
  100. package/lib/structures/ITtscPlugin.d.ts +24 -0
  101. package/lib/structures/ITtscPluginCapabilities.d.ts +29 -0
  102. package/lib/structures/ITtscPluginCapabilities.js +3 -0
  103. package/lib/structures/ITtscPluginCapabilities.js.map +1 -0
  104. package/lib/structures/index.d.ts +1 -0
  105. package/lib/structures/index.js +1 -0
  106. package/lib/structures/index.js.map +1 -1
  107. package/lib/structures/internal/ITtscLoadedNativePlugin.d.ts +5 -0
  108. package/lib/structures/internal/TtscCommonOptions.d.ts +19 -0
  109. package/lib/structures/internal/TtscSingleFileEmitOptions.d.ts +0 -2
  110. package/package.json +9 -9
  111. package/shim/ast/shim.go +24 -0
  112. package/shim/checker/shim.go +35 -0
  113. package/shim/core/shim.go +17 -0
  114. package/shim/diagnosticwriter/shim.go +4 -0
  115. package/shim/lsp/shim.go +3 -3
  116. package/shim/printer/shim.go +20 -0
  117. package/src/TtscCompiler.ts +7 -0
  118. package/src/compiler/internal/buildNativeCompiler.ts +23 -3
  119. package/src/compiler/internal/compileProjectInMemory.ts +34 -25
  120. package/src/compiler/internal/paths.ts +68 -0
  121. package/src/compiler/internal/project/readProjectConfig.ts +86 -1
  122. package/src/compiler/internal/project/resolveProjectConfig.ts +44 -1
  123. package/src/compiler/internal/resolveBinary.ts +17 -1
  124. package/src/compiler/internal/resolveEmittedJavaScript.ts +43 -12
  125. package/src/compiler/internal/resolveTsgo.ts +29 -1
  126. package/src/compiler/internal/runBuild.ts +398 -112
  127. package/src/compiler/internal/runSingleFileEmit.ts +14 -1
  128. package/src/compiler/internal/sharedHostHelpers.ts +7 -7
  129. package/src/compiler/internal/spawnNative.ts +64 -0
  130. package/src/compiler/internal/transformProjectInMemory.ts +47 -67
  131. package/src/flags/parser.ts +367 -0
  132. package/src/flags/schema.ts +570 -0
  133. package/src/launcher/internal/getCompilerVersionText.ts +7 -0
  134. package/src/launcher/internal/prepareExecution.ts +35 -0
  135. package/src/launcher/internal/resolveCacheDir.ts +19 -0
  136. package/src/launcher/internal/resolveTtscserverBinary.ts +2 -0
  137. package/src/launcher/internal/runTtsc.ts +97 -143
  138. package/src/launcher/internal/runTtscserver.ts +9 -1
  139. package/src/launcher/internal/runTtsx.ts +149 -82
  140. package/src/plugin/internal/buildSourcePlugin.ts +40 -14
  141. package/src/plugin/internal/loadProjectPlugins.ts +116 -45
  142. package/src/structures/ITtscCompilerTransformation.ts +15 -2
  143. package/src/structures/ITtscPlugin.ts +26 -1
  144. package/src/structures/ITtscPluginCapabilities.ts +29 -0
  145. package/src/structures/index.ts +1 -0
  146. package/src/structures/internal/ITtscLoadedNativePlugin.ts +5 -0
  147. package/src/structures/internal/TtscCommonOptions.ts +19 -0
  148. package/src/structures/internal/TtscSingleFileEmitOptions.ts +0 -2
  149. package/tools/gen_shims/main.go +43 -8
  150. package/utility/flags_gen.go +30 -0
  151. package/utility/host.go +304 -245
@@ -0,0 +1,30 @@
1
+ // Code generated by packages/ttsc/scripts/gen-flags.mts. DO NOT EDIT.
2
+ //
3
+ // Source of truth: packages/ttsc/src/flags/schema.ts.
4
+ // Regenerate with: pnpm format
5
+ // Verify in CI with: node packages/ttsc/scripts/check-flags.cjs
6
+
7
+ package main
8
+
9
+ // HostFlagAllowList is the allow-list of CLI flags this Go layer accepts. The map's
10
+ // value is true when the flag carries a separate value token (--flag VALUE
11
+ // or --flag=VALUE) and false when the flag is boolean (--flag).
12
+ //
13
+ // Generated from packages/ttsc/src/flags/schema.ts. Edit the schema, not
14
+ // this file.
15
+ var HostFlagAllowList = map[string]bool{
16
+ "checkers": true,
17
+ "cwd": true,
18
+ "emit": false,
19
+ "manifest": true,
20
+ "noEmit": false,
21
+ "outDir": true,
22
+ "p": true,
23
+ "plugins-json": true,
24
+ "project": true,
25
+ "quiet": false,
26
+ "singleThreaded": false,
27
+ "tsconfig": true,
28
+ "tsgo-args": true,
29
+ "verbose": false,
30
+ }
@@ -1,47 +1,58 @@
1
1
  package main
2
2
 
3
3
  import (
4
- "bytes"
5
- "errors"
6
- "os"
7
- "path/filepath"
8
- "testing"
9
- _ "unsafe"
4
+ "bytes"
5
+ "errors"
6
+ "os"
7
+ "path/filepath"
8
+ "testing"
9
+ _ "unsafe"
10
10
  )
11
11
 
12
+ // driverPluginRegistry is a linkname alias for the unexported plugin slice in
13
+ // the driver package, allowing tests to reset registered plugins between cases.
14
+ //
12
15
  //go:linkname driverPluginRegistry github.com/samchon/ttsc/packages/ttsc/driver.pluginRegistry
13
16
  var driverPluginRegistry []any
14
17
 
18
+ // captureCommand redirects the package-level stdout/stderr/getwd seams around
19
+ // fn, then returns the exit code and the captured output strings.
15
20
  func captureCommand(t *testing.T, fn func() int) (int, string, string) {
16
- t.Helper()
17
- prevOut, prevErr, prevGetwd := stdout, stderr, getwd
18
- var out, err bytes.Buffer
19
- stdout = &out
20
- stderr = &err
21
- defer func() {
22
- stdout = prevOut
23
- stderr = prevErr
24
- getwd = prevGetwd
25
- }()
26
- code := fn()
27
- return code, out.String(), err.String()
21
+ t.Helper()
22
+ prevOut, prevErr, prevGetwd := stdout, stderr, getwd
23
+ var out, err bytes.Buffer
24
+ stdout = &out
25
+ stderr = &err
26
+ defer func() {
27
+ stdout = prevOut
28
+ stderr = prevErr
29
+ getwd = prevGetwd
30
+ }()
31
+ code := fn()
32
+ return code, out.String(), err.String()
28
33
  }
29
34
 
35
+ // failGetwd is a getwd stub that always returns an error, used to exercise the
36
+ // cwd-resolution failure path in command entrypoints.
30
37
  func failGetwd() (string, error) {
31
- return "", errors.New("cwd boom")
38
+ return "", errors.New("cwd boom")
32
39
  }
33
40
 
41
+ // writeCommandProjectFile writes contents to root/name, creating intermediate
42
+ // directories as needed. Slashes in name are normalised to the OS separator.
34
43
  func writeCommandProjectFile(t *testing.T, root, name, contents string) {
35
- t.Helper()
36
- file := filepath.Join(root, filepath.FromSlash(name))
37
- if err := os.MkdirAll(filepath.Dir(file), 0o755); err != nil {
38
- t.Fatal(err)
39
- }
40
- if err := os.WriteFile(file, []byte(contents), 0o644); err != nil {
41
- t.Fatal(err)
42
- }
44
+ t.Helper()
45
+ file := filepath.Join(root, filepath.FromSlash(name))
46
+ if err := os.MkdirAll(filepath.Dir(file), 0o755); err != nil {
47
+ t.Fatal(err)
48
+ }
49
+ if err := os.WriteFile(file, []byte(contents), 0o644); err != nil {
50
+ t.Fatal(err)
51
+ }
43
52
  }
44
53
 
54
+ // resetCommandLinkedPluginRegistry clears the driver plugin registry so that
55
+ // tests that register plugins do not pollute subsequent test cases.
45
56
  func resetCommandLinkedPluginRegistry() {
46
- driverPluginRegistry = nil
57
+ driverPluginRegistry = nil
47
58
  }
package/cmd/ttsc/main.go CHANGED
@@ -12,104 +12,108 @@
12
12
  package main
13
13
 
14
14
  import (
15
- "flag"
16
- "fmt"
17
- "io"
18
- "os"
19
- "runtime"
20
- "strings"
15
+ "flag"
16
+ "fmt"
17
+ "io"
18
+ "os"
19
+ "runtime"
20
+ "strings"
21
21
  )
22
22
 
23
23
  // These are overridden via `-ldflags "-X main.version=... -X main.commit=..."`
24
24
  // in CI. Sensible defaults keep local `go run ./cmd/ttsc` usable.
25
25
  var (
26
- version = "0.0.0-dev"
27
- commit = "dev"
28
- date = "unknown"
26
+ version = "0.0.0-dev"
27
+ commit = "dev"
28
+ date = "unknown"
29
29
  )
30
30
 
31
31
  // stdout / stderr are package-level to keep the CLI testable.
32
32
  var (
33
- stdout io.Writer = os.Stdout
34
- stderr io.Writer = os.Stderr
35
- getwd = os.Getwd
33
+ stdout io.Writer = os.Stdout
34
+ stderr io.Writer = os.Stderr
35
+ getwd = os.Getwd
36
36
  )
37
37
 
38
38
  func main() {
39
- os.Exit(run(os.Args[1:]))
39
+ os.Exit(run(os.Args[1:]))
40
40
  }
41
41
 
42
42
  func run(args []string) int {
43
- if len(args) == 0 {
44
- return runBuild(nil)
45
- }
46
-
47
- switch args[0] {
48
- case "-h", "--help", "help":
49
- printHelp(stdout)
50
- return 0
51
- case "-v", "--version", "version":
52
- printVersion(stdout)
53
- return 0
54
- case "demo":
55
- return runDemo(args[1:])
56
- case "build":
57
- return runBuild(args[1:])
58
- case "api-compile":
59
- return runAPICompile(args[1:])
60
- case "api-transform":
61
- return runAPITransform(args[1:])
62
- case "check":
63
- // `ttsc check` runs the analyze pipeline without emitting JS — useful
64
- // in CI and pre-commit checks that only need schema validation.
65
- return runBuild(append([]string{"--noEmit"}, args[1:]...))
66
- case "-p", "--project":
67
- if len(args) < 2 {
68
- fmt.Fprintln(stderr, "ttsc: -p/--project requires a path argument")
69
- return 2
70
- }
71
- return runBuild(append([]string{"--tsconfig=" + args[1]}, args[2:]...))
72
- default:
73
- if isBuildAlias(args[0]) {
74
- return runBuild(args)
75
- }
76
- fmt.Fprintf(stderr, "ttsc: unknown command %q\n", args[0])
77
- fmt.Fprintln(stderr, `ttsc: run "ttsc --help" to see supported commands`)
78
- return 2
79
- }
43
+ if len(args) == 0 {
44
+ return runBuild(nil)
45
+ }
46
+
47
+ switch args[0] {
48
+ case "-h", "--help", "help":
49
+ printHelp(stdout)
50
+ return 0
51
+ case "-v", "--version", "version":
52
+ printVersion(stdout)
53
+ return 0
54
+ case "demo":
55
+ return runDemo(args[1:])
56
+ case "build":
57
+ return runBuild(args[1:])
58
+ case "api-compile":
59
+ return runAPICompile(args[1:])
60
+ case "api-transform":
61
+ return runAPITransform(args[1:])
62
+ case "check":
63
+ // `ttsc check` runs the analyze pipeline without emitting JS — useful
64
+ // in CI and pre-commit checks that only need schema validation.
65
+ return runBuild(append([]string{"--noEmit"}, args[1:]...))
66
+ case "-p", "--project":
67
+ if len(args) < 2 {
68
+ fmt.Fprintln(stderr, "ttsc: -p/--project requires a path argument")
69
+ return 2
70
+ }
71
+ return runBuild(append([]string{"--tsconfig=" + args[1]}, args[2:]...))
72
+ default:
73
+ if isBuildAlias(args[0]) {
74
+ return runBuild(args)
75
+ }
76
+ fmt.Fprintf(stderr, "ttsc: unknown command %q\n", args[0])
77
+ fmt.Fprintln(stderr, `ttsc: run "ttsc --help" to see supported commands`)
78
+ return 2
79
+ }
80
80
  }
81
81
 
82
+ // isBuildAlias reports whether arg should be forwarded to runBuild without
83
+ // requiring an explicit "build" verb. Any flag-shaped argument (leading "-")
84
+ // or a TypeScript-project file extension is treated as a build alias, matching
85
+ // the tsc/tsgo invocation convention.
82
86
  func isBuildAlias(arg string) bool {
83
- if strings.HasPrefix(arg, "-") {
84
- return true
85
- }
86
- switch {
87
- case strings.HasSuffix(arg, ".json"),
88
- strings.HasSuffix(arg, ".ts"),
89
- strings.HasSuffix(arg, ".tsx"),
90
- strings.HasSuffix(arg, ".mts"),
91
- strings.HasSuffix(arg, ".cts"):
92
- return true
93
- default:
94
- return false
95
- }
87
+ if strings.HasPrefix(arg, "-") {
88
+ return true
89
+ }
90
+ switch {
91
+ case strings.HasSuffix(arg, ".json"),
92
+ strings.HasSuffix(arg, ".ts"),
93
+ strings.HasSuffix(arg, ".tsx"),
94
+ strings.HasSuffix(arg, ".mts"),
95
+ strings.HasSuffix(arg, ".cts"):
96
+ return true
97
+ default:
98
+ return false
99
+ }
96
100
  }
97
101
 
98
102
  func printVersion(w io.Writer) {
99
- fmt.Fprintf(
100
- w,
101
- "ttsc %s (commit %s, built %s, %s/%s, go %s)\n",
102
- version,
103
- commit,
104
- date,
105
- runtime.GOOS,
106
- runtime.GOARCH,
107
- runtime.Version(),
108
- )
103
+ fmt.Fprintf(
104
+ w,
105
+ "ttsc %s (commit %s, built %s, %s/%s, go %s)\n",
106
+ version,
107
+ commit,
108
+ date,
109
+ runtime.GOOS,
110
+ runtime.GOARCH,
111
+ runtime.Version(),
112
+ )
109
113
  }
110
114
 
111
115
  func printHelp(w io.Writer) {
112
- fmt.Fprintln(w, strings.TrimSpace(`
116
+ fmt.Fprintln(w, strings.TrimSpace(`
113
117
  ttsc — standalone typescript-go host.
114
118
 
115
119
  Usage:
@@ -155,37 +159,40 @@ Integration guide (bundlers):
155
159
  }
156
160
 
157
161
  func runDemo(args []string) int {
158
- fs := flag.NewFlagSet("demo", flag.ContinueOnError)
159
- fs.SetOutput(stderr)
160
- typ := fs.String("type", "string", "atomic type to simulate")
161
- if err := fs.Parse(args); err != nil {
162
- return 2
163
- }
164
-
165
- arrow, err := demoArrow(*typ)
166
- if err != nil {
167
- fmt.Fprintf(stderr, "ttsc demo: %v\n", err)
168
- return 2
169
- }
170
-
171
- fmt.Fprintf(stdout, "// demo<%s> -> emitted by ttsc %s\n", *typ, version)
172
- fmt.Fprintln(stdout, arrow)
173
- return 0
162
+ fs := flag.NewFlagSet("demo", flag.ContinueOnError)
163
+ fs.SetOutput(stderr)
164
+ typ := fs.String("type", "string", "atomic type to simulate")
165
+ if err := fs.Parse(args); err != nil {
166
+ return 2
167
+ }
168
+
169
+ arrow, err := demoArrow(*typ)
170
+ if err != nil {
171
+ fmt.Fprintf(stderr, "ttsc demo: %v\n", err)
172
+ return 2
173
+ }
174
+
175
+ fmt.Fprintf(stdout, "// demo<%s> -> emitted by ttsc %s\n", *typ, version)
176
+ fmt.Fprintln(stdout, arrow)
177
+ return 0
174
178
  }
175
179
 
180
+ // demoArrow returns a JavaScript arrow-function expression that validates the
181
+ // named atomic TypeScript type at runtime. Used by the demo sub-command to
182
+ // produce a small synthetic emit that smoke tests can assert on.
176
183
  func demoArrow(name string) (string, error) {
177
- switch strings.ToLower(name) {
178
- case "any":
179
- return "(input) => true", nil
180
- case "boolean":
181
- return `(input) => "boolean" === typeof input`, nil
182
- case "number":
183
- return `(input) => "number" === typeof input`, nil
184
- case "bigint":
185
- return `(input) => "bigint" === typeof input`, nil
186
- case "string", "":
187
- return `(input) => "string" === typeof input`, nil
188
- default:
189
- return "", fmt.Errorf("unknown --type value %q (want: string|number|boolean|bigint|any)", name)
190
- }
184
+ switch strings.ToLower(name) {
185
+ case "any":
186
+ return "(input) => true", nil
187
+ case "boolean":
188
+ return `(input) => "boolean" === typeof input`, nil
189
+ case "number":
190
+ return `(input) => "number" === typeof input`, nil
191
+ case "bigint":
192
+ return `(input) => "bigint" === typeof input`, nil
193
+ case "string", "":
194
+ return `(input) => "string" === typeof input`, nil
195
+ default:
196
+ return "", fmt.Errorf("unknown --type value %q (want: string|number|boolean|bigint|any)", name)
197
+ }
191
198
  }
@@ -2,28 +2,26 @@ package main
2
2
 
3
3
  import "testing"
4
4
 
5
- /**
6
- * Verifies main command aliases cover flag-shaped demo and cts project inputs.
7
- *
8
- * The top-level dispatcher treats extension-shaped arguments as build aliases
9
- * while demo owns its own flag parser. These small branches keep compatibility
10
- * with `ttsc ./tsconfig.cts`-style invocations and malformed demo flags.
11
- *
12
- * 1. Run demo with a missing flag value.
13
- * 2. Dispatch a `.cts` argument through the build alias path.
14
- * 3. Assert both routes fail through their intended parser.
15
- */
5
+ // TestMainAliasBranches verifies main command aliases cover flag-shaped demo and cts project inputs.
6
+ //
7
+ // The top-level dispatcher treats extension-shaped arguments as build aliases
8
+ // while demo owns its own flag parser. These small branches keep compatibility
9
+ // with `ttsc ./tsconfig.cts`-style invocations and malformed demo flags.
10
+ //
11
+ // 1. Run demo with a missing flag value.
12
+ // 2. Dispatch a `.cts` argument through the build alias path.
13
+ // 3. Assert both routes fail through their intended parser.
16
14
  func TestMainAliasBranches(t *testing.T) {
17
- code, _, _ := captureCommand(t, func() int {
18
- return run([]string{"demo", "--type"})
19
- })
20
- if code != 2 {
21
- t.Fatalf("demo flag status mismatch: %d", code)
22
- }
23
- code, _, _ = captureCommand(t, func() int {
24
- return run([]string{"project.cts"})
25
- })
26
- if code != 2 {
27
- t.Fatalf("cts build alias status mismatch: %d", code)
28
- }
15
+ code, _, _ := captureCommand(t, func() int {
16
+ return run([]string{"demo", "--type"})
17
+ })
18
+ if code != 2 {
19
+ t.Fatalf("demo flag status mismatch: %d", code)
20
+ }
21
+ code, _, _ = captureCommand(t, func() int {
22
+ return run([]string{"project.cts"})
23
+ })
24
+ if code != 2 {
25
+ t.Fatalf("cts build alias status mismatch: %d", code)
26
+ }
29
27
  }
@@ -12,34 +12,34 @@
12
12
  package main
13
13
 
14
14
  import (
15
- "context"
16
- "errors"
17
- "flag"
18
- "fmt"
19
- "io"
20
- "os"
21
- "os/signal"
22
- "runtime"
23
- "strings"
24
- "syscall"
25
- "time"
26
-
27
- "github.com/samchon/ttsc/packages/ttsc/internal/lspserver"
15
+ "context"
16
+ "errors"
17
+ "flag"
18
+ "fmt"
19
+ "io"
20
+ "os"
21
+ "os/signal"
22
+ "runtime"
23
+ "strings"
24
+ "syscall"
25
+ "time"
26
+
27
+ "github.com/samchon/ttsc/packages/ttsc/internal/lspserver"
28
28
  )
29
29
 
30
30
  // Build metadata; overwritten via -ldflags in release builds.
31
31
  var (
32
- version = "0.0.0-dev"
33
- commit = "dev"
34
- date = "unknown"
32
+ version = "0.0.0-dev"
33
+ commit = "dev"
34
+ date = "unknown"
35
35
  )
36
36
 
37
37
  // Package-level writers so command tests can capture output without
38
38
  // patching os.Stdout / os.Stderr globally.
39
39
  var (
40
- stdout io.Writer = os.Stdout
41
- stderr io.Writer = os.Stderr
42
- stdin io.Reader = os.Stdin
40
+ stdout io.Writer = os.Stdout
41
+ stderr io.Writer = os.Stderr
42
+ stdin io.Reader = os.Stdin
43
43
  )
44
44
 
45
45
  // runLSPServer is the seam command tests use to substitute a fake LSP
@@ -56,89 +56,95 @@ var notifyContext = signal.NotifyContext
56
56
  var getwd = os.Getwd
57
57
 
58
58
  func main() {
59
- os.Exit(run(os.Args[1:]))
59
+ os.Exit(run(os.Args[1:]))
60
60
  }
61
61
 
62
+ // run dispatches top-level subcommands/flags and returns an exit code.
63
+ // Called by main with os.Args[1:] and overridden in tests with a synthetic
64
+ // argument slice to avoid spawning a real tsgo process.
62
65
  func run(args []string) int {
63
- if len(args) == 0 {
64
- printHelp(stdout)
65
- return 0
66
- }
67
- switch args[0] {
68
- case "-h", "--help", "help":
69
- printHelp(stdout)
70
- return 0
71
- case "-v", "--version", "version":
72
- printVersion(stdout)
73
- return 0
74
- }
75
- return runLSP(args)
66
+ if len(args) == 0 {
67
+ printHelp(stdout)
68
+ return 0
69
+ }
70
+ switch args[0] {
71
+ case "-h", "--help", "help":
72
+ printHelp(stdout)
73
+ return 0
74
+ case "-v", "--version", "version":
75
+ printVersion(stdout)
76
+ return 0
77
+ }
78
+ return runLSP(args)
76
79
  }
77
80
 
81
+ // runLSP parses LSP-mode flags and starts the proxy. It returns 0 on clean
82
+ // shutdown, 1 on a runtime error from the LSP host, and 2 on invalid
83
+ // invocation (missing --stdio, unresolvable cwd, unknown flags).
78
84
  func runLSP(args []string) int {
79
- fs := flag.NewFlagSet("ttscserver", flag.ContinueOnError)
80
- fs.SetOutput(stderr)
81
- stdioFlag := fs.Bool("stdio", false, "communicate with the editor over stdin/stdout")
82
- cwdFlag := fs.String("cwd", "", "project root (defaults to process cwd)")
83
- tsgoFlag := fs.String("tsgo", "", "absolute tsgo binary path (defaults to TTSC_TSGO_BINARY)")
84
- progressDelayFlag := fs.Duration("progress-delay", 250*time.Millisecond, "delay before showing tsgo's progress UI")
85
- if err := fs.Parse(args); err != nil {
86
- return 2
87
- }
88
- if !*stdioFlag {
89
- fmt.Fprintln(stderr, "ttscserver: only --stdio transport is supported")
90
- return 2
91
- }
92
-
93
- cwd := strings.TrimSpace(*cwdFlag)
94
- if cwd == "" {
95
- resolved, err := getwd()
96
- if err != nil {
97
- fmt.Fprintf(stderr, "ttscserver: could not resolve working directory: %v\n", err)
98
- return 2
99
- }
100
- cwd = resolved
101
- }
102
-
103
- ctx, stop := notifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
104
- defer stop()
105
-
106
- tsgoBinary := strings.TrimSpace(*tsgoFlag)
107
- if tsgoBinary == "" {
108
- tsgoBinary = strings.TrimSpace(os.Getenv("TTSC_TSGO_BINARY"))
109
- }
110
-
111
- err := runLSPServer(ctx, lspserver.LSPServerOptions{
112
- In: stdin,
113
- Out: stdout,
114
- Err: stderr,
115
- Cwd: cwd,
116
- TsgoBinary: tsgoBinary,
117
- Source: lspserver.NullPluginSource{},
118
- ProgressDelay: *progressDelayFlag,
119
- })
120
- if err != nil && !errors.Is(err, context.Canceled) {
121
- fmt.Fprintf(stderr, "ttscserver: %v\n", err)
122
- return 1
123
- }
124
- return 0
85
+ fs := flag.NewFlagSet("ttscserver", flag.ContinueOnError)
86
+ fs.SetOutput(stderr)
87
+ stdioFlag := fs.Bool("stdio", false, "communicate with the editor over stdin/stdout")
88
+ cwdFlag := fs.String("cwd", "", "project root (defaults to process cwd)")
89
+ tsgoFlag := fs.String("tsgo", "", "absolute tsgo binary path (defaults to TTSC_TSGO_BINARY)")
90
+ progressDelayFlag := fs.Duration("progress-delay", 250*time.Millisecond, "delay before showing tsgo's progress UI")
91
+ if err := fs.Parse(args); err != nil {
92
+ return 2
93
+ }
94
+ if !*stdioFlag {
95
+ fmt.Fprintln(stderr, "ttscserver: only --stdio transport is supported")
96
+ return 2
97
+ }
98
+
99
+ cwd := strings.TrimSpace(*cwdFlag)
100
+ if cwd == "" {
101
+ resolved, err := getwd()
102
+ if err != nil {
103
+ fmt.Fprintf(stderr, "ttscserver: could not resolve working directory: %v\n", err)
104
+ return 2
105
+ }
106
+ cwd = resolved
107
+ }
108
+
109
+ ctx, stop := notifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
110
+ defer stop()
111
+
112
+ tsgoBinary := strings.TrimSpace(*tsgoFlag)
113
+ if tsgoBinary == "" {
114
+ tsgoBinary = strings.TrimSpace(os.Getenv("TTSC_TSGO_BINARY"))
115
+ }
116
+
117
+ err := runLSPServer(ctx, lspserver.LSPServerOptions{
118
+ In: stdin,
119
+ Out: stdout,
120
+ Err: stderr,
121
+ Cwd: cwd,
122
+ TsgoBinary: tsgoBinary,
123
+ Source: lspserver.NullPluginSource{},
124
+ ProgressDelay: *progressDelayFlag,
125
+ })
126
+ if err != nil && !errors.Is(err, context.Canceled) {
127
+ fmt.Fprintf(stderr, "ttscserver: %v\n", err)
128
+ return 1
129
+ }
130
+ return 0
125
131
  }
126
132
 
127
133
  func printVersion(w io.Writer) {
128
- fmt.Fprintf(
129
- w,
130
- "ttscserver %s (commit %s, built %s, %s/%s, go %s)\n",
131
- version,
132
- commit,
133
- date,
134
- runtime.GOOS,
135
- runtime.GOARCH,
136
- runtime.Version(),
137
- )
134
+ fmt.Fprintf(
135
+ w,
136
+ "ttscserver %s (commit %s, built %s, %s/%s, go %s)\n",
137
+ version,
138
+ commit,
139
+ date,
140
+ runtime.GOOS,
141
+ runtime.GOARCH,
142
+ runtime.Version(),
143
+ )
138
144
  }
139
145
 
140
146
  func printHelp(w io.Writer) {
141
- fmt.Fprintln(w, strings.TrimSpace(`
147
+ fmt.Fprintln(w, strings.TrimSpace(`
142
148
  ttscserver — Language Server Protocol host for ttsc.
143
149
 
144
150
  Usage: