Merge branch 'interfaces' into interfaces2

* interfaces:
  Remove unnecessary interfaces for concrete classes
  cosmetic code formatting changes
  Correct interface name attributes that are internal
  interface macro changes to support templates
  Test non-virtual method in Derived classes
  interface tests for a most derived class inheriting the interfaces further up the chain
  Rename GetCPtr/getCPtr to SWIGInterfaceUpcast
  interface feature support for const ref pointers (used by the STL)
  Interface feature support for arrays
  More interface feature testing for return values
  interface feature support for passing by value
  interface feature support for references
  Multiple inheritance parameters as pointers testing
  Simplify multiple_inheritance_abstract Java runtime test
  Warning fixes
  Rename test functions in multiple_inheritance_abstract testcase
  Formatting fixes in generated code for interface feature
  Cosmetic spacing changes in test case
  interface feature typemap corrections to handle NULL pointers
  interface test added
  javadirectorin fix
  interface implementation visibility
  interface inheritance (2)
  interface inheritance (1)
  feature:interface ported to Java
  propagate non-abstract "interface" base methods (3)
  propagate non-abstract "interface" base methods (2)
  propagate non-abstract "interface" base methods (1)
  namespace support added GetCPtr now returns HandleRef "feature:interface:name" is now mandatory attribute
  interfaces (1)
  interfaces (1)

Conflicts:
	Source/Modules/csharp.cxx
	Source/Modules/java.cxx
This commit is contained in:
William S Fulton 2016-02-11 19:37:31 +00:00
commit abccc13a4a
11 changed files with 1166 additions and 39 deletions

View file

