ttsc 0.3.0 → 0.4.0-dev.20260424

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 (112) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +216 -302
  3. package/cmd/ttsc/build.go +128 -0
  4. package/cmd/ttsc/main.go +222 -0
  5. package/cmd/ttsc/main_test.go +288 -0
  6. package/cmd/ttsc/transform.go +166 -0
  7. package/driver/host.go +31 -0
  8. package/driver/program.go +298 -0
  9. package/driver/rewrite.go +315 -0
  10. package/go.mod +48 -0
  11. package/go.sum +22 -0
  12. package/lib/api.d.ts +91 -0
  13. package/lib/api.js +325 -0
  14. package/lib/api.js.map +1 -0
  15. package/lib/cli.d.ts +1 -0
  16. package/lib/cli.js +481 -0
  17. package/lib/cli.js.map +1 -0
  18. package/lib/index.d.ts +17 -0
  19. package/lib/index.js +34 -0
  20. package/lib/index.js.map +1 -0
  21. package/lib/native.d.ts +15 -0
  22. package/lib/native.js +34 -0
  23. package/lib/native.js.map +1 -0
  24. package/lib/platform.d.ts +66 -0
  25. package/lib/platform.js +170 -0
  26. package/lib/platform.js.map +1 -0
  27. package/lib/plugin.d.ts +47 -0
  28. package/lib/plugin.js +150 -0
  29. package/lib/plugin.js.map +1 -0
  30. package/lib/project.d.ts +32 -0
  31. package/lib/project.js +303 -0
  32. package/lib/project.js.map +1 -0
  33. package/package.json +70 -63
  34. package/shim/ast/extra-shim.json +4 -0
  35. package/shim/ast/go.mod +5 -0
  36. package/shim/ast/shim.go +117 -0
  37. package/shim/bundled/extra-shim.json +1 -0
  38. package/shim/bundled/go.mod +5 -0
  39. package/shim/bundled/shim.go +19 -0
  40. package/shim/checker/extra-shim.json +31 -0
  41. package/shim/checker/go.mod +5 -0
  42. package/shim/checker/shim.go +146 -0
  43. package/shim/compiler/extra-shim.json +4 -0
  44. package/shim/compiler/go.mod +5 -0
  45. package/shim/compiler/shim.go +50 -0
  46. package/shim/core/extra-shim.json +4 -0
  47. package/shim/core/go.mod +5 -0
  48. package/shim/core/shim.go +11 -0
  49. package/shim/diagnosticwriter/go.mod +5 -0
  50. package/shim/diagnosticwriter/shim.go +29 -0
  51. package/shim/parser/extra-shim.json +4 -0
  52. package/shim/parser/go.mod +5 -0
  53. package/shim/parser/shim.go +55 -0
  54. package/shim/scanner/extra-shim.json +4 -0
  55. package/shim/scanner/go.mod +5 -0
  56. package/shim/scanner/shim.go +96 -0
  57. package/shim/tsoptions/extra-shim.json +4 -0
  58. package/shim/tsoptions/go.mod +5 -0
  59. package/shim/tsoptions/shim.go +123 -0
  60. package/shim/tspath/extra-shim.json +4 -0
  61. package/shim/tspath/go.mod +5 -0
  62. package/shim/tspath/shim.go +165 -0
  63. package/shim/vfs/cachedvfs/extra-shim.json +4 -0
  64. package/shim/vfs/cachedvfs/go.mod +5 -0
  65. package/shim/vfs/cachedvfs/shim.go +12 -0
  66. package/shim/vfs/extra-shim.json +4 -0
  67. package/shim/vfs/go.mod +5 -0
  68. package/shim/vfs/osvfs/extra-shim.json +4 -0
  69. package/shim/vfs/osvfs/go.mod +5 -0
  70. package/shim/vfs/osvfs/shim.go +13 -0
  71. package/shim/vfs/shim.go +19 -0
  72. package/src/api.ts +416 -0
  73. package/src/cli.ts +492 -0
  74. package/src/index.ts +18 -0
  75. package/src/launcher/ttsc-dev.js +42 -0
  76. package/src/launcher/ttsc.js +19 -0
  77. package/src/native.ts +60 -0
  78. package/src/platform.ts +163 -0
  79. package/src/plugin.ts +241 -0
  80. package/src/project.ts +330 -0
  81. package/test/native.test.ts +60 -0
  82. package/test/package.test.ts +123 -0
  83. package/test/platform.test.ts +58 -0
  84. package/test/project.test.ts +195 -0
  85. package/tools/gen_shims/go.mod +14 -0
  86. package/tools/gen_shims/go.sum +12 -0
  87. package/tools/gen_shims/main.go +446 -0
  88. package/CHANGELOG.md +0 -2
  89. package/bin/tsc +0 -2
  90. package/bin/tsserver +0 -2
  91. package/lib/PluginCreator.d.ts +0 -67
  92. package/lib/PluginCreator.js +0 -190
  93. package/lib/cancelationToken.d.ts +0 -0
  94. package/lib/cancelationToken.js +0 -2
  95. package/lib/loadTypescript.d.ts +0 -7
  96. package/lib/loadTypescript.js +0 -56
  97. package/lib/patchCreateProgram.d.ts +0 -21
  98. package/lib/patchCreateProgram.js +0 -184
  99. package/lib/tsc.d.ts +0 -1
  100. package/lib/tsc.js +0 -24
  101. package/lib/tsserver.d.ts +0 -0
  102. package/lib/tsserver.js +0 -2
  103. package/lib/tsserverlibrary.d.ts +0 -3
  104. package/lib/tsserverlibrary.js +0 -4
  105. package/lib/typescript.d.ts +0 -3
  106. package/lib/typescript.js +0 -4
  107. package/lib/typescriptServices.d.ts +0 -3
  108. package/lib/typescriptServices.js +0 -4
  109. package/lib/typingsInstaller.d.ts +0 -0
  110. package/lib/typingsInstaller.js +0 -2
  111. package/lib/watchGuard.d.ts +0 -0
  112. package/lib/watchGuard.js +0 -2
