ttsc 0.12.2 → 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 (134) 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 +101 -16
  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/go.mod +9 -0
  94. package/shim/ast/go.sum +20 -0
  95. package/shim/ast/safe_text.go +86 -0
  96. package/shim/ast/shim.go +24 -0
  97. package/shim/ast/test/node_text_joins_multi_hop_qualified_name_test.go +32 -0
  98. package/shim/ast/test/node_text_joins_one_hop_qualified_name_test.go +31 -0
  99. package/shim/ast/test/node_text_returns_empty_for_nil_test.go +23 -0
  100. package/shim/ast/test/node_text_returns_identifier_text_test.go +27 -0
  101. package/shim/ast/test/node_text_skips_empty_qualified_left_test.go +30 -0
  102. package/shim/checker/shim.go +35 -0
  103. package/shim/core/shim.go +17 -0
  104. package/shim/diagnosticwriter/shim.go +4 -0
  105. package/shim/lsp/shim.go +3 -3
  106. package/shim/printer/shim.go +20 -0
  107. package/src/TtscCompiler.ts +7 -0
  108. package/src/compiler/internal/buildNativeCompiler.ts +23 -3
  109. package/src/compiler/internal/compileProjectInMemory.ts +34 -25
  110. package/src/compiler/internal/paths.ts +68 -0
  111. package/src/compiler/internal/project/readProjectConfig.ts +86 -1
  112. package/src/compiler/internal/project/resolveProjectConfig.ts +24 -1
  113. package/src/compiler/internal/resolveBinary.ts +17 -1
  114. package/src/compiler/internal/resolveEmittedJavaScript.ts +43 -12
  115. package/src/compiler/internal/resolveTsgo.ts +29 -1
  116. package/src/compiler/internal/runBuild.ts +110 -55
  117. package/src/compiler/internal/runSingleFileEmit.ts +14 -1
  118. package/src/compiler/internal/sharedHostHelpers.ts +7 -7
  119. package/src/compiler/internal/spawnNative.ts +64 -0
  120. package/src/compiler/internal/transformProjectInMemory.ts +47 -67
  121. package/src/launcher/internal/getCompilerVersionText.ts +7 -0
  122. package/src/launcher/internal/prepareExecution.ts +32 -0
  123. package/src/launcher/internal/resolveCacheDir.ts +19 -0
  124. package/src/launcher/internal/resolveTtscserverBinary.ts +2 -0
  125. package/src/launcher/internal/runTtsc.ts +120 -20
  126. package/src/launcher/internal/runTtscserver.ts +9 -1
  127. package/src/launcher/internal/runTtsx.ts +33 -8
  128. package/src/plugin/internal/buildSourcePlugin.ts +40 -14
  129. package/src/plugin/internal/loadProjectPlugins.ts +42 -18
  130. package/src/structures/ITtscCompilerTransformation.ts +15 -2
  131. package/src/structures/ITtscPlugin.ts +0 -1
  132. package/src/structures/internal/TtscSingleFileEmitOptions.ts +0 -2
  133. package/tools/gen_shims/main.go +43 -8
  134. package/utility/host.go +294 -245
@@ -34,6 +34,9 @@ func main() {
34
34
  os.Exit(run(os.Args[1:]))
35
35
  }
36
36
 
