gengo.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. // Copyright 2014 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/types"
  9. "strings"
  10. )
  11. type goGen struct {
  12. *Generator
  13. // imports is the list of imports, in the form
  14. // "the/package/path"
  15. //
  16. // or
  17. //
  18. // name "the/package/path"
  19. //
  20. // in case of duplicates.
  21. imports []string
  22. // The set of taken import names.
  23. importNames map[string]struct{}
  24. // importMap is a map from packages to their names. The name of a package is the last
  25. // segment of its path, with duplicates resolved by appending a underscore and a unique
  26. // number.
  27. importMap map[*types.Package]string
  28. }
  29. const (
  30. goPreamble = gobindPreamble + `// Package main is an autogenerated binder stub for package %[1]s.
  31. //
  32. // autogenerated by gobind -lang=go %[2]s
  33. package main
  34. /*
  35. #include <stdlib.h>
  36. #include <stdint.h>
  37. #include "seq.h"
  38. #include "%[1]s.h"
  39. */
  40. import "C"
  41. `
  42. )
  43. func (g *goGen) genFuncBody(o *types.Func, selectorLHS string) {
  44. sig := o.Type().(*types.Signature)
  45. params := sig.Params()
  46. for i := 0; i < params.Len(); i++ {
  47. p := params.At(i)
  48. pn := "param_" + g.paramName(params, i)
  49. g.genRead("_"+pn, pn, p.Type(), modeTransient)
  50. }
  51. res := sig.Results()
  52. if res.Len() > 2 || res.Len() == 2 && !isErrorType(res.At(1).Type()) {
  53. g.errorf("functions and methods must return either zero or one values, and optionally an error")
  54. return
  55. }
  56. if res.Len() > 0 {
  57. for i := 0; i < res.Len(); i++ {
  58. if i > 0 {
  59. g.Printf(", ")
  60. }
  61. g.Printf("res_%d", i)
  62. }
  63. g.Printf(" := ")
  64. }
  65. g.Printf("%s%s(", selectorLHS, o.Name())
  66. for i := 0; i < params.Len(); i++ {
  67. if i > 0 {
  68. g.Printf(", ")
  69. }
  70. g.Printf("_param_%s", g.paramName(params, i))
  71. }
  72. g.Printf(")\n")
  73. for i := 0; i < res.Len(); i++ {
  74. pn := fmt.Sprintf("res_%d", i)
  75. g.genWrite("_"+pn, pn, res.At(i).Type(), modeRetained)
  76. }
  77. if res.Len() > 0 {
  78. g.Printf("return ")
  79. for i := 0; i < res.Len(); i++ {
  80. if i > 0 {
  81. g.Printf(", ")
  82. }
  83. g.Printf("_res_%d", i)
  84. }
  85. g.Printf("\n")
  86. }
  87. }
  88. func (g *goGen) genWrite(toVar, fromVar string, t types.Type, mode varMode) {
  89. switch t := t.(type) {
  90. case *types.Basic:
  91. switch t.Kind() {
  92. case types.String:
  93. g.Printf("%s := encodeString(%s)\n", toVar, fromVar)
  94. case types.Bool:
  95. g.Printf("var %s C.%s = 0\n", toVar, g.cgoType(t))
  96. g.Printf("if %s { %s = 1 }\n", fromVar, toVar)
  97. default:
  98. g.Printf("%s := C.%s(%s)\n", toVar, g.cgoType(t), fromVar)
  99. }
  100. case *types.Slice:
  101. switch e := t.Elem().(type) {
  102. case *types.Basic:
  103. switch e.Kind() {
  104. case types.Uint8: // Byte.
  105. g.Printf("%s := fromSlice(%s, %v)\n", toVar, fromVar, mode == modeRetained)
  106. default:
  107. g.errorf("unsupported type: %s", t)
  108. }
  109. default:
  110. g.errorf("unsupported type: %s", t)
  111. }
  112. case *types.Pointer:
  113. // TODO(crawshaw): test *int
  114. // TODO(crawshaw): test **Generator
  115. switch t := t.Elem().(type) {
  116. case *types.Named:
  117. g.genToRefNum(toVar, fromVar)
  118. default:
  119. g.errorf("unsupported type %s", t)
  120. }
  121. case *types.Named:
  122. switch u := t.Underlying().(type) {
  123. case *types.Interface, *types.Pointer:
  124. g.genToRefNum(toVar, fromVar)
  125. default:
  126. g.errorf("unsupported, direct named type %s: %s", t, u)
  127. }
  128. default:
  129. g.errorf("unsupported type %s", t)
  130. }
  131. }
  132. // genToRefNum generates Go code for converting a variable to its refnum.
  133. // Note that the nil-check cannot be lifted into seq.ToRefNum, because a nil
  134. // struct pointer does not convert to a nil interface.
  135. func (g *goGen) genToRefNum(toVar, fromVar string) {
  136. g.Printf("var %s C.int32_t = _seq.NullRefNum\n", toVar)
  137. g.Printf("if %s != nil {\n", fromVar)
  138. g.Printf(" %s = C.int32_t(_seq.ToRefNum(%s))\n", toVar, fromVar)
  139. g.Printf("}\n")
  140. }
  141. func (g *goGen) genFuncSignature(o *types.Func, objName string) {
  142. g.Printf("//export proxy%s_%s_%s\n", g.pkgPrefix, objName, o.Name())
  143. g.Printf("func proxy%s_%s_%s(", g.pkgPrefix, objName, o.Name())
  144. if objName != "" {
  145. g.Printf("refnum C.int32_t")
  146. }
  147. sig := o.Type().(*types.Signature)
  148. params := sig.Params()
  149. for i := 0; i < params.Len(); i++ {
  150. if objName != "" || i > 0 {
  151. g.Printf(", ")
  152. }
  153. p := params.At(i)
  154. g.Printf("param_%s C.%s", g.paramName(params, i), g.cgoType(p.Type()))
  155. }
  156. g.Printf(") ")
  157. res := sig.Results()
  158. if res.Len() > 0 {
  159. g.Printf("(")
  160. for i := 0; i < res.Len(); i++ {
  161. if i > 0 {
  162. g.Printf(", ")
  163. }
  164. g.Printf("C.%s", g.cgoType(res.At(i).Type()))
  165. }
  166. g.Printf(") ")
  167. }
  168. g.Printf("{\n")
  169. }
  170. func (g *goGen) paramName(params *types.Tuple, pos int) string {
  171. return basicParamName(params, pos)
  172. }
  173. func (g *goGen) genFunc(o *types.Func) {
  174. if !g.isSigSupported(o.Type()) {
  175. g.Printf("// skipped function %s with unsupported parameter or result types\n", o.Name())
  176. return
  177. }
  178. g.genFuncSignature(o, "")
  179. g.Indent()
  180. g.genFuncBody(o, g.pkgName(g.Pkg))
  181. g.Outdent()
  182. g.Printf("}\n\n")
  183. }
  184. func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) {
  185. fields := exportedFields(T)
  186. methods := exportedMethodSet(types.NewPointer(obj.Type()))
  187. for _, f := range fields {
  188. if t := f.Type(); !g.isSupported(t) {
  189. g.Printf("// skipped field %s.%s with unsupported type: %s\n\n", obj.Name(), f.Name(), t)
  190. continue
  191. }
  192. g.Printf("//export proxy%s_%s_%s_Set\n", g.pkgPrefix, obj.Name(), f.Name())
  193. g.Printf("func proxy%s_%s_%s_Set(refnum C.int32_t, v C.%s) {\n", g.pkgPrefix, obj.Name(), f.Name(), g.cgoType(f.Type()))
  194. g.Indent()
  195. g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
  196. g.genRead("_v", "v", f.Type(), modeRetained)
  197. g.Printf("ref.Get().(*%s%s).%s = _v\n", g.pkgName(g.Pkg), obj.Name(), f.Name())
  198. g.Outdent()
  199. g.Printf("}\n\n")
  200. g.Printf("//export proxy%s_%s_%s_Get\n", g.pkgPrefix, obj.Name(), f.Name())
  201. g.Printf("func proxy%s_%s_%s_Get(refnum C.int32_t) C.%s {\n", g.pkgPrefix, obj.Name(), f.Name(), g.cgoType(f.Type()))
  202. g.Indent()
  203. g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
  204. g.Printf("v := ref.Get().(*%s%s).%s\n", g.pkgName(g.Pkg), obj.Name(), f.Name())
  205. g.genWrite("_v", "v", f.Type(), modeRetained)
  206. g.Printf("return _v\n")
  207. g.Outdent()
  208. g.Printf("}\n\n")
  209. }
  210. for _, m := range methods {
  211. if !g.isSigSupported(m.Type()) {
  212. g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", obj.Name(), m.Name())
  213. continue
  214. }
  215. g.genFuncSignature(m, obj.Name())
  216. g.Indent()
  217. g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
  218. g.Printf("v := ref.Get().(*%s%s)\n", g.pkgName(g.Pkg), obj.Name())
  219. g.genFuncBody(m, "v.")
  220. g.Outdent()
  221. g.Printf("}\n\n")
  222. }
  223. // Export constructor for ObjC and Java default no-arg constructors
  224. g.Printf("//export new_%s_%s\n", g.Pkg.Name(), obj.Name())
  225. g.Printf("func new_%s_%s() C.int32_t {\n", g.Pkg.Name(), obj.Name())
  226. g.Indent()
  227. g.Printf("return C.int32_t(_seq.ToRefNum(new(%s%s)))\n", g.pkgName(g.Pkg), obj.Name())
  228. g.Outdent()
  229. g.Printf("}\n")
  230. }
  231. func (g *goGen) genVar(o *types.Var) {
  232. if t := o.Type(); !g.isSupported(t) {
  233. g.Printf("// skipped variable %s with unsupported type %s\n\n", o.Name(), t)
  234. return
  235. }
  236. // TODO(hyangah): non-struct pointer types (*int), struct type.
  237. v := fmt.Sprintf("%s%s", g.pkgName(g.Pkg), o.Name())
  238. // var I int
  239. //
  240. // func var_setI(v int)
  241. g.Printf("//export var_set%s_%s\n", g.pkgPrefix, o.Name())
  242. g.Printf("func var_set%s_%s(v C.%s) {\n", g.pkgPrefix, o.Name(), g.cgoType(o.Type()))
  243. g.Indent()
  244. g.genRead("_v", "v", o.Type(), modeRetained)
  245. g.Printf("%s = _v\n", v)
  246. g.Outdent()
  247. g.Printf("}\n")
  248. // func var_getI() int
  249. g.Printf("//export var_get%s_%s\n", g.pkgPrefix, o.Name())
  250. g.Printf("func var_get%s_%s() C.%s {\n", g.pkgPrefix, o.Name(), g.cgoType(o.Type()))
  251. g.Indent()
  252. g.Printf("v := %s\n", v)
  253. g.genWrite("_v", "v", o.Type(), modeRetained)
  254. g.Printf("return _v\n")
  255. g.Outdent()
  256. g.Printf("}\n")
  257. }
  258. func (g *goGen) genInterface(obj *types.TypeName) {
  259. iface := obj.Type().(*types.Named).Underlying().(*types.Interface)
  260. summary := makeIfaceSummary(iface)
  261. // Define the entry points.
  262. for _, m := range summary.callable {
  263. if !g.isSigSupported(m.Type()) {
  264. g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", obj.Name(), m.Name())
  265. continue
  266. }
  267. g.genFuncSignature(m, obj.Name())
  268. g.Indent()
  269. g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
  270. g.Printf("v := ref.Get().(%s%s)\n", g.pkgName(g.Pkg), obj.Name())
  271. g.genFuncBody(m, "v.")
  272. g.Outdent()
  273. g.Printf("}\n\n")
  274. }
  275. // Define a proxy interface.
  276. if !summary.implementable {
  277. // The interface defines an unexported method or a method that
  278. // uses an unexported type. We cannot generate a proxy object
  279. // for such a type.
  280. return
  281. }
  282. g.Printf("type proxy%s_%s _seq.Ref\n\n", g.pkgPrefix, obj.Name())
  283. g.Printf("func (p *proxy%s_%s) Bind_proxy_refnum__() int32 {\n", g.pkgPrefix, obj.Name())
  284. g.Indent()
  285. g.Printf("return (*_seq.Ref)(p).Bind_IncNum()\n")
  286. g.Outdent()
  287. g.Printf("}\n\n")
  288. for _, m := range summary.callable {
  289. if !g.isSigSupported(m.Type()) {
  290. g.Printf("// skipped method %s.%s with unsupported parameter or result types\n", obj.Name(), m.Name())
  291. continue
  292. }
  293. sig := m.Type().(*types.Signature)
  294. params := sig.Params()
  295. res := sig.Results()
  296. if res.Len() > 2 ||
  297. (res.Len() == 2 && !isErrorType(res.At(1).Type())) {
  298. g.errorf("functions and methods must return either zero or one value, and optionally an error: %s.%s", obj.Name(), m.Name())
  299. continue
  300. }
  301. g.Printf("func (p *proxy%s_%s) %s(", g.pkgPrefix, obj.Name(), m.Name())
  302. for i := 0; i < params.Len(); i++ {
  303. if i > 0 {
  304. g.Printf(", ")
  305. }
  306. g.Printf("param_%s %s", g.paramName(params, i), g.typeString(params.At(i).Type()))
  307. }
  308. g.Printf(") ")
  309. if res.Len() == 1 {
  310. g.Printf(g.typeString(res.At(0).Type()))
  311. } else if res.Len() == 2 {
  312. g.Printf("(%s, error)", g.typeString(res.At(0).Type()))
  313. }
  314. g.Printf(" {\n")
  315. g.Indent()
  316. for i := 0; i < params.Len(); i++ {
  317. pn := "param_" + g.paramName(params, i)
  318. g.genWrite("_"+pn, pn, params.At(i).Type(), modeTransient)
  319. }
  320. if res.Len() > 0 {
  321. g.Printf("res := ")
  322. }
  323. g.Printf("C.cproxy%s_%s_%s(C.int32_t(p.Bind_proxy_refnum__())", g.pkgPrefix, obj.Name(), m.Name())
  324. for i := 0; i < params.Len(); i++ {
  325. g.Printf(", _param_%s", g.paramName(params, i))
  326. }
  327. g.Printf(")\n")
  328. var retName string
  329. if res.Len() > 0 {
  330. if res.Len() == 1 {
  331. T := res.At(0).Type()
  332. g.genRead("_res", "res", T, modeRetained)
  333. retName = "_res"
  334. } else {
  335. var rvs []string
  336. for i := 0; i < res.Len(); i++ {
  337. rv := fmt.Sprintf("res_%d", i)
  338. g.genRead(rv, fmt.Sprintf("res.r%d", i), res.At(i).Type(), modeRetained)
  339. rvs = append(rvs, rv)
  340. }
  341. retName = strings.Join(rvs, ", ")
  342. }
  343. g.Printf("return %s\n", retName)
  344. }
  345. g.Outdent()
  346. g.Printf("}\n\n")
  347. }
  348. }
  349. func (g *goGen) genRead(toVar, fromVar string, typ types.Type, mode varMode) {
  350. switch t := typ.(type) {
  351. case *types.Basic:
  352. switch t.Kind() {
  353. case types.String:
  354. g.Printf("%s := decodeString(%s)\n", toVar, fromVar)
  355. case types.Bool:
  356. g.Printf("%s := %s != 0\n", toVar, fromVar)
  357. default:
  358. g.Printf("%s := %s(%s)\n", toVar, t.Underlying().String(), fromVar)
  359. }
  360. case *types.Slice:
  361. switch e := t.Elem().(type) {
  362. case *types.Basic:
  363. switch e.Kind() {
  364. case types.Uint8: // Byte.
  365. g.Printf("%s := toSlice(%s, %v)\n", toVar, fromVar, mode == modeRetained)
  366. default:
  367. g.errorf("unsupported type: %s", t)
  368. }
  369. default:
  370. g.errorf("unsupported type: %s", t)
  371. }
  372. case *types.Pointer:
  373. switch u := t.Elem().(type) {
  374. case *types.Named:
  375. o := u.Obj()
  376. oPkg := o.Pkg()
  377. if !g.validPkg(oPkg) {
  378. g.errorf("type %s is defined in %s, which is not bound", u, oPkg)
  379. return
  380. }
  381. g.Printf("// Must be a Go object\n")
  382. g.Printf("var %s *%s%s\n", toVar, g.pkgName(oPkg), o.Name())
  383. g.Printf("if %s_ref := _seq.FromRefNum(int32(%s)); %s_ref != nil {\n", toVar, fromVar, toVar)
  384. g.Printf(" %s = %s_ref.Get().(*%s%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name())
  385. g.Printf("}\n")
  386. default:
  387. g.errorf("unsupported pointer type %s", t)
  388. }
  389. case *types.Named:
  390. switch t.Underlying().(type) {
  391. case *types.Interface, *types.Pointer:
  392. hasProxy := true
  393. if iface, ok := t.Underlying().(*types.Interface); ok {
  394. hasProxy = makeIfaceSummary(iface).implementable
  395. }
  396. pkgFirst := typePkgFirstElem(t)
  397. isWrapper := pkgFirst == "Java" || pkgFirst == "ObjC"
  398. o := t.Obj()
  399. oPkg := o.Pkg()
  400. if !isErrorType(t) && !g.validPkg(oPkg) && !isWrapper {
  401. g.errorf("type %s is defined in %s, which is not bound", t, oPkg)
  402. return
  403. }
  404. g.Printf("var %s %s\n", toVar, g.typeString(t))
  405. g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", toVar, fromVar)
  406. g.Printf("if %s_ref != nil {\n", toVar)
  407. g.Printf(" if %s < 0 { // go object \n", fromVar)
  408. g.Printf(" %s = %s_ref.Get().(%s%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name())
  409. if hasProxy {
  410. g.Printf(" } else { // foreign object \n")
  411. if isWrapper {
  412. var clsName string
  413. switch pkgFirst {
  414. case "Java":
  415. clsName = flattenName(classNameFor(t))
  416. case "ObjC":
  417. clsName = t.Obj().Name()
  418. }
  419. g.Printf(" %s = (*proxy_class_%s)(%s_ref)\n", toVar, clsName, toVar)
  420. } else {
  421. g.Printf(" %s = (*proxy%s_%s)(%s_ref)\n", toVar, pkgPrefix(oPkg), o.Name(), toVar)
  422. }
  423. }
  424. g.Printf(" }\n")
  425. g.Printf("}\n")
  426. default:
  427. g.errorf("unsupported named type %s", t)
  428. }
  429. default:
  430. g.errorf("unsupported type: %s", typ)
  431. }
  432. }
  433. func (g *goGen) typeString(typ types.Type) string {
  434. pkg := g.Pkg
  435. switch t := typ.(type) {
  436. case *types.Named:
  437. obj := t.Obj()
  438. if obj.Pkg() == nil { // e.g. error type is *types.Named.
  439. return types.TypeString(typ, types.RelativeTo(pkg))
  440. }
  441. oPkg := obj.Pkg()
  442. if !g.validPkg(oPkg) && !isWrapperType(t) {
  443. g.errorf("type %s is defined in %s, which is not bound", t, oPkg)
  444. return "TODO"
  445. }
  446. switch t.Underlying().(type) {
  447. case *types.Interface, *types.Struct:
  448. return fmt.Sprintf("%s%s", g.pkgName(oPkg), types.TypeString(typ, types.RelativeTo(oPkg)))
  449. default:
  450. g.errorf("unsupported named type %s / %T", t, t)
  451. }
  452. case *types.Pointer:
  453. switch t := t.Elem().(type) {
  454. case *types.Named:
  455. return fmt.Sprintf("*%s", g.typeString(t))
  456. default:
  457. g.errorf("not yet supported, pointer type %s / %T", t, t)
  458. }
  459. default:
  460. return types.TypeString(typ, types.RelativeTo(pkg))
  461. }
  462. return ""
  463. }
  464. // genPreamble generates the preamble. It is generated after everything
  465. // else, where we know which bound packages to import.
  466. func (g *goGen) genPreamble() {
  467. pkgName := ""
  468. pkgPath := ""
  469. if g.Pkg != nil {
  470. pkgName = g.Pkg.Name()
  471. pkgPath = g.Pkg.Path()
  472. } else {
  473. pkgName = "universe"
  474. }
  475. g.Printf(goPreamble, pkgName, pkgPath)
  476. g.Printf("import (\n")
  477. g.Indent()
  478. g.Printf("_seq \"golang.org/x/mobile/bind/seq\"\n")
  479. for _, imp := range g.imports {
  480. g.Printf("%s\n", imp)
  481. }
  482. g.Outdent()
  483. g.Printf(")\n\n")
  484. }
  485. func (g *goGen) gen() error {
  486. g.importNames = make(map[string]struct{})
  487. g.importMap = make(map[*types.Package]string)
  488. // Switch to a temporary buffer so the preamble can be
  489. // written last.
  490. oldBuf := g.Printer.Buf
  491. newBuf := new(bytes.Buffer)
  492. g.Printer.Buf = newBuf
  493. g.Printf("// suppress the error if seq ends up unused\n")
  494. g.Printf("var _ = _seq.FromRefNum\n")
  495. for _, s := range g.structs {
  496. g.genStruct(s.obj, s.t)
  497. }
  498. for _, intf := range g.interfaces {
  499. g.genInterface(intf.obj)
  500. }
  501. for _, v := range g.vars {
  502. g.genVar(v)
  503. }
  504. for _, f := range g.funcs {
  505. g.genFunc(f)
  506. }
  507. // Switch to the original buffer, write the preamble
  508. // and append the rest of the file.
  509. g.Printer.Buf = oldBuf
  510. g.genPreamble()
  511. g.Printer.Buf.Write(newBuf.Bytes())
  512. if len(g.err) > 0 {
  513. return g.err
  514. }
  515. return nil
  516. }
  517. // pkgName returns the package name and adds the package to the list of
  518. // imports.
  519. func (g *goGen) pkgName(pkg *types.Package) string {
  520. // The error type has no package
  521. if pkg == nil {
  522. return ""
  523. }
  524. if name, exists := g.importMap[pkg]; exists {
  525. return name + "."
  526. }
  527. i := 0
  528. pname := pkg.Name()
  529. name := pkg.Name()
  530. for {
  531. if _, exists := g.importNames[name]; !exists {
  532. g.importNames[name] = struct{}{}
  533. g.importMap[pkg] = name
  534. var imp string
  535. if pname != name {
  536. imp = fmt.Sprintf("%s %q", name, pkg.Path())
  537. } else {
  538. imp = fmt.Sprintf("%q", pkg.Path())
  539. }
  540. g.imports = append(g.imports, imp)
  541. break
  542. }
  543. i++
  544. name = fmt.Sprintf("%s_%d", pname, i)
  545. }
  546. g.importMap[pkg] = name
  547. return name + "."
  548. }