|
6 | 6 | "encoding/json"
|
7 | 7 | "fmt"
|
8 | 8 | "go/token"
|
| 9 | + "go/types" |
9 | 10 | "io"
|
10 | 11 | "os"
|
11 | 12 | "path"
|
@@ -61,7 +62,6 @@ func (ctb connectorTypeBuilder) String() string {
|
61 | 62 | bs.WriteString(")\n")
|
62 | 63 | }
|
63 | 64 |
|
64 |
| - bs.WriteString("var connector_Decoder = utils.NewDecoder()\n") |
65 | 65 | bs.WriteString(ctb.builder.String())
|
66 | 66 | return bs.String()
|
67 | 67 | }
|
@@ -642,51 +642,61 @@ func (cg *connectorGenerator) writeGetTypeValueDecoder(sb *connectorTypeBuilder,
|
642 | 642 | case "*[]*any", "*[]*interface{}":
|
643 | 643 | cg.writeScalarDecodeValue(sb, fieldName, "GetNullableArbitraryJSONPtrSlice", "", key, objectField, true)
|
644 | 644 | default:
|
| 645 | + sb.builder.WriteString(" j.") |
| 646 | + sb.builder.WriteString(fieldName) |
| 647 | + sb.builder.WriteString(", err = utils.") |
645 | 648 | switch t := ty.(type) {
|
646 | 649 | case *NullableType:
|
647 |
| - packagePaths := getTypePackagePaths(t.UnderlyingType, sb.packagePath) |
648 |
| - tyName := getTypeArgumentName(t.UnderlyingType, sb.packagePath, false) |
649 |
| - |
| 650 | + var tyName string |
| 651 | + var packagePaths []string |
| 652 | + if t.IsAnonymous() { |
| 653 | + tyName, packagePaths = cg.getAnonymousObjectTypeName(sb, field.TypeAST, true) |
| 654 | + } else { |
| 655 | + packagePaths = getTypePackagePaths(t.UnderlyingType, sb.packagePath) |
| 656 | + tyName = getTypeArgumentName(t.UnderlyingType, sb.packagePath, false) |
| 657 | + } |
650 | 658 | for _, pkgPath := range packagePaths {
|
651 | 659 | sb.imports[pkgPath] = ""
|
652 | 660 | }
|
653 |
| - sb.builder.WriteString(" j.") |
654 |
| - sb.builder.WriteString(fieldName) |
655 |
| - sb.builder.WriteString(" = new(") |
656 |
| - sb.builder.WriteString(tyName) |
657 |
| - sb.builder.WriteString(")\n err = connector_Decoder.") |
658 | 661 | if field.Embedded {
|
659 |
| - sb.builder.WriteString("DecodeObject(j.") |
660 |
| - sb.builder.WriteString(fieldName) |
661 |
| - sb.builder.WriteString(", input)") |
| 662 | + sb.builder.WriteString("DecodeNullableObject[") |
| 663 | + sb.builder.WriteString(tyName) |
| 664 | + sb.builder.WriteString("](input)") |
662 | 665 | } else {
|
663 |
| - sb.builder.WriteString("DecodeNullableObjectValue(j.") |
664 |
| - sb.builder.WriteString(fieldName) |
665 |
| - sb.builder.WriteString(`, input, "`) |
| 666 | + sb.builder.WriteString("DecodeNullableObjectValue[") |
| 667 | + sb.builder.WriteString(tyName) |
| 668 | + sb.builder.WriteString(`](input, "`) |
666 | 669 | sb.builder.WriteString(key)
|
667 | 670 | sb.builder.WriteString(`")`)
|
668 | 671 | }
|
669 | 672 | default:
|
670 |
| - var canEmpty bool |
671 |
| - if len(objectField.Type) > 0 { |
672 |
| - if typeEnum, err := objectField.Type.Type(); err == nil && typeEnum == schema.TypeNullable { |
673 |
| - canEmpty = true |
674 |
| - } |
| 673 | + var tyName string |
| 674 | + var packagePaths []string |
| 675 | + if t.IsAnonymous() { |
| 676 | + tyName, packagePaths = cg.getAnonymousObjectTypeName(sb, field.TypeAST, true) |
| 677 | + } else { |
| 678 | + packagePaths = getTypePackagePaths(ty, sb.packagePath) |
| 679 | + tyName = getTypeArgumentName(ty, sb.packagePath, false) |
| 680 | + } |
| 681 | + for _, pkgPath := range packagePaths { |
| 682 | + sb.imports[pkgPath] = "" |
675 | 683 | }
|
| 684 | + |
676 | 685 | if field.Embedded {
|
677 |
| - sb.builder.WriteString(" err = connector_Decoder.DecodeObject(&j.") |
678 |
| - sb.builder.WriteString(fieldName) |
679 |
| - sb.builder.WriteString(", input)") |
| 686 | + sb.builder.WriteString("DecodeObject") |
| 687 | + sb.builder.WriteRune('[') |
| 688 | + sb.builder.WriteString(tyName) |
| 689 | + sb.builder.WriteString("](input)") |
680 | 690 | } else {
|
681 |
| - sb.builder.WriteString(" err = connector_Decoder.") |
682 |
| - if canEmpty { |
683 |
| - sb.builder.WriteString("DecodeNullableObjectValue") |
684 |
| - } else { |
685 |
| - sb.builder.WriteString("DecodeObjectValue") |
| 691 | + sb.builder.WriteString("DecodeObjectValue") |
| 692 | + if len(objectField.Type) > 0 { |
| 693 | + if typeEnum, err := objectField.Type.Type(); err == nil && typeEnum == schema.TypeNullable { |
| 694 | + sb.builder.WriteString("Default") |
| 695 | + } |
686 | 696 | }
|
687 |
| - sb.builder.WriteString("(&j.") |
688 |
| - sb.builder.WriteString(fieldName) |
689 |
| - sb.builder.WriteString(`, input, "`) |
| 697 | + sb.builder.WriteRune('[') |
| 698 | + sb.builder.WriteString(tyName) |
| 699 | + sb.builder.WriteString(`](input, "`) |
690 | 700 | sb.builder.WriteString(key)
|
691 | 701 | sb.builder.WriteString(`")`)
|
692 | 702 | }
|
@@ -715,6 +725,86 @@ func (cg *connectorGenerator) writeScalarDecodeValue(sb *connectorTypeBuilder, f
|
715 | 725 | sb.builder.WriteString(`")`)
|
716 | 726 | }
|
717 | 727 |
|
| 728 | +// generate anonymous object type name with absolute package paths removed |
| 729 | +func (cg *connectorGenerator) getAnonymousObjectTypeName(sb *connectorTypeBuilder, goType types.Type, skipNullable bool) (string, []string) { |
| 730 | + switch inferredType := goType.(type) { |
| 731 | + case *types.Pointer: |
| 732 | + var result string |
| 733 | + if !skipNullable { |
| 734 | + result += "*" |
| 735 | + } |
| 736 | + underlyingName, packagePaths := cg.getAnonymousObjectTypeName(sb, inferredType.Elem(), false) |
| 737 | + return result + underlyingName, packagePaths |
| 738 | + case *types.Struct: |
| 739 | + packagePaths := []string{} |
| 740 | + result := "struct{" |
| 741 | + for i := 0; i < inferredType.NumFields(); i++ { |
| 742 | + fieldVar := inferredType.Field(i) |
| 743 | + fieldTag := inferredType.Tag(i) |
| 744 | + if i > 0 { |
| 745 | + result += "; " |
| 746 | + } |
| 747 | + result += fieldVar.Name() + " " |
| 748 | + underlyingName, pkgPaths := cg.getAnonymousObjectTypeName(sb, fieldVar.Type(), false) |
| 749 | + result += underlyingName |
| 750 | + packagePaths = append(packagePaths, pkgPaths...) |
| 751 | + if fieldTag != "" { |
| 752 | + result += " `" + fieldTag + "`" |
| 753 | + } |
| 754 | + } |
| 755 | + result += "}" |
| 756 | + return result, packagePaths |
| 757 | + case *types.Named: |
| 758 | + packagePaths := []string{} |
| 759 | + innerType := inferredType.Obj() |
| 760 | + if innerType == nil { |
| 761 | + return "", packagePaths |
| 762 | + } |
| 763 | + |
| 764 | + var result string |
| 765 | + typeInfo := &TypeInfo{ |
| 766 | + Name: innerType.Name(), |
| 767 | + } |
| 768 | + |
| 769 | + innerPkg := innerType.Pkg() |
| 770 | + if innerPkg != nil && innerPkg.Name() != "" && innerPkg.Path() != sb.packagePath { |
| 771 | + packagePaths = append(packagePaths, innerPkg.Path()) |
| 772 | + result += innerPkg.Name() + "." |
| 773 | + typeInfo.PackageName = innerPkg.Name() |
| 774 | + typeInfo.PackagePath = innerPkg.Path() |
| 775 | + } |
| 776 | + |
| 777 | + result += innerType.Name() |
| 778 | + typeParams := inferredType.TypeParams() |
| 779 | + if typeParams != nil && typeParams.Len() > 0 { |
| 780 | + // unwrap the generic type parameters such as Foo[T] |
| 781 | + if err := parseTypeParameters(typeInfo, inferredType.String()); err == nil { |
| 782 | + result += "[" |
| 783 | + for i, typeParam := range typeInfo.TypeParameters { |
| 784 | + if i > 0 { |
| 785 | + result += ", " |
| 786 | + } |
| 787 | + packagePaths = append(packagePaths, getTypePackagePaths(typeParam, sb.packagePath)...) |
| 788 | + result += getTypeArgumentName(typeParam, sb.packagePath, false) |
| 789 | + } |
| 790 | + result += "]" |
| 791 | + } |
| 792 | + } |
| 793 | + |
| 794 | + return result, packagePaths |
| 795 | + case *types.Basic: |
| 796 | + return inferredType.Name(), []string{} |
| 797 | + case *types.Array: |
| 798 | + result, packagePaths := cg.getAnonymousObjectTypeName(sb, inferredType.Elem(), false) |
| 799 | + return "[]" + result, packagePaths |
| 800 | + case *types.Slice: |
| 801 | + result, packagePaths := cg.getAnonymousObjectTypeName(sb, inferredType.Elem(), false) |
| 802 | + return "[]" + result, packagePaths |
| 803 | + default: |
| 804 | + return inferredType.String(), []string{} |
| 805 | + } |
| 806 | +} |
| 807 | + |
718 | 808 | func formatLocalFieldName(input string, others ...string) string {
|
719 | 809 | name := fieldNameRegex.ReplaceAllString(input, "_")
|
720 | 810 | return strings.Trim(strings.Join(append([]string{name}, others...), "_"), "_")
|
|
0 commit comments