bind: declare implemented ObjC protocols

Declare all implemented interfaces in the protocol list of a bound
struct. This is the ObjC equivalent of similar functionality for
Java.

Change-Id: Ibaea881f57fecf8a0716d25ec925de43974fe0fe
Reviewed-on: https://go-review.googlesource.com/52010
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/bind/genobjc.go b/bind/genobjc.go
index 38d723e..6c87827 100644
--- a/bind/genobjc.go
+++ b/bind/genobjc.go
@@ -178,14 +178,14 @@
 	}
 
 	// @interfaces
-	for _, s := range g.structs {
-		g.genStructH(s.obj, s.t)
-		g.Printf("\n")
-	}
 	for _, i := range g.interfaces {
 		g.genInterfaceH(i.obj, i.t)
 		g.Printf("\n")
 	}
+	for _, s := range g.structs {
+		g.genStructH(s.obj, s.t)
+		g.Printf("\n")
+	}
 
 	// const
 	// TODO: prefix with k?, or use a class method?
@@ -1041,8 +1041,8 @@
 func (g *ObjcGen) genStructH(obj *types.TypeName, t *types.Struct) {
 	g.Printf("@interface %s%s : ", g.namePrefix, obj.Name())
 	oinf := g.ostructs[obj]
+	var prots []string
 	if oinf != nil {
-		var prots []string
 		for _, sup := range oinf.supers {
 			if !sup.Protocol {
 				g.Printf(sup.Name)
@@ -1050,11 +1050,21 @@
 				prots = append(prots, sup.Name)
 			}
 		}
-		if len(prots) > 0 {
-			g.Printf(" <%s>", strings.Join(prots, ", "))
-		}
 	} else {
-		g.Printf("NSObject <goSeqRefInterface>")
+		g.Printf("NSObject")
+		prots = append(prots, "goSeqRefInterface")
+	}
+	pT := types.NewPointer(obj.Type())
+	for _, iface := range g.allIntf {
+		obj := iface.obj
+		if types.AssignableTo(pT, obj.Type()) {
+			n := fmt.Sprintf("%s%s", g.namePrefixOf(obj.Pkg()), obj.Name())
+			prots = append(prots, n)
+		}
+	}
+
+	if len(prots) > 0 {
+		g.Printf(" <%s>", strings.Join(prots, ", "))
 	}
 	g.Printf(" {\n")
 	g.Printf("}\n")
diff --git a/bind/testdata/ignore.objc.h.golden b/bind/testdata/ignore.objc.h.golden
index 055dde5..38656b9 100644
--- a/bind/testdata/ignore.objc.h.golden
+++ b/bind/testdata/ignore.objc.h.golden
@@ -14,7 +14,14 @@
 @protocol IgnoreI;
 @class IgnoreI;
 
-@interface IgnoreS : NSObject <goSeqRefInterface> {
+@protocol IgnoreI <NSObject>
+// skipped method I.Argument with unsupported parameter or return types
+
+// skipped method I.Result with unsupported parameter or return types
+
+@end
+
+@interface IgnoreS : NSObject <goSeqRefInterface, IgnoreI> {
 }
 @property(strong, readonly) id _ref;
 
@@ -28,13 +35,6 @@
 
 @end
 
-@protocol IgnoreI <NSObject>
-// skipped method I.Argument with unsupported parameter or return types
-
-// skipped method I.Result with unsupported parameter or return types
-
-@end
-
 // skipped const NamedConst with unsupported type: *types.Const
 
 
diff --git a/bind/testdata/issue10788.objc.h.golden b/bind/testdata/issue10788.objc.h.golden
index ee469df..1eb90ce 100644
--- a/bind/testdata/issue10788.objc.h.golden
+++ b/bind/testdata/issue10788.objc.h.golden
@@ -14,6 +14,11 @@
 @protocol Issue10788TestInterface;
 @class Issue10788TestInterface;
 
+@protocol Issue10788TestInterface <NSObject>
+- (void)doSomeWork:(Issue10788TestStruct*)s;
+- (void)multipleUnnamedParams:(long)p0 p1:(NSString*)p1 日本:(int64_t)日本;
+@end
+
 @interface Issue10788TestStruct : NSObject <goSeqRefInterface> {
 }
 @property(strong, readonly) id _ref;
@@ -24,11 +29,6 @@
 - (void)setValue:(NSString*)v;
 @end
 
-@protocol Issue10788TestInterface <NSObject>
-- (void)doSomeWork:(Issue10788TestStruct*)s;
-- (void)multipleUnnamedParams:(long)p0 p1:(NSString*)p1 日本:(int64_t)日本;
-@end
-
 @class Issue10788TestInterface;
 
 @interface Issue10788TestInterface : NSObject <goSeqRefInterface, Issue10788TestInterface> {
diff --git a/bind/testdata/structs.objc.h.golden b/bind/testdata/structs.objc.h.golden
index 00ad30c..0ba8eab 100644
--- a/bind/testdata/structs.objc.h.golden
+++ b/bind/testdata/structs.objc.h.golden
@@ -15,6 +15,10 @@
 @protocol StructsI;
 @class StructsI;
 
+@protocol StructsI <NSObject>
+- (void)m;
+@end
+
 @interface StructsS : NSObject <goSeqRefInterface> {
 }
 @property(strong, readonly) id _ref;
@@ -29,7 +33,7 @@
 - (double)sum;
 @end
 
-@interface StructsS2 : NSObject <goSeqRefInterface> {
+@interface StructsS2 : NSObject <goSeqRefInterface, StructsI> {
 }
 @property(strong, readonly) id _ref;
 
@@ -39,10 +43,6 @@
 - (NSString*)string;
 @end
 
-@protocol StructsI <NSObject>
-- (void)m;
-@end
-
 FOUNDATION_EXPORT StructsS* StructsIdentity(StructsS* s);
 
 FOUNDATION_EXPORT StructsS* StructsIdentityWithError(StructsS* s, NSError** error);
diff --git a/bind/testdata/vars.objc.h.golden b/bind/testdata/vars.objc.h.golden
index 9453f6f..666e16d 100644
--- a/bind/testdata/vars.objc.h.golden
+++ b/bind/testdata/vars.objc.h.golden
@@ -14,7 +14,10 @@
 @protocol VarsI;
 @class VarsI;
 
-@interface VarsS : NSObject <goSeqRefInterface> {
+@protocol VarsI <NSObject>
+@end
+
+@interface VarsS : NSObject <goSeqRefInterface, VarsI> {
 }
 @property(strong, readonly) id _ref;
 
@@ -22,9 +25,6 @@
 - (instancetype)init;
 @end
 
-@protocol VarsI <NSObject>
-@end
-
 @interface Vars : NSObject
 + (BOOL) aBool;
 + (void) setABool:(BOOL)v;