ttsc 0.12.3 → 0.12.4

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 (126) hide show
  1. package/cmd/platform/main.go +9 -0
  2. package/cmd/ttsc/api_compile.go +109 -101
  3. package/cmd/ttsc/api_compile_branches_test.go +55 -57
  4. package/cmd/ttsc/api_transform.go +54 -49
  5. package/cmd/ttsc/api_transform_branches_test.go +30 -32
  6. package/cmd/ttsc/build.go +111 -108
  7. package/cmd/ttsc/build_branches_test.go +95 -97
  8. package/cmd/ttsc/helpers_test.go +39 -28
  9. package/cmd/ttsc/main.go +111 -104
  10. package/cmd/ttsc/main_alias_branches_test.go +21 -23
  11. package/cmd/ttscserver/main.go +96 -90
  12. package/cmd/ttscserver/run_lsp_prefers_tsgo_flag_test.go +22 -22
  13. package/cmd/ttscserver/run_lsp_reports_server_error_test.go +22 -22
  14. package/cmd/ttscserver/run_lsp_uses_tsgo_environment_test.go +23 -23
  15. package/cmd/utility-host/main.go +30 -23
  16. package/driver/lsp.go +53 -7
  17. package/driver/plugins.go +88 -72
  18. package/driver/program.go +362 -339
  19. package/driver/rewrite.go +442 -380
  20. package/internal/lspserver/lsp_envelope.go +64 -64
  21. package/internal/lspserver/lsp_frame.go +60 -60
  22. package/internal/lspserver/lsp_plugin.go +57 -57
  23. package/internal/lspserver/lsp_proxy.go +265 -251
  24. package/internal/lspserver/lsp_server.go +155 -144
  25. package/lib/TtscCompiler.d.ts +7 -0
  26. package/lib/TtscCompiler.js +7 -0
  27. package/lib/TtscCompiler.js.map +1 -1
  28. package/lib/compiler/internal/buildNativeCompiler.d.ts +11 -1
  29. package/lib/compiler/internal/buildNativeCompiler.js +23 -3
  30. package/lib/compiler/internal/buildNativeCompiler.js.map +1 -1
  31. package/lib/compiler/internal/compileProjectInMemory.d.ts +9 -0
  32. package/lib/compiler/internal/compileProjectInMemory.js +36 -21
  33. package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
  34. package/lib/compiler/internal/paths.d.ts +27 -0
  35. package/lib/compiler/internal/paths.js +70 -0
  36. package/lib/compiler/internal/paths.js.map +1 -0
  37. package/lib/compiler/internal/project/readProjectConfig.d.ts +9 -1
  38. package/lib/compiler/internal/project/readProjectConfig.js +80 -1
  39. package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
  40. package/lib/compiler/internal/project/resolveProjectConfig.d.ts +13 -1
  41. package/lib/compiler/internal/project/resolveProjectConfig.js +24 -1
  42. package/lib/compiler/internal/project/resolveProjectConfig.js.map +1 -1
  43. package/lib/compiler/internal/resolveBinary.d.ts +9 -1
  44. package/lib/compiler/internal/resolveBinary.js +17 -1
  45. package/lib/compiler/internal/resolveBinary.js.map +1 -1
  46. package/lib/compiler/internal/resolveEmittedJavaScript.d.ts +16 -1
  47. package/lib/compiler/internal/resolveEmittedJavaScript.js +42 -10
  48. package/lib/compiler/internal/resolveEmittedJavaScript.js.map +1 -1
  49. package/lib/compiler/internal/resolveTsgo.d.ts +21 -1
  50. package/lib/compiler/internal/resolveTsgo.js +23 -1
  51. package/lib/compiler/internal/resolveTsgo.js.map +1 -1
  52. package/lib/compiler/internal/runBuild.d.ts +19 -0
  53. package/lib/compiler/internal/runBuild.js +112 -46
  54. package/lib/compiler/internal/runBuild.js.map +1 -1
  55. package/lib/compiler/internal/runSingleFileEmit.d.ts +10 -1
  56. package/lib/compiler/internal/runSingleFileEmit.js +14 -1
  57. package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
  58. package/lib/compiler/internal/sharedHostHelpers.d.ts +5 -0
  59. package/lib/compiler/internal/sharedHostHelpers.js +6 -2
  60. package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
  61. package/lib/compiler/internal/spawnNative.d.ts +21 -0
  62. package/lib/compiler/internal/spawnNative.js +59 -0
  63. package/lib/compiler/internal/spawnNative.js.map +1 -0
  64. package/lib/compiler/internal/transformProjectInMemory.d.ts +15 -1
  65. package/lib/compiler/internal/transformProjectInMemory.js +57 -61
  66. package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
  67. package/lib/launcher/internal/getCompilerVersionText.js +7 -0
  68. package/lib/launcher/internal/getCompilerVersionText.js.map +1 -1
  69. package/lib/launcher/internal/prepareExecution.js +32 -0
  70. package/lib/launcher/internal/prepareExecution.js.map +1 -1
  71. package/lib/launcher/internal/resolveCacheDir.d.ts +9 -0
  72. package/lib/launcher/internal/resolveCacheDir.js +22 -0
  73. package/lib/launcher/internal/resolveCacheDir.js.map +1 -0
  74. package/lib/launcher/internal/resolveTtscserverBinary.js +2 -0
  75. package/lib/launcher/internal/resolveTtscserverBinary.js.map +1 -1
  76. package/lib/launcher/internal/runTtsc.d.ts +10 -0
  77. package/lib/launcher/internal/runTtsc.js +22 -9
  78. package/lib/launcher/internal/runTtsc.js.map +1 -1
  79. package/lib/launcher/internal/runTtscserver.js +10 -35
  80. package/lib/launcher/internal/runTtscserver.js.map +1 -1
  81. package/lib/launcher/internal/runTtsx.d.ts +8 -0
  82. package/lib/launcher/internal/runTtsx.js +33 -7
  83. package/lib/launcher/internal/runTtsx.js.map +1 -1
  84. package/lib/plugin/internal/buildSourcePlugin.d.ts +38 -0
  85. package/lib/plugin/internal/buildSourcePlugin.js +40 -17
  86. package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
  87. package/lib/plugin/internal/loadProjectPlugins.d.ts +26 -0
  88. package/lib/plugin/internal/loadProjectPlugins.js +32 -18
  89. package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
  90. package/lib/structures/ITtscCompilerTransformation.d.ts +15 -2
  91. package/lib/structures/internal/TtscSingleFileEmitOptions.d.ts +0 -2
  92. package/package.json +9 -9
  93. package/shim/ast/shim.go +24 -0
  94. package/shim/checker/shim.go +35 -0
  95. package/shim/core/shim.go +17 -0
  96. package/shim/diagnosticwriter/shim.go +4 -0
  97. package/shim/lsp/shim.go +3 -3
  98. package/shim/printer/shim.go +20 -0
  99. package/src/TtscCompiler.ts +7 -0
  100. package/src/compiler/internal/buildNativeCompiler.ts +23 -3
  101. package/src/compiler/internal/compileProjectInMemory.ts +34 -25
  102. package/src/compiler/internal/paths.ts +68 -0
  103. package/src/compiler/internal/project/readProjectConfig.ts +86 -1
  104. package/src/compiler/internal/project/resolveProjectConfig.ts +24 -1
  105. package/src/compiler/internal/resolveBinary.ts +17 -1
  106. package/src/compiler/internal/resolveEmittedJavaScript.ts +43 -12
  107. package/src/compiler/internal/resolveTsgo.ts +29 -1
  108. package/src/compiler/internal/runBuild.ts +110 -55
  109. package/src/compiler/internal/runSingleFileEmit.ts +14 -1
  110. package/src/compiler/internal/sharedHostHelpers.ts +7 -7
  111. package/src/compiler/internal/spawnNative.ts +64 -0
  112. package/src/compiler/internal/transformProjectInMemory.ts +47 -67
  113. package/src/launcher/internal/getCompilerVersionText.ts +7 -0
  114. package/src/launcher/internal/prepareExecution.ts +32 -0
  115. package/src/launcher/internal/resolveCacheDir.ts +19 -0
  116. package/src/launcher/internal/resolveTtscserverBinary.ts +2 -0
  117. package/src/launcher/internal/runTtsc.ts +22 -10
  118. package/src/launcher/internal/runTtscserver.ts +9 -1
  119. package/src/launcher/internal/runTtsx.ts +33 -8
  120. package/src/plugin/internal/buildSourcePlugin.ts +40 -14
  121. package/src/plugin/internal/loadProjectPlugins.ts +42 -18
  122. package/src/structures/ITtscCompilerTransformation.ts +15 -2
  123. package/src/structures/ITtscPlugin.ts +0 -1
  124. package/src/structures/internal/TtscSingleFileEmitOptions.ts +0 -2
  125. package/tools/gen_shims/main.go +43 -8
  126. package/utility/host.go +294 -245
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:
@@ -1,11 +1,11 @@
1
1
  package main
