gen.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package bind
  5. import (
  6. "bytes"
  7. "fmt"
  8. "go/ast"
  9. "go/token"
  10. "go/types"
  11. "io"
  12. "regexp"
  13. "strings"
  14. "unicode"
  15. "unicode/utf8"
  16. )
  17. type (
  18. ErrorList []error
  19. // varMode describes the lifetime of an argument or
  20. // return value. Modes are used to guide the conversion
  21. // of string and byte slice values across the language
  22. // barrier. The same conversion mode must be used for
  23. // both the conversion before a foreign call and the
  24. // corresponding conversion after the call.
  25. // See the mode* constants for a description of
  26. // each mode.
  27. varMode int
  28. )
  29. const (
  30. // modeTransient are for function arguments that
  31. // are not used after the function returns.
  32. // Transient byte slices don't need copying
  33. // when passed across the language barrier.
  34. modeTransient varMode = iota
  35. // modeRetained are for returned values and for function
  36. // arguments that are used after the function returns.
  37. // Retained byte slices need an intermediate copy.
  38. modeRetained
  39. )
  40. func (list ErrorList) Error() string {
  41. buf := new(bytes.Buffer)
  42. for i, err := range list {
  43. if i > 0 {
  44. buf.WriteRune('\n')
  45. }
  46. io.WriteString(buf, err.Error())
  47. }
  48. return buf.String()
  49. }
  50. // interfaceInfo comes from Init and collects the auxiliary information
  51. // needed to generate bindings for an exported Go interface in a bound
  52. // package.
  53. type interfaceInfo struct {
  54. obj *types.TypeName
  55. t *types.Interface
  56. summary ifaceSummary
  57. }
  58. // structInfo comes from Init and collects the auxiliary information
  59. // needed to generate bindings for an exported Go struct in a bound
  60. // package.
  61. type structInfo struct {
  62. obj *types.TypeName
  63. t *types.Struct
  64. }
  65. // Generator contains the common Go package information
  66. // needed for the specific Go, Java, ObjC generators.
  67. //
  68. // After setting Printer, Fset, AllPkg, Pkg, the Init
  69. // method is used to initialize the auxiliary information
  70. // about the package to be generated, Pkg.
  71. type Generator struct {
  72. *Printer
  73. Fset *token.FileSet
  74. AllPkg []*types.Package
  75. Files []*ast.File
  76. Pkg *types.Package
  77. err ErrorList
  78. // fields set by init.
  79. pkgName string
  80. pkgPrefix string
  81. funcs []*types.Func
  82. constants []*types.Const
  83. vars []*types.Var
  84. interfaces []interfaceInfo
  85. structs []structInfo
  86. otherNames []*types.TypeName
  87. // allIntf contains interfaces from all bound packages.
  88. allIntf []interfaceInfo
  89. docs pkgDocs
  90. }
  91. // A pkgDocs maps the name of each exported package-level declaration to its extracted documentation.
  92. type pkgDocs map[string]*pkgDoc
  93. type pkgDoc struct {
  94. doc string
  95. // Struct or interface fields and methods.
  96. members map[string]string
  97. }
  98. // pkgPrefix returns a prefix that disambiguates symbol names for binding
  99. // multiple packages.
  100. //
  101. // TODO(elias.naur): Avoid (and test) name clashes from multiple packages
  102. // with the same name. Perhaps use the index from the order the package is
  103. // generated.
  104. func pkgPrefix(pkg *types.Package) string {
  105. // The error type has no package
  106. if pkg == nil {
  107. return ""
  108. }
  109. return pkg.Name()
  110. }
  111. func (g *Generator) Init() {
  112. if g.Pkg != nil {
  113. g.pkgName = g.Pkg.Name()
  114. }
  115. g.pkgPrefix = pkgPrefix(g.Pkg)
  116. if g.Pkg != nil {
  117. g.parseDocs()
  118. scope := g.Pkg.Scope()
  119. hasExported := false
  120. for _, name := range scope.Names() {
  121. obj := scope.Lookup(name)
  122. if !obj.Exported() {
  123. continue
  124. }
  125. hasExported = true
  126. switch obj := obj.(type) {
  127. case *types.Func:
  128. if isCallable(obj) {
  129. g.funcs = append(g.funcs, obj)
  130. }
  131. case *types.TypeName:
  132. named, ok := obj.Type().(*types.Named)
  133. if !ok {
  134. continue
  135. }
  136. switch t := named.Underlying().(type) {
  137. case *types.Struct:
  138. g.structs = append(g.structs, structInfo{obj, t})
  139. case *types.Interface:
  140. g.interfaces = append(g.interfaces, interfaceInfo{obj, t, makeIfaceSummary(t)})
  141. default:
  142. g.otherNames = append(g.otherNames, obj)
  143. }
  144. case *types.Const:
  145. g.constants = append(g.constants, obj)
  146. case *types.Var:
  147. g.vars = append(g.vars, obj)
  148. default:
  149. g.errorf("unsupported exported type for %s: %T", obj.Name(), obj)
  150. }
  151. }
  152. if !hasExported {
  153. g.errorf("no exported names in the package %q", g.Pkg.Path())
  154. }
  155. } else {
  156. // Bind the single supported type from the universe scope, error.
  157. errType := types.Universe.Lookup("error").(*types.TypeName)
  158. t := errType.Type().Underlying().(*types.Interface)
  159. g.interfaces = append(g.interfaces, interfaceInfo{errType, t, makeIfaceSummary(t)})
  160. }
  161. for _, p := range g.AllPkg {
  162. scope := p.Scope()
  163. for _, name := range scope.Names() {
  164. obj := scope.Lookup(name)
  165. if !obj.Exported() {
  166. continue
  167. }
  168. if obj, ok := obj.(*types.TypeName); ok {
  169. named, ok := obj.Type().(*types.Named)
  170. if !ok {
  171. continue
  172. }
  173. if t, ok := named.Underlying().(*types.Interface); ok {
  174. g.allIntf = append(g.allIntf, interfaceInfo{obj, t, makeIfaceSummary(t)})
  175. }
  176. }
  177. }
  178. }
  179. }
  180. // parseDocs extracts documentation from a package in a form useful for lookups.
  181. func (g *Generator) parseDocs() {
  182. d := make(pkgDocs)
  183. for _, f := range g.Files {
  184. for _, decl := range f.Decls {
  185. switch decl := decl.(type) {
  186. case *ast.GenDecl:
  187. for _, spec := range decl.Specs {
  188. switch spec := spec.(type) {
  189. case *ast.TypeSpec:
  190. d.addType(spec, decl.Doc)
  191. case *ast.ValueSpec:
  192. d.addValue(spec, decl.Doc)
  193. }
  194. }
  195. case *ast.FuncDecl:
  196. d.addFunc(decl)
  197. }
  198. }
  199. }
  200. g.docs = d
  201. }
  202. func (d pkgDocs) addValue(t *ast.ValueSpec, outerDoc *ast.CommentGroup) {
  203. for _, n := range t.Names {
  204. if !ast.IsExported(n.Name) {
  205. continue
  206. }
  207. doc := t.Doc
  208. if doc == nil {
  209. doc = outerDoc
  210. }
  211. if doc != nil {
  212. d[n.Name] = &pkgDoc{doc: doc.Text()}
  213. }
  214. }
  215. }
  216. func (d pkgDocs) addFunc(f *ast.FuncDecl) {
  217. doc := f.Doc
  218. if doc == nil {
  219. return
  220. }
  221. fn := f.Name.Name
  222. if !ast.IsExported(fn) {
  223. return
  224. }
  225. if r := f.Recv; r != nil {
  226. // f is a method.
  227. n := typeName(r.List[0].Type)
  228. pd, exists := d[n]
  229. if !exists {
  230. pd = &pkgDoc{members: make(map[string]string)}
  231. d[n] = pd
  232. }
  233. pd.members[fn] = doc.Text()
  234. } else {
  235. // f is a function.
  236. d[fn] = &pkgDoc{doc: doc.Text()}
  237. }
  238. }
  239. func (d pkgDocs) addType(t *ast.TypeSpec, outerDoc *ast.CommentGroup) {
  240. if !ast.IsExported(t.Name.Name) {
  241. return
  242. }
  243. doc := t.Doc
  244. if doc == nil {
  245. doc = outerDoc
  246. }
  247. pd := d[t.Name.Name]
  248. pd = &pkgDoc{members: make(map[string]string)}
  249. d[t.Name.Name] = pd
  250. if doc != nil {
  251. pd.doc = doc.Text()
  252. }
  253. var fields *ast.FieldList
  254. switch t := t.Type.(type) {
  255. case *ast.StructType:
  256. fields = t.Fields
  257. case *ast.InterfaceType:
  258. fields = t.Methods
  259. }
  260. if fields != nil {
  261. for _, field := range fields.List {
  262. if field.Doc != nil {
  263. if field.Names == nil {
  264. // Anonymous field. Extract name from its type.
  265. if n := typeName(field.Type); ast.IsExported(n) {
  266. pd.members[n] = field.Doc.Text()
  267. }
  268. }
  269. for _, n := range field.Names {
  270. if ast.IsExported(n.Name) {
  271. pd.members[n.Name] = field.Doc.Text()
  272. }
  273. }
  274. }
  275. }
  276. }
  277. }
  278. // typeName returns the type name T for expressions on the
  279. // T, *T, **T (etc.) form.
  280. func typeName(t ast.Expr) string {
  281. switch t := t.(type) {
  282. case *ast.StarExpr:
  283. return typeName(t.X)
  284. case *ast.Ident:
  285. return t.Name
  286. case *ast.SelectorExpr:
  287. return t.Sel.Name
  288. default:
  289. return ""
  290. }
  291. }
  292. func (d *pkgDoc) Doc() string {
  293. if d == nil {
  294. return ""
  295. }
  296. return d.doc
  297. }
  298. func (d *pkgDoc) Member(n string) string {
  299. if d == nil {
  300. return ""
  301. }
  302. return d.members[n]
  303. }
  304. // constructorType returns the type T for a function of the forms:
  305. //
  306. // func NewT...(...) *T
  307. // func NewT...(...) (*T, error)
  308. func (g *Generator) constructorType(f *types.Func) *types.TypeName {
  309. sig := f.Type().(*types.Signature)
  310. res := sig.Results()
  311. if res.Len() != 1 && !(res.Len() == 2 && isErrorType(res.At(1).Type())) {
  312. return nil
  313. }
  314. rt := res.At(0).Type()
  315. pt, ok := rt.(*types.Pointer)
  316. if !ok {
  317. return nil
  318. }
  319. nt, ok := pt.Elem().(*types.Named)
  320. if !ok {
  321. return nil
  322. }
  323. obj := nt.Obj()
  324. if !strings.HasPrefix(f.Name(), "New"+obj.Name()) {
  325. return nil
  326. }
  327. return obj
  328. }
  329. func toCFlag(v bool) int {
  330. if v {
  331. return 1
  332. }
  333. return 0
  334. }
  335. func (g *Generator) errorf(format string, args ...interface{}) {
  336. g.err = append(g.err, fmt.Errorf(format, args...))
  337. }
  338. // cgoType returns the name of a Cgo type suitable for converting a value of
  339. // the given type.
  340. func (g *Generator) cgoType(t types.Type) string {
  341. switch t := t.(type) {
  342. case *types.Basic:
  343. switch t.Kind() {
  344. case types.Bool, types.UntypedBool:
  345. return "char"
  346. case types.Int:
  347. return "nint"
  348. case types.Int8:
  349. return "int8_t"
  350. case types.Int16:
  351. return "int16_t"
  352. case types.Int32, types.UntypedRune: // types.Rune
  353. return "int32_t"
  354. case types.Int64, types.UntypedInt:
  355. return "int64_t"
  356. case types.Uint8: // types.Byte
  357. return "uint8_t"
  358. // TODO(crawshaw): case types.Uint, types.Uint16, types.Uint32, types.Uint64:
  359. case types.Float32:
  360. return "float"
  361. case types.Float64, types.UntypedFloat:
  362. return "double"
  363. case types.String:
  364. return "nstring"
  365. default:
  366. g.errorf("unsupported basic type: %s", t)
  367. }
  368. case *types.Slice:
  369. switch e := t.Elem().(type) {
  370. case *types.Basic:
  371. switch e.Kind() {
  372. case types.Uint8: // Byte.
  373. return "nbyteslice"
  374. default:
  375. g.errorf("unsupported slice type: %s", t)
  376. }
  377. default:
  378. g.errorf("unsupported slice type: %s", t)
  379. }
  380. case *types.Pointer:
  381. if _, ok := t.Elem().(*types.Named); ok {
  382. return g.cgoType(t.Elem())
  383. }
  384. g.errorf("unsupported pointer to type: %s", t)
  385. case *types.Named:
  386. return "int32_t"
  387. default:
  388. g.errorf("unsupported type: %s", t)
  389. }
  390. return "TODO"
  391. }
  392. func (g *Generator) genInterfaceMethodSignature(m *types.Func, iName string, header bool, g_paramName func(*types.Tuple, int) string) {
  393. sig := m.Type().(*types.Signature)
  394. params := sig.Params()
  395. res := sig.Results()
  396. if res.Len() == 0 {
  397. g.Printf("void ")
  398. } else {
  399. if res.Len() == 1 {
  400. g.Printf("%s ", g.cgoType(res.At(0).Type()))
  401. } else {
  402. if header {
  403. g.Printf("typedef struct cproxy%s_%s_%s_return {\n", g.pkgPrefix, iName, m.Name())
  404. g.Indent()
  405. for i := 0; i < res.Len(); i++ {
  406. t := res.At(i).Type()
  407. g.Printf("%s r%d;\n", g.cgoType(t), i)
  408. }
  409. g.Outdent()
  410. g.Printf("} cproxy%s_%s_%s_return;\n", g.pkgPrefix, iName, m.Name())
  411. }
  412. g.Printf("struct cproxy%s_%s_%s_return ", g.pkgPrefix, iName, m.Name())
  413. }
  414. }
  415. g.Printf("cproxy%s_%s_%s(int32_t refnum", g.pkgPrefix, iName, m.Name())
  416. for i := 0; i < params.Len(); i++ {
  417. t := params.At(i).Type()
  418. g.Printf(", %s %s", g.cgoType(t), g_paramName(params, i))
  419. }
  420. g.Printf(")")
  421. if header {
  422. g.Printf(";\n")
  423. } else {
  424. g.Printf(" {\n")
  425. }
  426. }
  427. func (g *Generator) validPkg(pkg *types.Package) bool {
  428. for _, p := range g.AllPkg {
  429. if p == pkg {
  430. return true
  431. }
  432. }
  433. return false
  434. }
  435. // isSigSupported reports whether the generators can handle a given
  436. // function signature.
  437. func (g *Generator) isSigSupported(t types.Type) bool {
  438. sig := t.(*types.Signature)
  439. params := sig.Params()
  440. for i := 0; i < params.Len(); i++ {
  441. if !g.isSupported(params.At(i).Type()) {
  442. return false
  443. }
  444. }
  445. res := sig.Results()
  446. for i := 0; i < res.Len(); i++ {
  447. if !g.isSupported(res.At(i).Type()) {
  448. return false
  449. }
  450. }
  451. return true
  452. }
  453. // isSupported reports whether the generators can handle the type.
  454. func (g *Generator) isSupported(t types.Type) bool {
  455. if isErrorType(t) || isWrapperType(t) {
  456. return true
  457. }
  458. switch t := t.(type) {
  459. case *types.Basic:
  460. switch t.Kind() {
  461. case types.Bool, types.UntypedBool,
  462. types.Int,
  463. types.Int8, types.Uint8, // types.Byte
  464. types.Int16,
  465. types.Int32, types.UntypedRune, // types.Rune
  466. types.Int64, types.UntypedInt,
  467. types.Float32,
  468. types.Float64, types.UntypedFloat,
  469. types.String, types.UntypedString:
  470. return true
  471. }
  472. return false
  473. case *types.Slice:
  474. switch e := t.Elem().(type) {
  475. case *types.Basic:
  476. return e.Kind() == types.Uint8
  477. }
  478. case *types.Pointer:
  479. switch t := t.Elem().(type) {
  480. case *types.Named:
  481. return g.validPkg(t.Obj().Pkg())
  482. }
  483. case *types.Named:
  484. switch t.Underlying().(type) {
  485. case *types.Interface, *types.Pointer:
  486. return g.validPkg(t.Obj().Pkg())
  487. }
  488. }
  489. return false
  490. }
  491. var paramRE = regexp.MustCompile(`^p[0-9]*$`)
  492. // basicParamName replaces incompatible name with a p0-pN name.
  493. // Missing names, or existing names of the form p[0-9] are incompatible.
  494. func basicParamName(params *types.Tuple, pos int) string {
  495. name := params.At(pos).Name()
  496. if name == "" || name[0] == '_' || paramRE.MatchString(name) {
  497. name = fmt.Sprintf("p%d", pos)
  498. }
  499. return name
  500. }
  501. func lowerFirst(s string) string {
  502. if s == "" {
  503. return ""
  504. }
  505. var conv []rune
  506. for len(s) > 0 {
  507. r, n := utf8.DecodeRuneInString(s)
  508. if !unicode.IsUpper(r) {
  509. if l := len(conv); l > 1 {
  510. conv[l-1] = unicode.ToUpper(conv[l-1])
  511. }
  512. return string(conv) + s
  513. }
  514. conv = append(conv, unicode.ToLower(r))
  515. s = s[n:]
  516. }
  517. return string(conv)
  518. }
  519. // newNameSanitizer returns a functions that replaces all dashes and dots
  520. // with underscores, as well as avoiding reserved words by suffixing such
  521. // identifiers with underscores.
  522. func newNameSanitizer(res []string) func(s string) string {
  523. reserved := make(map[string]bool)
  524. for _, word := range res {
  525. reserved[word] = true
  526. }
  527. symbols := strings.NewReplacer(
  528. "-", "_",
  529. ".", "_",
  530. )
  531. return func(s string) string {
  532. if reserved[s] {
  533. return s + "_"
  534. }
  535. return symbols.Replace(s)
  536. }
  537. }