37
+ // run dispatches CLI arguments for the platform helper binary. With no
38
+ // arguments it prints the help text. build/check print an explanatory error
39
+ // directing users to the JavaScript launcher instead of failing silently.
37
40
  func run(args []string) int {
38
41
  if len(args) == 0 {
39
42
  printHelp(stdout)
@@ -91,6 +94,9 @@ Usage:
91
94
  `))
92
95
  }
93
96
 
97
+ // runDemo implements the demo sub-command, printing a synthetic JavaScript
98
+ // arrow function for the requested atomic type. Smoke tests in CI invoke this
99
+ // to verify the binary executes correctly.
94
100
  func runDemo(args []string) int {
95
101
  fs := flag.NewFlagSet("demo", flag.ContinueOnError)
96
102
  fs.SetOutput(stderr)
@@ -110,6 +116,9 @@ func runDemo(args []string) int {
110
116
  return 0
111
117
  }
112
118
 
119
+ // demoArrow returns a JavaScript arrow-function expression for the named
120
+ // atomic TypeScript type. It is the platform-helper counterpart of the same
121
+ // function in cmd/ttsc, kept separate to avoid a shared-binary dependency.
113
122
  func demoArrow(name string) (string, error) {
114
123
  switch strings.ToLower(name) {
115
124
  case "any":
@@ -7,24 +7,24 @@
7
7
  package main
8
8
 
9
9
  import (
10
- "encoding/json"
11
- "flag"
12
- "fmt"
13
- "path/filepath"
14
- "strings"
10
+ "encoding/json"
11
+ "flag"
12
+ "fmt"
13
+ "path/filepath"
14
+ "strings"
15
15
 
16
- shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
16
+ shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
17
17
 
18
- "github.com/samchon/ttsc/packages/ttsc/driver"
19
- cwdutil "github.com/samchon/ttsc/packages/ttsc/internal/cwd"
18
+ "github.com/samchon/ttsc/packages/ttsc/driver"
19
+ cwdutil "github.com/samchon/ttsc/packages/ttsc/internal/cwd"
20
20
  )
21
21
 
22
22
  type apiCompileResult struct {
23
- // Diagnostics is omitted only when the compiler produced no diagnostics.
24
- // Output is still returned in diagnostic cases because TypeScript-Go may
25
- // produce partial emit text before a build-failing error is reported.
26
- Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
27
- Output map[string]string `json:"output"`
23
+ // Diagnostics is omitted only when the compiler produced no diagnostics.
24
+ // Output is still returned in diagnostic cases because TypeScript-Go may
25
+ // produce partial emit text before a build-failing error is reported.
26
+ Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
27
+ Output map[string]string `json:"output"`
28
28
  }
29
29
 
30
30
  // apiCompileDiagnostic mirrors the public TypeScript-side diagnostic DTO.
@@ -32,109 +32,117 @@ type apiCompileResult struct {
32
32
  // `character`) instead of Go naming so callers can pass the data through
33
33
  // without remapping.
34
34
  type apiCompileDiagnostic struct {
35
- File *string `json:"file"`
36
- Category string `json:"category"`
37
- Code int32 `json:"code"`
38
- Start *int `json:"start,omitempty"`
39
- Length *int `json:"length,omitempty"`
40
- Line int `json:"line,omitempty"`
41
- Character int `json:"character,omitempty"`
42
- MessageText string `json:"messageText"`
35
+ File *string `json:"file"`
36
+ Category string `json:"category"`
37
+ Code int32 `json:"code"`
38
+ Start *int `json:"start,omitempty"`
39
+ Length *int `json:"length,omitempty"`
40
+ Line int `json:"line,omitempty"`
41
+ Character int `json:"character,omitempty"`
42
+ MessageText string `json:"messageText"`
43
43
  }
44
44
 
45
45
  func runAPICompile(args []string) int {
46
- fs := flag.NewFlagSet("api-compile", flag.ContinueOnError)
47
- fs.SetOutput(stderr)
48
- tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
49
- cwdOverride := fs.String("cwd", "", "override the working directory")
50
- if err := fs.Parse(args); err != nil {
51
- return 2
52
- }
46
+ fs := flag.NewFlagSet("api-compile", flag.ContinueOnError)
47
+ fs.SetOutput(stderr)
48
+ tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
49
+ cwdOverride := fs.String("cwd", "", "override the working directory")
50
+ if err := fs.Parse(args); err != nil {
51
+ return 2
52
+ }
53
53
 
54
- cwd, err := cwdutil.Resolve(*cwdOverride, getwd)
55
- if err != nil {
56
- fmt.Fprintf(stderr, "ttsc: %v\n", err)
57
- return 2
58
- }
54
+ cwd, err := cwdutil.Resolve(*cwdOverride, getwd)
55
+ if err != nil {
56
+ fmt.Fprintf(stderr, "ttsc: %v\n", err)
57
+ return 2
58
+ }
59
59
 
60
- prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
61
- ForceEmit: true,
62
- })
63
- if err != nil {
64
- fmt.Fprintf(stderr, "ttsc api-compile: %v\n", err)
65
- return 2
66
- }
67
- if prog != nil {
68
- defer prog.Close()
69
- diags = append(diags, prog.Diagnostics()...)
70
- }
60
+ prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
61
+ ForceEmit: true,
62
+ })
63
+ if err != nil {
64
+ fmt.Fprintf(stderr, "ttsc api-compile: %v\n", err)
65
+ return 2
66
+ }
67
+ if prog != nil {
68
+ defer prog.Close()
69
+ diags = append(diags, prog.Diagnostics()...)
70
+ }
71
71
 
72
- output := map[string]string{}
73
- if prog != nil {
74
- rewrites := driver.NewRewriteSet()
75
- // Capture WriteFile output in a map keyed by project-relative paths. This
76
- // gives the JS API a deterministic object and avoids touching outDir.
77
- writeFile := shimcompiler.WriteFile(
78
- func(fileName, text string, _ *shimcompiler.WriteFileData) error {
79
- output[apiOutputKey(cwd, fileName)] = text
80
- return nil
81
- },
82
- )
83
- _, emitDiags, err := prog.EmitAll(rewrites, writeFile)
84
- if err != nil {
85
- fmt.Fprintf(stderr, "ttsc api-compile: emit failed: %v\n", err)
86
- return 3
87
- }
88
- diags = append(diags, emitDiags...)
89
- }
72
+ output := map[string]string{}
73
+ if prog != nil {
74
+ rewrites := driver.NewRewriteSet()
75
+ // Capture WriteFile output in a map keyed by project-relative paths. This
76
+ // gives the JS API a deterministic object and avoids touching outDir.
77
+ writeFile := shimcompiler.WriteFile(
78
+ func(fileName, text string, _ *shimcompiler.WriteFileData) error {
79
+ output[apiOutputKey(cwd, fileName)] = text
80
+ return nil
81
+ },
82
+ )
83
+ _, emitDiags, err := prog.EmitAll(rewrites, writeFile)
84
+ if err != nil {
85
+ fmt.Fprintf(stderr, "ttsc api-compile: emit failed: %v\n", err)
86
+ return 3
87
+ }
88
+ diags = append(diags, emitDiags...)
89
+ }
90
90
 
91
- result := apiCompileResult{
92
- Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
93
- Output: output,
94
- }
95
- for _, diag := range diags {
96
- result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
97
- }
91
+ result := apiCompileResult{
92
+ Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
93
+ Output: output,
94
+ }
95
+ for _, diag := range diags {
96
+ result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
97
+ }
98
98
 
99
- data, _ := json.Marshal(result)
100
- fmt.Fprintln(stdout, string(data))
101
- if driver.CountErrors(diags) > 0 {
102
- return 2
103
- }
104
- return 0
99
+ data, _ := json.Marshal(result)
100
+ fmt.Fprintln(stdout, string(data))
101
+ if driver.CountErrors(diags) > 0 {
102
+ return 2
103
+ }
104
+ return 0
105
105
  }
106
106
 
107
+ // toAPICompileDiagnostic converts an internal driver.Diagnostic into the
108
+ // JSON-serialisable form returned by the api-compile command. Category is
109
+ // lowercased to match the TypeScript Language Service convention.
107
110
  func toAPICompileDiagnostic(diag driver.Diagnostic) apiCompileDiagnostic {
108
- var file *string
109
- if diag.File != "" {
110
- value := diag.File
111
- file = &value
112
- }
113
- category := "error"
114
- if diag.Severity == driver.SeverityWarning {
115
- category = "warning"
116
- }
117
- return apiCompileDiagnostic{
118
- File: file,
119
- Category: category,
120
- Code: diag.Code,
121
- Start: diag.Start,
122
- Length: diag.Length,
123
- Line: diag.Line,
124
- Character: diag.Column,
125
- MessageText: diag.Message,
126
- }
111
+ var file *string
112
+ if diag.File != "" {
113
+ value := diag.File
114
+ file = &value
115
+ }
116
+ category := "error"
117
+ if diag.Severity == driver.SeverityWarning {
118
+ category = "warning"
119
+ }
120
+ return apiCompileDiagnostic{
121
+ File: file,
122
+ Category: category,
123
+ Code: diag.Code,
124
+ Start: diag.Start,
125
+ Length: diag.Length,
126
+ Line: diag.Line,
127
+ Character: diag.Column,
128
+ MessageText: diag.Message,
129
+ }
127
130
  }
128
131
 
132
+ // apiOutputKey returns the map key used in the api-compile result for a
133
+ // generated file. Files inside cwd use a slash-separated relative path (the
134
+ // API contract). Files outside cwd — rare, e.g. a monorepo output rooted
135
+ // above the project — are returned as an absolute slash path instead.
129
136
  func apiOutputKey(cwd, fileName string) string {
130
- // Relative keys are the API contract for files inside the project. Absolute
131
- // keys are preserved for uncommon compiler outputs outside cwd.
132
- if rel, err := filepath.Rel(cwd, fileName); err == nil && !isOutsideRelativePath(rel) {
133
- return filepath.ToSlash(rel)
134
- }
135
- return filepath.ToSlash(fileName)
137
+ if rel, err := filepath.Rel(cwd, fileName); err == nil && !isOutsideRelativePath(rel) {
138
+ return filepath.ToSlash(rel)
139
+ }
140
+ return filepath.ToSlash(fileName)
136
141
  }
137
142
 
143
+ // isOutsideRelativePath reports whether the result of filepath.Rel points
144
+ // above the base directory (starts with ".."), meaning the file lives outside
145
+ // the project root and cannot safely be expressed as a project-relative path.
138
146
  func isOutsideRelativePath(rel string) bool {
139
- return rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator))
147
+ return rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator))
140
148
  }
@@ -1,81 +1,79 @@
1
1
  package main
2
2
 
3
3
  import (
4
- "errors"
5
- "strings"
6
- "testing"
4
+ "errors"
5
+ "strings"
6
+ "testing"
7
7
 
8
- "github.com/samchon/ttsc/packages/ttsc/driver"
8
+ "github.com/samchon/ttsc/packages/ttsc/driver"
9
9
  )
10
10
 
11
11
  type apiCompileApplyErrorPlugin struct{}
12
12
 
13
13
  func (apiCompileApplyErrorPlugin) ApplyProgram(*driver.Program, driver.PluginContext) error {
14
- return errors.New("api compile apply boom")
14
+ return errors.New("api compile apply boom")
15
15
  }
16
16
 
17
- /**
18
- * Verifies api-compile handles parse, cwd, diagnostic, and emit failures.
19
- *
20
- * The JSON API path is used by the JS wrapper, so its command entrypoint must
21
- * return stable status codes for wrapper misuse, project diagnostics, and
22
- * linked transform failures.
23
- *
24
- * 1. Exercise bad flags and a failing cwd resolver.
25
- * 2. Compile missing and type-invalid projects.
26
- * 3. Assert linked ApplyProgram errors surface through the emit branch.
27
- */
17
+ // TestAPICompileBranches verifies api-compile handles parse, cwd, diagnostic, and emit failures.
18
+ //
19
+ // The JSON API path is used by the JS wrapper, so its command entrypoint must
20
+ // return stable status codes for wrapper misuse, project diagnostics, and
21
+ // linked transform failures.
22
+ //
23
+ // 1. Exercise bad flags and a failing cwd resolver.
24
+ // 2. Compile missing and type-invalid projects.
25
+ // 3. Assert linked ApplyProgram errors surface through the emit branch.
28
26
  func TestAPICompileBranches(t *testing.T) {
29
- code, _, _ := captureCommand(t, func() int {
30
- return runAPICompile([]string{"--cwd"})
31
- })
32
- if code != 2 {
33
- t.Fatalf("bad flag status mismatch: %d", code)
34
- }
27
+ code, _, _ := captureCommand(t, func() int {
28
+ return runAPICompile([]string{"--cwd"})
29
+ })
30
+ if code != 2 {
31
+ t.Fatalf("bad flag status mismatch: %d", code)
32
+ }
35
33
 
36
- code, _, errText := captureCommand(t, func() int {
37
- getwd = failGetwd
38
- return runAPICompile(nil)
39
- })
40
- if code != 2 || !strings.Contains(errText, "cwd boom") {
41
- t.Fatalf("cwd error mismatch: code=%d stderr=%q", code, errText)
42
- }
34
+ code, _, errText := captureCommand(t, func() int {
35
+ getwd = failGetwd
36
+ return runAPICompile(nil)
37
+ })
38
+ if code != 2 || !strings.Contains(errText, "cwd boom") {
39
+ t.Fatalf("cwd error mismatch: code=%d stderr=%q", code, errText)
40
+ }
43
41
 
44
- root := t.TempDir()
45
- code, _, errText = captureCommand(t, func() int {
46
- return runAPICompile([]string{"--cwd", root, "--tsconfig", "missing.json"})
47
- })
48
- if code != 2 || !strings.Contains(errText, "tsconfig not found") {
49
- t.Fatalf("missing config mismatch: code=%d stderr=%q", code, errText)
50
- }
42
+ root := t.TempDir()
43
+ code, _, errText = captureCommand(t, func() int {
44
+ return runAPICompile([]string{"--cwd", root, "--tsconfig", "missing.json"})
45
+ })
46
+ if code != 2 || !strings.Contains(errText, "tsconfig not found") {
47
+ t.Fatalf("missing config mismatch: code=%d stderr=%q", code, errText)
48
+ }
51
49
 
52
- writeCommandProjectFile(t, root, "tsconfig.json", `{
50
+ writeCommandProjectFile(t, root, "tsconfig.json", `{
53
51
  "compilerOptions": { "module": "commonjs", "target": "es2020", "strict": true },
54
52
  "files": ["index.ts"]
55
53
  }
56
54
  `)
57
- writeCommandProjectFile(t, root, "index.ts", `const value: number = "text";
55
+ writeCommandProjectFile(t, root, "index.ts", `const value: number = "text";
58
56
  export { value };
59
57
  `)
60
- code, out, _ := captureCommand(t, func() int {
61
- return runAPICompile([]string{"--cwd", root, "--tsconfig", "tsconfig.json"})
62
- })
63
- if code != 2 || !strings.Contains(out, `"diagnostics"`) {
64
- t.Fatalf("diagnostic compile mismatch: code=%d stdout=%q", code, out)
65
- }
66
- if got := toAPICompileDiagnostic(driver.Diagnostic{Severity: driver.SeverityWarning}).Category; got != "warning" {
67
- t.Fatalf("warning category mismatch: %q", got)
68
- }
58
+ code, out, _ := captureCommand(t, func() int {
59
+ return runAPICompile([]string{"--cwd", root, "--tsconfig", "tsconfig.json"})
60
+ })
61
+ if code != 2 || !strings.Contains(out, `"diagnostics"`) {
62
+ t.Fatalf("diagnostic compile mismatch: code=%d stdout=%q", code, out)
63
+ }
64
+ if got := toAPICompileDiagnostic(driver.Diagnostic{Severity: driver.SeverityWarning}).Category; got != "warning" {
65
+ t.Fatalf("warning category mismatch: %q", got)
66
+ }
69
67
 
70
- resetCommandLinkedPluginRegistry()
71
- driver.RegisterPlugin(apiCompileApplyErrorPlugin{})
72
- t.Setenv(driver.LinkedPluginsEnv, `[{"name":"error","stage":"transform","config":{}}]`)
73
- writeCommandProjectFile(t, root, "index.ts", `export const value = 1;
68
+ resetCommandLinkedPluginRegistry()
69
+ driver.RegisterPlugin(apiCompileApplyErrorPlugin{})
70
+ t.Setenv(driver.LinkedPluginsEnv, `[{"name":"error","stage":"transform","config":{}}]`)
71
+ writeCommandProjectFile(t, root, "index.ts", `export const value = 1;
74
72
  `)
75
- code, _, errText = captureCommand(t, func() int {
76
- return runAPICompile([]string{"--cwd", root, "--tsconfig", "tsconfig.json"})
77
- })
78
- if code != 3 || !strings.Contains(errText, "api compile apply boom") {
79
- t.Fatalf("emit error mismatch: code=%d stderr=%q", code, errText)
80
- }
73
+ code, _, errText = captureCommand(t, func() int {
74
+ return runAPICompile([]string{"--cwd", root, "--tsconfig", "tsconfig.json"})
75
+ })
76
+ if code != 3 || !strings.Contains(errText, "api compile apply boom") {
77
+ t.Fatalf("emit error mismatch: code=%d stderr=%q", code, errText)
78
+ }
81
79
  }
@@ -7,64 +7,69 @@
7
7
  package main
8
8
 
9
9
  import (
10
- "encoding/json"
11
- "flag"
12
- "fmt"
10
+ "encoding/json"
11
+ "flag"
12
+ "fmt"
13
13
 
14
- "github.com/samchon/ttsc/packages/ttsc/driver"
15
- cwdutil "github.com/samchon/ttsc/packages/ttsc/internal/cwd"
14
+ "github.com/samchon/ttsc/packages/ttsc/driver"
15
+ cwdutil "github.com/samchon/ttsc/packages/ttsc/internal/cwd"
16
16
  )
17
17
 
18
18
  type apiTransformResult struct {
19
- // TypeScript contains every non-library source file visible through the
20
- // Program facade, keyed the same way api-compile keys emitted files.
21
- Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
22
- TypeScript map[string]string `json:"typescript"`
19
+ // TypeScript contains every non-library source file visible through the
20
+ // Program facade, keyed the same way api-compile keys emitted files.
21
+ Diagnostics []apiCompileDiagnostic `json:"diagnostics,omitempty"`
22
+ TypeScript map[string]string `json:"typescript"`
23
23
  }
24
24
 
25
+ // runAPITransform implements the `api-transform` sub-command. It loads the
26
+ // TypeScript program in no-emit mode and returns the source text of every
27
+ // non-library file as a JSON object, keyed by the same relative-path
28
+ // convention as api-compile. Diagnostics are included; partial results are
29
+ // returned even when diagnostics are present.
25
30
  func runAPITransform(args []string) int {
26
- fs := flag.NewFlagSet("api-transform", flag.ContinueOnError)
27
- fs.SetOutput(stderr)
28
- tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
29
- cwdOverride := fs.String("cwd", "", "override the working directory")
30
- if err := fs.Parse(args); err != nil {
31
- return 2
32
- }
31
+ fs := flag.NewFlagSet("api-transform", flag.ContinueOnError)
32
+ fs.SetOutput(stderr)
33
+ tsconfigPath := fs.String("tsconfig", "tsconfig.json", "path to tsconfig.json")
34
+ cwdOverride := fs.String("cwd", "", "override the working directory")
35
+ if err := fs.Parse(args); err != nil {
36
+ return 2
37
+ }
33
38
 
34
- cwd, err := cwdutil.Resolve(*cwdOverride, getwd)
35
- if err != nil {
36
- fmt.Fprintf(stderr, "ttsc: %v\n", err)
37
- return 2
38
- }
39
+ cwd, err := cwdutil.Resolve(*cwdOverride, getwd)
40
+ if err != nil {
41
+ fmt.Fprintf(stderr, "ttsc: %v\n", err)
42
+ return 2
43
+ }
39
44
 
40
- prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
41
- ForceNoEmit: true,
42
- })
43
- if err != nil {
44
- fmt.Fprintf(stderr, "ttsc api-transform: %v\n", err)
45
- return 2
46
- }
47
- typescript := map[string]string{}
48
- if prog != nil {
49
- defer prog.Close()
50
- for _, file := range prog.SourceFiles() {
51
- typescript[apiOutputKey(cwd, file.FileName())] = file.Text()
52
- }
53
- diags = append(diags, prog.Diagnostics()...)
54
- }
45
+ prog, diags, err := driver.LoadProgram(cwd, *tsconfigPath, driver.LoadProgramOptions{
46
+ ForceNoEmit: true,
47
+ })
48
+ if err != nil {
49
+ fmt.Fprintf(stderr, "ttsc api-transform: %v\n", err)
50
+ return 2
51
+ }
52
+ typescript := map[string]string{}
53
+ if prog != nil {
54
+ defer prog.Close()
55
+ for _, file := range prog.SourceFiles() {
56
+ typescript[apiOutputKey(cwd, file.FileName())] = file.Text()
57
+ }
58
+ diags = append(diags, prog.Diagnostics()...)
59
+ }
55
60
 
56
- result := apiTransformResult{
57
- Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
58
- TypeScript: typescript,
59
- }
60
- for _, diag := range diags {
61
- result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
62
- }
61
+ result := apiTransformResult{
62
+ Diagnostics: make([]apiCompileDiagnostic, 0, len(diags)),
63
+ TypeScript: typescript,
64
+ }
65
+ for _, diag := range diags {
66
+ result.Diagnostics = append(result.Diagnostics, toAPICompileDiagnostic(diag))
67
+ }
63
68
 
64
- data, _ := json.Marshal(result)
65
- fmt.Fprintln(stdout, string(data))
66
- if driver.CountErrors(diags) > 0 {
67
- return 2
68
- }
69
- return 0
69
+ data, _ := json.Marshal(result)
70
+ fmt.Fprintln(stdout, string(data))
71
+ if driver.CountErrors(diags) > 0 {
72
+ return 2
73
+ }
74
+ return 0
70
75
  }
@@ -1,41 +1,39 @@
1
1
  package main
2
2
 
3
3
  import (
4
- "strings"
5
- "testing"
4
+ "strings"
5
+ "testing"
6
6
  )
7
7
 
8
- /**
9
- * Verifies api-transform rejects invalid command and project setup.
10
- *
11
- * Source-to-source API callers need the same stable wrapper diagnostics as the
12
- * compile API, but without touching emit. These branches are command-frontdoor
13
- * behavior rather than TypeScript-Go internals.
14
- *
15
- * 1. Pass an incomplete flag.
16
- * 2. Force cwd resolution to fail.
17
- * 3. Point the API at a missing tsconfig.
18
- */
8
+ // TestAPITransformBranches verifies api-transform rejects invalid command and project setup.
9
+ //
10
+ // Source-to-source API callers need the same stable wrapper diagnostics as the
11
+ // compile API, but without touching emit. These branches are command-frontdoor
12
+ // behavior rather than TypeScript-Go internals.
13
+ //
14
+ // 1. Pass an incomplete flag.
15
+ // 2. Force cwd resolution to fail.
16
+ // 3. Point the API at a missing tsconfig.
19
17
  func TestAPITransformBranches(t *testing.T) {
20
- code, _, _ := captureCommand(t, func() int {
21
- return runAPITransform([]string{"--cwd"})
22
- })
23
- if code != 2 {
24
- t.Fatalf("bad flag status mismatch: %d", code)
25
- }
18
+ code, _, _ := captureCommand(t, func() int {
19
+ return runAPITransform([]string{"--cwd"})
20
+ })
21
+ if code != 2 {
22
+ t.Fatalf("bad flag status mismatch: %d", code)
23
+ }
26
24
 
27
- code, _, errText := captureCommand(t, func() int {
28
- getwd = failGetwd
29
- return runAPITransform(nil)
30
- })
31
- if code != 2 || !strings.Contains(errText, "cwd boom") {
32
- t.Fatalf("cwd error mismatch: code=%d stderr=%q", code, errText)
33
- }
25
+ code, _, errText := captureCommand(t, func() int {
26
+ getwd = failGetwd
27
+ return runAPITransform(nil)
28
+ })
29
+ if code != 2 || !strings.Contains(errText, "cwd boom") {
30
+ t.Fatalf("cwd error mismatch: code=%d stderr=%q", code, errText)
31
+ }
34
32
 
35
- code, _, errText = captureCommand(t, func() int {
36
- return runAPITransform([]string{"--cwd", t.TempDir(), "--tsconfig", "missing.json"})
37
- })
38
- if code != 2 || !strings.Contains(errText, "tsconfig not found") {
39
- t.Fatalf("missing config mismatch: code=%d stderr=%q", code, errText)
40
- }
33
+ code, _, errText = captureCommand(t, func() int {
34
+ return runAPITransform([]string{"--cwd", t.TempDir(), "--tsconfig", "missing.json"})
35
+ })
36
+ if code != 2 || !strings.Contains(errText, "tsconfig not found") {
37
+ t.Fatalf("missing config mismatch: code=%d stderr=%q", code, errText)
38
+ }
41
39
  }