@@ -0,0 +1,195 @@
1
+ const assert = require("node:assert/strict");
2
+ const fs = require("node:fs");
3
+ const os = require("node:os");
4
+ const path = require("node:path");
5
+ const test = require("node:test");
6
+
7
+ const {
8
+ readProjectConfig,
9
+ resolveProjectConfig,
10
+ } = require("../src/project.ts");
11
+
12
+ test("resolveProjectConfig canonicalizes symlinked tsconfig paths", () => {
13
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-project-"));
14
+ const real = path.join(root, "real");
15
+ const link = path.join(root, "link");
16
+ fs.mkdirSync(real, { recursive: true });
17
+ fs.writeFileSync(path.join(real, "tsconfig.json"), "{}\n", "utf8");
18
+ fs.symlinkSync(real, link, "dir");
19
+
20
+ const resolved = resolveProjectConfig({
21
+ tsconfig: path.join(link, "tsconfig.json"),
22
+ });
23
+ assert.equal(resolved, fs.realpathSync(path.join(real, "tsconfig.json")));
24
+ });
25
+
26
+ test("readProjectConfig inherits plugins and outDir through tsconfig extends", () => {
27
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-project-"));
28
+ const shared = path.join(root, "config");
29
+ const project = path.join(root, "project");
30
+ fs.mkdirSync(shared, { recursive: true });
31
+ fs.mkdirSync(project, { recursive: true });
32
+ fs.writeFileSync(
33
+ path.join(shared, "tsconfig.json"),
34
+ JSON.stringify(
35
+ {
36
+ compilerOptions: {
37
+ outDir: "../dist/shared",
38
+ plugins: [{ transform: "./plugins/example.cjs" }],
39
+ },
40
+ },
41
+ null,
42
+ 2,
43
+ ),
44
+ "utf8",
45
+ );
46
+ fs.writeFileSync(
47
+ path.join(project, "tsconfig.json"),
48
+ JSON.stringify(
49
+ {
50
+ extends: "../config/tsconfig.json",
51
+ compilerOptions: {},
52
+ },
53
+ null,
54
+ 2,
55
+ ),
56
+ "utf8",
57
+ );
58
+
59
+ const parsed = readProjectConfig({
60
+ tsconfig: path.join(project, "tsconfig.json"),
61
+ });
62
+ assert.deepEqual(parsed.compilerOptions.plugins, [
63
+ { transform: "./plugins/example.cjs" },
64
+ ]);
65
+ assert.equal(parsed.compilerOptions.outDir, path.join(root, "dist/shared"));
66
+ });
67
+
68
+ test("readProjectConfig lets child tsconfig override inherited plugins", () => {
69
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-project-"));
70
+ const shared = path.join(root, "config");
71
+ const project = path.join(root, "project");
72
+ fs.mkdirSync(shared, { recursive: true });
73
+ fs.mkdirSync(project, { recursive: true });
74
+ fs.writeFileSync(
75
+ path.join(shared, "tsconfig.json"),
76
+ JSON.stringify(
77
+ {
78
+ compilerOptions: {
79
+ plugins: [{ transform: "./plugins/example.cjs" }],
80
+ },
81
+ },
82
+ null,
83
+ 2,
84
+ ),
85
+ "utf8",
86
+ );
87
+ fs.writeFileSync(
88
+ path.join(project, "tsconfig.json"),
89
+ JSON.stringify(
90
+ {
91
+ extends: "../config/tsconfig.json",
92
+ compilerOptions: {
93
+ plugins: [{ transform: "./local-plugin.cjs" }],
94
+ },
95
+ },
96
+ null,
97
+ 2,
98
+ ),
99
+ "utf8",
100
+ );
101
+
102
+ const parsed = readProjectConfig({
103
+ tsconfig: path.join(project, "tsconfig.json"),
104
+ });
105
+ assert.deepEqual(parsed.compilerOptions.plugins, [
106
+ { transform: "./local-plugin.cjs" },
107
+ ]);
108
+ });
109
+
110
+ test("readProjectConfig resolves package tsconfig extends", () => {
111
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-project-"));
112
+ const preset = path.join(root, "node_modules", "@scope", "tsconfig");
113
+ const project = path.join(root, "project");
114
+ fs.mkdirSync(preset, { recursive: true });
115
+ fs.mkdirSync(project, { recursive: true });
116
+ fs.writeFileSync(
117
+ path.join(preset, "base.json"),
118
+ JSON.stringify(
119
+ {
120
+ compilerOptions: {
121
+ outDir: "../../dist/preset",
122
+ plugins: [{ transform: "./plugins/from-preset.cjs" }],
123
+ },
124
+ },
125
+ null,
126
+ 2,
127
+ ),
128
+ "utf8",
129
+ );
130
+ fs.writeFileSync(
131
+ path.join(project, "tsconfig.json"),
132
+ JSON.stringify(
133
+ {
134
+ extends: "@scope/tsconfig/base.json",
135
+ compilerOptions: {},
136
+ },
137
+ null,
138
+ 2,
139
+ ),
140
+ "utf8",
141
+ );
142
+
143
+ const parsed = readProjectConfig({
144
+ tsconfig: path.join(project, "tsconfig.json"),
145
+ });
146
+ assert.deepEqual(parsed.compilerOptions.plugins, [
147
+ { transform: "./plugins/from-preset.cjs" },
148
+ ]);
149
+ assert.equal(
150
+ parsed.compilerOptions.outDir,
151
+ path.join(root, "node_modules", "dist", "preset"),
152
+ );
153
+ });
154
+
155
+ test("readProjectConfig accepts JSONC comments and trailing commas", () => {
156
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-project-"));
157
+ fs.writeFileSync(
158
+ path.join(root, "tsconfig.json"),
159
+ `{
160
+ // plugin host configuration may live in JSONC tsconfig files
161
+ "compilerOptions": {
162
+ "plugins": [
163
+ { "transform": "./plugins/jsonc.cjs" },
164
+ ],
165
+ },
166
+ }\n`,
167
+ "utf8",
168
+ );
169
+
170
+ const parsed = readProjectConfig({
171
+ tsconfig: path.join(root, "tsconfig.json"),
172
+ });
173
+ assert.deepEqual(parsed.compilerOptions.plugins, [
174
+ { transform: "./plugins/jsonc.cjs" },
175
+ ]);
176
+ });
177
+
178
+ test("readProjectConfig rejects circular tsconfig extends", () => {
179
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-project-"));
180
+ fs.writeFileSync(
181
+ path.join(root, "a.json"),
182
+ JSON.stringify({ extends: "./b.json" }),
183
+ "utf8",
184
+ );
185
+ fs.writeFileSync(
186
+ path.join(root, "b.json"),
187
+ JSON.stringify({ extends: "./a.json" }),
188
+ "utf8",
189
+ );
190
+
191
+ assert.throws(
192
+ () => readProjectConfig({ tsconfig: path.join(root, "a.json") }),
193
+ /circular tsconfig extends detected/,
194
+ );
195
+ });
@@ -0,0 +1,14 @@
1
+ module github.com/samchon/ttsc/packages/ttsc/tools/gen_shims
2
+
3
+ go 1.26
4
+
5
+ require (
6
+ github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433
7
+ golang.org/x/text v0.35.0
8
+ golang.org/x/tools v0.43.0
9
+ )
10
+
11
+ require (
12
+ golang.org/x/mod v0.34.0 // indirect
13
+ golang.org/x/sync v0.20.0 // indirect
14
+ )
@@ -0,0 +1,12 @@
1
+ github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 h1:vymEbVwYFP/L05h5TKQxvkXoKxNvTpjxYKdF1Nlwuao=
2
+ github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg=
3
+ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
4
+ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
5
+ golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
6
+ golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
7
+ golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
8
+ golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
9
+ golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
10
+ golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
11
+ golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
12
+ golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
@@ -0,0 +1,446 @@
1
+ // Package main generates go:linkname-based shim.go files for every
2
+ // typescript-go internal package listed below.
3
+ //
4
+ // Adapted from tsgolint's tools/gen_shims/main.go
5
+ // (https://github.com/oxc-project/tsgolint, MIT License).
6
+ // Copyright (c) 2025 VoidZero Inc. & Contributors.
7
+ // Copyright (c) 2025 typescript-eslint and other contributors.
8
+ // Copyright (c) 2026 Jeongho Nam (ttsc adaptation — host-specific packages
9
+ // list and extra_shim lookup path; generator algorithm unchanged).
10
+ //
11
+ // Usage:
12
+ //
13
+ // cd packages/ttsc
14
+ // go run ./tools/gen_shims
15
+ //
16
+ // Each shim directory (`packages/ttsc/shim/<name>`) must contain an
17
+ // `extra-shim.json` file; the generator writes its output to
18
+ // `packages/ttsc/shim/<name>/shim.go`.
19
+ package main
20
+
21
+ import (
22
+ "bytes"
23
+ "fmt"
24
+ "go/types"
25
+ "log"
26
+ "maps"
27
+ "os"
28
+ "path"
29
+ "slices"
30
+ "strings"
31
+
32
+ "github.com/go-json-experiment/json"
33
+
34
+ "golang.org/x/text/cases"
35
+ "golang.org/x/text/language"
36
+ "golang.org/x/tools/go/packages"
37
+ )
38
+
39
+ const tsgoInternalPrefix = "github.com/microsoft/typescript-go/internal/"
40
+
41
+ // Packages for which we generate a shim. Mirrors tsgolint's list with
42
+ // project/lsp/lsproto removed for the current host boundary and the rest kept
43
+ // verbatim so gen_shims output stays comparable across projects.
44
+ var packagesToShim = []string{
45
+ "ast",
46
+ "bundled",
47
+ "checker",
48
+ "compiler",
49
+ "core",
50
+ "parser",
51
+ "scanner",
52
+ "tsoptions",
53
+ "tspath",
54
+ "vfs",
55
+ "vfs/cachedvfs",
56
+ "vfs/osvfs",
57
+ }
58
+
59
+ type ExtraShim struct {
60
+ ExtraFunctions []string
61
+ ExtraMethods map[string][]string
62
+ ExtraFields map[string][]string
63
+ IgnoreFunctions []string
64
+ }
65
+
66
+ func signatureHasUnexportedType(t types.Signature) bool {
67
+ if params := t.Params(); params != nil {
68
+ for v := range params.Variables() {
69
+ ty := v.Type()
70
+ if ptrType, ok := ty.(*types.Pointer); ok {
71
+ ty = ptrType.Elem()
72
+ }
73
+ if named, ok := ty.(*types.Named); ok {
74
+ if !named.Obj().Exported() {
75
+ return true
76
+ }
77
+ }
78
+ }
79
+ }
80
+ return false
81
+ }
82
+
83
+ func main() {
84
+ fullNames := make([]string, len(packagesToShim))
85
+ for i, pkg := range packagesToShim {
86
+ fullNames[i] = tsgoInternalPrefix + pkg
87
+ }
88
+
89
+ loaded, err := packages.Load(&packages.Config{
90
+ Dir: "./shim/ast", // any shim module works as anchor; they all require typescript-go
91
+ Mode: packages.LoadSyntax,
92
+ }, fullNames...)
93
+ if err != nil {
94
+ log.Fatalf("gen_shims: packages.Load: %v", err)
95
+ }
96
+
97
+ var shimHeaderBuilder strings.Builder
98
+ var shimBuilder strings.Builder
99
+ var tempBuffer bytes.Buffer
100
+
101
+ for _, pkg := range loaded {
102
+ if len(pkg.Errors) != 0 {
103
+ for _, e := range pkg.Errors {
104
+ fmt.Fprintln(os.Stderr, "gen_shims:", e)
105
+ }
106
+ log.Fatalf("gen_shims: package %s failed to load (see errors above)", pkg.PkgPath)
107
+ }
108
+ shimDirPath := path.Join("./shim/", strings.TrimPrefix(pkg.PkgPath, tsgoInternalPrefix))
109
+
110
+ var extraShim ExtraShim
111
+ extraShimFilePath := path.Join(shimDirPath, "extra-shim.json")
112
+ if data, err := os.ReadFile(extraShimFilePath); err == nil {
113
+ if err := json.Unmarshal(data, &extraShim); err != nil {
114
+ fmt.Fprintf(os.Stderr, "gen_shims: error parsing %v: %v\n", extraShimFilePath, err)
115
+ os.Exit(1)
116
+ }
117
+ }
118
+ if extraShim.ExtraMethods == nil {
119
+ extraShim.ExtraMethods = map[string][]string{}
120
+ }
121
+ if extraShim.ExtraFunctions == nil {
122
+ extraShim.ExtraFunctions = []string{}
123
+ }
124
+ if extraShim.ExtraFields == nil {
125
+ extraShim.ExtraFields = map[string][]string{}
126
+ }
127
+ if extraShim.IgnoreFunctions == nil {
128
+ extraShim.IgnoreFunctions = []string{}
129
+ }
130
+
131
+ importedPackages := map[string]bool{}
132
+ importPackage := func(path string, directly bool) {
133
+ if directly {
134
+ importedPackages[path] = true
135
+ } else if _, ok := importedPackages[path]; !ok {
136
+ importedPackages[path] = false
137
+ }
138
+ }
139
+
140
+ var qualifierOnlyPackageName types.Qualifier = func(p *types.Package) string {
141
+ importPackage(p.Path(), true)
142
+ return p.Name()
143
+ }
144
+ var qualifierEmptyPackageName types.Qualifier = func(p *types.Package) string { return "" }
145
+
146
+ emitGoLinknameDirective := func(localName string, fn *types.Func) {
147
+ importPackage("unsafe", false)
148
+ importPackage(pkg.Types.Path(), false)
149
+ shimBuilder.WriteString("//go:linkname ")
150
+ shimBuilder.WriteString(localName)
151
+ shimBuilder.WriteByte(' ')
152
+ shimBuilder.WriteString(fn.Pkg().Path())
153
+ shimBuilder.WriteByte('.')
154
+ if recv := fn.Signature().Recv(); recv != nil {
155
+ shimBuilder.WriteByte('(')
156
+ shimBuilder.WriteString(types.TypeString(recv.Type(), qualifierEmptyPackageName))
157
+ shimBuilder.WriteByte(')')
158
+ shimBuilder.WriteByte('.')
159
+ }
160
+ shimBuilder.WriteString(fn.Name())
161
+ shimBuilder.WriteByte('\n')
162
+ }
163
+
164
+ emitLinkedFunction := func(fn *types.Func) bool {
165
+ if fn.Signature().TypeParams() != nil {
166
+ return false
167
+ }
168
+ if signatureHasUnexportedType(*fn.Signature()) {
169
+ fmt.Fprintf(os.Stderr, "gen_shims: skipping %s.%s (unexported types)\n", fn.Pkg().Name(), fn.Name())
170
+ return false
171
+ }
172
+ name := cases.Title(language.English, cases.NoLower).String(fn.Name())
173
+ emitGoLinknameDirective(name, fn)
174
+ shimBuilder.WriteString("func ")
175
+ shimBuilder.WriteString(name)
176
+ types.WriteSignature(&tempBuffer, fn.Signature(), qualifierOnlyPackageName)
177
+ shimBuilder.Write(tempBuffer.Bytes())
178
+ tempBuffer.Reset()
179
+ shimBuilder.WriteString("\n")
180
+ return true
181
+ }
182
+
183
+ matchedExtraFunctions := make(map[string]bool, len(extraShim.ExtraFunctions))
184
+ for _, name := range extraShim.ExtraFunctions {
185
+ matchedExtraFunctions[name] = false
186
+ }
187
+ matchedExtraMethods := make(map[string]map[string]bool, len(extraShim.ExtraMethods))
188
+ for name, methods := range extraShim.ExtraMethods {
189
+ matchedExtraMethods[name] = make(map[string]bool, len(methods))
190
+ for _, method := range methods {
191
+ matchedExtraMethods[name][method] = false
192
+ }
193
+ }
194
+ matchedExtraFields := make(map[string]bool, len(extraShim.ExtraFields))
195
+ for name := range extraShim.ExtraFields {
196
+ matchedExtraFields[name] = false
197
+ }
198
+
199
+ scope := pkg.Types.Scope()
200
+ for _, name := range scope.Names() {
201
+ object := scope.Lookup(name)
202
+ if !object.Exported() {
203
+ fn, isFunc := object.(*types.Func)
204
+ if _, exists := matchedExtraFunctions[name]; isFunc && exists {
205
+ if emitLinkedFunction(fn) {
206
+ matchedExtraFunctions[name] = true
207
+ }
208
+ }
209
+ continue
210
+ }
211
+
212
+ printReexport := func(kind string) {
213
+ importPackage(pkg.Types.Path(), true)
214
+ shimBuilder.WriteString(kind)
215
+ shimBuilder.WriteString(" ")
216
+ shimBuilder.WriteString(name)
217
+ shimBuilder.WriteString(" = ")
218
+ shimBuilder.WriteString(pkg.Name)
219
+ shimBuilder.WriteString(".")
220
+ shimBuilder.WriteString(name)
221
+ shimBuilder.WriteString("\n")
222
+ }
223
+
224
+ switch object.(type) {
225
+ case *types.TypeName:
226
+ typeName := object.(*types.TypeName)
227
+ t := typeName.Type()
228
+ named, isNamed := t.(*types.Named)
229
+ if isNamed {
230
+ _, nameWithTypeParams, _ := strings.Cut(types.TypeString(named, qualifierOnlyPackageName), ".")
231
+ importPackage(pkg.Types.Path(), true)
232
+ shimBuilder.WriteString("type ")
233
+ shimBuilder.WriteString(nameWithTypeParams)
234
+ shimBuilder.WriteString(" = ")
235
+ shimBuilder.WriteString(pkg.Name)
236
+ shimBuilder.WriteString(".")
237
+ shimBuilder.WriteString(name)
238
+
239
+ typeParams := slices.Collect(named.TypeParams().TypeParams())
240
+ if len(typeParams) > 0 {
241
+ shimBuilder.WriteByte('[')
242
+ for i, ty := range typeParams {
243
+ if i > 0 {
244
+ shimBuilder.WriteByte(',')
245
+ }
246
+ shimBuilder.WriteString(ty.String())
247
+ }
248
+ shimBuilder.WriteByte(']')
249
+ }
250
+ shimBuilder.WriteString("\n")
251
+ } else {
252
+ printReexport("type")
253
+ }
254
+
255
+ if extraMethods, ok := matchedExtraMethods[name]; isNamed && ok {
256
+ for method := range named.Methods() {
257
+ methodName := method.Name()
258
+ if _, exists := extraMethods[methodName]; !exists {
259
+ continue
260
+ }
261
+ extraMethods[methodName] = true
262
+ prefix := name + "_"
263
+ emitGoLinknameDirective(prefix+methodName, method)
264
+ funcDeclStr := types.ObjectString(method, qualifierOnlyPackageName)
265
+ recvStart := 0
266
+ recvEnd := 0
267
+ paramsStart := 0
268
+ for i, s := range funcDeclStr {
269
+ if s == '(' {
270
+ if recvStart == 0 {
271
+ recvStart = i + 1
272
+ }
273
+ if recvEnd != 0 {
274
+ paramsStart = i + 1
275
+ break
276
+ }
277
+ }
278
+ if s == ')' && recvEnd == 0 {
279
+ recvEnd = i
280
+ }
281
+ }
282
+ shimBuilder.WriteString("func ")
283
+ shimBuilder.WriteString(prefix)
284
+ shimBuilder.WriteString(funcDeclStr[recvEnd+2 : paramsStart])
285
+ shimBuilder.WriteString("recv ")
286
+ shimBuilder.WriteString(funcDeclStr[recvStart:recvEnd])
287
+ if method.Signature().Params() != nil {
288
+ shimBuilder.WriteString(", ")
289
+ }
290
+ shimBuilder.WriteString(funcDeclStr[paramsStart:])
291
+ shimBuilder.WriteString("\n")
292
+ }
293
+ }
294
+
295
+ if _, ok := matchedExtraFields[name]; isNamed && ok {
296
+ importPackage("unsafe", true)
297
+ matchedExtraFields[name] = true
298
+ mirrorStructName := "extra_" + name
299
+
300
+ var emitExtraStruct func(name string, s *types.Struct)
301
+ emitExtraStruct = func(name string, s *types.Struct) {
302
+ shimBuilder.WriteString("type extra_")
303
+ shimBuilder.WriteString(name)
304
+ shimBuilder.WriteString(" struct {")
305
+
306
+ dependencies := []struct {
307
+ string
308
+ *types.Struct
309
+ }{}
310
+ for field := range s.Fields() {
311
+ shimBuilder.WriteString("\n ")
312
+ if !field.Embedded() {
313
+ shimBuilder.WriteString(field.Name())
314
+ shimBuilder.WriteByte(' ')
315
+ }
316
+
317
+ ptrType, ok := field.Type().(*types.Pointer)
318
+ if ok {
319
+ named, ok := ptrType.Elem().(*types.Named)
320
+ if ok && !named.Obj().Exported() {
321
+ strct, ok := named.Underlying().(*types.Struct)
322
+ if ok {
323
+ n := named.Obj().Name()
324
+ dependencies = append(dependencies, struct {
325
+ string
326
+ *types.Struct
327
+ }{n, strct})
328
+ shimBuilder.WriteString("extra_")
329
+ shimBuilder.WriteString(n)
330
+ continue
331
+ }
332
+ }
333
+ }
334
+
335
+ shimBuilder.WriteString(
336
+ strings.ReplaceAll(types.TypeString(field.Type(), qualifierOnlyPackageName), "checker.thisAssignmentDeclarationKind", "int32"),
337
+ )
338
+ }
339
+ shimBuilder.WriteString("\n}\n")
340
+ for _, dep := range dependencies {
341
+ emitExtraStruct(dep.string, dep.Struct)
342
+ }
343
+ }
344
+
345
+ strct, ok := named.Underlying().(*types.Struct)
346
+ if !ok {
347
+ log.Fatalf("gen_shims: expected %v to be struct", name)
348
+ }
349
+ emitExtraStruct(name, strct)
350
+
351
+ mappedFieldTypes := make(map[string]*types.Var, strct.NumFields())
352
+ for field := range strct.Fields() {
353
+ mappedFieldTypes[field.Name()] = field
354
+ }
355
+
356
+ for _, field := range extraShim.ExtraFields[name] {
357
+ shimBuilder.WriteString("func ")
358
+ shimBuilder.WriteString(name)
359
+ shimBuilder.WriteByte('_')
360
+ shimBuilder.WriteString(field)
361
+ shimBuilder.WriteString("(v *")
362
+ shimBuilder.WriteString(pkg.Name)
363
+ shimBuilder.WriteByte('.')
364
+ shimBuilder.WriteString(name)
365
+ shimBuilder.WriteString(") ")
366
+
367
+ fieldVar, ok := mappedFieldTypes[field]
368
+ if !ok {
369
+ log.Fatalf("gen_shims: expected struct %q to contain field %q", name, field)
370
+ }
371
+ shimBuilder.WriteString(types.TypeString(fieldVar.Type(), qualifierOnlyPackageName))
372
+ shimBuilder.WriteString(" {\n")
373
+ shimBuilder.WriteString(" return ((*")
374
+ shimBuilder.WriteString(mirrorStructName)
375
+ shimBuilder.WriteString(")(unsafe.Pointer(v))).")
376
+ shimBuilder.WriteString(field)
377
+ shimBuilder.WriteString("\n")
378
+ shimBuilder.WriteString("}\n")
379
+ }
380
+ }
381
+ case *types.Const:
382
+ printReexport("const")
383
+ case *types.Var:
384
+ printReexport("var")
385
+ case *types.Func:
386
+ if !slices.Contains(extraShim.IgnoreFunctions, name) {
387
+ funcType := object.(*types.Func)
388
+ emitLinkedFunction(funcType)
389
+ }
390
+ }
391
+ }
392
+
393
+ exit := false
394
+ for fnName, found := range matchedExtraFunctions {
395
+ if found {
396
+ continue
397
+ }
398
+ fmt.Fprintf(os.Stderr, "gen_shims: ERROR couldn't find %v function\n", fnName)
399
+ exit = true
400
+ }
401
+ for name, methods := range matchedExtraMethods {
402
+ for methodName, found := range methods {
403
+ if found {
404
+ continue
405
+ }
406
+ fmt.Fprintf(os.Stderr, "gen_shims: ERROR couldn't find %v.%v method\n", name, methodName)
407
+ exit = true
408
+ }
409
+ }
410
+ if exit {
411
+ os.Exit(1)
412
+ }
413
+
414
+ shimHeaderBuilder.WriteString("\n// Code generated by packages/ttsc/tools/gen_shims. DO NOT EDIT.\n\n")
415
+ shimHeaderBuilder.WriteString("package ")
416
+ shimHeaderBuilder.WriteString(pkg.Name)
417
+ shimHeaderBuilder.WriteString("\n\n")
418
+ importsList := slices.Collect(maps.Keys(importedPackages))
419
+ slices.Sort(importsList)
420
+ for _, imported := range importsList {
421
+ shimHeaderBuilder.WriteString("import ")
422
+ if !importedPackages[imported] {
423
+ shimHeaderBuilder.WriteString("_ ")
424
+ }
425
+ shimHeaderBuilder.WriteString("\"")
426
+ shimHeaderBuilder.WriteString(imported)
427
+ shimHeaderBuilder.WriteString("\"\n")
428
+ }
429
+ shimHeaderBuilder.WriteString("\n")
430
+
431
+ shimGoPath := path.Join(shimDirPath, "shim.go")
432
+ file, err := os.Create(shimGoPath)
433
+ if err != nil {
434
+ log.Fatalf("gen_shims: opening %v for write: %v", shimGoPath, err)
435
+ }
436
+ file.WriteString(shimHeaderBuilder.String())
437
+ file.WriteString(shimBuilder.String())
438
+ if err := file.Close(); err != nil {
439
+ log.Fatalf("gen_shims: closing %v: %v", shimGoPath, err)
440
+ }
441
+ fmt.Fprintf(os.Stdout, "gen_shims: wrote %s (%d bytes)\n", shimGoPath, len(shimBuilder.String()))
442
+
443
+ shimHeaderBuilder.Reset()
444
+ shimBuilder.Reset()
445
+ }
446
+ }
package/CHANGELOG.md DELETED
@@ -1,2 +0,0 @@
1
- # Change Log
2
-
package/bin/tsc DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- require('../lib/tsc.js')
package/bin/tsserver DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- require('../lib/tsserver.js')