output.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package internal
  2. import (
  3. "bytes"
  4. "errors"
  5. "go/format"
  6. "go/scanner"
  7. "io"
  8. "reflect"
  9. "strings"
  10. "unicode"
  11. )
  12. // Identifier turns a C style type or field name into an exportable Go equivalent.
  13. func Identifier(str string) string {
  14. prev := rune(-1)
  15. return strings.Map(func(r rune) rune {
  16. // See https://golang.org/ref/spec#Identifiers
  17. switch {
  18. case unicode.IsLetter(r):
  19. if prev == -1 {
  20. r = unicode.ToUpper(r)
  21. }
  22. case r == '_':
  23. switch {
  24. // The previous rune was deleted, or we are at the
  25. // beginning of the string.
  26. case prev == -1:
  27. fallthrough
  28. // The previous rune is a lower case letter or a digit.
  29. case unicode.IsDigit(prev) || (unicode.IsLetter(prev) && unicode.IsLower(prev)):
  30. // delete the current rune, and force the
  31. // next character to be uppercased.
  32. r = -1
  33. }
  34. case unicode.IsDigit(r):
  35. default:
  36. // Delete the current rune. prev is unchanged.
  37. return -1
  38. }
  39. prev = r
  40. return r
  41. }, str)
  42. }
  43. // WriteFormatted outputs a formatted src into out.
  44. //
  45. // If formatting fails it returns an informative error message.
  46. func WriteFormatted(src []byte, out io.Writer) error {
  47. formatted, err := format.Source(src)
  48. if err == nil {
  49. _, err = out.Write(formatted)
  50. return err
  51. }
  52. var el scanner.ErrorList
  53. if !errors.As(err, &el) {
  54. return err
  55. }
  56. var nel scanner.ErrorList
  57. for _, err := range el {
  58. if !err.Pos.IsValid() {
  59. nel = append(nel, err)
  60. continue
  61. }
  62. buf := src[err.Pos.Offset:]
  63. nl := bytes.IndexRune(buf, '\n')
  64. if nl == -1 {
  65. nel = append(nel, err)
  66. continue
  67. }
  68. err.Msg += ": " + string(buf[:nl])
  69. nel = append(nel, err)
  70. }
  71. return nel
  72. }
  73. // GoTypeName is like %T, but elides the package name.
  74. //
  75. // Pointers to a type are peeled off.
  76. func GoTypeName(t any) string {
  77. rT := reflect.TypeOf(t)
  78. for rT.Kind() == reflect.Pointer {
  79. rT = rT.Elem()
  80. }
  81. // Doesn't return the correct Name for generic types due to https://github.com/golang/go/issues/55924
  82. return rT.Name()
  83. }