diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 94ae4f876..64e3301cf 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1599,35 +1599,40 @@ public: } return ret; } - void addInterfaceNameAndUpcasts(String* interface_list, String* interface_upcasts, Node* base, String* c_classname) { - String* c_baseclass = SwigType_namestr(Getattr(base, "name")); - String* iname = getQualifiedInterfaceName(base); - if (Len(interface_list)) - Append(interface_list, ", "); - Append(interface_list, iname); + void addInterfaceNameAndUpcasts(String* interface_list, String* interface_upcasts, Hash* base_list, String* c_classname) { + List* keys = Keys(base_list); + for (Iterator it = First(keys); it.item; it = Next(it)) { + Node* base = Getattr(base_list, it.item); + String* c_baseclass = SwigType_namestr(Getattr(base, "name")); + String* iname = getQualifiedInterfaceName(base); + if (Len(interface_list)) + Append(interface_list, ", "); + Append(interface_list, iname); - Printf(interface_upcasts, " [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n"); - String* upcast_name = 0; - if (String* cptr_func = Getattr(base, "feature:interface:cptr")) - upcast_name = NewStringf("%s.%s", iname, cptr_func); - else - upcast_name = NewStringf("%s.GetCPtr", iname); - Printf(interface_upcasts, " public HandleRef %s()", upcast_name); - Replaceall(upcast_name, ".", "_"); - String *upcast_method = Swig_name_member(getNSpace(), proxy_class_name, upcast_name); - String *wname = Swig_name_wrapper(upcast_method); - Printf(interface_upcasts, "{ return new HandleRef((%s)this, %s.%s(swigCPtr.Handle)); }\n", iname, imclass_name, upcast_method ); - Printv(imclass_cppcasts_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL); - Printf(imclass_cppcasts_code, " public static extern IntPtr %s(IntPtr jarg1);\n", upcast_method); - Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); - Printv(upcasts_code, - "SWIGEXPORT ", c_baseclass, " * SWIGSTDCALL ", wname, "(", c_classname, " *jarg1) {\n", - " return (", c_baseclass, " *)jarg1;\n" - "}\n", "\n", NIL); - Delete(upcast_name); - Delete(wname); - Delete(upcast_method); - Delete(c_baseclass); + Printf(interface_upcasts, " [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n"); + String* upcast_name = 0; + if (String* cptr_func = Getattr(base, "feature:interface:cptr")) + upcast_name = NewStringf("%s.%s", iname, cptr_func); + else + upcast_name = NewStringf("%s.GetCPtr", iname); + Printf(interface_upcasts, " public HandleRef %s()", upcast_name); + Replaceall(upcast_name, ".", "_"); + String *upcast_method = Swig_name_member(getNSpace(), proxy_class_name, upcast_name); + String *wname = Swig_name_wrapper(upcast_method); + Printf(interface_upcasts, "{ return new HandleRef((%s)this, %s.%s(swigCPtr.Handle)); }\n", iname, imclass_name, upcast_method ); + Printv(imclass_cppcasts_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL); + Printf(imclass_cppcasts_code, " public static extern IntPtr %s(IntPtr jarg1);\n", upcast_method); + Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); + Printv(upcasts_code, + "SWIGEXPORT ", c_baseclass, " * SWIGSTDCALL ", wname, "(", c_classname, " *jarg1) {\n", + " return (", c_baseclass, " *)jarg1;\n" + "}\n", "\n", NIL); + Delete(upcast_name); + Delete(wname); + Delete(upcast_method); + Delete(c_baseclass); + } + Delete(keys); } /* ----------------------------------------------------------------------------- * emitProxyClassDefAndCPPCasts() @@ -1655,13 +1660,8 @@ public: List *baselist = Getattr(n, "bases"); if (baselist) { Iterator base = First(baselist); - while (base.item && GetFlag(base.item, "feature:ignore")) { - base = Next(base); - } - while (base.item && Getattr(base.item, "feature:interface")) { - addInterfaceNameAndUpcasts(interface_list, interface_upcasts, base.item, c_classname); + while (base.item && (GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface"))) base = Next(base); - } if (base.item) { c_baseclassname = Getattr(base.item, "name"); baseclass = Copy(getProxyName(c_baseclassname)); @@ -1670,9 +1670,7 @@ public: base = Next(base); /* Warn about multiple inheritance for additional base class(es) */ while (base.item) { - if (Getattr(base.item, "feature:interface")) { - addInterfaceNameAndUpcasts(interface_list, interface_upcasts, base.item, c_classname); - } else if (!GetFlag(base.item, "feature:ignore")) { + if (!GetFlag(base.item, "feature:ignore") && !Getattr(base.item, "feature:interface")) { String *proxyclassname = Getattr(n, "classtypeobj"); String *baseclassname = Getattr(base.item, "name"); Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n), @@ -1682,10 +1680,9 @@ public: } } } - if (Getattr(n, "feature:interface")) { - addInterfaceNameAndUpcasts(interface_list, interface_upcasts, n, c_classname); - } } + if (Hash* interface_classes = Getattr(n, "feature:interface:bases")) + addInterfaceNameAndUpcasts(interface_list, interface_upcasts, interface_classes, c_classname); bool derived = baseclass && getProxyName(c_baseclassname); if (derived && purebase_notderived) @@ -2144,7 +2141,8 @@ public: String *pre_code = NewString(""); String *post_code = NewString(""); String *terminator_code = NewString(""); - bool is_interface = Getattr(parentNode(n), "feature:interface") != 0 && !static_flag; + bool is_interface = Getattr(parentNode(n), "feature:interface") != 0 + && !static_flag && Getattr(n, "feature:interface:owner") == 0; if (!proxy_flag) return; diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 280cbe6cc..a6b7576cd 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -1763,20 +1763,6 @@ public: Delete(c_baseclass); } Delete(keys); - Delete(base_list); - } - - void collectInterfaceBases(Hash* bases, Node* n) { - if (Getattr(n, "feature:interface")) { - String* name = Getattr(n, "feature:interface:name"); - if (Getattr(bases, name)) - return; - Setattr(bases, name, n); - } - if (List *baselist = Getattr(n, "bases")) { - for (Iterator base = First(baselist); base.item; base = Next(base)) - collectInterfaceBases(bases, base.item); - } } /* ----------------------------------------------------------------------------- @@ -1827,8 +1813,8 @@ public: } } } - collectInterfaceBases(interface_classes, n); - addInterfaceNameAndUpcasts(interface_list, interface_upcasts, interface_classes, c_classname); + if (Hash* interface_classes = Getattr(n, "feature:interface:bases")) + addInterfaceNameAndUpcasts(interface_list, interface_upcasts, interface_classes, c_classname); bool derived = baseclass && getProxyName(c_baseclassname); if (derived && purebase_notderived) @@ -2002,9 +1988,8 @@ public: if (List *baselist = Getattr(n, "bases")) { String* bases = 0; for (Iterator base = First(baselist); base.item; base = Next(base)) { - if (GetFlag(base.item, "feature:ignore") || !Getattr(base.item, "feature:interface")) { + if (GetFlag(base.item, "feature:ignore") || !Getattr(base.item, "feature:interface")) continue; // TODO: warn about skipped non-interface bases - } String* base_iname = Getattr(base.item, "feature:interface:name"); if (!bases) bases = Copy(base_iname); @@ -2271,7 +2256,8 @@ public: bool setter_flag = false; String *pre_code = NewString(""); String *post_code = NewString(""); - bool is_interface = Getattr(parentNode(n), "feature:interface") != 0 && !static_flag; + bool is_interface = Getattr(parentNode(n), "feature:interface") != 0 + && !static_flag && Getattr(n, "feature:interface:owner") == 0; if (!proxy_flag) return; diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 78e959bfc..b8462a182 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -3604,35 +3604,65 @@ Hash *Language::getClassHash() const { return classhash; } -// 2 methods below are used in C# && Java module "feature:interface" implementation +// 4 methods below are used in C# && Java module "feature:interface" implementation // // Collect all not abstract methods from the bases marked as "interface" -void Swig_collect_non_abstract_methods(Node* n, List* methods) { - if (List *baselist = Getattr(n, "bases")) { - for (Iterator base = First(baselist); base.item; base = Next(base)) { - if (GetFlag(base.item, "feature:ignore") || !Getattr(base.item, "feature:interface")) +static void collect_interface_methods(Node* n, List* methods) { + if (Hash* bases = Getattr(n, "feature:interface:bases")){ + List* keys = Keys(bases); + for (Iterator base = First(keys); base.item; base = Next(base)) { + Node* cls = Getattr(bases, base.item); + if (cls == n) continue; - for (Node* child = firstChild(base.item); child; child = nextSibling(child)) { + for (Node* child = firstChild(cls); child; child = nextSibling(child)) { if (strcmp(Char(nodeType(child)), "cdecl") == 0) { - if (GetFlag(child, "feature:ignore") || Getattr(child, "feature:interface:owner") || GetFlag(child, "abstract")) - continue; // skip methods propagated to bases and abstracts + if (GetFlag(child, "feature:ignore") || Getattr(child, "feature:interface:owner")) + continue; // skip methods propagated to bases Node* m = Copy(child); set_nextSibling(m, NIL); set_previousSibling(m, NIL); - Setattr(m, "feature:interface:owner", base.item); + Setattr(m, "feature:interface:owner", cls); Append(methods, m); } } - Swig_collect_non_abstract_methods(base.item, methods); } + Delete(keys); } } + +static void collect_interface_bases(Hash* bases, Node* n) { + if (Getattr(n, "feature:interface")) { + String* name = Getattr(n, "feature:interface:name"); + if (Getattr(bases, name)) + return; + Setattr(bases, name, n); + } + if (List *baselist = Getattr(n, "bases")) { + for (Iterator base = First(baselist); base.item; base = Next(base)) + if (!GetFlag(base.item, "feature:ignore")) + collect_interface_bases(bases, base.item); + } +} + +static void Swig_collect_interface_bases(Node* n) { + Hash* interface_classes = NewHash(); + collect_interface_bases(interface_classes, n); + if (Len(interface_classes) == 0) + Delete(interface_classes); + else + Setattr(n, "feature:interface:bases", interface_classes); +} + // Append all the interface methods not implemented in the current class, so that it would not be abstract void Swig_propagate_interface_methods(Node *n) { + Swig_collect_interface_bases(n); List* methods = NewList(); - Swig_collect_non_abstract_methods(n, methods); + collect_interface_methods(n, methods); + bool is_interface = Getattr(n, "feature:interface") != 0; for (Iterator mi = First(methods); mi.item; mi = Next(mi)) { + if (!is_interface && GetFlag(mi.item, "abstract")) + continue; String *this_decl = Getattr(mi.item, "decl"); String *resolved_decl = SwigType_typedef_resolve_all(this_decl); bool overloaded = false;