Remove unnecessary interfaces for concrete classes

Add Java test for checking expected base and interfaces are generated (to be expanded further)
In the example, E was previously implementing IA, IB, IC. Now it doesn't implement any.
C# virtual/override still to be fixed for this test case
This commit is contained in:
William S Fulton 2016-02-10 19:52:52 +00:00
commit 3931b5800c
5 changed files with 117 additions and 8 deletions

View file

@ -258,6 +258,7 @@ CPP_TEST_CASES += \
mixed_types \
multiple_inheritance \
multiple_inheritance_abstract \
multiple_inheritance_interfaces \
name_cxx \
name_warnings \
namespace_class \

View file

@ -0,0 +1,61 @@
import multiple_inheritance_interfaces.*;
import java.util.Arrays;
public class multiple_inheritance_interfaces_runme {
static {
try {
System.loadLibrary("multiple_inheritance_interfaces");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
private static void checkBaseAndInterfaces(Class cls, boolean interfaceExpected, String base, String[] interfaces) {
String[] expectedInterfaces = new String[interfaces.length];
for (int i=0; i<interfaces.length; ++i)
expectedInterfaces[i] = "interface multiple_inheritance_interfaces." + interfaces[i];
Class[] actualInterfaces = cls.getInterfaces();
String expectedInterfacesString = Arrays.toString(expectedInterfaces);
String actualInterfacesString = Arrays.toString(actualInterfaces);
if (!expectedInterfacesString.equals(actualInterfacesString))
throw new RuntimeException("Expected interfaces for " + cls.getName() + ": \n" + expectedInterfacesString + "\n" + "Actual interfaces: \n" + actualInterfacesString);
String expectedBaseString = null;
if (interfaceExpected) {
// expecting an interface
if (!cls.isInterface())
throw new RuntimeException(cls.getName() + " should be an interface but is not");
expectedBaseString = base.isEmpty() ? "" : "multiple_inheritance_interfaces." + base;
} else {
// expecting a class
if (cls.isInterface())
throw new RuntimeException(cls.getName() + " is an interface but it should not be");
expectedBaseString = base.isEmpty() ? "java.lang.Object" : "multiple_inheritance_interfaces." + base;
}
String actualBaseString = cls.getSuperclass() == null ? "" : cls.getSuperclass().getName();
if (!expectedBaseString.equals(actualBaseString))
throw new RuntimeException("Expected base for " + cls.getName() + ": [" + expectedBaseString + "]" + " Actual base: [" + actualBaseString + "]");
}
public static void main(String argv[]) {
checkBaseAndInterfaces(IA.class, true, "", new String[] {});
checkBaseAndInterfaces(IB.class, true, "", new String[] {});
checkBaseAndInterfaces(IC.class, true, "", new String[] {"IA", "IB"});
checkBaseAndInterfaces(A.class, false, "", new String[] {"IA"});
checkBaseAndInterfaces(B.class, false, "", new String[] {"IB"});
checkBaseAndInterfaces(C.class, false, "", new String[] {"IA", "IB", "IC"});
checkBaseAndInterfaces(D.class, false, "", new String[] {"IA", "IB", "IC"});
checkBaseAndInterfaces(E.class, false, "D", new String[] {});
checkBaseAndInterfaces(IJ.class, true, "", new String[] {});
checkBaseAndInterfaces(IK.class, true, "", new String[] {"IJ"});
checkBaseAndInterfaces(IL.class, true, "", new String[] {"IK"});
checkBaseAndInterfaces(J.class, false, "", new String[] {"IJ"});
checkBaseAndInterfaces(K.class, false, "", new String[] {"IJ", "IK"});
checkBaseAndInterfaces(L.class, false, "", new String[] {"IJ", "IK", "IL"});
checkBaseAndInterfaces(M.class, false, "", new String[] {"IJ", "IK", "IL"});
}
}

View file

@ -0,0 +1,28 @@
%module multiple_inheritance_interfaces
#if defined(SWIGJAVA) || defined(SWIGCSHARP)
%include "feature_interface.i"
DECLARE_INTERFACE_RENAME(IA, A, IA)
DECLARE_INTERFACE_RENAME(IB, B, IB)
DECLARE_INTERFACE_RENAME(IC, C, IC)
#endif
%inline %{
struct IA { virtual void ia() {} };
struct IB { virtual void ib() {} };
struct IC : IA, IB {};
struct D : IC {};
struct E : D {};
%}
#if defined(SWIGJAVA) || defined(SWIGCSHARP)
DECLARE_INTERFACE_RENAME(IJ, J, IJ)
DECLARE_INTERFACE_RENAME(IK, K, IK)
DECLARE_INTERFACE_RENAME(IL, L, IL)
#endif
%inline %{
struct IJ { virtual void ij() {} };
struct IK : IJ {};
struct IL : IK {};
struct M : IL {};
%}

View file

@ -1726,6 +1726,7 @@ public:
}
void addInterfaceNameAndUpcasts(String *interface_list, String *interface_upcasts, Hash *base_list, String *c_classname) {
// Printf(stdout, "addInterfaceNameAndUpcasts %s base_list", c_classname);
List *keys = Keys(base_list);
for (Iterator it = First(keys); it.item; it = Next(it)) {
Node *base = Getattr(base_list, it.item);
@ -1764,6 +1765,7 @@ public:
Delete(upcast_method);
Delete(c_baseclass);
}
// Printf(stdout, " => %s\n", interface_list);
Delete(keys);
}

View file

@ -3630,21 +3630,38 @@ static void collect_interface_methods(Node *n, List *methods) {
}
}
/* -----------------------------------------------------------------------------
* collect_interface_bases
* ----------------------------------------------------------------------------- */
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 (!Getattr(bases, name))
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);
for (Iterator base = First(baselist); base.item; base = Next(base)) {
if (!GetFlag(base.item, "feature:ignore")) {
if (Getattr(base.item, "feature:interface"))
collect_interface_bases(bases, base.item);
}
}
}
}
static void Swig_collect_interface_bases(Node *n) {
/* -----------------------------------------------------------------------------
* collect_and_set_interface_bases()
*
* Create a hash containing all the classes up the inheritance hierarchy
* marked with feature:interface (including this class n).
* Stops going up the inheritance chain as soon as a class is found without
* feature:interface.
* The idea is to find all the base interfaces that a class must implement.
* ----------------------------------------------------------------------------- */
static void collect_and_set_interface_bases(Node *n) {
Hash *interface_bases = NewHash();
collect_interface_bases(interface_bases, n);
if (Len(interface_bases) == 0)
@ -3655,7 +3672,7 @@ static void Swig_collect_interface_bases(Node *n) {
// 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);
collect_and_set_interface_bases(n);
List *methods = NewList();
collect_interface_methods(n, methods);
bool is_interface = Getattr(n, "feature:interface") != 0;