@ -18,6 +18,8 @@
/* Hash type used for upcalls from C/C++ */
typedef DOH UpcallData;
// helper function used in feature:interface implementation
void Swig_propagate_interface_methods(Node *n);
class CSHARP:public Language {
static const char *usage;
@ -52,6 +54,7 @@ class CSHARP:public Language {
String *imclass_class_code; // intermediary class code
String *proxy_class_def;
String *proxy_class_code;
String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
String *module_class_code;
String *proxy_class_name; // proxy class name
String *full_imclass_name; // fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
@ -126,6 +129,7 @@ public:
imclass_class_code(NULL),
proxy_class_def(NULL),
proxy_class_code(NULL),
interface_class_code(NULL),
module_class_code(NULL),
proxy_class_name(NULL),
full_imclass_name(NULL),
@ -1643,6 +1647,62 @@ public:
return Language::pragmaDirective(n);
}
String *getQualifiedInterfaceName(Node *n) {
String *ret = Getattr(n, "interface:qname");
if (!ret) {
String *nspace = Getattr(n, "sym:nspace");
String *iname = Getattr(n, "feature:interface:name");
if (nspace) {
if (namespce)
ret = NewStringf("%s.%s.%s", namespce, nspace, iname);
else
ret = NewStringf("%s.%s", nspace, iname);
} else {
ret = Copy(iname);
}
Setattr(n, "interface:qname", ret);
}
return ret;
}
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, "\n");
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.SWIGInterfaceUpcast", iname);
Printf(interface_upcasts, " HandleRef %s() {\n", 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);
Printf(interface_upcasts, " }\n");
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()
* ----------------------------------------------------------------------------- */
@ -1652,6 +1712,8 @@ public:
String *c_baseclass = NULL;
String *baseclass = NULL;
String *c_baseclassname = NULL;
String *interface_list = NewStringEmpty();
String *interface_upcasts = NewStringEmpty();
SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
bool feature_director = Swig_directorclass(n) ? true : false;
bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
@ -1668,9 +1730,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 && (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));
@ -1679,19 +1740,20 @@ public:
base = Next(base);
/* Warn about multiple inheritance for additional base class(es) */
while (base.item) {
if (GetFlag(base.item, "feature:ignore")) {
base = Next(base);
continue;
}
String *proxyclassname = Getattr(n, "classtypeobj");
String *baseclassname = Getattr(base.item, "name");
Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
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),
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
}
base = Next(base);
}
}
}
}
Hash *interface_bases = Getattr(n, "interface:bases");
if (interface_bases)
addInterfaceNameAndUpcasts(interface_list, interface_upcasts, interface_bases, c_classname);
bool derived = baseclass && getProxyName(c_baseclassname);
if (derived && purebase_notderived)
@ -1713,6 +1775,9 @@ public:
// Pure C# interfaces
const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
if (*Char(interface_list) && *Char(pure_interfaces))
Append(interface_list, ", ");
Append(interface_list, pure_interfaces);
// Start writing the proxy class
if (!has_outerclass)
Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
@ -1725,8 +1790,8 @@ public:
Printv(proxy_class_def, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
" $csclassname", // Class name and base class
(*Char(wanted_base) || *Char(pure_interfaces)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(pure_interfaces)) ? // Interfaces
", " : "", pure_interfaces, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
(*Char(wanted_base) || *Char(interface_list)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(interface_list)) ? // Interfaces
", " : "", interface_list, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
NIL);
@ -1771,6 +1836,8 @@ public:
Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n",
NIL);
}
if (*Char(interface_upcasts))
Printv(proxy_class_def, interface_upcasts, NIL);
if (feature_director) {
// Generate director connect method
@ -1852,6 +1919,8 @@ public:
Delete(director_connect_method_name);
}
Delete(interface_upcasts);
Delete(interface_list);
Delete(attributes);
Delete(destruct);
@ -1899,12 +1968,40 @@ public:
Delete(baseclass);
}
void emitInterfaceDeclaration(Node *n, String *iname, File *f_interface) {
Printv(f_interface, typemapLookup(n, "csimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
Printf(f_interface, "public interface %s", iname);
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"))
continue; // TODO: warn about skipped non-interface bases
String *base_iname = Getattr(base.item, "feature:interface:name");
if (!bases)
bases = NewStringf(" : %s", base_iname);
else {
Append(bases, ", ");
Append(bases, base_iname);
}
}
if (bases) {
Printv(f_interface, bases, NIL);
Delete(bases);
}
}
Printf(f_interface, " {\n");
Printf(f_interface, " [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n");
if (String *cptr_func = Getattr(n, "feature:interface:cptr"))
Printf(f_interface, " HandleRef %s();\n", cptr_func);
else
Printf(f_interface, " HandleRef SWIGInterfaceUpcast();\n");
}
/* ----------------------------------------------------------------------
* classHandler()
* ---------------------------------------------------------------------- */
virtual int classHandler(Node *n) {
String *nspace = getNSpace();
File *f_proxy = NULL;
// save class local variables
@ -1915,6 +2012,9 @@ public:
String *old_proxy_class_def = proxy_class_def;
String *old_proxy_class_code = proxy_class_code;
bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested");
File *f_interface = NULL;
String *old_interface_class_code = interface_class_code;
interface_class_code = 0;
if (proxy_flag) {
proxy_class_name = NewString(Getattr(n, "sym:name"));
@ -1963,10 +2063,36 @@ public:
}
else
++nesting_depth;
proxy_class_def = NewString("");
proxy_class_code = NewString("");
destructor_call = NewString("");
proxy_class_constants_code = NewString("");
// Start writing out the proxy class file
emitBanner(f_proxy);
addOpenNamespace(nspace, f_proxy);
Clear(proxy_class_def);
Clear(proxy_class_code);
destructor_call = NewStringEmpty();
proxy_class_constants_code = NewStringEmpty();
Swig_propagate_interface_methods(n);
if (Getattr(n, "feature:interface")) {
interface_class_code = NewStringEmpty();
String *iname = Getattr(n, "feature:interface:name");
if (!iname) {
Swig_error(Getfile(n), Getline(n), "Interface %s has no name attribute", proxy_class_name);
SWIG_exit(EXIT_FAILURE);
}
filen = NewStringf("%s%s.cs", output_directory, iname);
f_interface = NewFile(filen, "w", SWIG_output_files());
if (!f_interface) {
FileErrorDisplay(filen);
SWIG_exit(EXIT_FAILURE);
}
Append(filenames_list, filen); // file name ownership goes to the list
emitBanner(f_interface);
addOpenNamespace(nspace, f_interface);
emitInterfaceDeclaration(n, iname, f_interface);
}
Delete(output_directory);
}
Language::classHandler(n);
@ -2056,10 +2182,17 @@ public:
Delete(norm_name);
Delete(wname);
Delete(downcast_method);
if (f_interface) {
Printv(f_interface, interface_class_code, "}\n", NIL);
addCloseNamespace(nspace, f_interface);
Delete(f_interface);
}
emitDirectorExtraMethods(n);
Delete(interface_class_code);
interface_class_code = old_interface_class_code;
Delete(csclazzname);
Delete(proxy_class_name);
proxy_class_name = old_proxy_class_name;
@ -2145,6 +2278,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 && Getattr(n, "interface:owner") == 0;
if (!proxy_flag)
return;
@ -2217,8 +2352,10 @@ public:
Printf(function_code, " %s ", methodmods);
if (!is_smart_pointer()) {
// Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
if (Getattr(n, "override"))
Printf(function_code, "override ");
if (Node *base = Getattr(n, "override")) {
if (!Getattr(parentNode(base), "feature:interface"))
Printf(function_code, "override ");
}
else if (checkAttribute(n, "storage", "virtual"))
Printf(function_code, "virtual ");
if (Getattr(n, "hides"))
@ -2228,6 +2365,9 @@ public:
if (static_flag)
Printf(function_code, "static ");
Printf(function_code, "%s %s(", return_type, proxy_function_name);
if (is_interface)
Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
if (!static_flag)
@ -2307,10 +2447,15 @@ public:
}
/* Add parameter to proxy function */
if (gencomma >= 2)
if (gencomma >= 2) {
Printf(function_code, ", ");
if (is_interface)
Printf(interface_class_code, ", ");
}
gencomma = 2;
Printf(function_code, "%s %s", param_type, arg);
if (is_interface)
Printf(interface_class_code, "%s %s", param_type, arg);
Delete(arg);
Delete(param_type);
@ -2320,6 +2465,8 @@ public:
Printf(imcall, ")");
Printf(function_code, ")");
if (is_interface)
Printf(interface_class_code, ");\n");
// Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class)
if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {