format.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package format
  2. import (
  3. "bufio"
  4. "errors"
  5. "fmt"
  6. "go/scanner"
  7. "io/ioutil"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "github.com/tal-tech/go-zero/core/errorx"
  12. "github.com/tal-tech/go-zero/tools/goctl/api/parser"
  13. "github.com/tal-tech/go-zero/tools/goctl/api/util"
  14. "github.com/urfave/cli"
  15. )
  16. const (
  17. leftParenthesis = "("
  18. rightParenthesis = ")"
  19. leftBrace = "{"
  20. rightBrace = "}"
  21. )
  22. func GoFormatApi(c *cli.Context) error {
  23. useStdin := c.Bool("stdin")
  24. var be errorx.BatchError
  25. if useStdin {
  26. if err := ApiFormatByStdin(); err != nil {
  27. be.Add(err)
  28. }
  29. } else {
  30. dir := c.String("dir")
  31. if len(dir) == 0 {
  32. return errors.New("missing -dir")
  33. }
  34. _, err := os.Lstat(dir)
  35. if err != nil {
  36. return errors.New(dir + ": No such file or directory")
  37. }
  38. err = filepath.Walk(dir, func(path string, fi os.FileInfo, errBack error) (err error) {
  39. if strings.HasSuffix(path, ".api") {
  40. if err := ApiFormatByPath(path); err != nil {
  41. be.Add(util.WrapErr(err, fi.Name()))
  42. }
  43. }
  44. return nil
  45. })
  46. be.Add(err)
  47. }
  48. if be.NotNil() {
  49. scanner.PrintError(os.Stderr, be.Err())
  50. os.Exit(1)
  51. }
  52. return be.Err()
  53. }
  54. func ApiFormatByStdin() error {
  55. data, err := ioutil.ReadAll(os.Stdin)
  56. if err != nil {
  57. return err
  58. }
  59. result, err := apiFormat(string(data))
  60. if err != nil {
  61. return err
  62. }
  63. _, err = fmt.Print(result)
  64. if err != nil {
  65. return err
  66. }
  67. return nil
  68. }
  69. func ApiFormatByPath(apiFilePath string) error {
  70. data, err := ioutil.ReadFile(apiFilePath)
  71. if err != nil {
  72. return err
  73. }
  74. result, err := apiFormat(string(data))
  75. if err != nil {
  76. return err
  77. }
  78. if err := ioutil.WriteFile(apiFilePath, []byte(result), os.ModePerm); err != nil {
  79. return err
  80. }
  81. return nil
  82. }
  83. func apiFormat(data string) (string, error) {
  84. _, err := parser.ParseApi(data)
  85. if err != nil {
  86. return "", err
  87. }
  88. var builder strings.Builder
  89. s := bufio.NewScanner(strings.NewReader(data))
  90. var tapCount = 0
  91. for s.Scan() {
  92. line := strings.TrimSpace(s.Text())
  93. noCommentLine := util.RemoveComment(line)
  94. if noCommentLine == rightParenthesis || noCommentLine == rightBrace {
  95. tapCount -= 1
  96. }
  97. if tapCount < 0 {
  98. line = strings.TrimSuffix(line, rightBrace)
  99. line = strings.TrimSpace(line)
  100. if strings.HasSuffix(line, leftBrace) {
  101. tapCount += 1
  102. }
  103. }
  104. util.WriteIndent(&builder, tapCount)
  105. builder.WriteString(line + "\n")
  106. if strings.HasSuffix(noCommentLine, leftParenthesis) || strings.HasSuffix(noCommentLine, leftBrace) {
  107. tapCount += 1
  108. }
  109. }
  110. return strings.TrimSpace(builder.String()), nil
  111. }