parser.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package parser
  2. import (
  3. "go/ast"
  4. "go/parser"
  5. "go/token"
  6. "os/exec"
  7. "strings"
  8. )
  9. const structComment = "easyjson:json"
  10. type Parser struct {
  11. PkgPath string
  12. PkgName string
  13. StructNames []string
  14. AllStructs bool
  15. }
  16. type visitor struct {
  17. *Parser
  18. name string
  19. explicit bool
  20. }
  21. func (p *Parser) needType(comments string) bool {
  22. for _, v := range strings.Split(comments, "\n") {
  23. if strings.HasPrefix(v, structComment) {
  24. return true
  25. }
  26. }
  27. return false
  28. }
  29. func (v *visitor) Visit(n ast.Node) (w ast.Visitor) {
  30. switch n := n.(type) {
  31. case *ast.Package:
  32. return v
  33. case *ast.File:
  34. v.PkgName = n.Name.String()
  35. return v
  36. case *ast.GenDecl:
  37. v.explicit = v.needType(n.Doc.Text())
  38. if !v.explicit && !v.AllStructs {
  39. return nil
  40. }
  41. return v
  42. case *ast.TypeSpec:
  43. v.name = n.Name.String()
  44. // Allow to specify non-structs explicitly independent of '-all' flag.
  45. if v.explicit {
  46. v.StructNames = append(v.StructNames, v.name)
  47. return nil
  48. }
  49. return v
  50. case *ast.StructType:
  51. v.StructNames = append(v.StructNames, v.name)
  52. return nil
  53. }
  54. return nil
  55. }
  56. func (p *Parser) Parse(fname string, isDir bool) error {
  57. var err error
  58. if p.PkgPath, err = getPkgPath(fname, isDir); err != nil {
  59. return err
  60. }
  61. fset := token.NewFileSet()
  62. if isDir {
  63. packages, err := parser.ParseDir(fset, fname, nil, parser.ParseComments)
  64. if err != nil {
  65. return err
  66. }
  67. for _, pckg := range packages {
  68. ast.Walk(&visitor{Parser: p}, pckg)
  69. }
  70. } else {
  71. f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments)
  72. if err != nil {
  73. return err
  74. }
  75. ast.Walk(&visitor{Parser: p}, f)
  76. }
  77. return nil
  78. }
  79. func getDefaultGoPath() (string, error) {
  80. output, err := exec.Command("go", "env", "GOPATH").Output()
  81. return string(output), err
  82. }