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
|
@@ -80,9 +80,8 @@ func (c *GoToTSCompiler) writeArrayTypeConversion(exp *ast.CallExpr) (handled bo
|
|
|
80
80
|
if argType := c.pkg.TypesInfo.TypeOf(arg); argType != nil {
|
|
81
81
|
// Check if the argument is a named type with a slice underlying type
|
|
82
82
|
if namedArgType, isNamed := argType.(*types.Named); isNamed {
|
|
83
|
-
// Check if the named type has receiver methods (is a wrapper
|
|
84
|
-
|
|
85
|
-
if c.hasReceiverMethods(typeName) {
|
|
83
|
+
// Check if the named type has receiver methods (is a wrapper type)
|
|
84
|
+
if c.analysis.IsWrapperType(namedArgType) {
|
|
86
85
|
// Check if the underlying type matches the target slice type
|
|
87
86
|
if sliceUnderlying, isSlice := namedArgType.Underlying().(*types.Slice); isSlice {
|
|
88
87
|
// Get the target slice type
|
|
@@ -90,12 +89,11 @@ func (c *GoToTSCompiler) writeArrayTypeConversion(exp *ast.CallExpr) (handled bo
|
|
|
90
89
|
if targetSliceType, isTargetSlice := targetType.Underlying().(*types.Slice); isTargetSlice {
|
|
91
90
|
// Check if element types are compatible
|
|
92
91
|
if types.Identical(sliceUnderlying.Elem(), targetSliceType.Elem()) {
|
|
93
|
-
// This is a conversion from
|
|
94
|
-
//
|
|
92
|
+
// This is a conversion from wrapper slice type to []T
|
|
93
|
+
// Since wrapper types are now type aliases, just write the value directly
|
|
95
94
|
if err := c.WriteValueExpr(arg); err != nil {
|
|
96
95
|
return true, fmt.Errorf("failed to write argument for slice type conversion: %w", err)
|
|
97
96
|
}
|
|
98
|
-
c.tsw.WriteLiterally(".valueOf()")
|
|
99
97
|
return true, nil
|
|
100
98
|
}
|
|
101
99
|
}
|
|
@@ -217,19 +215,17 @@ func (c *GoToTSCompiler) writeTypeConversion(exp *ast.CallExpr, funIdent *ast.Id
|
|
|
217
215
|
// Check if we're converting FROM a type with receiver methods TO its underlying type
|
|
218
216
|
if argType := c.pkg.TypesInfo.TypeOf(arg); argType != nil {
|
|
219
217
|
if namedArgType, isNamed := argType.(*types.Named); isNamed {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if c.hasReceiverMethods(argTypeName) {
|
|
218
|
+
// Check if the argument type is a wrapper type
|
|
219
|
+
if c.analysis.IsWrapperType(namedArgType) {
|
|
223
220
|
// Check if we're converting to the underlying type
|
|
224
221
|
targetType := typeName.Type()
|
|
225
222
|
underlyingType := namedArgType.Underlying()
|
|
226
223
|
if types.Identical(targetType, underlyingType) {
|
|
227
|
-
// This is a conversion from a type
|
|
228
|
-
//
|
|
224
|
+
// This is a conversion from a wrapper type to its underlying type
|
|
225
|
+
// Since wrapper types are now type aliases, just write the value directly
|
|
229
226
|
if err := c.WriteValueExpr(arg); err != nil {
|
|
230
|
-
return true, fmt.Errorf("failed to write argument for
|
|
227
|
+
return true, fmt.Errorf("failed to write argument for type conversion: %w", err)
|
|
231
228
|
}
|
|
232
|
-
c.tsw.WriteLiterally(".valueOf()")
|
|
233
229
|
return true, nil
|
|
234
230
|
}
|
|
235
231
|
}
|
|
@@ -250,29 +246,115 @@ func (c *GoToTSCompiler) writeTypeConversion(exp *ast.CallExpr, funIdent *ast.Id
|
|
|
250
246
|
c.tsw.WriteLiterallyf(", { __goTypeName: '%s' })", funIdent.String())
|
|
251
247
|
return true, nil
|
|
252
248
|
} else {
|
|
249
|
+
// Check if this is a wrapper type
|
|
250
|
+
isWrapperType := c.analysis.IsWrapperType(typeName.Type())
|
|
251
|
+
if isWrapperType {
|
|
252
|
+
// For wrapper types, use type casting instead of constructor calls
|
|
253
|
+
c.tsw.WriteLiterally("(")
|
|
254
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
255
|
+
return true, fmt.Errorf("failed to write argument for wrapper type cast: %w", err)
|
|
256
|
+
}
|
|
257
|
+
c.tsw.WriteLiterally(" as ")
|
|
258
|
+
c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
|
|
259
|
+
c.tsw.WriteLiterally(")")
|
|
260
|
+
return true, nil
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Check if this is a simple named type (no methods, not struct, not interface)
|
|
264
|
+
if namedType, ok := typeName.Type().(*types.Named); ok {
|
|
265
|
+
// Don't use constructors for simple named types without methods
|
|
266
|
+
if namedType.NumMethods() == 0 {
|
|
267
|
+
// Exclude struct and interface types - they should still use constructors
|
|
268
|
+
if _, isStruct := namedType.Underlying().(*types.Struct); !isStruct {
|
|
269
|
+
if _, isInterface := namedType.Underlying().(*types.Interface); !isInterface {
|
|
270
|
+
// Simple named type without methods - use type casting
|
|
271
|
+
c.tsw.WriteLiterally("(")
|
|
272
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
273
|
+
return true, fmt.Errorf("failed to write argument for simple named type cast: %w", err)
|
|
274
|
+
}
|
|
275
|
+
c.tsw.WriteLiterally(" as ")
|
|
276
|
+
c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
|
|
277
|
+
c.tsw.WriteLiterally(")")
|
|
278
|
+
return true, nil
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
253
284
|
// Check if this type has receiver methods
|
|
254
285
|
if c.hasReceiverMethods(funIdent.String()) {
|
|
255
|
-
// For types with methods, use class constructor
|
|
286
|
+
// For types with methods that are NOT wrapper types, still use class constructor
|
|
256
287
|
c.tsw.WriteLiterally("new ")
|
|
257
288
|
c.tsw.WriteLiterally(funIdent.String())
|
|
258
289
|
c.tsw.WriteLiterally("(")
|
|
259
|
-
|
|
290
|
+
|
|
291
|
+
fmt.Printf("DEBUG: Type conversion constructor for %s\n", funIdent.String())
|
|
292
|
+
|
|
293
|
+
// Use auto-wrapping for the constructor argument
|
|
294
|
+
// The constructor parameter type is the underlying type of the named type
|
|
295
|
+
// For MyMode (which is type MyMode os.FileMode), the constructor expects os.FileMode
|
|
296
|
+
constructorParamType := typeName.Type()
|
|
297
|
+
if namedType, ok := typeName.Type().(*types.Named); ok {
|
|
298
|
+
// For named types, the constructor expects the underlying type
|
|
299
|
+
constructorParamType = namedType.Underlying()
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
fmt.Printf("DEBUG: Constructor param type: %v\n", constructorParamType)
|
|
303
|
+
|
|
304
|
+
if err := c.writeAutoWrappedArgument(exp.Args[0], constructorParamType); err != nil {
|
|
260
305
|
return true, fmt.Errorf("failed to write argument for type constructor: %w", err)
|
|
261
306
|
}
|
|
262
307
|
c.tsw.WriteLiterally(")")
|
|
263
308
|
return true, nil
|
|
264
309
|
} else {
|
|
265
|
-
//
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
310
|
+
// Determine if this type should use constructor syntax
|
|
311
|
+
shouldUseConstructor := false
|
|
312
|
+
|
|
313
|
+
// Check if it's a type alias (like os.FileMode)
|
|
314
|
+
if alias, isAlias := typeName.Type().(*types.Alias); isAlias {
|
|
315
|
+
// For type aliases, check the underlying type
|
|
316
|
+
if _, isInterface := alias.Underlying().(*types.Interface); !isInterface {
|
|
317
|
+
if _, isStruct := alias.Underlying().(*types.Struct); !isStruct {
|
|
318
|
+
// For non-struct, non-interface type aliases, use constructor
|
|
319
|
+
shouldUseConstructor = true
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
} else if namedType, isNamed := typeName.Type().(*types.Named); isNamed {
|
|
323
|
+
// For named types, check if they have receiver methods in the current package
|
|
324
|
+
// or if they follow the pattern of non-struct, non-interface named types
|
|
325
|
+
if c.hasReceiverMethods(funIdent.String()) {
|
|
326
|
+
shouldUseConstructor = true
|
|
327
|
+
} else if _, isInterface := namedType.Underlying().(*types.Interface); !isInterface {
|
|
328
|
+
if _, isStruct := namedType.Underlying().(*types.Struct); !isStruct {
|
|
329
|
+
// For non-struct, non-interface named types, use constructor
|
|
330
|
+
shouldUseConstructor = true
|
|
331
|
+
}
|
|
332
|
+
}
|
|
269
333
|
}
|
|
270
334
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
335
|
+
if shouldUseConstructor {
|
|
336
|
+
// For types that should use constructors, use class constructor
|
|
337
|
+
c.tsw.WriteLiterally("new ")
|
|
338
|
+
c.tsw.WriteLiterally(funIdent.String())
|
|
339
|
+
c.tsw.WriteLiterally("(")
|
|
340
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
341
|
+
return true, fmt.Errorf("failed to write argument for type constructor: %w", err)
|
|
342
|
+
}
|
|
343
|
+
c.tsw.WriteLiterally(")")
|
|
344
|
+
return true, nil
|
|
345
|
+
} else {
|
|
346
|
+
// For types that don't need constructors, use the TypeScript "as" operator
|
|
347
|
+
c.tsw.WriteLiterally("(")
|
|
348
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
349
|
+
return true, fmt.Errorf("failed to write argument for type cast: %w", err)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Then use the TypeScript "as" operator with the mapped type name
|
|
353
|
+
c.tsw.WriteLiterally(" as ")
|
|
354
|
+
c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
|
|
355
|
+
c.tsw.WriteLiterally(")")
|
|
356
|
+
return true, nil
|
|
357
|
+
}
|
|
276
358
|
}
|
|
277
359
|
}
|
|
278
360
|
}
|
|
@@ -293,17 +375,15 @@ func (c *GoToTSCompiler) writeIntConversion(exp *ast.CallExpr) error {
|
|
|
293
375
|
// Check if we're converting FROM a type with receiver methods TO int
|
|
294
376
|
if argType := c.pkg.TypesInfo.TypeOf(arg); argType != nil {
|
|
295
377
|
if namedArgType, isNamed := argType.(*types.Named); isNamed {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if c.hasReceiverMethods(argTypeName) {
|
|
378
|
+
// Check if the argument type is a wrapper type
|
|
379
|
+
if c.analysis.IsWrapperType(namedArgType) {
|
|
299
380
|
// Check if we're converting to int (the underlying type)
|
|
300
381
|
if types.Identical(types.Typ[types.Int], namedArgType.Underlying()) {
|
|
301
|
-
// This is a conversion from a type
|
|
302
|
-
//
|
|
382
|
+
// This is a conversion from a wrapper type to int
|
|
383
|
+
// Since wrapper types are now type aliases, just write the value directly
|
|
303
384
|
if err := c.WriteValueExpr(arg); err != nil {
|
|
304
|
-
return fmt.Errorf("failed to write argument for
|
|
385
|
+
return fmt.Errorf("failed to write argument for int conversion: %w", err)
|
|
305
386
|
}
|
|
306
|
-
c.tsw.WriteLiterally(".valueOf()")
|
|
307
387
|
return nil
|
|
308
388
|
}
|
|
309
389
|
}
|
|
@@ -332,19 +412,17 @@ func (c *GoToTSCompiler) writeQualifiedTypeConversion(exp *ast.CallExpr, selecto
|
|
|
332
412
|
// Check if we're converting FROM a type with receiver methods TO its underlying type
|
|
333
413
|
if argType := c.pkg.TypesInfo.TypeOf(arg); argType != nil {
|
|
334
414
|
if namedArgType, isNamed := argType.(*types.Named); isNamed {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
if c.hasReceiverMethods(argTypeName) {
|
|
415
|
+
// Check if the argument type is a wrapper type
|
|
416
|
+
if c.analysis.IsWrapperType(namedArgType) {
|
|
338
417
|
// Check if we're converting to the underlying type
|
|
339
418
|
targetType := typeName.Type()
|
|
340
419
|
underlyingType := namedArgType.Underlying()
|
|
341
420
|
if types.Identical(targetType, underlyingType) {
|
|
342
|
-
// This is a conversion from a type
|
|
343
|
-
//
|
|
421
|
+
// This is a conversion from a wrapper type to its underlying type
|
|
422
|
+
// Since wrapper types are now type aliases, just write the value directly
|
|
344
423
|
if err := c.WriteValueExpr(arg); err != nil {
|
|
345
|
-
return true, fmt.Errorf("failed to write argument for
|
|
424
|
+
return true, fmt.Errorf("failed to write argument for type conversion: %w", err)
|
|
346
425
|
}
|
|
347
|
-
c.tsw.WriteLiterally(".valueOf()")
|
|
348
426
|
return true, nil
|
|
349
427
|
}
|
|
350
428
|
}
|
|
@@ -365,33 +443,44 @@ func (c *GoToTSCompiler) writeQualifiedTypeConversion(exp *ast.CallExpr, selecto
|
|
|
365
443
|
c.tsw.WriteLiterallyf(", { __goTypeName: '%s' })", selectorExpr.Sel.Name)
|
|
366
444
|
return true, nil
|
|
367
445
|
} else {
|
|
368
|
-
//
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if _, isStruct := alias.Underlying().(*types.Struct); !isStruct {
|
|
376
|
-
// For non-struct, non-interface type aliases, use constructor
|
|
377
|
-
shouldUseConstructor = true
|
|
378
|
-
}
|
|
446
|
+
// Check if this is a wrapper type
|
|
447
|
+
isWrapperType := c.analysis.IsWrapperType(typeName.Type())
|
|
448
|
+
if isWrapperType {
|
|
449
|
+
// For wrapper types, use type casting instead of constructor calls
|
|
450
|
+
c.tsw.WriteLiterally("(")
|
|
451
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
452
|
+
return true, fmt.Errorf("failed to write argument for wrapper type cast: %w", err)
|
|
379
453
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
454
|
+
c.tsw.WriteLiterally(" as ")
|
|
455
|
+
c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
|
|
456
|
+
c.tsw.WriteLiterally(")")
|
|
457
|
+
return true, nil
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Check if this is a simple named type (no methods, not struct, not interface)
|
|
461
|
+
if namedType, ok := typeName.Type().(*types.Named); ok {
|
|
462
|
+
// Don't use constructors for simple named types without methods
|
|
463
|
+
if namedType.NumMethods() == 0 {
|
|
464
|
+
// Exclude struct and interface types - they should still use constructors
|
|
386
465
|
if _, isStruct := namedType.Underlying().(*types.Struct); !isStruct {
|
|
387
|
-
|
|
388
|
-
|
|
466
|
+
if _, isInterface := namedType.Underlying().(*types.Interface); !isInterface {
|
|
467
|
+
// Simple named type without methods - use type casting
|
|
468
|
+
c.tsw.WriteLiterally("(")
|
|
469
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
470
|
+
return true, fmt.Errorf("failed to write argument for simple named type cast: %w", err)
|
|
471
|
+
}
|
|
472
|
+
c.tsw.WriteLiterally(" as ")
|
|
473
|
+
c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
|
|
474
|
+
c.tsw.WriteLiterally(")")
|
|
475
|
+
return true, nil
|
|
476
|
+
}
|
|
389
477
|
}
|
|
390
478
|
}
|
|
391
479
|
}
|
|
392
480
|
|
|
393
|
-
if
|
|
394
|
-
|
|
481
|
+
// Check if this type has receiver methods
|
|
482
|
+
if c.hasReceiverMethods(selectorExpr.Sel.Name) {
|
|
483
|
+
// For types with methods that are NOT wrapper types, still use class constructor
|
|
395
484
|
c.tsw.WriteLiterally("new ")
|
|
396
485
|
if err := c.WriteSelectorExpr(selectorExpr); err != nil {
|
|
397
486
|
return true, fmt.Errorf("failed to write qualified type name: %w", err)
|
package/compiler/expr-call.go
CHANGED
|
@@ -5,6 +5,7 @@ import (
|
|
|
5
5
|
"go/ast"
|
|
6
6
|
"go/token"
|
|
7
7
|
"go/types"
|
|
8
|
+
"strings"
|
|
8
9
|
)
|
|
9
10
|
|
|
10
11
|
// WriteCallExpr translates a Go function call expression (`ast.CallExpr`)
|
|
@@ -89,6 +90,11 @@ func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error {
|
|
|
89
90
|
if handled, err := c.writeQualifiedTypeConversion(exp, selectorExpr); handled {
|
|
90
91
|
return err
|
|
91
92
|
}
|
|
93
|
+
|
|
94
|
+
// Handle wrapper type method calls: obj.Method() -> TypeName_Method(obj, ...)
|
|
95
|
+
if handled, err := c.writeWrapperTypeMethodCall(exp, selectorExpr); handled {
|
|
96
|
+
return err
|
|
97
|
+
}
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
// Handle non-identifier function expressions (method calls, function literals, etc.)
|
|
@@ -123,27 +129,213 @@ func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error {
|
|
|
123
129
|
// writeCallArguments writes the argument list for a function call
|
|
124
130
|
func (c *GoToTSCompiler) writeCallArguments(exp *ast.CallExpr) error {
|
|
125
131
|
c.tsw.WriteLiterally("(")
|
|
132
|
+
|
|
133
|
+
// Get function signature for parameter type checking
|
|
134
|
+
var funcSig *types.Signature
|
|
135
|
+
if c.pkg != nil && c.pkg.TypesInfo != nil {
|
|
136
|
+
if funcType := c.pkg.TypesInfo.TypeOf(exp.Fun); funcType != nil {
|
|
137
|
+
if sig, ok := funcType.(*types.Signature); ok {
|
|
138
|
+
funcSig = sig
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
126
143
|
for i, arg := range exp.Args {
|
|
127
144
|
if i != 0 {
|
|
128
145
|
c.tsw.WriteLiterally(", ")
|
|
129
146
|
}
|
|
130
147
|
// Check if this is the last argument and we have ellipsis (variadic call)
|
|
131
148
|
if exp.Ellipsis != token.NoPos && i == len(exp.Args)-1 {
|
|
132
|
-
c.tsw.WriteLiterally("...")
|
|
149
|
+
c.tsw.WriteLiterally("...(")
|
|
150
|
+
// Write the argument
|
|
151
|
+
if err := c.writeArgumentWithTypeHandling(arg, funcSig, i); err != nil {
|
|
152
|
+
return err
|
|
153
|
+
}
|
|
154
|
+
// Add null coalescing for slice spread to prevent TypeScript errors
|
|
155
|
+
c.tsw.WriteLiterally(" ?? [])")
|
|
156
|
+
continue
|
|
133
157
|
}
|
|
134
|
-
|
|
135
|
-
|
|
158
|
+
|
|
159
|
+
if err := c.writeArgumentWithTypeHandling(arg, funcSig, i); err != nil {
|
|
160
|
+
return err
|
|
136
161
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
c.tsw.WriteLiterally(")")
|
|
165
|
+
return nil
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// writeArgumentWithTypeHandling writes a single argument with proper type handling
|
|
169
|
+
func (c *GoToTSCompiler) writeArgumentWithTypeHandling(arg ast.Expr, funcSig *types.Signature, argIndex int) error {
|
|
170
|
+
if funcSig != nil && argIndex < funcSig.Params().Len() {
|
|
171
|
+
paramType := funcSig.Params().At(argIndex).Type()
|
|
172
|
+
isWrapper := c.analysis.IsWrapperType(paramType)
|
|
173
|
+
|
|
174
|
+
if isWrapper {
|
|
175
|
+
// For wrapper types (now type aliases), no auto-wrapping is needed
|
|
176
|
+
// Just use type casting if the types don't match exactly
|
|
177
|
+
argType := c.pkg.TypesInfo.TypeOf(arg)
|
|
178
|
+
|
|
179
|
+
// Only add type casting if needed
|
|
180
|
+
if argType != nil && !types.Identical(argType, paramType) {
|
|
181
|
+
c.tsw.WriteLiterally("(")
|
|
182
|
+
if err := c.WriteValueExpr(arg); err != nil {
|
|
183
|
+
return fmt.Errorf("failed to write argument for type cast: %w", err)
|
|
184
|
+
}
|
|
185
|
+
c.tsw.WriteLiterally(" as ")
|
|
186
|
+
c.WriteGoType(paramType, GoTypeContextGeneral)
|
|
187
|
+
c.tsw.WriteLiterally(")")
|
|
188
|
+
} else {
|
|
189
|
+
// Types match, just write the argument directly
|
|
190
|
+
if err := c.WriteValueExpr(arg); err != nil {
|
|
191
|
+
return fmt.Errorf("failed to write argument: %w", err)
|
|
143
192
|
}
|
|
144
193
|
}
|
|
194
|
+
return nil
|
|
145
195
|
}
|
|
146
196
|
}
|
|
147
|
-
|
|
197
|
+
|
|
198
|
+
// For non-wrapper types, normal argument writing
|
|
199
|
+
if err := c.WriteValueExpr(arg); err != nil {
|
|
200
|
+
return fmt.Errorf("failed to write argument: %w", err)
|
|
201
|
+
}
|
|
148
202
|
return nil
|
|
149
203
|
}
|
|
204
|
+
|
|
205
|
+
// getImportAlias returns the import alias for a given package path
|
|
206
|
+
func (c *GoToTSCompiler) getImportAlias(pkgPath string) string {
|
|
207
|
+
if c.analysis == nil {
|
|
208
|
+
return ""
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// First try to find by exact package path
|
|
212
|
+
for importAlias := range c.analysis.Imports {
|
|
213
|
+
if importInfo := c.analysis.Imports[importAlias]; importInfo != nil {
|
|
214
|
+
if importInfo.importPath == pkgPath {
|
|
215
|
+
return importAlias
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Fallback: try to match by package name extracted from path
|
|
221
|
+
parts := strings.Split(pkgPath, "/")
|
|
222
|
+
defaultPkgName := parts[len(parts)-1]
|
|
223
|
+
|
|
224
|
+
for importAlias := range c.analysis.Imports {
|
|
225
|
+
if importAlias == defaultPkgName {
|
|
226
|
+
return importAlias
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return ""
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// writeAutoWrappedArgument writes an argument, auto-wrapping it if needed based on the expected parameter type
|
|
234
|
+
func (c *GoToTSCompiler) writeAutoWrappedArgument(arg ast.Expr, expectedType types.Type) error {
|
|
235
|
+
// For wrapper types (now type aliases), no auto-wrapping is needed
|
|
236
|
+
// Just use type casting if the types don't match exactly
|
|
237
|
+
if c.analysis.IsWrapperType(expectedType) {
|
|
238
|
+
argType := c.pkg.TypesInfo.TypeOf(arg)
|
|
239
|
+
|
|
240
|
+
// Only add type casting if needed
|
|
241
|
+
if argType != nil && !types.Identical(argType, expectedType) {
|
|
242
|
+
c.tsw.WriteLiterally("(")
|
|
243
|
+
if err := c.WriteValueExpr(arg); err != nil {
|
|
244
|
+
return fmt.Errorf("failed to write argument for wrapper type cast: %w", err)
|
|
245
|
+
}
|
|
246
|
+
c.tsw.WriteLiterally(" as ")
|
|
247
|
+
c.WriteGoType(expectedType, GoTypeContextGeneral)
|
|
248
|
+
c.tsw.WriteLiterally(")")
|
|
249
|
+
} else {
|
|
250
|
+
// Types match, just write the argument directly
|
|
251
|
+
if err := c.WriteValueExpr(arg); err != nil {
|
|
252
|
+
return fmt.Errorf("failed to write argument: %w", err)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return nil
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// For non-wrapper types, normal argument writing
|
|
259
|
+
if err := c.WriteValueExpr(arg); err != nil {
|
|
260
|
+
return fmt.Errorf("failed to write argument: %w", err)
|
|
261
|
+
}
|
|
262
|
+
return nil
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// writeWrapperTypeMethodCall handles method calls on wrapper types by converting them to function calls
|
|
266
|
+
// obj.Method(args) -> TypeName_Method(obj, args)
|
|
267
|
+
func (c *GoToTSCompiler) writeWrapperTypeMethodCall(exp *ast.CallExpr, selectorExpr *ast.SelectorExpr) (handled bool, err error) {
|
|
268
|
+
// Get the type of the base expression (the receiver)
|
|
269
|
+
baseType := c.pkg.TypesInfo.TypeOf(selectorExpr.X)
|
|
270
|
+
if baseType == nil {
|
|
271
|
+
return false, nil
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Check if this is a wrapper type
|
|
275
|
+
if !c.analysis.IsWrapperType(baseType) {
|
|
276
|
+
return false, nil
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Get the type name for the function call
|
|
280
|
+
var typeName string
|
|
281
|
+
if namedType, ok := baseType.(*types.Named); ok {
|
|
282
|
+
if obj := namedType.Obj(); obj != nil {
|
|
283
|
+
if obj.Pkg() != nil && obj.Pkg() != c.pkg.Types {
|
|
284
|
+
// Imported type like os.FileMode
|
|
285
|
+
if importAlias := c.getImportAlias(obj.Pkg().Path()); importAlias != "" {
|
|
286
|
+
typeName = importAlias + "." + obj.Name()
|
|
287
|
+
} else {
|
|
288
|
+
typeName = obj.Name()
|
|
289
|
+
}
|
|
290
|
+
} else {
|
|
291
|
+
// Local type
|
|
292
|
+
typeName = obj.Name()
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
} else if aliasType, ok := baseType.(*types.Alias); ok {
|
|
296
|
+
if obj := aliasType.Obj(); obj != nil {
|
|
297
|
+
if obj.Pkg() != nil && obj.Pkg() != c.pkg.Types {
|
|
298
|
+
// Imported type alias
|
|
299
|
+
if importAlias := c.getImportAlias(obj.Pkg().Path()); importAlias != "" {
|
|
300
|
+
typeName = importAlias + "." + obj.Name()
|
|
301
|
+
} else {
|
|
302
|
+
typeName = obj.Name()
|
|
303
|
+
}
|
|
304
|
+
} else {
|
|
305
|
+
// Local type alias
|
|
306
|
+
typeName = obj.Name()
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if typeName == "" {
|
|
312
|
+
return false, nil
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Write the function call: TypeName_MethodName(receiver, args...)
|
|
316
|
+
c.tsw.WriteLiterally(typeName)
|
|
317
|
+
c.tsw.WriteLiterally("_")
|
|
318
|
+
c.tsw.WriteLiterally(selectorExpr.Sel.Name)
|
|
319
|
+
c.tsw.WriteLiterally("(")
|
|
320
|
+
|
|
321
|
+
// First argument is the receiver
|
|
322
|
+
if err := c.WriteValueExpr(selectorExpr.X); err != nil {
|
|
323
|
+
return true, fmt.Errorf("failed to write wrapper type method receiver: %w", err)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Add other arguments
|
|
327
|
+
if len(exp.Args) > 0 {
|
|
328
|
+
c.tsw.WriteLiterally(", ")
|
|
329
|
+
for i, arg := range exp.Args {
|
|
330
|
+
if i != 0 {
|
|
331
|
+
c.tsw.WriteLiterally(", ")
|
|
332
|
+
}
|
|
333
|
+
if err := c.WriteValueExpr(arg); err != nil {
|
|
334
|
+
return true, fmt.Errorf("failed to write wrapper type method argument %d: %w", i, err)
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
c.tsw.WriteLiterally(")")
|
|
340
|
+
return true, nil
|
|
341
|
+
}
|
package/compiler/expr.go
CHANGED
|
@@ -294,70 +294,6 @@ func (c *GoToTSCompiler) isNamedNumericType(t types.Type) bool {
|
|
|
294
294
|
return false
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
-
// isWrapperType checks if a type is implemented as a wrapper class with valueOf() method
|
|
298
|
-
// This is true for named types that have methods defined on them
|
|
299
|
-
func (c *GoToTSCompiler) isWrapperType(t types.Type) bool {
|
|
300
|
-
if t == nil {
|
|
301
|
-
return false
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Follow any type aliases to get to the actual named type
|
|
305
|
-
namedType, ok := t.(*types.Named)
|
|
306
|
-
if !ok {
|
|
307
|
-
return false
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// If the named type has methods, it's implemented as a class with valueOf()
|
|
311
|
-
numMethods := namedType.NumMethods()
|
|
312
|
-
return numMethods > 0
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// needsValueOfForBitwiseOp checks if an operand in a bitwise operation needs .valueOf() to be called
|
|
316
|
-
// This is needed for custom types (like FileMode) that have a valueOf() method and need to be treated as numbers
|
|
317
|
-
func (c *GoToTSCompiler) needsValueOfForBitwiseOp(expr ast.Expr) bool {
|
|
318
|
-
if c.pkg == nil || c.pkg.TypesInfo == nil {
|
|
319
|
-
return false
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
exprType := c.pkg.TypesInfo.TypeOf(expr)
|
|
323
|
-
if exprType == nil {
|
|
324
|
-
return false
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// Don't add valueOf() for basic literals (numeric, string, bool literals)
|
|
328
|
-
switch expr.(type) {
|
|
329
|
-
case *ast.BasicLit:
|
|
330
|
-
return false
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Check if this is a compile-time constant of a primitive type
|
|
334
|
-
if tv, ok := c.pkg.TypesInfo.Types[expr]; ok {
|
|
335
|
-
if tv.Value != nil {
|
|
336
|
-
// This is a constant expression - but only skip valueOf() if it's truly a primitive type
|
|
337
|
-
// (not a named type with methods that happens to be constant)
|
|
338
|
-
if _, isBasic := exprType.(*types.Basic); isBasic {
|
|
339
|
-
// Primitive constant, don't add valueOf()
|
|
340
|
-
return false
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Check if this type is implemented as a wrapper class with valueOf()
|
|
346
|
-
return c.isWrapperType(exprType)
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// writeBitwiseOperand writes an operand for a bitwise operation, adding .valueOf() if needed
|
|
350
|
-
func (c *GoToTSCompiler) writeBitwiseOperand(expr ast.Expr) error {
|
|
351
|
-
if c.needsValueOfForBitwiseOp(expr) {
|
|
352
|
-
if err := c.WriteValueExpr(expr); err != nil {
|
|
353
|
-
return err
|
|
354
|
-
}
|
|
355
|
-
c.tsw.WriteLiterally(".valueOf()")
|
|
356
|
-
return nil
|
|
357
|
-
}
|
|
358
|
-
return c.WriteValueExpr(expr)
|
|
359
|
-
}
|
|
360
|
-
|
|
361
297
|
// WriteBinaryExpr translates a Go binary expression (`ast.BinaryExpr`) into its
|
|
362
298
|
// TypeScript equivalent.
|
|
363
299
|
// It handles several cases:
|
|
@@ -542,16 +478,10 @@ func (c *GoToTSCompiler) WriteBinaryExpr(exp *ast.BinaryExpr) error {
|
|
|
542
478
|
c.tsw.WriteLiterally("(") // Add opening parenthesis for bitwise operations
|
|
543
479
|
}
|
|
544
480
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
if err := c.writeBitwiseOperand(exp.X); err != nil {
|
|
548
|
-
return fmt.Errorf("failed to write binary expression left operand: %w", err)
|
|
549
|
-
}
|
|
550
|
-
} else {
|
|
551
|
-
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
552
|
-
return fmt.Errorf("failed to write binary expression left operand: %w", err)
|
|
553
|
-
}
|
|
481
|
+
if err := c.WriteValueExpr(exp.X); err != nil {
|
|
482
|
+
return fmt.Errorf("failed to write binary expression left operand: %w", err)
|
|
554
483
|
}
|
|
484
|
+
|
|
555
485
|
c.tsw.WriteLiterally(" ")
|
|
556
486
|
tokStr, ok := TokenToTs(exp.Op)
|
|
557
487
|
if !ok {
|
|
@@ -561,15 +491,8 @@ func (c *GoToTSCompiler) WriteBinaryExpr(exp *ast.BinaryExpr) error {
|
|
|
561
491
|
c.tsw.WriteLiterally(tokStr)
|
|
562
492
|
c.tsw.WriteLiterally(" ")
|
|
563
493
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
if err := c.writeBitwiseOperand(exp.Y); err != nil {
|
|
567
|
-
return fmt.Errorf("failed to write binary expression right operand: %w", err)
|
|
568
|
-
}
|
|
569
|
-
} else {
|
|
570
|
-
if err := c.WriteValueExpr(exp.Y); err != nil {
|
|
571
|
-
return fmt.Errorf("failed to write binary expression right operand: %w", err)
|
|
572
|
-
}
|
|
494
|
+
if err := c.WriteValueExpr(exp.Y); err != nil {
|
|
495
|
+
return fmt.Errorf("failed to write binary expression right operand: %w", err)
|
|
573
496
|
}
|
|
574
497
|
|
|
575
498
|
if isBitwise {
|