util.go 4.5 KB

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