dump.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package jet
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "reflect"
  7. )
  8. // dumpAll returns
  9. // - everything in Runtime.context
  10. // - everything in Runtime.variables
  11. // - everything in Runtime.set.globals
  12. // - everything in Runtime.blocks
  13. func dumpAll(a Arguments, depth int) reflect.Value {
  14. var b bytes.Buffer
  15. var vars VarMap
  16. ctx := a.runtime.context
  17. fmt.Fprintln(&b, "Context:")
  18. fmt.Fprintf(&b, "\t%s %#v\n", ctx.Type(), ctx)
  19. dumpScopeVars(&b, a.runtime.scope, 0)
  20. dumpScopeVarsToDepth(&b, a.runtime.parent, depth)
  21. vars = a.runtime.set.globals
  22. for i, name := range vars.SortedKeys() {
  23. if i == 0 {
  24. fmt.Fprintln(&b, "Globals:")
  25. }
  26. val := vars[name]
  27. fmt.Fprintf(&b, "\t%s:=%#v // %s\n", name, val, val.Type())
  28. }
  29. blockKeys := a.runtime.scope.sortedBlocks()
  30. fmt.Fprintln(&b, "Blocks:")
  31. for _, k := range blockKeys {
  32. block := a.runtime.blocks[k]
  33. dumpBlock(&b, block)
  34. }
  35. return reflect.ValueOf(b.String())
  36. }
  37. // dumpScopeVarsToDepth prints all variables in the scope, and all parent scopes,
  38. // to the limit of maxDepth.
  39. func dumpScopeVarsToDepth(w io.Writer, scope *scope, maxDepth int) {
  40. for i := 1; i <= maxDepth; i++ {
  41. if scope == nil {
  42. break // do not panic if something bad happens
  43. }
  44. dumpScopeVars(w, scope, i)
  45. scope = scope.parent
  46. }
  47. }
  48. // dumpScopeVars prints all variables in the scope.
  49. func dumpScopeVars(w io.Writer, scope *scope, lvl int) {
  50. if scope == nil {
  51. return // do not panic if something bad happens
  52. }
  53. if lvl == 0 {
  54. fmt.Fprint(w, "Variables in current scope:\n")
  55. } else {
  56. fmt.Fprintf(w, "Variables in scope %d level(s) up:\n", lvl)
  57. }
  58. vars := scope.variables
  59. for _, k := range vars.SortedKeys() {
  60. fmt.Fprintf(w, "\t%s=%#v\n", k, vars[k])
  61. }
  62. }
  63. // dumpIdentified accepts a runtime and slice of names.
  64. // Then, it prints all variables and blocks in the runtime, with names equal to one of the names
  65. // in the slice.
  66. func dumpIdentified(rnt *Runtime, ids []string) reflect.Value {
  67. var b bytes.Buffer
  68. for _, id := range ids {
  69. dumpFindVar(&b, rnt, id)
  70. dumpFindBlock(&b, rnt, id)
  71. }
  72. return reflect.ValueOf(b.String())
  73. }
  74. // dumpFindBlock finds the block by name, prints the header of the block, and name of the template in which it was defined.
  75. func dumpFindBlock(w io.Writer, rnt *Runtime, name string) {
  76. if block, ok := rnt.scope.blocks[name]; ok {
  77. dumpBlock(w, block)
  78. }
  79. }
  80. // dumpBlock prints header of the block, and template in which the block was first defined.
  81. func dumpBlock(w io.Writer, block *BlockNode) {
  82. if block == nil {
  83. return
  84. }
  85. fmt.Fprintf(w, "\tblock %s(%s), from %s\n", block.Name, block.Parameters.String(), block.TemplatePath)
  86. }
  87. // dumpFindBlock finds the variable by name, and prints the variable, if it is in the runtime.
  88. func dumpFindVar(w io.Writer, rnt *Runtime, name string) {
  89. val, err := rnt.resolve(name)
  90. if err != nil {
  91. return
  92. }
  93. fmt.Fprintf(w, "\t%s:=%#v // %s\n", name, val, val.Type())
  94. }