2
2
 
3
3
  import (
4
- "bytes"
5
- "context"
6
- "testing"
4
+ "bytes"
5
+ "context"
6
+ "testing"
7
7
 
8
- "github.com/samchon/ttsc/packages/ttsc/internal/lspserver"
8
+ "github.com/samchon/ttsc/packages/ttsc/internal/lspserver"
9
9
  )
10
10
 
11
11
  // TestRunLSPPrefersTsgoFlag verifies the native command forwards an explicit
@@ -19,24 +19,24 @@ import (
19
19
  // 2. Run runLSP with --stdio, --cwd, and --tsgo.
20
20
  // 3. Assert the captured TsgoBinary is the flag value.
21
21
  func TestRunLSPPrefersTsgoFlag(t *testing.T) {
22
- const expected = "/tmp/tsgo-test-binary"
23
- prev := runLSPServer
24
- var captured lspserver.LSPServerOptions
25
- runLSPServer = func(_ context.Context, opts lspserver.LSPServerOptions) error {
26
- captured = opts
27
- return nil
28
- }
29
- defer func() { runLSPServer = prev }()
22
+ const expected = "/tmp/tsgo-test-binary"
23
+ prev := runLSPServer
24
+ var captured lspserver.LSPServerOptions
25
+ runLSPServer = func(_ context.Context, opts lspserver.LSPServerOptions) error {
26
+ captured = opts
27
+ return nil
28
+ }
29
+ defer func() { runLSPServer = prev }()
30
30
 
31
- outBuf := &bytes.Buffer{}
32
- errBuf := &bytes.Buffer{}
33
- withIO(t, outBuf, errBuf, nil, func() {
34
- if code := runLSP([]string{"--stdio", "--cwd", t.TempDir(), "--tsgo", expected}); code != 0 {
35
- t.Fatalf("expected exit 0, got %d (stderr=%q)", code, errBuf.String())
36
- }
37
- })
31
+ outBuf := &bytes.Buffer{}
32
+ errBuf := &bytes.Buffer{}
33
+ withIO(t, outBuf, errBuf, nil, func() {
34
+ if code := runLSP([]string{"--stdio", "--cwd", t.TempDir(), "--tsgo", expected}); code != 0 {
35
+ t.Fatalf("expected exit 0, got %d (stderr=%q)", code, errBuf.String())
36
+ }
37
+ })
38
38
 
39
- if captured.TsgoBinary != expected {
40
- t.Fatalf("expected TsgoBinary %q, got %q", expected, captured.TsgoBinary)
41
- }
39
+ if captured.TsgoBinary != expected {
40
+ t.Fatalf("expected TsgoBinary %q, got %q", expected, captured.TsgoBinary)
41
+ }
42
42
  }
@@ -1,13 +1,13 @@
1
1
  package main
2
2
 
3
3
  import (
4
- "bytes"
5
- "context"
6
- "errors"
7
- "strings"
8
- "testing"
4
+ "bytes"
5
+ "context"
6
+ "errors"
7
+ "strings"
8
+ "testing"
9
9
 
10
- "github.com/samchon/ttsc/packages/ttsc/internal/lspserver"
10
+ "github.com/samchon/ttsc/packages/ttsc/internal/lspserver"
11
11
  )
12
12
 
13
13
  // TestRunLSPReportsServerError pins the non-cancellation error path in
@@ -19,22 +19,22 @@ import (
19
19
  // 2. Run runLSP with --stdio --cwd <tempdir>.
20
20
  // 3. Assert exit 1 and the sentinel text on stderr.
21
21
  func TestRunLSPReportsServerError(t *testing.T) {
22
- sentinel := errors.New("lsp host blew up")
23
- prev := runLSPServer
24
- runLSPServer = func(_ context.Context, _ lspserver.LSPServerOptions) error {
25
- return sentinel
26
- }
27
- defer func() { runLSPServer = prev }()
22
+ sentinel := errors.New("lsp host blew up")
23
+ prev := runLSPServer
24
+ runLSPServer = func(_ context.Context, _ lspserver.LSPServerOptions) error {
25
+ return sentinel
26
+ }
27
+ defer func() { runLSPServer = prev }()
28
28
 
29
- outBuf := &bytes.Buffer{}
30
- errBuf := &bytes.Buffer{}
31
- withIO(t, outBuf, errBuf, nil, func() {
32
- if code := runLSP([]string{"--stdio", "--cwd", t.TempDir()}); code != 1 {
33
- t.Fatalf("expected exit 1, got %d", code)
34
- }
35
- })
29
+ outBuf := &bytes.Buffer{}
30
+ errBuf := &bytes.Buffer{}
31
+ withIO(t, outBuf, errBuf, nil, func() {
32
+ if code := runLSP([]string{"--stdio", "--cwd", t.TempDir()}); code != 1 {
33
+ t.Fatalf("expected exit 1, got %d", code)
34
+ }
35
+ })
36
36
 
37
- if !strings.Contains(errBuf.String(), sentinel.Error()) {
38
- t.Fatalf("expected sentinel on stderr, got: %q", errBuf.String())
39
- }
37
+ if !strings.Contains(errBuf.String(), sentinel.Error()) {
38
+ t.Fatalf("expected sentinel on stderr, got: %q", errBuf.String())
39
+ }
40
40
  }