goscript 0.0.83 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/cmd/goscript/cmd_compile.go +70 -69
- package/cmd/goscript/cmd_compile_test.go +79 -0
- package/cmd/goscript/main.go +10 -5
- package/compiler/compile-request.go +218 -0
- package/compiler/compiler.go +16 -1336
- package/compiler/compliance_test.go +196 -0
- package/compiler/config.go +6 -13
- package/compiler/diagnostic.go +70 -0
- package/compiler/index.test.ts +28 -28
- package/compiler/index.ts +40 -72
- package/compiler/lowered-program.go +132 -0
- package/compiler/lowering.go +3576 -0
- package/compiler/override-registry.go +422 -0
- package/compiler/override-registry_test.go +207 -0
- package/compiler/package-graph.go +231 -0
- package/compiler/package-graph_test.go +281 -0
- package/compiler/result.go +13 -0
- package/compiler/runtime-contract.go +279 -0
- package/compiler/runtime-contract_test.go +90 -0
- package/compiler/semantic-model-types.go +110 -0
- package/compiler/semantic-model.go +922 -0
- package/compiler/semantic-model_test.go +416 -0
- package/compiler/service.go +133 -0
- package/compiler/skeleton_test.go +1145 -0
- package/compiler/typescript-emitter.go +663 -0
- package/compiler/wasm/compile.go +2 -3
- package/compiler/wasm/compile_test.go +29 -0
- package/compiler/wasm_api.go +10 -159
- package/dist/compiler/index.d.ts +1 -3
- package/dist/compiler/index.js +31 -55
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/builtin/builtin.d.ts +13 -0
- package/dist/gs/builtin/builtin.js +27 -7
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +3 -3
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +86 -0
- package/dist/gs/builtin/hostio.js +266 -0
- package/dist/gs/builtin/hostio.js.map +1 -0
- package/dist/gs/builtin/index.d.ts +1 -0
- package/dist/gs/builtin/index.js +1 -0
- package/dist/gs/builtin/index.js.map +1 -1
- package/dist/gs/builtin/print.d.ts +8 -0
- package/dist/gs/builtin/print.js +111 -0
- package/dist/gs/builtin/print.js.map +1 -0
- package/dist/gs/builtin/slice.d.ts +1 -1
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +11 -0
- package/dist/gs/builtin/type.js +55 -1
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/crypto/rand/index.d.ts +5 -0
- package/dist/gs/crypto/rand/index.js +77 -0
- package/dist/gs/crypto/rand/index.js.map +1 -0
- package/dist/gs/encoding/json/index.d.ts +3 -0
- package/dist/gs/encoding/json/index.js +160 -0
- package/dist/gs/encoding/json/index.js.map +1 -0
- package/dist/gs/fmt/fmt.js +2 -22
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
- package/dist/gs/go/scanner/index.d.ts +29 -0
- package/dist/gs/go/scanner/index.js +120 -0
- package/dist/gs/go/scanner/index.js.map +1 -0
- package/dist/gs/go/token/index.d.ts +31 -0
- package/dist/gs/go/token/index.js +82 -0
- package/dist/gs/go/token/index.js.map +1 -0
- package/dist/gs/internal/abi/index.js.map +1 -1
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/readfile.js.map +1 -1
- package/dist/gs/io/fs/stat.js.map +1 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/error.gs.js +2 -4
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/rawconn_js.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/tempfile.gs.js +66 -9
- package/dist/gs/os/tempfile.gs.js.map +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +2 -51
- package/dist/gs/os/types_js.gs.js +67 -105
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/match.js.map +1 -1
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +2 -2
- package/dist/gs/reflect/index.js +1 -1
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +2 -1
- package/dist/gs/reflect/type.js +85 -14
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/sort/sort.gs.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/quote.gs.js.map +1 -1
- package/dist/gs/strings/builder.js.map +1 -1
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +1 -0
- package/dist/gs/sync/sync.js +12 -0
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/go.mod +2 -2
- package/gs/builtin/builtin.ts +31 -6
- package/gs/builtin/hostio.test.ts +246 -0
- package/gs/builtin/hostio.ts +413 -0
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/print.test.ts +48 -0
- package/gs/builtin/print.ts +154 -0
- package/gs/builtin/runtime-contract.test.ts +230 -0
- package/gs/builtin/type.ts +84 -1
- package/gs/crypto/rand/index.test.ts +32 -0
- package/gs/crypto/rand/index.ts +90 -0
- package/gs/crypto/rand/meta.json +5 -0
- package/gs/encoding/json/index.test.ts +65 -0
- package/gs/encoding/json/index.ts +186 -0
- package/gs/fmt/fmt.test.ts +41 -30
- package/gs/fmt/fmt.ts +2 -22
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +23 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +3 -1
- package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/meta.json +3 -1
- package/gs/go/scanner/index.test.ts +50 -0
- package/gs/go/scanner/index.ts +157 -0
- package/gs/go/token/index.test.ts +21 -0
- package/gs/go/token/index.ts +120 -0
- package/gs/os/file_unix_js.test.ts +103 -0
- package/gs/os/meta.json +1 -2
- package/gs/os/tempfile.gs.test.ts +85 -0
- package/gs/os/tempfile.gs.ts +71 -11
- package/gs/os/types_js.gs.ts +74 -153
- package/gs/reflect/index.ts +1 -1
- package/gs/reflect/type.ts +106 -17
- package/gs/reflect/typefor.test.ts +75 -0
- package/gs/sync/sync.test.ts +24 -0
- package/gs/sync/sync.ts +12 -0
- package/package.json +13 -13
- package/compiler/analysis.go +0 -3475
- package/compiler/analysis_test.go +0 -338
- package/compiler/assignment.go +0 -580
- package/compiler/builtin_test.go +0 -92
- package/compiler/code-writer.go +0 -115
- package/compiler/compiler_test.go +0 -149
- package/compiler/composite-lit.go +0 -779
- package/compiler/config_test.go +0 -62
- package/compiler/constraint.go +0 -86
- package/compiler/decl.go +0 -801
- package/compiler/expr-call-async.go +0 -188
- package/compiler/expr-call-builtins.go +0 -208
- package/compiler/expr-call-helpers.go +0 -382
- package/compiler/expr-call-make.go +0 -318
- package/compiler/expr-call-type-conversion.go +0 -520
- package/compiler/expr-call.go +0 -413
- package/compiler/expr-selector.go +0 -343
- package/compiler/expr-star.go +0 -82
- package/compiler/expr-type.go +0 -442
- package/compiler/expr-value.go +0 -89
- package/compiler/expr.go +0 -773
- package/compiler/field.go +0 -183
- package/compiler/gs_dependencies_test.go +0 -298
- package/compiler/lit.go +0 -322
- package/compiler/output.go +0 -72
- package/compiler/primitive.go +0 -149
- package/compiler/protobuf.go +0 -697
- package/compiler/sanitize.go +0 -100
- package/compiler/spec-struct.go +0 -995
- package/compiler/spec-value.go +0 -540
- package/compiler/spec.go +0 -725
- package/compiler/stmt-assign.go +0 -664
- package/compiler/stmt-for.go +0 -266
- package/compiler/stmt-range.go +0 -475
- package/compiler/stmt-select.go +0 -262
- package/compiler/stmt-type-switch.go +0 -147
- package/compiler/stmt.go +0 -1308
- package/compiler/type-assert.go +0 -386
- package/compiler/type-info.go +0 -156
- package/compiler/type-utils.go +0 -207
- package/compiler/type.go +0 -892
package/compiler/protobuf.go
DELETED
|
@@ -1,697 +0,0 @@
|
|
|
1
|
-
package compiler
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
"go/ast"
|
|
6
|
-
"go/token"
|
|
7
|
-
"go/types"
|
|
8
|
-
"os"
|
|
9
|
-
"path/filepath"
|
|
10
|
-
"strings"
|
|
11
|
-
|
|
12
|
-
"golang.org/x/tools/go/packages"
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
// getProtobufMessageInterface attempts to find the protobuf-go-lite Message interface
|
|
16
|
-
// from the loaded packages in analysis. Returns nil if not found.
|
|
17
|
-
func (c *GoToTSCompiler) getProtobufMessageInterface() *types.Interface {
|
|
18
|
-
if c.analysis == nil || c.analysis.AllPackages == nil {
|
|
19
|
-
return nil
|
|
20
|
-
}
|
|
21
|
-
pkg := c.analysis.AllPackages["github.com/aperturerobotics/protobuf-go-lite"]
|
|
22
|
-
if pkg == nil || pkg.Types == nil {
|
|
23
|
-
return nil
|
|
24
|
-
}
|
|
25
|
-
obj := pkg.Types.Scope().Lookup("Message")
|
|
26
|
-
if obj == nil {
|
|
27
|
-
return nil
|
|
28
|
-
}
|
|
29
|
-
if tn, ok := obj.(*types.TypeName); ok {
|
|
30
|
-
if iface, ok := tn.Type().Underlying().(*types.Interface); ok {
|
|
31
|
-
return iface
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return nil
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// typeHasMethods returns true if the given type's method set contains all the specified names.
|
|
38
|
-
func (c *GoToTSCompiler) typeHasMethods(t types.Type, names ...string) bool {
|
|
39
|
-
mset := types.NewMethodSet(t)
|
|
40
|
-
for _, name := range names {
|
|
41
|
-
if mset.Lookup(nil, name) == nil {
|
|
42
|
-
return false
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return true
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// convertProtobufFieldName converts Go PascalCase field names to TypeScript camelCase
|
|
49
|
-
// for protobuf types (e.g., ExampleField -> exampleField)
|
|
50
|
-
func (c *GoToTSCompiler) convertProtobufFieldName(goFieldName string) string {
|
|
51
|
-
if len(goFieldName) == 0 {
|
|
52
|
-
return goFieldName
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Convert first character to lowercase if ASCII uppercase
|
|
56
|
-
runes := []rune(goFieldName)
|
|
57
|
-
if runes[0] >= 'A' && runes[0] <= 'Z' {
|
|
58
|
-
runes[0] = runes[0] + ('a' - 'A')
|
|
59
|
-
}
|
|
60
|
-
return string(runes)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// isProtobufGoLitePackage checks if a package path is a protobuf-go-lite package
|
|
64
|
-
// that should be skipped during compilation
|
|
65
|
-
func isProtobufGoLitePackage(pkgPath string) bool {
|
|
66
|
-
// Skip the main protobuf-go-lite package and all its subpackages
|
|
67
|
-
if strings.HasPrefix(pkgPath, "github.com/aperturerobotics/protobuf-go-lite") {
|
|
68
|
-
return true
|
|
69
|
-
}
|
|
70
|
-
// Skip json-iterator-lite which is used by protobuf-go-lite
|
|
71
|
-
if strings.HasPrefix(pkgPath, "github.com/aperturerobotics/json-iterator-lite") {
|
|
72
|
-
return true
|
|
73
|
-
}
|
|
74
|
-
return false
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// isPackageOnlyUsedByProtobufFiles checks if a package is only imported by .pb.go files
|
|
78
|
-
// in the given package, which means we can skip compiling it
|
|
79
|
-
func isPackageOnlyUsedByProtobufFiles(pkg *packages.Package, importedPkgPath string) bool {
|
|
80
|
-
// Check all files in the package to see which ones import the given package
|
|
81
|
-
usedByNonPbFiles := false
|
|
82
|
-
usedByPbFiles := false
|
|
83
|
-
|
|
84
|
-
for i, syntax := range pkg.Syntax {
|
|
85
|
-
fileName := pkg.CompiledGoFiles[i]
|
|
86
|
-
isPbFile := strings.HasSuffix(filepath.Base(fileName), ".pb.go")
|
|
87
|
-
|
|
88
|
-
// Check if this file imports the package
|
|
89
|
-
for _, imp := range syntax.Imports {
|
|
90
|
-
if imp.Path != nil {
|
|
91
|
-
importPath := strings.Trim(imp.Path.Value, `"`)
|
|
92
|
-
if importPath == importedPkgPath {
|
|
93
|
-
if isPbFile {
|
|
94
|
-
usedByPbFiles = true
|
|
95
|
-
} else {
|
|
96
|
-
usedByNonPbFiles = true
|
|
97
|
-
}
|
|
98
|
-
break
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// If the package is only used by .pb.go files and not by regular files, we can skip it
|
|
105
|
-
return usedByPbFiles && !usedByNonPbFiles
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// copyProtobufTSFile copies a .pb.ts file to the output directory
|
|
109
|
-
func (c *PackageCompiler) copyProtobufTSFile(sourcePath, fileName string) error {
|
|
110
|
-
// Read the source file
|
|
111
|
-
content, err := os.ReadFile(sourcePath)
|
|
112
|
-
if err != nil {
|
|
113
|
-
return fmt.Errorf("failed to read protobuf .pb.ts file %s: %w", sourcePath, err)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Ensure output directory exists
|
|
117
|
-
if err := os.MkdirAll(c.outputPath, 0o755); err != nil {
|
|
118
|
-
return fmt.Errorf("failed to create output directory: %w", err)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Write to output directory
|
|
122
|
-
outputPath := filepath.Join(c.outputPath, fileName)
|
|
123
|
-
if err := os.WriteFile(outputPath, content, 0o644); err != nil {
|
|
124
|
-
return fmt.Errorf("failed to write protobuf .pb.ts file to %s: %w", outputPath, err)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return nil
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// writeProtobufExports writes exports for a protobuf file to the index.ts file
|
|
131
|
-
func (c *PackageCompiler) writeProtobufExports(indexFile *os.File, fileName string) error {
|
|
132
|
-
// For protobuf files, try to parse the copied .pb.ts file in the output directory
|
|
133
|
-
// to discover exported symbols and re-export them from the index. This avoids
|
|
134
|
-
// hard-coding names like ExampleMsg and protobufPackage.
|
|
135
|
-
|
|
136
|
-
pbTsPath := filepath.Join(c.outputPath, fileName+".ts")
|
|
137
|
-
content, err := os.ReadFile(pbTsPath)
|
|
138
|
-
if err != nil {
|
|
139
|
-
return err
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Very simple export discovery: capture names from
|
|
143
|
-
// - export const Name
|
|
144
|
-
// - export interface Name
|
|
145
|
-
// - export class Name
|
|
146
|
-
// - export function Name
|
|
147
|
-
// We avoid type-only exports for now.
|
|
148
|
-
var exports []string
|
|
149
|
-
lines := strings.SplitSeq(string(content), "\n")
|
|
150
|
-
for ln := range lines {
|
|
151
|
-
l := strings.TrimSpace(ln)
|
|
152
|
-
if after, ok := strings.CutPrefix(l, "export const "); ok {
|
|
153
|
-
rest := after
|
|
154
|
-
name := takeIdent(rest)
|
|
155
|
-
if name != "" {
|
|
156
|
-
exports = append(exports, name)
|
|
157
|
-
}
|
|
158
|
-
continue
|
|
159
|
-
}
|
|
160
|
-
if after, ok := strings.CutPrefix(l, "export interface "); ok {
|
|
161
|
-
rest := after
|
|
162
|
-
name := takeIdent(rest)
|
|
163
|
-
if name != "" {
|
|
164
|
-
exports = append(exports, name)
|
|
165
|
-
}
|
|
166
|
-
continue
|
|
167
|
-
}
|
|
168
|
-
if after, ok := strings.CutPrefix(l, "export class "); ok {
|
|
169
|
-
rest := after
|
|
170
|
-
name := takeIdent(rest)
|
|
171
|
-
if name != "" {
|
|
172
|
-
exports = append(exports, name)
|
|
173
|
-
}
|
|
174
|
-
continue
|
|
175
|
-
}
|
|
176
|
-
if after, ok := strings.CutPrefix(l, "export function "); ok {
|
|
177
|
-
rest := after
|
|
178
|
-
name := takeIdent(rest)
|
|
179
|
-
if name != "" {
|
|
180
|
-
exports = append(exports, name)
|
|
181
|
-
}
|
|
182
|
-
continue
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// If nothing found, fallback to default
|
|
187
|
-
if len(exports) == 0 {
|
|
188
|
-
return fmt.Errorf("no exported symbols discovered in %s.ts while generating protobuf exports", fileName)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Deduplicate while preserving order
|
|
192
|
-
seen := map[string]bool{}
|
|
193
|
-
uniq := make([]string, 0, len(exports))
|
|
194
|
-
for _, n := range exports {
|
|
195
|
-
if !seen[n] {
|
|
196
|
-
seen[n] = true
|
|
197
|
-
uniq = append(uniq, n)
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
exportLine := fmt.Sprintf("export { %s } from \"./%s.js\"\n", strings.Join(uniq, ", "), fileName)
|
|
202
|
-
_, err = indexFile.WriteString(exportLine)
|
|
203
|
-
return err
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// takeIdent extracts a leading identifier token from the beginning of s.
|
|
207
|
-
// Returns an empty string if no valid identifier is found.
|
|
208
|
-
func takeIdent(s string) string {
|
|
209
|
-
s = strings.TrimSpace(s)
|
|
210
|
-
if s == "" {
|
|
211
|
-
return ""
|
|
212
|
-
}
|
|
213
|
-
// Identifier: letter or _ followed by letters, digits, or _
|
|
214
|
-
var b strings.Builder
|
|
215
|
-
for i, r := range s {
|
|
216
|
-
if i == 0 {
|
|
217
|
-
if !(r == '_' || r >= 'A' && r <= 'Z' || r >= 'a' && r <= 'z') {
|
|
218
|
-
break
|
|
219
|
-
}
|
|
220
|
-
b.WriteRune(r)
|
|
221
|
-
continue
|
|
222
|
-
}
|
|
223
|
-
if r == '_' || r >= 'A' && r <= 'Z' || r >= 'a' && r <= 'z' || r >= '0' && r <= '9' {
|
|
224
|
-
b.WriteRune(r)
|
|
225
|
-
continue
|
|
226
|
-
}
|
|
227
|
-
break
|
|
228
|
-
}
|
|
229
|
-
return b.String()
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// addProtobufImports adds imports for protobuf types when .pb.ts files are present in the package
|
|
233
|
-
func (c *FileCompiler) addProtobufImports() error {
|
|
234
|
-
// Check if there are any .pb.go files in this package that have corresponding .pb.ts files
|
|
235
|
-
packageDir := filepath.Dir(c.fullPath)
|
|
236
|
-
|
|
237
|
-
for _, fileName := range c.pkg.CompiledGoFiles {
|
|
238
|
-
baseFileName := filepath.Base(fileName)
|
|
239
|
-
if before, ok := strings.CutSuffix(baseFileName, ".pb.go"); ok {
|
|
240
|
-
// Check if there's a corresponding .pb.ts file
|
|
241
|
-
pbTsFileName := before + ".pb.ts"
|
|
242
|
-
pbTsPath := filepath.Join(packageDir, pbTsFileName)
|
|
243
|
-
|
|
244
|
-
if _, err := os.Stat(pbTsPath); err == nil {
|
|
245
|
-
// .pb.ts file exists, parse it for exports and add imports accordingly
|
|
246
|
-
pbBaseName := strings.TrimSuffix(baseFileName, ".pb.go")
|
|
247
|
-
|
|
248
|
-
content, rerr := os.ReadFile(pbTsPath)
|
|
249
|
-
if rerr != nil {
|
|
250
|
-
return fmt.Errorf("failed to read %s for protobuf imports: %w", pbTsPath, rerr)
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Discover exported identifiers (const/interface/class/function)
|
|
254
|
-
var exports []string
|
|
255
|
-
for ln := range strings.SplitSeq(string(content), "\n") {
|
|
256
|
-
l := strings.TrimSpace(ln)
|
|
257
|
-
if after, ok := strings.CutPrefix(l, "export const "); ok {
|
|
258
|
-
if name := takeIdent(after); name != "" {
|
|
259
|
-
exports = append(exports, name)
|
|
260
|
-
}
|
|
261
|
-
continue
|
|
262
|
-
}
|
|
263
|
-
if after, ok := strings.CutPrefix(l, "export interface "); ok {
|
|
264
|
-
if name := takeIdent(after); name != "" {
|
|
265
|
-
exports = append(exports, name)
|
|
266
|
-
}
|
|
267
|
-
continue
|
|
268
|
-
}
|
|
269
|
-
if after, ok := strings.CutPrefix(l, "export class "); ok {
|
|
270
|
-
if name := takeIdent(after); name != "" {
|
|
271
|
-
exports = append(exports, name)
|
|
272
|
-
}
|
|
273
|
-
continue
|
|
274
|
-
}
|
|
275
|
-
if after, ok := strings.CutPrefix(l, "export function "); ok {
|
|
276
|
-
if name := takeIdent(after); name != "" {
|
|
277
|
-
exports = append(exports, name)
|
|
278
|
-
}
|
|
279
|
-
continue
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
if len(exports) == 0 {
|
|
284
|
-
return fmt.Errorf("no exported symbols discovered in %s for protobuf imports", pbTsPath)
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Deduplicate
|
|
288
|
-
seen := map[string]bool{}
|
|
289
|
-
uniq := make([]string, 0, len(exports))
|
|
290
|
-
for _, n := range exports {
|
|
291
|
-
if !seen[n] {
|
|
292
|
-
seen[n] = true
|
|
293
|
-
uniq = append(uniq, n)
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
c.codeWriter.WriteLinef("import { %s } from %q;",
|
|
298
|
-
strings.Join(uniq, ", "), translateGeneratedProtobufFileToImportPath(pbBaseName))
|
|
299
|
-
break
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return nil
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// isProtobufMethodCall checks if a call expression is a protobuf method call
|
|
308
|
-
func (c *GoToTSCompiler) isProtobufMethodCall(callExpr *ast.CallExpr, methodName string) bool {
|
|
309
|
-
if selectorExpr, ok := callExpr.Fun.(*ast.SelectorExpr); ok {
|
|
310
|
-
if selectorExpr.Sel.Name == methodName {
|
|
311
|
-
if receiverType := c.pkg.TypesInfo.TypeOf(selectorExpr.X); receiverType != nil {
|
|
312
|
-
// Handle pointer types
|
|
313
|
-
if ptrType, ok := receiverType.(*types.Pointer); ok {
|
|
314
|
-
receiverType = ptrType.Elem()
|
|
315
|
-
}
|
|
316
|
-
isProtobuf := c.isProtobufType(receiverType)
|
|
317
|
-
return isProtobuf
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
return false
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// writeProtobufMarshalAssignment handles: data, err := msg.MarshalVT()
|
|
325
|
-
// Generates: const data = ExampleMsg.toBinary(msg); const err = null;
|
|
326
|
-
func (c *GoToTSCompiler) writeProtobufMarshalAssignment(lhs []ast.Expr, callExpr *ast.CallExpr, tok token.Token) error {
|
|
327
|
-
if len(lhs) != 2 {
|
|
328
|
-
return fmt.Errorf("protobuf marshal assignment requires exactly 2 LHS variables, got %d", len(lhs))
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
selectorExpr := callExpr.Fun.(*ast.SelectorExpr)
|
|
332
|
-
receiverType := c.pkg.TypesInfo.TypeOf(selectorExpr.X)
|
|
333
|
-
if ptrType, ok := receiverType.(*types.Pointer); ok {
|
|
334
|
-
receiverType = ptrType.Elem()
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// Get the type name for the static method call
|
|
338
|
-
var typeName string
|
|
339
|
-
if namedType, ok := receiverType.(*types.Named); ok {
|
|
340
|
-
typeName = namedType.Obj().Name()
|
|
341
|
-
} else {
|
|
342
|
-
return fmt.Errorf("could not determine protobuf type name")
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Handle data variable
|
|
346
|
-
dataExpr := lhs[0]
|
|
347
|
-
if dataIdent, ok := dataExpr.(*ast.Ident); ok && dataIdent.Name != "_" {
|
|
348
|
-
if tok == token.DEFINE {
|
|
349
|
-
c.tsw.WriteLiterally("const ")
|
|
350
|
-
}
|
|
351
|
-
c.tsw.WriteLiterally(dataIdent.Name)
|
|
352
|
-
c.tsw.WriteLiterally(" = ")
|
|
353
|
-
c.tsw.WriteLiterally(typeName)
|
|
354
|
-
c.tsw.WriteLiterally(".toBinary(")
|
|
355
|
-
if err := c.WriteValueExpr(selectorExpr.X); err != nil {
|
|
356
|
-
return fmt.Errorf("failed to write receiver for MarshalVT: %w", err)
|
|
357
|
-
}
|
|
358
|
-
c.tsw.WriteLiterally(")")
|
|
359
|
-
c.tsw.WriteLine("")
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Handle err variable with proper type annotation
|
|
363
|
-
errExpr := lhs[1]
|
|
364
|
-
if errIdent, ok := errExpr.(*ast.Ident); ok && errIdent.Name != "_" {
|
|
365
|
-
if tok == token.DEFINE {
|
|
366
|
-
c.tsw.WriteLiterally("let ")
|
|
367
|
-
}
|
|
368
|
-
c.tsw.WriteLiterally(errIdent.Name)
|
|
369
|
-
c.tsw.WriteLiterally(": $.GoError | null = null as $.GoError | null")
|
|
370
|
-
c.tsw.WriteLine("")
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
return nil
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// writeProtobufUnmarshalAssignment handles: err = out.UnmarshalVT(data)
|
|
377
|
-
// Generates: out = ExampleMsg.fromBinary(data); err = null;
|
|
378
|
-
func (c *GoToTSCompiler) writeProtobufUnmarshalAssignment(lhs []ast.Expr, callExpr *ast.CallExpr) error {
|
|
379
|
-
if len(lhs) != 1 {
|
|
380
|
-
return fmt.Errorf("protobuf unmarshal assignment requires exactly 1 LHS variable, got %d", len(lhs))
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
selectorExpr := callExpr.Fun.(*ast.SelectorExpr)
|
|
384
|
-
receiverType := c.pkg.TypesInfo.TypeOf(selectorExpr.X)
|
|
385
|
-
if ptrType, ok := receiverType.(*types.Pointer); ok {
|
|
386
|
-
receiverType = ptrType.Elem()
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Get the type name for the static method call
|
|
390
|
-
var typeName string
|
|
391
|
-
if namedType, ok := receiverType.(*types.Named); ok {
|
|
392
|
-
typeName = namedType.Obj().Name()
|
|
393
|
-
} else {
|
|
394
|
-
return fmt.Errorf("could not determine protobuf type name")
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// The LHS should be the err variable, but we need to assign to the receiver instead
|
|
398
|
-
errExpr := lhs[0]
|
|
399
|
-
if errIdent, ok := errExpr.(*ast.Ident); ok {
|
|
400
|
-
// First, assign the result of fromBinary to the receiver
|
|
401
|
-
if err := c.WriteValueExpr(selectorExpr.X); err != nil {
|
|
402
|
-
return fmt.Errorf("failed to write receiver for UnmarshalVT: %w", err)
|
|
403
|
-
}
|
|
404
|
-
c.tsw.WriteLiterally(" = ")
|
|
405
|
-
c.tsw.WriteLiterally(typeName)
|
|
406
|
-
c.tsw.WriteLiterally(".fromBinary(")
|
|
407
|
-
if len(callExpr.Args) > 0 {
|
|
408
|
-
c.tsw.WriteLiterally("$.normalizeBytes(")
|
|
409
|
-
if err := c.WriteValueExpr(callExpr.Args[0]); err != nil {
|
|
410
|
-
return fmt.Errorf("failed to write argument for UnmarshalVT: %w", err)
|
|
411
|
-
}
|
|
412
|
-
c.tsw.WriteLiterally(")")
|
|
413
|
-
}
|
|
414
|
-
c.tsw.WriteLiterally(")")
|
|
415
|
-
c.tsw.WriteLine("")
|
|
416
|
-
|
|
417
|
-
// Then set err to null (but only if it's not a blank identifier)
|
|
418
|
-
// Note: We don't set err = null here because err was declared as const
|
|
419
|
-
// The error handling will be skipped since err is always null for protobuf-es-lite
|
|
420
|
-
if errIdent.Name != "_" {
|
|
421
|
-
// Actually reassign err to maintain proper typing for subsequent error checks
|
|
422
|
-
c.tsw.WriteLiterally(errIdent.Name)
|
|
423
|
-
c.tsw.WriteLiterally(" = null as $.GoError | null")
|
|
424
|
-
c.tsw.WriteLine("")
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
return nil
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// writeProtobufMethodCall handles protobuf method calls in expression context
|
|
432
|
-
// Returns true if the call was handled as a protobuf method, false otherwise
|
|
433
|
-
func (c *GoToTSCompiler) writeProtobufMethodCall(exp *ast.CallExpr) (bool, error) {
|
|
434
|
-
selectorExpr, ok := exp.Fun.(*ast.SelectorExpr)
|
|
435
|
-
if !ok {
|
|
436
|
-
return false, nil
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
methodName := selectorExpr.Sel.Name
|
|
440
|
-
|
|
441
|
-
// Check if this is a protobuf method call
|
|
442
|
-
if methodName == "MarshalVT" || methodName == "UnmarshalVT" || methodName == "MarshalJSON" || methodName == "UnmarshalJSON" {
|
|
443
|
-
// Get the receiver type
|
|
444
|
-
if receiverType := c.pkg.TypesInfo.TypeOf(selectorExpr.X); receiverType != nil {
|
|
445
|
-
// Handle pointer types
|
|
446
|
-
if ptrType, ok := receiverType.(*types.Pointer); ok {
|
|
447
|
-
receiverType = ptrType.Elem()
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// Check if the receiver is a protobuf type
|
|
451
|
-
if c.isProtobufType(receiverType) {
|
|
452
|
-
if namedType, ok := receiverType.(*types.Named); ok {
|
|
453
|
-
typeName := namedType.Obj().Name()
|
|
454
|
-
|
|
455
|
-
switch methodName {
|
|
456
|
-
case "MarshalVT":
|
|
457
|
-
// Transform msg.MarshalVT() to ExampleMsg.toBinary(msg)
|
|
458
|
-
c.tsw.WriteLiterally(typeName)
|
|
459
|
-
c.tsw.WriteLiterally(".toBinary(")
|
|
460
|
-
if err := c.WriteValueExpr(selectorExpr.X); err != nil {
|
|
461
|
-
return true, fmt.Errorf("failed to write receiver for MarshalVT: %w", err)
|
|
462
|
-
}
|
|
463
|
-
c.tsw.WriteLiterally(")")
|
|
464
|
-
return true, nil
|
|
465
|
-
case "MarshalJSON":
|
|
466
|
-
// Transform msg.MarshalJSON() to ExampleMsg.toJsonString(msg)
|
|
467
|
-
c.tsw.WriteLiterally(typeName)
|
|
468
|
-
c.tsw.WriteLiterally(".toJsonString(")
|
|
469
|
-
if err := c.WriteValueExpr(selectorExpr.X); err != nil {
|
|
470
|
-
return true, fmt.Errorf("failed to write receiver for MarshalJSON: %w", err)
|
|
471
|
-
}
|
|
472
|
-
c.tsw.WriteLiterally(")")
|
|
473
|
-
return true, nil
|
|
474
|
-
case "UnmarshalVT":
|
|
475
|
-
// Transform out.UnmarshalVT(data) to ExampleMsg.fromBinary(data)
|
|
476
|
-
c.tsw.WriteLiterally(typeName)
|
|
477
|
-
c.tsw.WriteLiterally(".fromBinary($.normalizeBytes(")
|
|
478
|
-
if len(exp.Args) > 0 {
|
|
479
|
-
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
480
|
-
return true, fmt.Errorf("failed to write argument for UnmarshalVT: %w", err)
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
c.tsw.WriteLiterally("))")
|
|
484
|
-
return true, nil
|
|
485
|
-
case "UnmarshalJSON":
|
|
486
|
-
// Transform out.UnmarshalJSON(data) to ExampleMsg.fromJsonString(data)
|
|
487
|
-
c.tsw.WriteLiterally(typeName)
|
|
488
|
-
c.tsw.WriteLiterally(".fromJsonString(")
|
|
489
|
-
if len(exp.Args) > 0 {
|
|
490
|
-
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
491
|
-
return true, fmt.Errorf("failed to write argument for UnmarshalJSON: %w", err)
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
c.tsw.WriteLiterally(")")
|
|
495
|
-
return true, nil
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
return false, nil
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
// writeProtobufCompositeLit handles protobuf composite literals
|
|
506
|
-
// Returns true if the literal was handled as a protobuf type, false otherwise
|
|
507
|
-
func (c *GoToTSCompiler) writeProtobufCompositeLit(exp *ast.CompositeLit, litType types.Type) (bool, error) {
|
|
508
|
-
// Check if this is a protobuf type
|
|
509
|
-
var isProtobuf bool
|
|
510
|
-
|
|
511
|
-
if nt, ok := litType.(*types.Named); ok {
|
|
512
|
-
if c.isProtobufType(nt) {
|
|
513
|
-
isProtobuf = true
|
|
514
|
-
}
|
|
515
|
-
} else if ptrType, ok := litType.(*types.Pointer); ok {
|
|
516
|
-
if namedElem, ok := ptrType.Elem().(*types.Named); ok {
|
|
517
|
-
if c.isProtobufType(namedElem) {
|
|
518
|
-
isProtobuf = true
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
if !isProtobuf {
|
|
524
|
-
return false, nil
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
// For protobuf types, use MessageType.create() instead of new Constructor()
|
|
528
|
-
if _, ok := litType.(*types.Pointer); ok {
|
|
529
|
-
// For pointer types, we need to get the element type
|
|
530
|
-
if starExpr, ok := exp.Type.(*ast.StarExpr); ok {
|
|
531
|
-
c.WriteTypeExpr(starExpr.X)
|
|
532
|
-
} else {
|
|
533
|
-
// Fallback: write the pointer type and use create
|
|
534
|
-
c.WriteTypeExpr(exp.Type)
|
|
535
|
-
}
|
|
536
|
-
} else {
|
|
537
|
-
c.WriteTypeExpr(exp.Type)
|
|
538
|
-
}
|
|
539
|
-
c.tsw.WriteLiterally(".create")
|
|
540
|
-
|
|
541
|
-
return true, nil
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
// convertProtobufFieldNameInLiteral converts field names for protobuf composite literals
|
|
545
|
-
func (c *GoToTSCompiler) convertProtobufFieldNameInLiteral(keyName string, litType types.Type) string {
|
|
546
|
-
// Check if this is a protobuf type
|
|
547
|
-
if namedType, ok := litType.(*types.Named); ok {
|
|
548
|
-
if c.isProtobufType(namedType) {
|
|
549
|
-
return c.convertProtobufFieldName(keyName)
|
|
550
|
-
}
|
|
551
|
-
} else if ptrType, ok := litType.(*types.Pointer); ok {
|
|
552
|
-
if namedElem, ok := ptrType.Elem().(*types.Named); ok {
|
|
553
|
-
if c.isProtobufType(namedElem) {
|
|
554
|
-
return c.convertProtobufFieldName(keyName)
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
return keyName
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// writeProtobufMarshalJSONAssignment handles: data, err := msg.MarshalJSON()
|
|
562
|
-
// Generates: const data = ExampleMsg.toJsonString(msg); err = null;
|
|
563
|
-
func (c *GoToTSCompiler) writeProtobufMarshalJSONAssignment(lhs []ast.Expr, callExpr *ast.CallExpr, tok token.Token) error {
|
|
564
|
-
if len(lhs) != 2 {
|
|
565
|
-
return fmt.Errorf("protobuf marshal JSON assignment requires exactly 2 LHS variables, got %d", len(lhs))
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
selectorExpr := callExpr.Fun.(*ast.SelectorExpr)
|
|
569
|
-
receiverType := c.pkg.TypesInfo.TypeOf(selectorExpr.X)
|
|
570
|
-
if ptrType, ok := receiverType.(*types.Pointer); ok {
|
|
571
|
-
receiverType = ptrType.Elem()
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// Get the type name for the static method call
|
|
575
|
-
var typeName string
|
|
576
|
-
if namedType, ok := receiverType.(*types.Named); ok {
|
|
577
|
-
typeName = namedType.Obj().Name()
|
|
578
|
-
} else {
|
|
579
|
-
return fmt.Errorf("could not determine protobuf type name")
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
// Handle data variable (first variable)
|
|
583
|
-
dataExpr := lhs[0]
|
|
584
|
-
if dataIdent, ok := dataExpr.(*ast.Ident); ok && dataIdent.Name != "_" {
|
|
585
|
-
// For := assignments, check if this is a new variable
|
|
586
|
-
isNewVar := true
|
|
587
|
-
if tok == token.DEFINE {
|
|
588
|
-
// Check if the variable is already in scope by looking at Uses
|
|
589
|
-
if obj := c.pkg.TypesInfo.Uses[dataIdent]; obj != nil {
|
|
590
|
-
isNewVar = false
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
if tok == token.DEFINE && isNewVar {
|
|
595
|
-
c.tsw.WriteLiterally("const ")
|
|
596
|
-
}
|
|
597
|
-
c.tsw.WriteLiterally(dataIdent.Name)
|
|
598
|
-
c.tsw.WriteLiterally(" = ")
|
|
599
|
-
c.tsw.WriteLiterally(typeName)
|
|
600
|
-
c.tsw.WriteLiterally(".toJsonString(")
|
|
601
|
-
if err := c.WriteValueExpr(selectorExpr.X); err != nil {
|
|
602
|
-
return fmt.Errorf("failed to write receiver for MarshalJSON: %w", err)
|
|
603
|
-
}
|
|
604
|
-
c.tsw.WriteLiterally(")")
|
|
605
|
-
c.tsw.WriteLine("")
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
// Handle err variable (second variable)
|
|
609
|
-
errExpr := lhs[1]
|
|
610
|
-
if errIdent, ok := errExpr.(*ast.Ident); ok && errIdent.Name != "_" {
|
|
611
|
-
// For := assignments, check if this is a new variable
|
|
612
|
-
isNewVar := true
|
|
613
|
-
if tok == token.DEFINE {
|
|
614
|
-
// Check if the variable is already in scope by looking at Uses
|
|
615
|
-
if obj := c.pkg.TypesInfo.Uses[errIdent]; obj != nil {
|
|
616
|
-
isNewVar = false
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
if tok == token.DEFINE && isNewVar {
|
|
621
|
-
c.tsw.WriteLiterally("let ")
|
|
622
|
-
}
|
|
623
|
-
c.tsw.WriteLiterally(errIdent.Name)
|
|
624
|
-
if tok == token.DEFINE && isNewVar {
|
|
625
|
-
c.tsw.WriteLiterally(": $.GoError | null")
|
|
626
|
-
}
|
|
627
|
-
c.tsw.WriteLiterally(" = null as $.GoError | null")
|
|
628
|
-
c.tsw.WriteLine("")
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
return nil
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
// writeProtobufUnmarshalJSONAssignment handles: err = out.UnmarshalJSON(data)
|
|
635
|
-
// Generates: out = ExampleMsg.fromJsonString(data); err = null;
|
|
636
|
-
func (c *GoToTSCompiler) writeProtobufUnmarshalJSONAssignment(lhs []ast.Expr, callExpr *ast.CallExpr, tok token.Token) error {
|
|
637
|
-
if len(lhs) != 1 {
|
|
638
|
-
return fmt.Errorf("protobuf unmarshal JSON assignment requires exactly 1 LHS variable, got %d", len(lhs))
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
selectorExpr := callExpr.Fun.(*ast.SelectorExpr)
|
|
642
|
-
receiverType := c.pkg.TypesInfo.TypeOf(selectorExpr.X)
|
|
643
|
-
if ptrType, ok := receiverType.(*types.Pointer); ok {
|
|
644
|
-
receiverType = ptrType.Elem()
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// Get the type name for the static method call
|
|
648
|
-
var typeName string
|
|
649
|
-
if namedType, ok := receiverType.(*types.Named); ok {
|
|
650
|
-
typeName = namedType.Obj().Name()
|
|
651
|
-
} else {
|
|
652
|
-
return fmt.Errorf("could not determine protobuf type name")
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
// The LHS should be the err variable, but we need to assign to the receiver instead
|
|
656
|
-
errExpr := lhs[0]
|
|
657
|
-
if errIdent, ok := errExpr.(*ast.Ident); ok {
|
|
658
|
-
// First, assign the result of fromJsonString to the receiver
|
|
659
|
-
if err := c.WriteValueExpr(selectorExpr.X); err != nil {
|
|
660
|
-
return fmt.Errorf("failed to write receiver for UnmarshalJSON: %w", err)
|
|
661
|
-
}
|
|
662
|
-
c.tsw.WriteLiterally(" = ")
|
|
663
|
-
c.tsw.WriteLiterally(typeName)
|
|
664
|
-
c.tsw.WriteLiterally(".fromJsonString(")
|
|
665
|
-
if len(callExpr.Args) > 0 {
|
|
666
|
-
if err := c.WriteValueExpr(callExpr.Args[0]); err != nil {
|
|
667
|
-
return fmt.Errorf("failed to write argument for UnmarshalJSON: %w", err)
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
c.tsw.WriteLiterally(")")
|
|
671
|
-
c.tsw.WriteLine("")
|
|
672
|
-
|
|
673
|
-
// Then set err to null (but only if it's not a blank identifier)
|
|
674
|
-
if errIdent.Name != "_" {
|
|
675
|
-
// For := assignments, check if this is a new variable
|
|
676
|
-
isNewVar := true
|
|
677
|
-
if tok == token.DEFINE {
|
|
678
|
-
// Check if the variable is already in scope by looking at Uses
|
|
679
|
-
if obj := c.pkg.TypesInfo.Uses[errIdent]; obj != nil {
|
|
680
|
-
isNewVar = false
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
if tok == token.DEFINE && isNewVar {
|
|
685
|
-
c.tsw.WriteLiterally("let ")
|
|
686
|
-
}
|
|
687
|
-
c.tsw.WriteLiterally(errIdent.Name)
|
|
688
|
-
if tok == token.DEFINE && isNewVar {
|
|
689
|
-
c.tsw.WriteLiterally(": $.GoError | null")
|
|
690
|
-
}
|
|
691
|
-
c.tsw.WriteLiterally(" = null as $.GoError | null")
|
|
692
|
-
c.tsw.WriteLine("")
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
return nil
|
|
697
|
-
}
|