goscript 0.0.47 → 0.0.49
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/cmd/goscript/deps.go +1 -4
- package/compiler/analysis.go +224 -63
- package/compiler/analysis_test.go +112 -0
- package/compiler/compiler.go +19 -87
- package/compiler/expr-call-type-conversion.go +148 -59
- package/compiler/expr-call.go +202 -10
- package/compiler/expr.go +5 -82
- package/compiler/gs_dependencies_test.go +60 -1
- package/compiler/spec-value.go +73 -51
- package/compiler/spec.go +293 -151
- package/compiler/stmt.go +192 -81
- package/dist/gs/builtin/builtin.d.ts +1 -5
- package/dist/gs/builtin/builtin.js +1 -34
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/fmt/fmt.js +20 -4
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/io/fs/fs.d.ts +6 -12
- package/dist/gs/io/fs/fs.js +52 -67
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/os/index.d.ts +2 -1
- package/dist/gs/os/index.js +1 -1
- package/dist/gs/os/index.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +7 -1
- package/dist/gs/os/types_js.gs.js +16 -1
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js +2 -2
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +3 -3
- package/dist/gs/reflect/index.js +2 -2
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js +2 -2
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +8 -9
- package/dist/gs/reflect/type.js +101 -103
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +1 -10
- package/dist/gs/reflect/types.js +3 -26
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.js +23 -23
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +3 -3
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/time/time.d.ts +11 -22
- package/dist/gs/time/time.js +29 -57
- package/dist/gs/time/time.js.map +1 -1
- package/gs/TODO.md +129 -0
- package/gs/builtin/builtin.ts +3 -41
- package/gs/builtin/slice.ts +1 -1
- package/gs/bytes/meta.json +10 -0
- package/gs/fmt/fmt.ts +18 -4
- package/gs/fmt/meta.json +5 -0
- package/gs/internal/meta.json +5 -0
- package/gs/io/fs/fs.ts +58 -73
- package/gs/io/meta.json +9 -0
- package/gs/maps/meta.json +6 -0
- package/gs/math/meta.json +5 -0
- package/gs/os/index.ts +8 -1
- package/gs/os/meta.json +15 -0
- package/gs/os/types_js.gs.ts +22 -1
- package/gs/os/types_unix.gs.ts +2 -2
- package/gs/path/meta.json +6 -0
- package/gs/reflect/function-types.test.ts +10 -10
- package/gs/reflect/index.ts +6 -6
- package/gs/reflect/map.ts +2 -2
- package/gs/reflect/meta.json +5 -0
- package/gs/reflect/type.ts +108 -103
- package/gs/reflect/types.ts +2 -28
- package/gs/reflect/value.ts +23 -23
- package/gs/reflect/visiblefields.ts +3 -3
- package/gs/strconv/meta.json +5 -0
- package/gs/strings/meta.json +9 -0
- package/gs/sync/meta.json +19 -0
- package/gs/time/time.ts +32 -65
- package/package.json +1 -1
- package/dist/gs/builtin/io.d.ts +0 -16
- package/dist/gs/builtin/io.js +0 -15
- package/dist/gs/builtin/io.js.map +0 -1
- package/dist/gs/internal/testlog/index.d.ts +0 -1
- package/dist/gs/internal/testlog/index.js +0 -5
- package/dist/gs/internal/testlog/index.js.map +0 -1
- package/dist/gs/maps/iter.gs.d.ts +0 -7
- package/dist/gs/maps/iter.gs.js +0 -65
- package/dist/gs/maps/iter.gs.js.map +0 -1
- package/dist/gs/maps/maps.gs.d.ts +0 -7
- package/dist/gs/maps/maps.gs.js +0 -79
- package/dist/gs/maps/maps.gs.js.map +0 -1
- package/dist/gs/reflect/abi.d.ts +0 -59
- package/dist/gs/reflect/abi.gs.d.ts +0 -59
- package/dist/gs/reflect/abi.gs.js +0 -79
- package/dist/gs/reflect/abi.gs.js.map +0 -1
- package/dist/gs/reflect/abi.js +0 -79
- package/dist/gs/reflect/abi.js.map +0 -1
- package/dist/gs/reflect/badlinkname.d.ts +0 -52
- package/dist/gs/reflect/badlinkname.gs.d.ts +0 -52
- package/dist/gs/reflect/badlinkname.gs.js +0 -72
- package/dist/gs/reflect/badlinkname.gs.js.map +0 -1
- package/dist/gs/reflect/badlinkname.js +0 -72
- package/dist/gs/reflect/badlinkname.js.map +0 -1
- package/dist/gs/reflect/deepequal.gs.d.ts +0 -25
- package/dist/gs/reflect/deepequal.gs.js +0 -308
- package/dist/gs/reflect/deepequal.gs.js.map +0 -1
- package/dist/gs/reflect/float32reg_generic.gs.d.ts +0 -2
- package/dist/gs/reflect/float32reg_generic.gs.js +0 -10
- package/dist/gs/reflect/float32reg_generic.gs.js.map +0 -1
- package/dist/gs/reflect/index.gs.d.ts +0 -1
- package/dist/gs/reflect/index.gs.js +0 -3
- package/dist/gs/reflect/index.gs.js.map +0 -1
- package/dist/gs/reflect/iter.gs.d.ts +0 -3
- package/dist/gs/reflect/iter.gs.js +0 -24
- package/dist/gs/reflect/iter.gs.js.map +0 -1
- package/dist/gs/reflect/makefunc.gs.d.ts +0 -34
- package/dist/gs/reflect/makefunc.gs.js +0 -288
- package/dist/gs/reflect/makefunc.gs.js.map +0 -1
- package/dist/gs/reflect/map_swiss.gs.d.ts +0 -14
- package/dist/gs/reflect/map_swiss.gs.js +0 -70
- package/dist/gs/reflect/map_swiss.gs.js.map +0 -1
- package/dist/gs/reflect/reflect.gs.d.ts +0 -132
- package/dist/gs/reflect/reflect.gs.js +0 -437
- package/dist/gs/reflect/reflect.gs.js.map +0 -1
- package/dist/gs/reflect/swapper.gs.d.ts +0 -1
- package/dist/gs/reflect/swapper.gs.js +0 -32
- package/dist/gs/reflect/swapper.gs.js.map +0 -1
- package/dist/gs/reflect/type.gs.d.ts +0 -4
- package/dist/gs/reflect/type.gs.js +0 -21
- package/dist/gs/reflect/type.gs.js.map +0 -1
- package/dist/gs/reflect/value.gs.d.ts +0 -4
- package/dist/gs/reflect/value.gs.js +0 -12
- package/dist/gs/reflect/value.gs.js.map +0 -1
- package/dist/gs/reflect/visiblefields.gs.d.ts +0 -3
- package/dist/gs/reflect/visiblefields.gs.js +0 -123
- package/dist/gs/reflect/visiblefields.gs.js.map +0 -1
- package/dist/gs/stringslite/index.d.ts +0 -1
- package/dist/gs/stringslite/index.js +0 -2
- package/dist/gs/stringslite/index.js.map +0 -1
- package/dist/gs/stringslite/strings.d.ts +0 -11
- package/dist/gs/stringslite/strings.js +0 -67
- package/dist/gs/stringslite/strings.js.map +0 -1
- package/gs/bytes/metadata.go +0 -12
- package/gs/fmt/metadata.go +0 -7
- package/gs/internal/metadata.go +0 -7
- package/gs/io/io.go +0 -75
- package/gs/io/metadata.go +0 -11
- package/gs/maps/metadata.go +0 -8
- package/gs/math/metadata.go +0 -7
- package/gs/os/metadata.go +0 -17
- package/gs/path/metadata.go +0 -8
- package/gs/reflect/metadata.go +0 -7
- package/gs/strconv/metadata.go +0 -7
- package/gs/strings/metadata.go +0 -11
- package/gs/sync/metadata.go +0 -7
- package/gs/sync/sync.go +0 -64
package/compiler/spec.go
CHANGED
|
@@ -92,123 +92,196 @@ func (c *GoToTSCompiler) writeVarRefedFieldInitializer(fieldName string, fieldTy
|
|
|
92
92
|
c.tsw.WriteLiterally(": $.varRef(")
|
|
93
93
|
|
|
94
94
|
if isEmbedded {
|
|
95
|
-
|
|
96
|
-
_, isInterface := fieldType.Underlying().(*types.Interface)
|
|
97
|
-
if isPtr || isInterface {
|
|
98
|
-
c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
|
|
99
|
-
} else {
|
|
100
|
-
// Check if the embedded type is an interface
|
|
101
|
-
embeddedTypeUnderlying := fieldType
|
|
102
|
-
if named, isNamed := embeddedTypeUnderlying.(*types.Named); isNamed {
|
|
103
|
-
embeddedTypeUnderlying = named.Underlying()
|
|
104
|
-
}
|
|
105
|
-
if _, isInterface := embeddedTypeUnderlying.(*types.Interface); isInterface {
|
|
106
|
-
// For interfaces, use the provided value or null instead of trying to instantiate
|
|
107
|
-
c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
|
|
108
|
-
} else {
|
|
109
|
-
// For structs, instantiate with provided fields
|
|
110
|
-
typeForNew := fieldName
|
|
111
|
-
c.tsw.WriteLiterallyf("new %s(init?.%s)", typeForNew, fieldName)
|
|
112
|
-
}
|
|
113
|
-
}
|
|
95
|
+
c.writeEmbeddedFieldInitializer(fieldName, fieldType)
|
|
114
96
|
} else {
|
|
115
|
-
|
|
116
|
-
var structTypeNameForClone string
|
|
117
|
-
if named, ok := fieldType.(*types.Named); ok {
|
|
118
|
-
if _, isStruct := named.Underlying().(*types.Struct); isStruct {
|
|
119
|
-
isStructValueType = true
|
|
120
|
-
structTypeNameForClone = c.getTypeString(fieldType)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if isStructValueType {
|
|
125
|
-
c.tsw.WriteLiterallyf("init?.%s?.clone() ?? new %s()", fieldName, structTypeNameForClone)
|
|
126
|
-
} else {
|
|
127
|
-
c.tsw.WriteLiterallyf("init?.%s ?? ", fieldName)
|
|
128
|
-
// Check if this is a named type or type alias and use constructor instead of null
|
|
129
|
-
if named, isNamed := fieldType.(*types.Named); isNamed {
|
|
130
|
-
// This is a named type
|
|
131
|
-
// Check if underlying type is an interface
|
|
132
|
-
if _, isInterface := named.Underlying().(*types.Interface); isInterface {
|
|
133
|
-
// For interfaces, use null as the zero value
|
|
134
|
-
c.tsw.WriteLiterally("null")
|
|
135
|
-
} else if _, isStruct := named.Underlying().(*types.Struct); !isStruct {
|
|
136
|
-
// For non-struct, non-interface named types, use constructor
|
|
137
|
-
c.tsw.WriteLiterally("new ")
|
|
138
|
-
c.WriteNamedType(named)
|
|
139
|
-
c.tsw.WriteLiterally("(")
|
|
140
|
-
c.WriteZeroValueForType(named.Underlying())
|
|
141
|
-
c.tsw.WriteLiterally(")")
|
|
142
|
-
} else {
|
|
143
|
-
c.WriteZeroValueForType(fieldType)
|
|
144
|
-
}
|
|
145
|
-
} else if alias, isAlias := fieldType.(*types.Alias); isAlias {
|
|
146
|
-
// This is a type alias (like os.FileMode)
|
|
147
|
-
// Check if underlying type is an interface
|
|
148
|
-
if _, isInterface := alias.Underlying().(*types.Interface); isInterface {
|
|
149
|
-
// For interface type aliases, use null as the zero value
|
|
150
|
-
c.tsw.WriteLiterally("null")
|
|
151
|
-
} else if _, isStruct := alias.Underlying().(*types.Struct); !isStruct {
|
|
152
|
-
// For non-struct, non-interface type aliases, use constructor
|
|
153
|
-
c.tsw.WriteLiterally("new ")
|
|
154
|
-
// Use AST type information if available to preserve qualified names
|
|
155
|
-
if astType != nil {
|
|
156
|
-
c.WriteTypeExpr(astType)
|
|
157
|
-
} else {
|
|
158
|
-
c.WriteGoType(fieldType, GoTypeContextGeneral)
|
|
159
|
-
}
|
|
160
|
-
c.tsw.WriteLiterally("(")
|
|
161
|
-
c.WriteZeroValueForType(alias.Underlying())
|
|
162
|
-
c.tsw.WriteLiterally(")")
|
|
163
|
-
} else {
|
|
164
|
-
c.WriteZeroValueForType(fieldType)
|
|
165
|
-
}
|
|
166
|
-
} else {
|
|
167
|
-
c.WriteZeroValueForType(fieldType)
|
|
168
|
-
}
|
|
169
|
-
}
|
|
97
|
+
c.writeRegularFieldInitializer(fieldName, fieldType, astType)
|
|
170
98
|
}
|
|
171
99
|
|
|
172
100
|
c.tsw.WriteLiterally(")")
|
|
173
101
|
}
|
|
174
102
|
|
|
175
|
-
func (c *GoToTSCompiler)
|
|
176
|
-
|
|
177
|
-
|
|
103
|
+
func (c *GoToTSCompiler) writeEmbeddedFieldInitializer(fieldName string, fieldType types.Type) {
|
|
104
|
+
_, isPtr := fieldType.(*types.Pointer)
|
|
105
|
+
_, isInterface := fieldType.Underlying().(*types.Interface)
|
|
178
106
|
|
|
179
|
-
if
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
trueType = ptr.Elem()
|
|
184
|
-
isPointerToStruct = true
|
|
185
|
-
}
|
|
107
|
+
if isPtr || isInterface {
|
|
108
|
+
c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
|
|
109
|
+
return
|
|
110
|
+
}
|
|
186
111
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
112
|
+
// Check if the embedded type is an interface
|
|
113
|
+
embeddedTypeUnderlying := fieldType
|
|
114
|
+
if named, isNamed := embeddedTypeUnderlying.(*types.Named); isNamed {
|
|
115
|
+
embeddedTypeUnderlying = named.Underlying()
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if _, isInterface := embeddedTypeUnderlying.(*types.Interface); isInterface {
|
|
119
|
+
// For interfaces, use the provided value or null instead of trying to instantiate
|
|
120
|
+
c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// For structs, instantiate with provided fields
|
|
125
|
+
typeForNew := fieldName
|
|
126
|
+
c.tsw.WriteLiterallyf("new %s(init?.%s)", typeForNew, fieldName)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
func (c *GoToTSCompiler) writeRegularFieldInitializer(fieldName string, fieldType types.Type, astType ast.Expr) {
|
|
130
|
+
// Check if this is a struct value type that needs cloning
|
|
131
|
+
if c.isStructValueType(fieldType) {
|
|
132
|
+
structTypeNameForClone := c.getTypeString(fieldType)
|
|
133
|
+
c.tsw.WriteLiterallyf("init?.%s?.clone() ?? new %s()", fieldName, structTypeNameForClone)
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
c.tsw.WriteLiterallyf("init?.%s ?? ", fieldName)
|
|
138
|
+
|
|
139
|
+
// Debugging: print field type info
|
|
140
|
+
if astType != nil {
|
|
141
|
+
if named, ok := fieldType.(*types.Named); ok {
|
|
142
|
+
if pkgPath := named.Obj().Pkg().Path(); pkgPath != "" {
|
|
143
|
+
c.tsw.WriteCommentLinef("DEBUG: Field %s has type %s (%T)", fieldName, fieldType, fieldType)
|
|
193
144
|
}
|
|
194
145
|
} else {
|
|
195
|
-
c.tsw.
|
|
146
|
+
c.tsw.WriteCommentLinef("DEBUG: Field %s has type %s (%T)", fieldName, fieldType, fieldType)
|
|
196
147
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
isValueTypeStruct = true
|
|
148
|
+
if typeName, ok := c.pkg.TypesInfo.TypeOf(astType).(*types.Named); ok {
|
|
149
|
+
pkgPath := ""
|
|
150
|
+
if typeName.Obj().Pkg() != nil {
|
|
151
|
+
pkgPath = typeName.Obj().Pkg().Path()
|
|
202
152
|
}
|
|
153
|
+
c.tsw.WriteCommentLinef("DEBUG: Package=%s, TypeName=%s", pkgPath, typeName)
|
|
203
154
|
}
|
|
155
|
+
}
|
|
204
156
|
|
|
205
|
-
|
|
206
|
-
|
|
157
|
+
// Priority 1: Check if this is a wrapper type
|
|
158
|
+
if c.analysis.IsWrapperType(fieldType) {
|
|
159
|
+
c.tsw.WriteCommentLinef("DEBUG: Using wrapper type zero value")
|
|
160
|
+
// For wrapper types, use the zero value of the underlying type with type casting
|
|
161
|
+
if named, ok := fieldType.(*types.Named); ok {
|
|
162
|
+
c.WriteZeroValueForType(named.Underlying())
|
|
163
|
+
c.tsw.WriteLiterally(" as ")
|
|
164
|
+
c.WriteGoType(fieldType, GoTypeContextGeneral)
|
|
165
|
+
} else if alias, ok := fieldType.(*types.Alias); ok {
|
|
166
|
+
c.WriteZeroValueForType(alias.Underlying())
|
|
167
|
+
c.tsw.WriteLiterally(" as ")
|
|
168
|
+
c.WriteGoType(fieldType, GoTypeContextGeneral)
|
|
207
169
|
} else {
|
|
208
|
-
|
|
170
|
+
// Fallback to original behavior
|
|
171
|
+
c.WriteZeroValueForType(fieldType)
|
|
209
172
|
}
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Priority 2: Handle imported types with basic underlying types (like os.FileMode)
|
|
177
|
+
if c.isImportedBasicType(fieldType) {
|
|
178
|
+
c.tsw.WriteCommentLinef("DEBUG: Using imported basic type zero value")
|
|
179
|
+
c.writeImportedBasicTypeZeroValue(fieldType)
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Priority 3: Handle named types
|
|
184
|
+
if named, isNamed := fieldType.(*types.Named); isNamed {
|
|
185
|
+
c.tsw.WriteCommentLinef("DEBUG: Using named type zero value")
|
|
186
|
+
c.writeNamedTypeZeroValue(named)
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Priority 4: Handle type aliases
|
|
191
|
+
if alias, isAlias := fieldType.(*types.Alias); isAlias {
|
|
192
|
+
c.tsw.WriteCommentLinef("DEBUG: Using type alias zero value")
|
|
193
|
+
c.writeTypeAliasZeroValue(alias, astType)
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Default: use WriteZeroValueForType
|
|
198
|
+
c.tsw.WriteCommentLinef("DEBUG: Using default zero value")
|
|
199
|
+
c.WriteZeroValueForType(fieldType)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
func (c *GoToTSCompiler) isStructValueType(fieldType types.Type) bool {
|
|
203
|
+
if named, ok := fieldType.(*types.Named); ok {
|
|
204
|
+
if _, isStruct := named.Underlying().(*types.Struct); isStruct {
|
|
205
|
+
return true
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return false
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
func (c *GoToTSCompiler) isImportedBasicType(fieldType types.Type) bool {
|
|
212
|
+
named, isNamed := fieldType.(*types.Named)
|
|
213
|
+
if !isNamed {
|
|
214
|
+
return false
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
obj := named.Obj()
|
|
218
|
+
if obj == nil || obj.Pkg() == nil || obj.Pkg() == c.pkg.Types {
|
|
219
|
+
return false // Not imported or is local
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
underlying := named.Underlying()
|
|
223
|
+
if underlying == nil {
|
|
224
|
+
return false
|
|
210
225
|
}
|
|
211
226
|
|
|
227
|
+
_, isBasic := underlying.(*types.Basic)
|
|
228
|
+
return isBasic
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
func (c *GoToTSCompiler) writeImportedBasicTypeZeroValue(fieldType types.Type) {
|
|
232
|
+
named := fieldType.(*types.Named)
|
|
233
|
+
underlying := named.Underlying()
|
|
234
|
+
|
|
235
|
+
// Write zero value of underlying type with type casting
|
|
236
|
+
c.WriteZeroValueForType(underlying)
|
|
237
|
+
c.tsw.WriteLiterally(" as ")
|
|
238
|
+
c.WriteGoType(fieldType, GoTypeContextGeneral)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
func (c *GoToTSCompiler) writeNamedTypeZeroValue(named *types.Named) {
|
|
242
|
+
// Check if underlying type is an interface
|
|
243
|
+
if _, isInterface := named.Underlying().(*types.Interface); isInterface {
|
|
244
|
+
c.tsw.WriteLiterally("null")
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Check if underlying type is a struct
|
|
249
|
+
if _, isStruct := named.Underlying().(*types.Struct); isStruct {
|
|
250
|
+
c.WriteZeroValueForType(named)
|
|
251
|
+
return
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// For non-struct, non-interface named types, use constructor
|
|
255
|
+
c.tsw.WriteLiterally("new ")
|
|
256
|
+
c.WriteNamedType(named)
|
|
257
|
+
c.tsw.WriteLiterally("(")
|
|
258
|
+
c.WriteZeroValueForType(named.Underlying())
|
|
259
|
+
c.tsw.WriteLiterally(")")
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
func (c *GoToTSCompiler) writeTypeAliasZeroValue(alias *types.Alias, astType ast.Expr) {
|
|
263
|
+
// Check if underlying type is an interface
|
|
264
|
+
if _, isInterface := alias.Underlying().(*types.Interface); isInterface {
|
|
265
|
+
c.tsw.WriteLiterally("null")
|
|
266
|
+
return
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Check if underlying type is a struct
|
|
270
|
+
if _, isStruct := alias.Underlying().(*types.Struct); isStruct {
|
|
271
|
+
c.WriteZeroValueForType(alias)
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// For non-struct, non-interface type aliases, use constructor
|
|
276
|
+
c.tsw.WriteLiterally("new ")
|
|
277
|
+
// Use AST type information if available to preserve qualified names
|
|
278
|
+
if astType != nil {
|
|
279
|
+
c.WriteTypeExpr(astType)
|
|
280
|
+
} else {
|
|
281
|
+
c.WriteGoType(alias, GoTypeContextGeneral)
|
|
282
|
+
}
|
|
283
|
+
c.tsw.WriteLiterally("(")
|
|
284
|
+
c.WriteZeroValueForType(alias.Underlying())
|
|
212
285
|
c.tsw.WriteLiterally(")")
|
|
213
286
|
}
|
|
214
287
|
|
|
@@ -244,7 +317,11 @@ func (c *GoToTSCompiler) hasReceiverMethods(typeName string) bool {
|
|
|
244
317
|
return false
|
|
245
318
|
}
|
|
246
319
|
|
|
247
|
-
// WriteNamedTypeWithMethods generates
|
|
320
|
+
// WriteNamedTypeWithMethods generates TypeScript code for Go named types that have methods.
|
|
321
|
+
// Instead of generating a class, it now generates:
|
|
322
|
+
// 1. A type alias for the underlying type
|
|
323
|
+
// 2. Function declarations for each method (TypeName_MethodName)
|
|
324
|
+
// 3. Function implementations for each method
|
|
248
325
|
func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
|
|
249
326
|
className := a.Name.Name
|
|
250
327
|
|
|
@@ -258,49 +335,16 @@ func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
|
|
|
258
335
|
c.tsw.WriteLiterally("export ")
|
|
259
336
|
}
|
|
260
337
|
|
|
261
|
-
|
|
262
|
-
c.tsw.
|
|
263
|
-
c.tsw.
|
|
264
|
-
|
|
265
|
-
// Constructor that takes the underlying type value
|
|
266
|
-
c.tsw.WriteLiterally("constructor(private _value: ")
|
|
267
|
-
// Use AST-based type writing to preserve qualified names like os.FileInfo
|
|
268
|
-
c.WriteTypeExpr(a.Type)
|
|
269
|
-
c.tsw.WriteLine(") {}")
|
|
270
|
-
c.tsw.WriteLine("")
|
|
271
|
-
|
|
272
|
-
// valueOf method to get the underlying value (for type conversions and operations)
|
|
273
|
-
c.tsw.WriteLiterally("valueOf(): ")
|
|
274
|
-
// Use AST-based type writing to preserve qualified names like os.FileInfo
|
|
275
|
-
c.WriteTypeExpr(a.Type)
|
|
276
|
-
c.tsw.WriteLine(" {")
|
|
277
|
-
c.tsw.Indent(1)
|
|
278
|
-
c.tsw.WriteLine("return this._value")
|
|
279
|
-
c.tsw.Indent(-1)
|
|
280
|
-
c.tsw.WriteLine("}")
|
|
281
|
-
c.tsw.WriteLine("")
|
|
282
|
-
|
|
283
|
-
// toString method for string conversion
|
|
284
|
-
c.tsw.WriteLine("toString(): string {")
|
|
285
|
-
c.tsw.Indent(1)
|
|
286
|
-
c.tsw.WriteLine("return String(this._value)")
|
|
287
|
-
c.tsw.Indent(-1)
|
|
288
|
-
c.tsw.WriteLine("}")
|
|
289
|
-
c.tsw.WriteLine("")
|
|
290
|
-
|
|
291
|
-
// Static from method for type conversion
|
|
292
|
-
c.tsw.WriteLiterallyf("static from(value: ")
|
|
338
|
+
// Generate type alias instead of class
|
|
339
|
+
c.tsw.WriteLiterally("type ")
|
|
340
|
+
c.tsw.WriteLiterally(className)
|
|
341
|
+
c.tsw.WriteLiterally(" = ")
|
|
293
342
|
// Use AST-based type writing to preserve qualified names like os.FileInfo
|
|
294
343
|
c.WriteTypeExpr(a.Type)
|
|
295
|
-
c.tsw.
|
|
296
|
-
c.tsw.WriteLine("")
|
|
297
|
-
c.tsw.Indent(1)
|
|
298
|
-
c.tsw.WriteLiterallyf("return new %s(value)", className)
|
|
344
|
+
c.tsw.WriteLine(";")
|
|
299
345
|
c.tsw.WriteLine("")
|
|
300
|
-
c.tsw.Indent(-1)
|
|
301
|
-
c.tsw.WriteLine("}")
|
|
302
346
|
|
|
303
|
-
//
|
|
347
|
+
// Generate function declarations and implementations for each method
|
|
304
348
|
for _, fileSyntax := range c.pkg.Syntax {
|
|
305
349
|
for _, decl := range fileSyntax.Decls {
|
|
306
350
|
funcDecl, isFunc := decl.(*ast.FuncDecl)
|
|
@@ -324,28 +368,86 @@ func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
|
|
|
324
368
|
}
|
|
325
369
|
|
|
326
370
|
if recvTypeName == className {
|
|
327
|
-
|
|
328
|
-
|
|
371
|
+
if !isInsideFunction {
|
|
372
|
+
c.tsw.WriteLiterally("export ")
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Generate function signature: export function TypeName_MethodName(receiver: TypeName, ...args): ReturnType
|
|
376
|
+
c.tsw.WriteLiterally("function ")
|
|
377
|
+
c.tsw.WriteLiterally(className)
|
|
378
|
+
c.tsw.WriteLiterally("_")
|
|
379
|
+
c.tsw.WriteLiterally(funcDecl.Name.Name)
|
|
380
|
+
c.tsw.WriteLiterally("(")
|
|
381
|
+
|
|
382
|
+
// First parameter is the receiver - use the original receiver parameter name
|
|
383
|
+
var receiverParamName string = "receiver" // default fallback
|
|
384
|
+
if funcDecl.Recv != nil && len(funcDecl.Recv.List) > 0 {
|
|
385
|
+
if len(funcDecl.Recv.List[0].Names) > 0 {
|
|
386
|
+
if name := funcDecl.Recv.List[0].Names[0]; name != nil && name.Name != "_" {
|
|
387
|
+
receiverParamName = name.Name
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
c.tsw.WriteLiterally(receiverParamName)
|
|
392
|
+
c.tsw.WriteLiterally(": ")
|
|
393
|
+
c.tsw.WriteLiterally(className)
|
|
394
|
+
|
|
395
|
+
// Add other parameters
|
|
396
|
+
if funcDecl.Type.Params != nil && len(funcDecl.Type.Params.List) > 0 {
|
|
397
|
+
c.tsw.WriteLiterally(", ")
|
|
398
|
+
c.WriteFieldList(funcDecl.Type.Params, true) // true = arguments
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
c.tsw.WriteLiterally(")")
|
|
402
|
+
|
|
403
|
+
// Add return type
|
|
404
|
+
if funcDecl.Type.Results != nil && len(funcDecl.Type.Results.List) > 0 {
|
|
405
|
+
c.tsw.WriteLiterally(": ")
|
|
406
|
+
if len(funcDecl.Type.Results.List) == 1 {
|
|
407
|
+
c.WriteTypeExpr(funcDecl.Type.Results.List[0].Type)
|
|
408
|
+
} else {
|
|
409
|
+
c.tsw.WriteLiterally("[")
|
|
410
|
+
for i, field := range funcDecl.Type.Results.List {
|
|
411
|
+
if i > 0 {
|
|
412
|
+
c.tsw.WriteLiterally(", ")
|
|
413
|
+
}
|
|
414
|
+
c.WriteTypeExpr(field.Type)
|
|
415
|
+
}
|
|
416
|
+
c.tsw.WriteLiterally("]")
|
|
417
|
+
}
|
|
418
|
+
} else {
|
|
419
|
+
c.tsw.WriteLiterally(": void")
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
c.tsw.WriteLine(" {")
|
|
423
|
+
c.tsw.Indent(1)
|
|
424
|
+
|
|
425
|
+
// Write method body with receiver as first parameter
|
|
426
|
+
if err := c.writeWrapperFunctionBody(funcDecl, className); err != nil {
|
|
329
427
|
return err
|
|
330
428
|
}
|
|
429
|
+
|
|
430
|
+
c.tsw.Indent(-1)
|
|
431
|
+
c.tsw.WriteLine("}")
|
|
432
|
+
c.tsw.WriteLine("")
|
|
331
433
|
}
|
|
332
434
|
}
|
|
333
435
|
}
|
|
334
436
|
|
|
335
|
-
c.tsw.Indent(-1)
|
|
336
|
-
c.tsw.WriteLine("}")
|
|
337
|
-
|
|
338
437
|
return nil
|
|
339
438
|
}
|
|
340
439
|
|
|
341
|
-
//
|
|
342
|
-
func (c *GoToTSCompiler)
|
|
343
|
-
|
|
344
|
-
if
|
|
345
|
-
|
|
440
|
+
// writeWrapperFunctionBody writes the body of a wrapper function, treating the receiver as the first parameter
|
|
441
|
+
func (c *GoToTSCompiler) writeWrapperFunctionBody(decl *ast.FuncDecl, typeName string) error {
|
|
442
|
+
// Write function body statements directly - identifier mapping is handled by pre-computed analysis
|
|
443
|
+
if decl.Body != nil {
|
|
444
|
+
for _, stmt := range decl.Body.List {
|
|
445
|
+
if err := c.WriteStmt(stmt); err != nil {
|
|
446
|
+
return err
|
|
447
|
+
}
|
|
448
|
+
}
|
|
346
449
|
}
|
|
347
|
-
|
|
348
|
-
return c.writeMethodBodyWithReceiverBinding(decl, "this._value")
|
|
450
|
+
return nil
|
|
349
451
|
}
|
|
350
452
|
|
|
351
453
|
// WriteTypeSpec writes the type specification to the output.
|
|
@@ -515,3 +617,43 @@ func (c *GoToTSCompiler) WriteImportSpec(a *ast.ImportSpec) {
|
|
|
515
617
|
|
|
516
618
|
c.tsw.WriteImport(impName, tsImportPath+"/index.js")
|
|
517
619
|
}
|
|
620
|
+
|
|
621
|
+
func (c *GoToTSCompiler) writeClonedFieldInitializer(fieldName string, fieldType types.Type, isEmbedded bool) {
|
|
622
|
+
c.tsw.WriteLiterally(fieldName)
|
|
623
|
+
c.tsw.WriteLiterally(": $.varRef(")
|
|
624
|
+
|
|
625
|
+
if isEmbedded {
|
|
626
|
+
isPointerToStruct := false
|
|
627
|
+
trueType := fieldType
|
|
628
|
+
if ptr, isPtr := trueType.(*types.Pointer); isPtr {
|
|
629
|
+
trueType = ptr.Elem()
|
|
630
|
+
isPointerToStruct = true
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if named, isNamed := trueType.(*types.Named); isNamed {
|
|
634
|
+
_, isUnderlyingStruct := named.Underlying().(*types.Struct)
|
|
635
|
+
if isUnderlyingStruct && !isPointerToStruct { // Is a value struct
|
|
636
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value.clone()", fieldName)
|
|
637
|
+
} else { // Is a pointer to a struct, or not a struct
|
|
638
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
|
|
639
|
+
}
|
|
640
|
+
} else {
|
|
641
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
|
|
642
|
+
}
|
|
643
|
+
} else {
|
|
644
|
+
isValueTypeStruct := false
|
|
645
|
+
if named, ok := fieldType.(*types.Named); ok {
|
|
646
|
+
if _, isStruct := named.Underlying().(*types.Struct); isStruct {
|
|
647
|
+
isValueTypeStruct = true
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
if isValueTypeStruct {
|
|
652
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value?.clone() ?? null", fieldName)
|
|
653
|
+
} else {
|
|
654
|
+
c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
c.tsw.WriteLiterally(")")
|
|
659
|
+
}
|