bind: generate wrappers for generated ObjC types
This is the Objective-C equivalent of CL 34776, generating reverse
wrappers for generated ObjC types. The implementation follows the same
strategy as the Java implementation: use the Go ast package to find
exported structs with embedded Objective-C types and synthesize their
types as if they were imported through clang.
In turn, the handling of the implicit "self" parameter changes in the
same way as well: the type of self parameters must be the wrapped type
for the generated type. For example:
func (d *GoNSDate) Description(self Foundation.NSDate) string
becomes
import gopkg "ObjC/Objcpkg"
func (d *GoNSDate) Description(self gopkg.GoNSDate) string
Change-Id: I26f838b06a622864be463f81dbb4dcae76f70f20
Reviewed-on: https://go-review.googlesource.com/34780
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/bind/bind_test.go b/bind/bind_test.go
index 9fe39a0..5864319 100644
--- a/bind/bind_test.go
+++ b/bind/bind_test.go
@@ -179,14 +179,7 @@
}
}
-func genObjcPackages(t *testing.T, dir string, types []*objc.Named, buf *bytes.Buffer) *ObjcWrapper {
- cg := &ObjcWrapper{
- Printer: &Printer{
- IndentEach: []byte("\t"),
- Buf: buf,
- },
- }
- cg.Init(types)
+func genObjcPackages(t *testing.T, dir string, cg *ObjcWrapper) {
pkgBase := filepath.Join(dir, "src", "ObjC")
if err := os.MkdirAll(pkgBase, 0700); err != nil {
t.Fatal(err)
@@ -197,16 +190,16 @@
t.Fatal(err)
}
pkgFile := filepath.Join(pkgDir, "package.go")
- buf.Reset()
+ cg.Buf.Reset()
cg.GenPackage(i)
- if err := ioutil.WriteFile(pkgFile, buf.Bytes(), 0600); err != nil {
+ if err := ioutil.WriteFile(pkgFile, cg.Buf.Bytes(), 0600); err != nil {
t.Fatal(err)
}
}
- buf.Reset()
+ cg.Buf.Reset()
cg.GenInterfaces()
clsFile := filepath.Join(pkgBase, "interfaces.go")
- if err := ioutil.WriteFile(clsFile, buf.Bytes(), 0600); err != nil {
+ if err := ioutil.WriteFile(clsFile, cg.Buf.Bytes(), 0600); err != nil {
t.Fatal(err)
}
@@ -220,7 +213,6 @@
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("failed to go install the generated ObjC wrappers: %v: %s", err, string(out))
}
- return cg
}
func genJavaPackages(t *testing.T, dir string, cg *ClassGen) {
@@ -422,7 +414,18 @@
t.Fatal(err)
}
defer os.RemoveAll(tmpGopath)
- cg := genObjcPackages(t, tmpGopath, types, &buf)
+ cg := &ObjcWrapper{
+ Printer: &Printer{
+ IndentEach: []byte("\t"),
+ Buf: &buf,
+ },
+ }
+ var genNames []string
+ for _, emb := range refs.Embedders {
+ genNames = append(genNames, emb.Name)
+ }
+ cg.Init(types, genNames)
+ genObjcPackages(t, tmpGopath, cg)
pkg := typeCheck(t, filename, tmpGopath)
cg.GenGo()
testGenGo(t, filename, &buf, pkg)
diff --git a/bind/genobjc.go b/bind/genobjc.go
index d374974..32ec399 100644
--- a/bind/genobjc.go
+++ b/bind/genobjc.go
@@ -51,7 +51,9 @@
for _, w := range wrappers {
g.wrapMap[w.GoName] = w
if _, exists := modMap[w.Module]; !exists {
- g.modules = append(g.modules, w.Module)
+ if !w.Generated {
+ g.modules = append(g.modules, w.Module)
+ }
modMap[w.Module] = struct{}{}
}
}
@@ -412,19 +414,20 @@
name string
}
-func (g *ObjcGen) funcSummary(oinf *objcClassInfo, obj *types.Func) *funcSummary {
- sig := obj.Type().(*types.Signature)
- s := &funcSummary{goname: obj.Name(), sig: sig}
+func (g *ObjcGen) funcSummary(obj *types.TypeName, f *types.Func) *funcSummary {
+ sig := f.Type().(*types.Signature)
+ s := &funcSummary{goname: f.Name(), sig: sig}
var om *objc.Func
var sigElems []string
+ oinf := g.ostructs[obj]
if oinf != nil {
- om = oinf.methods[obj.Name()]
+ om = oinf.methods[f.Name()]
}
if om != nil {
sigElems = strings.Split(om.Sig, ":")
s.name = sigElems[0]
} else {
- s.name = obj.Name()
+ s.name = f.Name()
}
params := sig.Params()
first := 0
@@ -433,20 +436,16 @@
v := params.At(0)
if v.Name() == "self" {
t := v.Type()
- if isObjcType(t) {
- s.hasself = true
- first = 1
- ot := g.wrapMap[t.(*types.Named).Obj().Name()]
- found := false
- for _, sup := range oinf.supers {
- if ot == sup {
- found = true
- break
+ if t, ok := t.(*types.Named); ok {
+ if pkg := t.Obj().Pkg(); pkgFirstElem(pkg) == "ObjC" {
+ s.hasself = true
+ module := pkg.Path()[len("ObjC/"):]
+ typName := module + "." + t.Obj().Name()
+ exp := g.namePrefix + "." + obj.Name()
+ if typName != exp {
+ g.errorf("the type %s of the `this` argument to method %s is not %s", typName, f.Name(), exp)
}
}
- if !found {
- g.errorf("the type %s of the `this` argument to method %s is not a super class of the enclosing struct", ot.Name, obj.Name())
- }
}
}
}
@@ -501,7 +500,7 @@
}
if !isErrorType(res.At(1).Type()) {
- g.errorf("second result value must be of type error: %s", obj)
+ g.errorf("second result value must be of type error: %s", f)
return nil
}
s.retParams = append(s.retParams, paramInfo{
@@ -510,7 +509,7 @@
})
default:
// TODO(hyangah): relax the constraint on multiple return params.
- g.errorf("too many result values: %s", obj)
+ g.errorf("too many result values: %s", f)
return nil
}
@@ -534,14 +533,18 @@
func (s *funcSummary) asMethod(g *ObjcGen) string {
var params []string
- for i, p := range s.params {
+ skip := 0
+ if s.hasself {
+ skip = 1
+ }
+ for i, p := range s.params[skip:] {
var key string
if i != 0 {
key = p.name
}
params = append(params, fmt.Sprintf("%s:(%s)%s", key, g.objcType(p.typ), p.name))
}
- skip := 0
+ skip = 0
if s.returnsVal() {
skip = 1
}
@@ -743,13 +746,15 @@
}
func (g *ObjcGen) genFunc(s *funcSummary, objName string) {
+ skip := 0
if objName != "" {
g.Printf("int32_t refnum = go_seq_go_to_refnum(self._ref);\n")
if s.hasself {
- g.genRefWrite("self")
+ skip = 1
+ g.Printf("int32_t _self = go_seq_to_refnum(self);\n")
}
}
- for _, p := range s.params {
+ for _, p := range s.params[skip:] {
g.genWrite(p.name, p.typ, modeTransient)
}
resPrefix := ""
@@ -768,7 +773,7 @@
g.Printf(", _self")
}
}
- for i, p := range s.params {
+ for i, p := range s.params[skip:] {
if i > 0 || objName != "" {
g.Printf(", ")
}
@@ -782,7 +787,7 @@
for i, r := range s.retParams {
g.genRead("_"+r.name, fmt.Sprintf("%sr%d", resPrefix, i), r.typ, modeRetained)
}
- skip := 0
+ skip = 0
if s.returnsVal() {
skip = 1
}
@@ -1045,7 +1050,7 @@
g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", obj.Name(), m.Name())
continue
}
- s := g.funcSummary(g.ostructs[obj], m)
+ s := g.funcSummary(obj, m)
g.Printf("- %s;\n", objcNameReplacer(lowerFirst(s.asMethod(g))))
}
g.Printf("@end\n")
@@ -1094,7 +1099,7 @@
g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", obj.Name(), m.Name())
continue
}
- s := g.funcSummary(g.ostructs[obj], m)
+ s := g.funcSummary(obj, m)
g.Printf("- %s {\n", s.asMethod(g))
g.Indent()
g.genFunc(s, obj.Name())
diff --git a/bind/genobjcw.go b/bind/genobjcw.go
index 99f8f14..b277f77 100644
--- a/bind/genobjcw.go
+++ b/bind/genobjcw.go
@@ -26,10 +26,18 @@
// For each module/name Go package path, the ObjC type
// with static functions or constants.
typePkgs map[string]*objc.Named
+ // supers is the map of types that need Super methods.
+ supers map[string]struct{}
}
)
-func (g *ObjcWrapper) Init(types []*objc.Named) {
+// Init initializes the ObjC types wrapper generator. Types is the
+// list of types to wrap, genNames the list of generated type names.
+func (g *ObjcWrapper) Init(types []*objc.Named, genNames []string) {
+ g.supers = make(map[string]struct{})
+ for _, s := range genNames {
+ g.supers[s] = struct{}{}
+ }
g.types = types
g.imported = make(map[string]*objc.Named)
g.modMap = make(map[string][]*objc.Named)
@@ -39,8 +47,10 @@
g.imported[n.GoName] = n
typePkg := n.Module + "/" + n.GoName
g.typePkgs[typePkg] = n
- if _, exists := g.modMap[n.Module]; !exists {
- g.modules = append(g.modules, n.Module)
+ if !n.Generated {
+ if _, exists := g.modMap[n.Module]; !exists {
+ g.modules = append(g.modules, n.Module)
+ }
}
g.modMap[n.Module] = append(g.modMap[n.Module], n)
if _, exists := pkgSet[n.Module]; !exists {
@@ -68,7 +78,7 @@
}
g.genCFuncDecl("cproxy", n.GoName, f)
g.genCFuncBody(n, f, false)
- if !n.Protocol {
+ if _, exists := g.supers[n.GoName]; exists {
g.genCFuncDecl("csuper", n.GoName, f)
g.genCFuncBody(n, f, true)
}
@@ -99,7 +109,7 @@
if super {
g.Printf("struct objc_super _super = {\n")
g.Printf(" .receiver = _this,\n")
- g.Printf(" .super_class = [%s class],\n", n.Name)
+ g.Printf(" .super_class = class_getSuperclass([%s class]),\n", n.Name)
g.Printf("};\n")
}
retType := "void"
@@ -123,7 +133,7 @@
switch f.Ret.Kind {
case objc.String, objc.Bool, objc.Data, objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double, objc.Class, objc.Protocol:
default:
- // If support struct is added, objc_msgSend_stret must be used
+ // If support for struct results is added, objc_msgSend_stret must be used
panic("unsupported type kind - use objc_msgSend_stret?")
}
}
@@ -214,6 +224,19 @@
for _, m := range g.modules {
g.Printf("@import %s;\n", m)
}
+ // Include header files for generated types
+ for _, n := range g.pkgNames {
+ hasGen := false
+ for _, t := range g.modMap[n] {
+ if t.Generated {
+ hasGen = true
+ break
+ }
+ }
+ if hasGen {
+ g.Printf("#import %q\n", n+".objc.h")
+ }
+ }
for _, tn := range []string{"int", "nstring", "nbyteslice", "long", "unsigned long", "short", "unsigned short", "bool", "char", "unsigned char", "float", "double"} {
sn := strings.Replace(tn, " ", "_", -1)
g.Printf("typedef struct ret_%s {\n", sn)
@@ -230,7 +253,7 @@
g.Printf("extern ")
g.genCFuncDecl("cproxy", n.GoName, f)
g.Printf(";\n")
- if !n.Protocol {
+ if _, exists := g.supers[n.GoName]; exists {
g.Printf("extern ")
g.genCFuncDecl("csuper", n.GoName, f)
g.Printf(";\n")
@@ -341,7 +364,7 @@
g.genFuncDecl(false, f)
g.genFuncBody(n, f, "cproxy")
}
- if !n.Protocol {
+ if _, exists := g.supers[n.GoName]; exists {
g.Printf("func (p *proxy_class_%s) Super() ObjC.%s {\n", n.GoName, n.Module+"_"+n.GoName)
g.Printf(" return &super_%s{p}\n", n.GoName)
g.Printf("}\n\n")
@@ -557,7 +580,7 @@
g.genFuncDecl(true, f)
g.Printf("\n")
}
- if !n.Protocol {
+ if _, exists := g.supers[n.GoName]; exists {
g.Printf("Super() %s\n", n.Module+"_"+n.GoName)
}
g.Outdent()
diff --git a/bind/testdata/objc.go.golden b/bind/testdata/objc.go.golden
index eaa3ce7..c03ecf1 100644
--- a/bind/testdata/objc.go.golden
+++ b/bind/testdata/objc.go.golden
@@ -6,15 +6,12 @@
const Dummy = 0
type Foundation_NSString interface {
- Super() Foundation_NSString
}
type Foundation_NSDate interface {
- Super() Foundation_NSDate
}
type Foundation_NSObjectC interface {
- Super() Foundation_NSObjectC
}
// File is generated by gobind. Do not edit.
@@ -42,12 +39,6 @@
func (p *proxy_class_NSString) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
-func (p *proxy_class_NSString) Super() ObjC.Foundation_NSString {
- return &super_NSString{p}
-}
-
-type super_NSString struct {*proxy_class_NSString}
-
func init() {
}
@@ -55,12 +46,6 @@
func (p *proxy_class_NSDate) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
-func (p *proxy_class_NSDate) Super() ObjC.Foundation_NSDate {
- return &super_NSDate{p}
-}
-
-type super_NSDate struct {*proxy_class_NSDate}
-
func init() {
}
@@ -68,12 +53,6 @@
func (p *proxy_class_NSObjectC) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
-func (p *proxy_class_NSObjectC) Super() ObjC.Foundation_NSObjectC {
- return &super_NSObjectC{p}
-}
-
-type super_NSObjectC struct {*proxy_class_NSObjectC}
-
// Package gomobile_bind is an autogenerated binder stub for package objc.
// gobind -lang=go objc
//
@@ -96,24 +75,14 @@
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
-// skipped method D.Super with unsupported parameter or return types
-
type proxyobjc_D _seq.Ref
func (p *proxyobjc_D) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
-// skipped method D.Super with unsupported parameter or result types
-// skipped method O.Super with unsupported parameter or return types
-
type proxyobjc_O _seq.Ref
func (p *proxyobjc_O) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
-// skipped method O.Super with unsupported parameter or result types
-// skipped method S.Super with unsupported parameter or return types
-
type proxyobjc_S _seq.Ref
func (p *proxyobjc_S) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
-
-// skipped method S.Super with unsupported parameter or result types
diff --git a/bind/testdata/objcw.go.golden b/bind/testdata/objcw.go.golden
index 056a784..f0f237b 100644
--- a/bind/testdata/objcw.go.golden
+++ b/bind/testdata/objcw.go.golden
@@ -8,13 +8,11 @@
type Foundation_NSDate interface {
Hash() (uint)
Description() (string)
- Super() Foundation_NSDate
}
type Foundation_NSObjectC interface {
Hash() (uint)
Description() (string)
- Super() Foundation_NSObjectC
}
type Foundation_NSObjectP interface {
@@ -25,19 +23,34 @@
type Foundation_NSSet interface {
Hash() (uint)
Description() (string)
- Super() Foundation_NSSet
}
type UIKit_UIResponder interface {
Hash() (uint)
Description() (string)
- Super() UIKit_UIResponder
}
type UIKit_UIPressesEvent interface {
Hash() (uint)
Description() (string)
- Super() UIKit_UIPressesEvent
+}
+
+type Objc_GoNSDate interface {
+ Hash() (uint)
+ Description() (string)
+ Super() Objc_GoNSDate
+}
+
+type Objc_GoNSObject interface {
+ Hash() (uint)
+ Description() (string)
+ Super() Objc_GoNSObject
+}
+
+type Objc_GoUIResponder interface {
+ Hash() (uint)
+ Description() (string)
+ Super() Objc_GoUIResponder
}
// File is generated by gobind. Do not edit.
@@ -77,24 +90,6 @@
return _res
}
-func (p *proxy_class_NSDate) Super() ObjC.Foundation_NSDate {
- return &super_NSDate{p}
-}
-
-type super_NSDate struct {*proxy_class_NSDate}
-
-func (p *super_NSDate) Hash() (uint) {
- res := C.csuper_NSDate_Hash(C.int(p.Bind_proxy_refnum__()))
- _res := uint(res)
- return _res
-}
-
-func (p *super_NSDate) Description() (string) {
- res := C.csuper_NSDate_Description(C.int(p.Bind_proxy_refnum__()))
- _res := decodeString(res)
- return _res
-}
-
func init() {
}
@@ -114,24 +109,6 @@
return _res
}
-func (p *proxy_class_NSObjectC) Super() ObjC.Foundation_NSObjectC {
- return &super_NSObjectC{p}
-}
-
-type super_NSObjectC struct {*proxy_class_NSObjectC}
-
-func (p *super_NSObjectC) Hash() (uint) {
- res := C.csuper_NSObjectC_Hash(C.int(p.Bind_proxy_refnum__()))
- _res := uint(res)
- return _res
-}
-
-func (p *super_NSObjectC) Description() (string) {
- res := C.csuper_NSObjectC_Description(C.int(p.Bind_proxy_refnum__()))
- _res := decodeString(res)
- return _res
-}
-
func init() {
}
@@ -170,24 +147,6 @@
return _res
}
-func (p *proxy_class_NSSet) Super() ObjC.Foundation_NSSet {
- return &super_NSSet{p}
-}
-
-type super_NSSet struct {*proxy_class_NSSet}
-
-func (p *super_NSSet) Hash() (uint) {
- res := C.csuper_NSSet_Hash(C.int(p.Bind_proxy_refnum__()))
- _res := uint(res)
- return _res
-}
-
-func (p *super_NSSet) Description() (string) {
- res := C.csuper_NSSet_Description(C.int(p.Bind_proxy_refnum__()))
- _res := decodeString(res)
- return _res
-}
-
func init() {
}
@@ -207,24 +166,6 @@
return _res
}
-func (p *proxy_class_UIResponder) Super() ObjC.UIKit_UIResponder {
- return &super_UIResponder{p}
-}
-
-type super_UIResponder struct {*proxy_class_UIResponder}
-
-func (p *super_UIResponder) Hash() (uint) {
- res := C.csuper_UIResponder_Hash(C.int(p.Bind_proxy_refnum__()))
- _res := uint(res)
- return _res
-}
-
-func (p *super_UIResponder) Description() (string) {
- res := C.csuper_UIResponder_Description(C.int(p.Bind_proxy_refnum__()))
- _res := decodeString(res)
- return _res
-}
-
func init() {
}
@@ -244,20 +185,113 @@
return _res
}
-func (p *proxy_class_UIPressesEvent) Super() ObjC.UIKit_UIPressesEvent {
- return &super_UIPressesEvent{p}
+func init() {
}
-type super_UIPressesEvent struct {*proxy_class_UIPressesEvent}
+type proxy_class_GoNSDate _seq.Ref
-func (p *super_UIPressesEvent) Hash() (uint) {
- res := C.csuper_UIPressesEvent_Hash(C.int(p.Bind_proxy_refnum__()))
+func (p *proxy_class_GoNSDate) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
+
+func (p *proxy_class_GoNSDate) Hash() (uint) {
+ res := C.cproxy_GoNSDate_Hash(C.int(p.Bind_proxy_refnum__()))
_res := uint(res)
return _res
}
-func (p *super_UIPressesEvent) Description() (string) {
- res := C.csuper_UIPressesEvent_Description(C.int(p.Bind_proxy_refnum__()))
+func (p *proxy_class_GoNSDate) Description() (string) {
+ res := C.cproxy_GoNSDate_Description(C.int(p.Bind_proxy_refnum__()))
+ _res := decodeString(res)
+ return _res
+}
+
+func (p *proxy_class_GoNSDate) Super() ObjC.Objc_GoNSDate {
+ return &super_GoNSDate{p}
+}
+
+type super_GoNSDate struct {*proxy_class_GoNSDate}
+
+func (p *super_GoNSDate) Hash() (uint) {
+ res := C.csuper_GoNSDate_Hash(C.int(p.Bind_proxy_refnum__()))
+ _res := uint(res)
+ return _res
+}
+
+func (p *super_GoNSDate) Description() (string) {
+ res := C.csuper_GoNSDate_Description(C.int(p.Bind_proxy_refnum__()))
+ _res := decodeString(res)
+ return _res
+}
+
+func init() {
+}
+
+type proxy_class_GoNSObject _seq.Ref
+
+func (p *proxy_class_GoNSObject) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
+
+func (p *proxy_class_GoNSObject) Hash() (uint) {
+ res := C.cproxy_GoNSObject_Hash(C.int(p.Bind_proxy_refnum__()))
+ _res := uint(res)
+ return _res
+}
+
+func (p *proxy_class_GoNSObject) Description() (string) {
+ res := C.cproxy_GoNSObject_Description(C.int(p.Bind_proxy_refnum__()))
+ _res := decodeString(res)
+ return _res
+}
+
+func (p *proxy_class_GoNSObject) Super() ObjC.Objc_GoNSObject {
+ return &super_GoNSObject{p}
+}
+
+type super_GoNSObject struct {*proxy_class_GoNSObject}
+
+func (p *super_GoNSObject) Hash() (uint) {
+ res := C.csuper_GoNSObject_Hash(C.int(p.Bind_proxy_refnum__()))
+ _res := uint(res)
+ return _res
+}
+
+func (p *super_GoNSObject) Description() (string) {
+ res := C.csuper_GoNSObject_Description(C.int(p.Bind_proxy_refnum__()))
+ _res := decodeString(res)
+ return _res
+}
+
+func init() {
+}
+
+type proxy_class_GoUIResponder _seq.Ref
+
+func (p *proxy_class_GoUIResponder) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
+
+func (p *proxy_class_GoUIResponder) Hash() (uint) {
+ res := C.cproxy_GoUIResponder_Hash(C.int(p.Bind_proxy_refnum__()))
+ _res := uint(res)
+ return _res
+}
+
+func (p *proxy_class_GoUIResponder) Description() (string) {
+ res := C.cproxy_GoUIResponder_Description(C.int(p.Bind_proxy_refnum__()))
+ _res := decodeString(res)
+ return _res
+}
+
+func (p *proxy_class_GoUIResponder) Super() ObjC.Objc_GoUIResponder {
+ return &super_GoUIResponder{p}
+}
+
+type super_GoUIResponder struct {*proxy_class_GoUIResponder}
+
+func (p *super_GoUIResponder) Hash() (uint) {
+ res := C.csuper_GoUIResponder_Hash(C.int(p.Bind_proxy_refnum__()))
+ _res := uint(res)
+ return _res
+}
+
+func (p *super_GoUIResponder) Description() (string) {
+ res := C.csuper_GoUIResponder_Description(C.int(p.Bind_proxy_refnum__()))
_res := decodeString(res)
return _res
}
diff --git a/bind/testpkg/objcpkg/classes.go b/bind/testpkg/objcpkg/classes.go
index 7fd761f..d90a294 100644
--- a/bind/testpkg/objcpkg/classes.go
+++ b/bind/testpkg/objcpkg/classes.go
@@ -6,6 +6,7 @@
import (
"ObjC/Foundation"
+ gopkg "ObjC/Objcpkg"
"ObjC/UIKit"
)
@@ -18,11 +19,11 @@
Foundation.NSDate
}
-func (d *GoNSDate) Hash(self Foundation.NSDate) int {
+func (d *GoNSDate) Hash(self gopkg.GoNSDate) int {
return Hash
}
-func (d *GoNSDate) Description(self Foundation.NSDate) string {
+func (d *GoNSDate) Description(self gopkg.GoNSDate) string {
// Test self call
if h := self.Hash(); h != Hash {
panic("hash mismatch")
@@ -30,7 +31,7 @@
return DescriptionStr
}
-func (d *GoNSDate) GetSelf(self Foundation.NSDate) Foundation.NSDate {
+func (d *GoNSDate) GetSelf(self gopkg.GoNSDate) Foundation.NSDate {
return self
}
@@ -44,7 +45,7 @@
UseSelf bool
}
-func (o *GoNSObject) Description(self Foundation.NSObjectC) string {
+func (o *GoNSObject) Description(self gopkg.GoNSObject) string {
if o.UseSelf {
return DescriptionStr
} else {
diff --git a/cmd/gomobile/bind.go b/cmd/gomobile/bind.go
index e9a685b..1256265 100644
--- a/cmd/gomobile/bind.go
+++ b/cmd/gomobile/bind.go
@@ -311,7 +311,11 @@
Buf: &buf,
},
}
- g.Init(types)
+ var genNames []string
+ for _, emb := range refs.Embedders {
+ genNames = append(genNames, emb.Name)
+ }
+ g.Init(types, genNames)
for i, name := range g.Packages() {
pkgDir := filepath.Join(pkgGen, "src", "ObjC", name)
if err := os.MkdirAll(pkgDir, 0700); err != nil {
diff --git a/internal/importers/objc/objc.go b/internal/importers/objc/objc.go
index 517ae08..a202d15 100644
--- a/internal/importers/objc/objc.go
+++ b/internal/importers/objc/objc.go
@@ -45,6 +45,9 @@
// declarations.
funcMap map[string]struct{}
Protocol bool
+ // Generated is true if the type is wrapper of a
+ // generated Go struct.
+ Generated bool
}
// Super denotes a super class or protocol.
@@ -111,6 +114,10 @@
modMap := make(map[string]struct{})
typeNames := make(map[string][]string)
typeSet := make(map[string]struct{})
+ genMods := make(map[string]struct{})
+ for _, emb := range refs.Embedders {
+ genMods[initialUpper(emb.Pkg)] = struct{}{}
+ }
for _, ref := range refs.Refs {
var module, name string
if idx := strings.Index(ref.Pkg, "/"); idx != -1 {
@@ -128,8 +135,11 @@
typeSet[fullName] = struct{}{}
}
if _, exists := modMap[module]; !exists {
- modMap[module] = struct{}{}
- modules = append(modules, module)
+ // Include the module only if it is generated.
+ if _, exists := genMods[module]; !exists {
+ modMap[module] = struct{}{}
+ modules = append(modules, module)
+ }
}
}
var allTypes []*Named
@@ -141,6 +151,30 @@
}
allTypes = append(allTypes, types...)
}
+ // Embedders refer to every exported Go struct that will have its class
+ // generated. Allow Go code to reverse bind to those classes by synthesizing
+ // their descriptors.
+ for _, emb := range refs.Embedders {
+ module := initialUpper(emb.Pkg)
+ named := &Named{
+ Name: module + emb.Name,
+ GoName: emb.Name,
+ Module: module,
+ Generated: true,
+ }
+ for _, ref := range emb.Refs {
+ t, exists := typeMap[ref.Name]
+ if !exists {
+ return nil, fmt.Errorf("type not found: %q", ref.Name)
+ }
+ named.Supers = append(named.Supers, Super{
+ Name: t.Name,
+ Protocol: t.Protocol,
+ })
+ }
+ typeMap[emb.Name] = named
+ allTypes = append(allTypes, named)
+ }
for _, t := range allTypes {
fillAllMethods(t, typeMap)
}