diff --git a/Examples/test-suite/cpp11_strongly_typed_enumerations.i b/Examples/test-suite/cpp11_strongly_typed_enumerations.i index 451688736..8846d6877 100644 --- a/Examples/test-suite/cpp11_strongly_typed_enumerations.i +++ b/Examples/test-suite/cpp11_strongly_typed_enumerations.i @@ -112,6 +112,121 @@ public: }; }; +class Class2 +{ +public: + enum class Enum12 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + + enum Enum13 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + + struct Struct1 + { + enum class Enum14 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + + enum Enum15 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + }; +}; + +/* +enum class Enum12 +{ + Val1 = 300, + Val2 = 400, + Val3, + Val4 +}; + +enum Enum13 +{ + Val1 = 300, + Val2 = 400, + Val3, + Val4 +}; +*/ + +namespace NS1 +{ + enum class Enum12 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + + enum Enum13 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + + class Class3 + { + public: + enum class Enum12 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + + enum Enum13 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + + struct Struct1 + { + enum class Enum14 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + + enum Enum15 + { + Val1 = 300, + Val2 = 400, + Val3, + Val4 + }; + }; + }; +} + /* TODO enum class MyClass {AAA, BBB, CCC}; diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 9e16bb422..411f7ad31 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -838,7 +838,7 @@ public: bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0); if (!Getattr(n, "sym:overloaded")) { - if (!addSymbol(Getattr(n, "sym:name"), n, imclass_name)) + if (!addSymbol(symname, n, imclass_name)) return SWIG_ERROR; } @@ -1556,6 +1556,22 @@ public: } else if (!const_feature_flag) { // Default enum and constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call. + String* pureSymname = NULL; + if (Equal(Getattr(n, "nodeType"), "enumitem")) { + // If enum is strongly-typed, generate fully-qualified symname + Node* parent = parentNode(n); + String* pureSymname = NULL; + if (GetFlag(parent, "scopedenum") && !GetFlag(n, "symname_has_enumscope")) { + pureSymname = symname; + + String* enumClassName = Swig_scopename_last(Getattr(parent, "name")); + symname = Swig_name_member(0, enumClassName, pureSymname); + Delete(enumClassName); + + /* Printf(stdout, "Renamed strong enum value symname (java:1) '%s' -> '%s'\n", pureSymname, symname); */ + } + } + if (classname_substituted_flag) { if (SwigType_isenum(t)) { // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on) @@ -1568,6 +1584,13 @@ public: Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname)); } + // Delete temporary symname if it was created + if (pureSymname) { + Delete(symname); + symname = pureSymname; + pureSymname = NULL; + } + // Each constant and enum value is wrapped with a separate JNI function call SetFlag(n, "feature:immutable"); enum_constant_flag = true; @@ -2959,6 +2982,19 @@ public: // Use the C syntax to make a true Java constant and hope that it compiles as Java code value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex")); } else { + // If enum is strongly-typed, generate fully-qualified symname + Node* parent = parentNode(n); + String* pureSymname = NULL; + if (GetFlag(parent, "scopedenum") && !GetFlag(n, "symname_has_enumscope")) { + pureSymname = symname; + + String* enumClassName = Swig_scopename_last(Getattr(parent, "name")); + symname = Swig_name_member(0, enumClassName, pureSymname); + Delete(enumClassName); + + /* Printf(stdout, "Renamed strong enum value symname (java:2) '%s' -> '%s'\n", pureSymname, symname); */ + } + // Get the enumvalue from a JNI call if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) { // Strange hack to change the name @@ -2967,7 +3003,17 @@ public: value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname)); } else { memberconstantHandler(n); - value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, proxy_class_name, symname))); + String* full_proxy_class_sym_name = NewString(full_proxy_class_name); + Replaceall(full_proxy_class_sym_name, ".", "_"); + value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, full_proxy_class_sym_name, symname))); + Delete(full_proxy_class_sym_name); + } + + // Delete temporary symname if it was created + if (pureSymname) { + Delete(symname); + symname = pureSymname; + pureSymname = NULL; } } } diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx index 5ea79f0ab..04eec8af3 100644 --- a/Source/Modules/lang.cxx +++ b/Source/Modules/lang.cxx @@ -1721,6 +1721,24 @@ int Language::memberconstantHandler(Node *n) { String *value = Getattr(n, "value"); String *mrename = Swig_name_member(0, ClassPrefix, symname); + if (Equal(Getattr(n, "nodeType"), "enumitem")) { + // If enum is strongly-typed, generate fully-qualified symname + Node* parent = parentNode(n); + if (GetFlag(parent, "scopedenum") && !GetFlag(n, "symname_has_enumscope")) + { + SetFlag(n, "symname_has_enumscope"); + Delete(mrename); + + String* enumClassName = Swig_scopename_last(Getattr(parent, "name")); + String* scopedItemName = Swig_name_member(0, enumClassName, symname); + mrename = Swig_name_member(0, ClassPrefix, scopedItemName); + + /* Printf(stdout, "Renamed strong enum value symname (lang:1) '%s' -> '%s'\n", symname, mrename); */ + + Delete(enumClassName); + Delete(scopedItemName); + } + } Setattr(n, "sym:name", mrename); String *new_name = 0; @@ -1728,6 +1746,24 @@ int Language::memberconstantHandler(Node *n) { new_name = Copy(value); else new_name = NewStringf("%s::%s", isNonVirtualProtectedAccess(n) ? DirectorClassName : ClassName, name); + if (Equal(Getattr(n, "nodeType"), "enumitem")) { + // If enum is strongly-typed, generate fully-qualified symname + Node* parent = parentNode(n); + if (GetFlag(parent, "scopedenum") && !GetFlag(n, "name_has_enumscope")) + { + SetFlag(n, "name_has_enumscope"); + Delete(new_name); + + String* enumClassName = Swig_scopename_last(Getattr(parent, "name")); + String* scopedItemName = NewStringf("%s::%s", enumClassName, name); + new_name = NewStringf("%s::%s", isNonVirtualProtectedAccess(n) ? DirectorClassName : ClassName, scopedItemName); + + /* Printf(stdout, "Renamed strong enum value name (lang:1) '%s' -> '%s'\n", name, new_name); */ + + Delete(enumClassName); + Delete(scopedItemName); + } + } Setattr(n, "name", new_name); constantWrapper(n); @@ -2962,6 +2998,22 @@ int Language::variableWrapper(Node *n) { Delattr(n,"varset"); Delattr(n,"varget"); + String* pureSymname = NULL; + if (Equal(Getattr(n, "nodeType"), "enumitem")) { + // If enum is strongly-typed, generate fully-qualified symname + Node* parent = parentNode(n); + if (GetFlag(parent, "scopedenum") && !GetFlag(n, "symname_has_enumscope")) + { + pureSymname = symname; + + String* enumClassName = Swig_scopename_last(Getattr(parent, "name")); + symname = Swig_name_member(0, enumClassName, pureSymname); + Delete(enumClassName); + + /* Printf(stdout, "Renamed strong enum value symname (lang:2) '%s' -> '%s'\n", pureSymname, symname); */ + } + } + /* If no way to set variables. We simply create functions */ int assignable = is_assignable(n); int flags = use_naturalvar_mode(n); @@ -3019,6 +3071,14 @@ int Language::variableWrapper(Node *n) { functionWrapper(n); Delattr(n, "varget"); Swig_restore(n); + + // Delete temporary symname if it was created + if (pureSymname) { + Delete(symname); + symname = pureSymname; + pureSymname = NULL; + } + return SWIG_OK; }