util.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package tsgen
  2. import (
  3. "fmt"
  4. "io"
  5. "strings"
  6. "github.com/tal-tech/go-zero/tools/goctl/api/spec"
  7. apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util"
  8. "github.com/tal-tech/go-zero/tools/goctl/util"
  9. )
  10. func writeProperty(writer io.Writer, member spec.Member, indent int, prefixForType func(string) string) error {
  11. writeIndent(writer, indent)
  12. ty, err := goTypeToTs(member.Type, prefixForType)
  13. optionalTag := ""
  14. if member.IsOptional() || member.IsOmitempty() {
  15. optionalTag = "?"
  16. }
  17. name, err := member.GetPropertyName()
  18. if err != nil {
  19. return err
  20. }
  21. comment := member.GetComment()
  22. if len(comment) > 0 {
  23. comment = strings.TrimPrefix(comment, "//")
  24. comment = " // " + strings.TrimSpace(comment)
  25. }
  26. if len(member.Docs) > 0 {
  27. _, err = fmt.Fprintf(writer, "%s\n", strings.Join(member.Docs, ""))
  28. writeIndent(writer, 1)
  29. }
  30. _, err = fmt.Fprintf(writer, "%s%s: %s%s\n", name, optionalTag, ty, comment)
  31. return err
  32. }
  33. func writeIndent(writer io.Writer, indent int) {
  34. for i := 0; i < indent; i++ {
  35. fmt.Fprint(writer, "\t")
  36. }
  37. }
  38. func goTypeToTs(tp string, prefixForType func(string) string) (string, error) {
  39. if val, pri := primitiveType(tp); pri {
  40. return val, nil
  41. }
  42. if tp == "[]byte" {
  43. return "Blob", nil
  44. } else if strings.HasPrefix(tp, "[][]") {
  45. tys, err := apiutil.DecomposeType(tp)
  46. if err != nil {
  47. return "", err
  48. }
  49. if len(tys) == 0 {
  50. return "", fmt.Errorf("%s tp parse error", tp)
  51. }
  52. innerType, err := goTypeToTs(tys[0], prefixForType)
  53. if err != nil {
  54. return "", err
  55. }
  56. return fmt.Sprintf("Array<Array<%s>>", innerType), nil
  57. } else if strings.HasPrefix(tp, "[]") {
  58. tys, err := apiutil.DecomposeType(tp)
  59. if err != nil {
  60. return "", err
  61. }
  62. if len(tys) == 0 {
  63. return "", fmt.Errorf("%s tp parse error", tp)
  64. }
  65. innerType, err := goTypeToTs(tys[0], prefixForType)
  66. if err != nil {
  67. return "", err
  68. }
  69. return fmt.Sprintf("Array<%s>", innerType), nil
  70. } else if strings.HasPrefix(tp, "map") {
  71. tys, err := apiutil.DecomposeType(tp)
  72. if err != nil {
  73. return "", err
  74. }
  75. if len(tys) != 2 {
  76. return "", fmt.Errorf("%s tp parse error", tp)
  77. }
  78. innerType, err := goTypeToTs(tys[1], prefixForType)
  79. if err != nil {
  80. return "", err
  81. }
  82. return fmt.Sprintf("{ [key: string]: %s }", innerType), nil
  83. }
  84. return addPrefixIfNeed(util.Title(tp), prefixForType), nil
  85. }
  86. func addPrefixIfNeed(tp string, prefixForType func(string) string) string {
  87. if val, pri := primitiveType(tp); pri {
  88. return val
  89. }
  90. tp = strings.Replace(tp, "*", "", 1)
  91. return prefixForType(tp) + util.Title(tp)
  92. }
  93. func primitiveType(tp string) (string, bool) {
  94. switch tp {
  95. case "string":
  96. return "string", true
  97. case "int", "int8", "int32", "int64":
  98. return "number", true
  99. case "float", "float32", "float64":
  100. return "number", true
  101. case "bool":
  102. return "boolean", true
  103. case "[]byte":
  104. return "Blob", true
  105. case "interface{}":
  106. return "any", true
  107. }
  108. return "", false
  109. }
  110. func writeType(writer io.Writer, tp spec.Type, inlineType func(string) (*spec.Type, error), prefixForType func(string) string) error {
  111. fmt.Fprintf(writer, "export interface %s {\n", util.Title(tp.Name))
  112. if err := genMembers(writer, tp, false, inlineType, prefixForType); err != nil {
  113. return err
  114. }
  115. fmt.Fprintf(writer, "}\n")
  116. err := genParamsTypesIfNeed(writer, tp, inlineType, prefixForType)
  117. if err != nil {
  118. return err
  119. }
  120. return nil
  121. }
  122. func genParamsTypesIfNeed(writer io.Writer, tp spec.Type, inlineType func(string) (*spec.Type, error), prefixForType func(string) string) error {
  123. members := tp.GetNonBodyMembers()
  124. if len(members) == 0 {
  125. return nil
  126. }
  127. fmt.Fprintf(writer, "\n")
  128. fmt.Fprintf(writer, "export interface %sParams {\n", util.Title(tp.Name))
  129. if err := genMembers(writer, tp, true, inlineType, prefixForType); err != nil {
  130. return err
  131. }
  132. fmt.Fprintf(writer, "}\n")
  133. return nil
  134. }
  135. func genMembers(writer io.Writer, tp spec.Type, isParam bool, inlineType func(string) (*spec.Type, error), prefixForType func(string) string) error {
  136. members := tp.GetBodyMembers()
  137. if isParam {
  138. members = tp.GetNonBodyMembers()
  139. }
  140. for _, member := range members {
  141. if member.IsInline {
  142. // 获取inline类型的成员然后添加到type中
  143. it, err := inlineType(strings.TrimPrefix(member.Type, "*"))
  144. if err != nil {
  145. return err
  146. }
  147. if err := genMembers(writer, *it, isParam, inlineType, prefixForType); err != nil {
  148. return err
  149. }
  150. continue
  151. }
  152. if err := writeProperty(writer, member, 1, prefixForType); err != nil {
  153. return apiutil.WrapErr(err, " type "+tp.Name)
  154. }
  155. }
  156. return nil
  157. }