parser.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "go/ast"
  6. "go/parser"
  7. "go/token"
  8. "reflect"
  9. )
  10. var ErrBadReturn = errors.New("found return arg with no name: all args must be named")
  11. type ErrUnexpectedType struct {
  12. expected string
  13. actual interface{}
  14. }
  15. func (e ErrUnexpectedType) Error() string {
  16. return fmt.Sprintf("got wrong type expecting %s, got: %v", e.expected, reflect.TypeOf(e.actual))
  17. }
  18. type parsedPkg struct {
  19. Name string
  20. Functions []function
  21. }
  22. type function struct {
  23. Name string
  24. Args []arg
  25. Returns []arg
  26. Doc string
  27. }
  28. type arg struct {
  29. Name string
  30. ArgType string
  31. }
  32. func (a *arg) String() string {
  33. return a.Name + " " + a.ArgType
  34. }
  35. // Parses the given file for an interface definition with the given name
  36. func Parse(filePath string, objName string) (*parsedPkg, error) {
  37. fs := token.NewFileSet()
  38. pkg, err := parser.ParseFile(fs, filePath, nil, parser.AllErrors)
  39. if err != nil {
  40. return nil, err
  41. }
  42. p := &parsedPkg{}
  43. p.Name = pkg.Name.Name
  44. obj, exists := pkg.Scope.Objects[objName]
  45. if !exists {
  46. return nil, fmt.Errorf("could not find object %s in %s", objName, filePath)
  47. }
  48. if obj.Kind != ast.Typ {
  49. return nil, fmt.Errorf("exected type, got %s", obj.Kind)
  50. }
  51. spec, ok := obj.Decl.(*ast.TypeSpec)
  52. if !ok {
  53. return nil, ErrUnexpectedType{"*ast.TypeSpec", obj.Decl}
  54. }
  55. iface, ok := spec.Type.(*ast.InterfaceType)
  56. if !ok {
  57. return nil, ErrUnexpectedType{"*ast.InterfaceType", spec.Type}
  58. }
  59. p.Functions, err = parseInterface(iface)
  60. if err != nil {
  61. return nil, err
  62. }
  63. return p, nil
  64. }
  65. func parseInterface(iface *ast.InterfaceType) ([]function, error) {
  66. var functions []function
  67. for _, field := range iface.Methods.List {
  68. switch f := field.Type.(type) {
  69. case *ast.FuncType:
  70. method, err := parseFunc(field)
  71. if err != nil {
  72. return nil, err
  73. }
  74. if method == nil {
  75. continue
  76. }
  77. functions = append(functions, *method)
  78. case *ast.Ident:
  79. spec, ok := f.Obj.Decl.(*ast.TypeSpec)
  80. if !ok {
  81. return nil, ErrUnexpectedType{"*ast.TypeSpec", f.Obj.Decl}
  82. }
  83. iface, ok := spec.Type.(*ast.InterfaceType)
  84. if !ok {
  85. return nil, ErrUnexpectedType{"*ast.TypeSpec", spec.Type}
  86. }
  87. funcs, err := parseInterface(iface)
  88. if err != nil {
  89. fmt.Println(err)
  90. continue
  91. }
  92. functions = append(functions, funcs...)
  93. default:
  94. return nil, ErrUnexpectedType{"*astFuncType or *ast.Ident", f}
  95. }
  96. }
  97. return functions, nil
  98. }
  99. func parseFunc(field *ast.Field) (*function, error) {
  100. f := field.Type.(*ast.FuncType)
  101. method := &function{Name: field.Names[0].Name}
  102. if _, exists := skipFuncs[method.Name]; exists {
  103. fmt.Println("skipping:", method.Name)
  104. return nil, nil
  105. }
  106. if f.Params != nil {
  107. args, err := parseArgs(f.Params.List)
  108. if err != nil {
  109. return nil, err
  110. }
  111. method.Args = args
  112. }
  113. if f.Results != nil {
  114. returns, err := parseArgs(f.Results.List)
  115. if err != nil {
  116. return nil, fmt.Errorf("error parsing function returns for %q: %v", method.Name, err)
  117. }
  118. method.Returns = returns
  119. }
  120. return method, nil
  121. }
  122. func parseArgs(fields []*ast.Field) ([]arg, error) {
  123. var args []arg
  124. for _, f := range fields {
  125. if len(f.Names) == 0 {
  126. return nil, ErrBadReturn
  127. }
  128. for _, name := range f.Names {
  129. var typeName string
  130. switch argType := f.Type.(type) {
  131. case *ast.Ident:
  132. typeName = argType.Name
  133. case *ast.StarExpr:
  134. i, ok := argType.X.(*ast.Ident)
  135. if !ok {
  136. return nil, ErrUnexpectedType{"*ast.Ident", f.Type}
  137. }
  138. typeName = "*" + i.Name
  139. default:
  140. return nil, ErrUnexpectedType{"*ast.Ident or *ast.StarExpr", f.Type}
  141. }
  142. args = append(args, arg{name.Name, typeName})
  143. }
  144. }
  145. return args, nil
  146. }