parser.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "go/ast"
  6. "go/parser"
  7. "go/token"
  8. "path"
  9. "reflect"
  10. "strings"
  11. )
  12. var errBadReturn = errors.New("found return arg with no name: all args must be named")
  13. type errUnexpectedType struct {
  14. expected string
  15. actual interface{}
  16. }
  17. func (e errUnexpectedType) Error() string {
  18. return fmt.Sprintf("got wrong type expecting %s, got: %v", e.expected, reflect.TypeOf(e.actual))
  19. }
  20. // ParsedPkg holds information about a package that has been parsed,
  21. // its name and the list of functions.
  22. type ParsedPkg struct {
  23. Name string
  24. Functions []function
  25. Imports []importSpec
  26. }
  27. type function struct {
  28. Name string
  29. Args []arg
  30. Returns []arg
  31. Doc string
  32. }
  33. type arg struct {
  34. Name string
  35. ArgType string
  36. PackageSelector string
  37. }
  38. func (a *arg) String() string {
  39. return a.Name + " " + a.ArgType
  40. }
  41. type importSpec struct {
  42. Name string
  43. Path string
  44. }
  45. func (s *importSpec) String() string {
  46. var ss string
  47. if len(s.Name) != 0 {
  48. ss += s.Name
  49. }
  50. ss += s.Path
  51. return ss
  52. }
  53. // Parse parses the given file for an interface definition with the given name.
  54. func Parse(filePath string, objName string) (*ParsedPkg, error) {
  55. fs := token.NewFileSet()
  56. pkg, err := parser.ParseFile(fs, filePath, nil, parser.AllErrors)
  57. if err != nil {
  58. return nil, err
  59. }
  60. p := &ParsedPkg{}
  61. p.Name = pkg.Name.Name
  62. obj, exists := pkg.Scope.Objects[objName]
  63. if !exists {
  64. return nil, fmt.Errorf("could not find object %s in %s", objName, filePath)
  65. }
  66. if obj.Kind != ast.Typ {
  67. return nil, fmt.Errorf("exected type, got %s", obj.Kind)
  68. }
  69. spec, ok := obj.Decl.(*ast.TypeSpec)
  70. if !ok {
  71. return nil, errUnexpectedType{"*ast.TypeSpec", obj.Decl}
  72. }
  73. iface, ok := spec.Type.(*ast.InterfaceType)
  74. if !ok {
  75. return nil, errUnexpectedType{"*ast.InterfaceType", spec.Type}
  76. }
  77. p.Functions, err = parseInterface(iface)
  78. if err != nil {
  79. return nil, err
  80. }
  81. // figure out what imports will be needed
  82. imports := make(map[string]importSpec)
  83. for _, f := range p.Functions {
  84. args := append(f.Args, f.Returns...)
  85. for _, arg := range args {
  86. if len(arg.PackageSelector) == 0 {
  87. continue
  88. }
  89. for _, i := range pkg.Imports {
  90. if i.Name != nil {
  91. if i.Name.Name != arg.PackageSelector {
  92. continue
  93. }
  94. imports[i.Path.Value] = importSpec{Name: arg.PackageSelector, Path: i.Path.Value}
  95. break
  96. }
  97. _, name := path.Split(i.Path.Value)
  98. splitName := strings.Split(name, "-")
  99. if len(splitName) > 1 {
  100. name = splitName[len(splitName)-1]
  101. }
  102. // import paths have quotes already added in, so need to remove them for name comparison
  103. name = strings.TrimPrefix(name, `"`)
  104. name = strings.TrimSuffix(name, `"`)
  105. if name == arg.PackageSelector {
  106. imports[i.Path.Value] = importSpec{Path: i.Path.Value}
  107. break
  108. }
  109. }
  110. }
  111. }
  112. for _, spec := range imports {
  113. p.Imports = append(p.Imports, spec)
  114. }
  115. return p, nil
  116. }
  117. func parseInterface(iface *ast.InterfaceType) ([]function, error) {
  118. var functions []function
  119. for _, field := range iface.Methods.List {
  120. switch f := field.Type.(type) {
  121. case *ast.FuncType:
  122. method, err := parseFunc(field)
  123. if err != nil {
  124. return nil, err
  125. }
  126. if method == nil {
  127. continue
  128. }
  129. functions = append(functions, *method)
  130. case *ast.Ident:
  131. spec, ok := f.Obj.Decl.(*ast.TypeSpec)
  132. if !ok {
  133. return nil, errUnexpectedType{"*ast.TypeSpec", f.Obj.Decl}
  134. }
  135. iface, ok := spec.Type.(*ast.InterfaceType)
  136. if !ok {
  137. return nil, errUnexpectedType{"*ast.TypeSpec", spec.Type}
  138. }
  139. funcs, err := parseInterface(iface)
  140. if err != nil {
  141. fmt.Println(err)
  142. continue
  143. }
  144. functions = append(functions, funcs...)
  145. default:
  146. return nil, errUnexpectedType{"*astFuncType or *ast.Ident", f}
  147. }
  148. }
  149. return functions, nil
  150. }
  151. func parseFunc(field *ast.Field) (*function, error) {
  152. f := field.Type.(*ast.FuncType)
  153. method := &function{Name: field.Names[0].Name}
  154. if _, exists := skipFuncs[method.Name]; exists {
  155. fmt.Println("skipping:", method.Name)
  156. return nil, nil
  157. }
  158. if f.Params != nil {
  159. args, err := parseArgs(f.Params.List)
  160. if err != nil {
  161. return nil, err
  162. }
  163. method.Args = args
  164. }
  165. if f.Results != nil {
  166. returns, err := parseArgs(f.Results.List)
  167. if err != nil {
  168. return nil, fmt.Errorf("error parsing function returns for %q: %v", method.Name, err)
  169. }
  170. method.Returns = returns
  171. }
  172. return method, nil
  173. }
  174. func parseArgs(fields []*ast.Field) ([]arg, error) {
  175. var args []arg
  176. for _, f := range fields {
  177. if len(f.Names) == 0 {
  178. return nil, errBadReturn
  179. }
  180. for _, name := range f.Names {
  181. p, err := parseExpr(f.Type)
  182. if err != nil {
  183. return nil, err
  184. }
  185. args = append(args, arg{name.Name, p.value, p.pkg})
  186. }
  187. }
  188. return args, nil
  189. }
  190. type parsedExpr struct {
  191. value string
  192. pkg string
  193. }
  194. func parseExpr(e ast.Expr) (parsedExpr, error) {
  195. var parsed parsedExpr
  196. switch i := e.(type) {
  197. case *ast.Ident:
  198. parsed.value += i.Name
  199. case *ast.StarExpr:
  200. p, err := parseExpr(i.X)
  201. if err != nil {
  202. return parsed, err
  203. }
  204. parsed.value += "*"
  205. parsed.value += p.value
  206. parsed.pkg = p.pkg
  207. case *ast.SelectorExpr:
  208. p, err := parseExpr(i.X)
  209. if err != nil {
  210. return parsed, err
  211. }
  212. parsed.pkg = p.value
  213. parsed.value += p.value + "."
  214. parsed.value += i.Sel.Name
  215. case *ast.MapType:
  216. parsed.value += "map["
  217. p, err := parseExpr(i.Key)
  218. if err != nil {
  219. return parsed, err
  220. }
  221. parsed.value += p.value
  222. parsed.value += "]"
  223. p, err = parseExpr(i.Value)
  224. if err != nil {
  225. return parsed, err
  226. }
  227. parsed.value += p.value
  228. parsed.pkg = p.pkg
  229. case *ast.ArrayType:
  230. parsed.value += "[]"
  231. p, err := parseExpr(i.Elt)
  232. if err != nil {
  233. return parsed, err
  234. }
  235. parsed.value += p.value
  236. parsed.pkg = p.pkg
  237. default:
  238. return parsed, errUnexpectedType{"*ast.Ident or *ast.StarExpr", i}
  239. }
  240. return parsed, nil
  241. }