ssa.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package main
  2. import (
  3. "golang.org/x/text/language"
  4. "golang.org/x/text/message"
  5. )
  6. // In this test, lowercap strings are ones that need to be picked up for
  7. // translation, whereas uppercap strings should not be picked up.
  8. func main() {
  9. p := message.NewPrinter(language.English)
  10. // TODO: probably should use type instead of string content for argument
  11. // substitution.
  12. wrapf(p, "inline %s", "ARG1")
  13. gwrapf("global printer used %s", "ARG1")
  14. w := wrapped{p}
  15. // Comment about wrapf.
  16. w.wrapf("number: %d, string: %s, bool: %v", 2, "STRING ARG", true)
  17. w.wrapf("empty string")
  18. w.wrap("Lovely weather today!")
  19. more(&w)
  20. }
  21. var printer = message.NewPrinter(language.English)
  22. func more(w wrapper) {
  23. w.wrap("number one")
  24. w.wrapf("speed of light: %s", "C")
  25. }
  26. func gwrapf(format string, args ...interface{}) {
  27. v := format
  28. a := args
  29. printer.Printf(v, a...)
  30. }
  31. func wrapf(p *message.Printer, format string, args ...interface{}) {
  32. v := format
  33. a := args
  34. p.Printf(v, a...)
  35. }
  36. func wrap(p *message.Printer, format string) {
  37. v := format
  38. b := "0"
  39. a := []interface{}{3, b}
  40. s := a[:]
  41. p.Printf(v, s...)
  42. }
  43. type wrapper interface {
  44. wrapf(format string, args ...interface{})
  45. wrap(msg string)
  46. }
  47. type wrapped struct {
  48. p *message.Printer
  49. }
  50. // TODO: calls over interfaces do not get picked up. It looks like this is
  51. // because w is not a pointer receiver, while the other method is. Mixing of
  52. // receiver types does not seem to be allowed by callgraph/cha.
  53. func (w wrapped) wrapf(format string, args ...interface{}) {
  54. w.p.Printf(format, args...)
  55. }
  56. func (w *wrapped) wrap(msg string) {
  57. w.p.Printf(msg)
  58. }
  59. func fint(p *message.Printer, x int) {
  60. v := "number: %d"
  61. const c = "DAFDA"
  62. p.Printf(v, c)
  63. }
  64. const format = "constant local" + " %s"
  65. // NOTE: pass is not called. Ensure it is picked up anyway.
  66. func pass(p *message.Printer, args ...interface{}) {
  67. // TODO: find an example caller to find substituted types and argument
  68. // examples.
  69. p.Sprintf(format, args...)
  70. }
  71. func lookup(p *message.Printer, x int) {
  72. // TODO: pick up all elements from slice foo.
  73. p.Printf(foo[x])
  74. }
  75. var foo = []string{
  76. "aaaa",
  77. "bbbb",
  78. }
  79. func field(p *message.Printer, x int) {
  80. // TODO: pick up strings in field BAR from all composite literals of
  81. // typeof(strct.Foo.Bar).
  82. p.Printf(strct.Foo.Bar, x)
  83. }
  84. type fooStruct struct {
  85. Foo barStruct
  86. }
  87. type barStruct struct {
  88. other int
  89. Bar string
  90. }
  91. var strct = fooStruct{
  92. Foo: barStruct{0, "foo %d"},
  93. }
  94. func call(p *message.Printer, x int) {
  95. // TODO: pick up constant return values.
  96. p.Printf(fn())
  97. }
  98. func fn() string {
  99. return "const str"
  100. }
  101. // Both strings get picked up.
  102. func ifConst(p *message.Printer, cond bool, arg1 string) {
  103. a := "foo %s %s"
  104. if cond {
  105. a = "bar %s %s"
  106. }
  107. b := "FOO"
  108. if cond {
  109. b = "BAR"
  110. }
  111. wrapf(p, a, arg1, b)
  112. }
  113. // Pick up all non-empty strings in this function.
  114. func ifConst2(x int) {
  115. a := ""
  116. switch x {
  117. case 0:
  118. a = "foo"
  119. case 1:
  120. a = "bar"
  121. case 2:
  122. a = "baz"
  123. }
  124. gwrapf(a)
  125. }
  126. // TODO: pick up strings passed to the second argument in calls to freeVar.
  127. func freeVar(p *message.Printer, str string) {
  128. fn := func(p *message.Printer) {
  129. p.Printf(str)
  130. }
  131. fn(p)
  132. }
  133. func freeConst(p *message.Printer) {
  134. // str is a message
  135. const str = "const str"
  136. fn := func(p *message.Printer) {
  137. p.Printf(str)
  138. }
  139. fn(p)
  140. }
  141. func global(p *message.Printer) {
  142. // city describes the expected next meeting place
  143. city := "Amsterdam"
  144. // See a person around.
  145. p.Printf(globalStr, city)
  146. }
  147. // globalStr is a global variable with a string constant assigned to it.
  148. var globalStr = "See you around in %s!"
  149. func global2(p *message.Printer) {
  150. const food = "Pastrami"
  151. wrapf(p, constFood,
  152. food, // the food to be consumed by the subject
  153. )
  154. }
  155. // Comment applying to all constants in a block are ignored.
  156. var (
  157. // Ho ho ho
  158. notAMessage, constFood, msgHello = "NOPE!", consume, hello
  159. )
  160. // A block comment.
  161. var (
  162. // This comment takes precedence.
  163. hello = "Hello, %d and %s!"
  164. consume = "Please eat your %s!"
  165. )