goscript 0.0.48 → 0.0.50
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 +1120 -513
- package/compiler/analysis_test.go +113 -4
- package/compiler/compiler.go +88 -124
- package/compiler/decl.go +22 -0
- package/compiler/expr-call-async.go +46 -52
- package/compiler/expr-call-type-conversion.go +144 -59
- package/compiler/expr-call.go +235 -12
- 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 +337 -151
- package/compiler/stmt-assign.go +7 -4
- package/compiler/stmt.go +250 -81
- package/compiler/type.go +13 -0
- 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/context/context.d.ts +16 -18
- package/dist/gs/context/context.js +23 -13
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/fmt/fmt.js +22 -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 +98 -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 +13 -23
- package/dist/gs/time/time.js +57 -75
- package/dist/gs/time/time.js.map +1 -1
- package/gs/builtin/builtin.ts +3 -47
- package/gs/builtin/slice.ts +1 -1
- package/gs/bytes/meta.json +10 -0
- package/gs/context/context.ts +63 -45
- package/gs/fmt/fmt.ts +22 -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 +105 -105
- 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 +65 -84
- package/package.json +2 -2
- 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.IsNamedBasicType(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.IsNamedBasicType(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,111 @@ 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.IsNamedBasicType(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
|
+
// Use auto-wrapping for the constructor argument
|
|
292
|
+
// The constructor parameter type is the underlying type of the named type
|
|
293
|
+
// For MyMode (which is type MyMode os.FileMode), the constructor expects os.FileMode
|
|
294
|
+
constructorParamType := typeName.Type()
|
|
295
|
+
if namedType, ok := typeName.Type().(*types.Named); ok {
|
|
296
|
+
// For named types, the constructor expects the underlying type
|
|
297
|
+
constructorParamType = namedType.Underlying()
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if err := c.writeAutoWrappedArgument(exp.Args[0], constructorParamType); err != nil {
|
|
260
301
|
return true, fmt.Errorf("failed to write argument for type constructor: %w", err)
|
|
261
302
|
}
|
|
262
303
|
c.tsw.WriteLiterally(")")
|
|
263
304
|
return true, nil
|
|
264
305
|
} else {
|
|
265
|
-
//
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
306
|
+
// Determine if this type should use constructor syntax
|
|
307
|
+
shouldUseConstructor := false
|
|
308
|
+
|
|
309
|
+
// Check if it's a type alias (like os.FileMode)
|
|
310
|
+
if alias, isAlias := typeName.Type().(*types.Alias); isAlias {
|
|
311
|
+
// For type aliases, check the underlying type
|
|
312
|
+
if _, isInterface := alias.Underlying().(*types.Interface); !isInterface {
|
|
313
|
+
if _, isStruct := alias.Underlying().(*types.Struct); !isStruct {
|
|
314
|
+
// For non-struct, non-interface type aliases, use constructor
|
|
315
|
+
shouldUseConstructor = true
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
} else if namedType, isNamed := typeName.Type().(*types.Named); isNamed {
|
|
319
|
+
// For named types, check if they have receiver methods in the current package
|
|
320
|
+
// or if they follow the pattern of non-struct, non-interface named types
|
|
321
|
+
if c.hasReceiverMethods(funIdent.String()) {
|
|
322
|
+
shouldUseConstructor = true
|
|
323
|
+
} else if _, isInterface := namedType.Underlying().(*types.Interface); !isInterface {
|
|
324
|
+
if _, isStruct := namedType.Underlying().(*types.Struct); !isStruct {
|
|
325
|
+
// For non-struct, non-interface named types, use constructor
|
|
326
|
+
shouldUseConstructor = true
|
|
327
|
+
}
|
|
328
|
+
}
|
|
269
329
|
}
|
|
270
330
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
331
|
+
if shouldUseConstructor {
|
|
332
|
+
// For types that should use constructors, use class constructor
|
|
333
|
+
c.tsw.WriteLiterally("new ")
|
|
334
|
+
c.tsw.WriteLiterally(funIdent.String())
|
|
335
|
+
c.tsw.WriteLiterally("(")
|
|
336
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
337
|
+
return true, fmt.Errorf("failed to write argument for type constructor: %w", err)
|
|
338
|
+
}
|
|
339
|
+
c.tsw.WriteLiterally(")")
|
|
340
|
+
return true, nil
|
|
341
|
+
} else {
|
|
342
|
+
// For types that don't need constructors, use the TypeScript "as" operator
|
|
343
|
+
c.tsw.WriteLiterally("(")
|
|
344
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
345
|
+
return true, fmt.Errorf("failed to write argument for type cast: %w", err)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Then use the TypeScript "as" operator with the mapped type name
|
|
349
|
+
c.tsw.WriteLiterally(" as ")
|
|
350
|
+
c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
|
|
351
|
+
c.tsw.WriteLiterally(")")
|
|
352
|
+
return true, nil
|
|
353
|
+
}
|
|
276
354
|
}
|
|
277
355
|
}
|
|
278
356
|
}
|
|
@@ -293,17 +371,15 @@ func (c *GoToTSCompiler) writeIntConversion(exp *ast.CallExpr) error {
|
|
|
293
371
|
// Check if we're converting FROM a type with receiver methods TO int
|
|
294
372
|
if argType := c.pkg.TypesInfo.TypeOf(arg); argType != nil {
|
|
295
373
|
if namedArgType, isNamed := argType.(*types.Named); isNamed {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if c.hasReceiverMethods(argTypeName) {
|
|
374
|
+
// Check if the argument type is a wrapper type
|
|
375
|
+
if c.analysis.IsNamedBasicType(namedArgType) {
|
|
299
376
|
// Check if we're converting to int (the underlying type)
|
|
300
377
|
if types.Identical(types.Typ[types.Int], namedArgType.Underlying()) {
|
|
301
|
-
// This is a conversion from a type
|
|
302
|
-
//
|
|
378
|
+
// This is a conversion from a wrapper type to int
|
|
379
|
+
// Since wrapper types are now type aliases, just write the value directly
|
|
303
380
|
if err := c.WriteValueExpr(arg); err != nil {
|
|
304
|
-
return fmt.Errorf("failed to write argument for
|
|
381
|
+
return fmt.Errorf("failed to write argument for int conversion: %w", err)
|
|
305
382
|
}
|
|
306
|
-
c.tsw.WriteLiterally(".valueOf()")
|
|
307
383
|
return nil
|
|
308
384
|
}
|
|
309
385
|
}
|
|
@@ -332,19 +408,17 @@ func (c *GoToTSCompiler) writeQualifiedTypeConversion(exp *ast.CallExpr, selecto
|
|
|
332
408
|
// Check if we're converting FROM a type with receiver methods TO its underlying type
|
|
333
409
|
if argType := c.pkg.TypesInfo.TypeOf(arg); argType != nil {
|
|
334
410
|
if namedArgType, isNamed := argType.(*types.Named); isNamed {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
if c.hasReceiverMethods(argTypeName) {
|
|
411
|
+
// Check if the argument type is a wrapper type
|
|
412
|
+
if c.analysis.IsNamedBasicType(namedArgType) {
|
|
338
413
|
// Check if we're converting to the underlying type
|
|
339
414
|
targetType := typeName.Type()
|
|
340
415
|
underlyingType := namedArgType.Underlying()
|
|
341
416
|
if types.Identical(targetType, underlyingType) {
|
|
342
|
-
// This is a conversion from a type
|
|
343
|
-
//
|
|
417
|
+
// This is a conversion from a wrapper type to its underlying type
|
|
418
|
+
// Since wrapper types are now type aliases, just write the value directly
|
|
344
419
|
if err := c.WriteValueExpr(arg); err != nil {
|
|
345
|
-
return true, fmt.Errorf("failed to write argument for
|
|
420
|
+
return true, fmt.Errorf("failed to write argument for type conversion: %w", err)
|
|
346
421
|
}
|
|
347
|
-
c.tsw.WriteLiterally(".valueOf()")
|
|
348
422
|
return true, nil
|
|
349
423
|
}
|
|
350
424
|
}
|
|
@@ -365,33 +439,44 @@ func (c *GoToTSCompiler) writeQualifiedTypeConversion(exp *ast.CallExpr, selecto
|
|
|
365
439
|
c.tsw.WriteLiterallyf(", { __goTypeName: '%s' })", selectorExpr.Sel.Name)
|
|
366
440
|
return true, nil
|
|
367
441
|
} 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
|
-
}
|
|
442
|
+
// Check if this is a wrapper type
|
|
443
|
+
isWrapperType := c.analysis.IsNamedBasicType(typeName.Type())
|
|
444
|
+
if isWrapperType {
|
|
445
|
+
// For wrapper types, use type casting instead of constructor calls
|
|
446
|
+
c.tsw.WriteLiterally("(")
|
|
447
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
448
|
+
return true, fmt.Errorf("failed to write argument for wrapper type cast: %w", err)
|
|
379
449
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
450
|
+
c.tsw.WriteLiterally(" as ")
|
|
451
|
+
c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
|
|
452
|
+
c.tsw.WriteLiterally(")")
|
|
453
|
+
return true, nil
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Check if this is a simple named type (no methods, not struct, not interface)
|
|
457
|
+
if namedType, ok := typeName.Type().(*types.Named); ok {
|
|
458
|
+
// Don't use constructors for simple named types without methods
|
|
459
|
+
if namedType.NumMethods() == 0 {
|
|
460
|
+
// Exclude struct and interface types - they should still use constructors
|
|
386
461
|
if _, isStruct := namedType.Underlying().(*types.Struct); !isStruct {
|
|
387
|
-
|
|
388
|
-
|
|
462
|
+
if _, isInterface := namedType.Underlying().(*types.Interface); !isInterface {
|
|
463
|
+
// Simple named type without methods - use type casting
|
|
464
|
+
c.tsw.WriteLiterally("(")
|
|
465
|
+
if err := c.WriteValueExpr(exp.Args[0]); err != nil {
|
|
466
|
+
return true, fmt.Errorf("failed to write argument for simple named type cast: %w", err)
|
|
467
|
+
}
|
|
468
|
+
c.tsw.WriteLiterally(" as ")
|
|
469
|
+
c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
|
|
470
|
+
c.tsw.WriteLiterally(")")
|
|
471
|
+
return true, nil
|
|
472
|
+
}
|
|
389
473
|
}
|
|
390
474
|
}
|
|
391
475
|
}
|
|
392
476
|
|
|
393
|
-
if
|
|
394
|
-
|
|
477
|
+
// Check if this type has receiver methods
|
|
478
|
+
if c.hasReceiverMethods(selectorExpr.Sel.Name) {
|
|
479
|
+
// For types with methods that are NOT wrapper types, still use class constructor
|
|
395
480
|
c.tsw.WriteLiterally("new ")
|
|
396
481
|
if err := c.WriteSelectorExpr(selectorExpr); err != nil {
|
|
397
482
|
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`)
|
|
@@ -73,7 +74,7 @@ func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error {
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
// Check if this is an async function call
|
|
76
|
-
|
|
77
|
+
c.writeAsyncCallIfNeeded(exp)
|
|
77
78
|
|
|
78
79
|
// Not a special built-in, treat as a regular function call
|
|
79
80
|
if err := c.WriteValueExpr(expFun); err != nil {
|
|
@@ -89,11 +90,16 @@ 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.)
|
|
95
101
|
// Check if this is an async method call (e.g., mu.Lock())
|
|
96
|
-
|
|
102
|
+
c.writeAsyncCallIfNeeded(exp)
|
|
97
103
|
|
|
98
104
|
// If expFun is a function literal, it needs to be wrapped in parentheses for IIFE syntax
|
|
99
105
|
if _, isFuncLit := expFun.(*ast.FuncLit); isFuncLit {
|
|
@@ -123,27 +129,244 @@ 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.IsNamedBasicType(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
|
+
}
|
|
202
|
+
return nil
|
|
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.IsNamedBasicType(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
|
+
}
|
|
148
262
|
return nil
|
|
149
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 using the analysis
|
|
275
|
+
isWrapperType := c.analysis.IsNamedBasicType(baseType)
|
|
276
|
+
|
|
277
|
+
// Special handling for type aliases to basic types that might have wrapper functions
|
|
278
|
+
// Even if IsNamedBasicType returns false, we should check for known wrapper type patterns
|
|
279
|
+
var typeName string
|
|
280
|
+
if !isWrapperType {
|
|
281
|
+
// Check if this is a type alias to a basic type that might have wrapper methods
|
|
282
|
+
if aliasType, ok := baseType.(*types.Alias); ok {
|
|
283
|
+
if aliasType.Obj() != nil && aliasType.Obj().Pkg() != nil {
|
|
284
|
+
// Check if the underlying type is a basic type
|
|
285
|
+
underlying := aliasType.Underlying()
|
|
286
|
+
if _, isBasic := underlying.(*types.Basic); isBasic {
|
|
287
|
+
// This is a type alias to a basic type - treat it as a potential wrapper type
|
|
288
|
+
isWrapperType = true
|
|
289
|
+
if aliasType.Obj().Pkg() != c.pkg.Types {
|
|
290
|
+
// Imported type alias like os.FileMode
|
|
291
|
+
if importAlias := c.getImportAlias(aliasType.Obj().Pkg().Path()); importAlias != "" {
|
|
292
|
+
typeName = importAlias + "." + aliasType.Obj().Name()
|
|
293
|
+
} else {
|
|
294
|
+
typeName = aliasType.Obj().Name()
|
|
295
|
+
}
|
|
296
|
+
} else {
|
|
297
|
+
// Local type alias
|
|
298
|
+
typeName = aliasType.Obj().Name()
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if !isWrapperType {
|
|
306
|
+
return false, nil
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Get the type name for the function call if not already set
|
|
310
|
+
if typeName == "" {
|
|
311
|
+
if namedType, ok := baseType.(*types.Named); ok {
|
|
312
|
+
if obj := namedType.Obj(); obj != nil {
|
|
313
|
+
if obj.Pkg() != nil && obj.Pkg() != c.pkg.Types {
|
|
314
|
+
// Imported type like os.FileMode
|
|
315
|
+
if importAlias := c.getImportAlias(obj.Pkg().Path()); importAlias != "" {
|
|
316
|
+
typeName = importAlias + "." + obj.Name()
|
|
317
|
+
} else {
|
|
318
|
+
typeName = obj.Name()
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
// Local type
|
|
322
|
+
typeName = obj.Name()
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
} else if aliasType, ok := baseType.(*types.Alias); ok {
|
|
326
|
+
if obj := aliasType.Obj(); obj != nil {
|
|
327
|
+
if obj.Pkg() != nil && obj.Pkg() != c.pkg.Types {
|
|
328
|
+
// Imported type alias
|
|
329
|
+
if importAlias := c.getImportAlias(obj.Pkg().Path()); importAlias != "" {
|
|
330
|
+
typeName = importAlias + "." + obj.Name()
|
|
331
|
+
} else {
|
|
332
|
+
typeName = obj.Name()
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
// Local type alias
|
|
336
|
+
typeName = obj.Name()
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if typeName == "" {
|
|
343
|
+
return false, nil
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Write the function call: TypeName_MethodName(receiver, args...)
|
|
347
|
+
c.tsw.WriteLiterally(typeName)
|
|
348
|
+
c.tsw.WriteLiterally("_")
|
|
349
|
+
c.tsw.WriteLiterally(selectorExpr.Sel.Name)
|
|
350
|
+
c.tsw.WriteLiterally("(")
|
|
351
|
+
|
|
352
|
+
// First argument is the receiver
|
|
353
|
+
if err := c.WriteValueExpr(selectorExpr.X); err != nil {
|
|
354
|
+
return true, fmt.Errorf("failed to write wrapper type method receiver: %w", err)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Add other arguments
|
|
358
|
+
if len(exp.Args) > 0 {
|
|
359
|
+
c.tsw.WriteLiterally(", ")
|
|
360
|
+
for i, arg := range exp.Args {
|
|
361
|
+
if i != 0 {
|
|
362
|
+
c.tsw.WriteLiterally(", ")
|
|
363
|
+
}
|
|
364
|
+
if err := c.WriteValueExpr(arg); err != nil {
|
|
365
|
+
return true, fmt.Errorf("failed to write wrapper type method argument %d: %w", i, err)
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
c.tsw.WriteLiterally(")")
|
|
371
|
+
return true, nil
|
|
372
|
+
}
|