Fix prefix erasing for the generated C# enum constants
This commit is contained in:
parent
b550f93cfd
commit
2adef1e52f
2 changed files with 89 additions and 63 deletions
|
@ -97,7 +97,7 @@
|
|||
#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type
|
||||
#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array"
|
||||
|
||||
#define BINDINGS_GENERATOR_VERSION UINT32_C(4)
|
||||
#define BINDINGS_GENERATOR_VERSION UINT32_C(5)
|
||||
|
||||
const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
|
||||
|
||||
|
@ -173,23 +173,74 @@ static String snake_to_camel_case(const String &p_identifier, bool p_input_is_up
|
|||
return ret;
|
||||
}
|
||||
|
||||
String BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
|
||||
int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
|
||||
|
||||
CRASH_COND(p_ienum.constants.empty());
|
||||
|
||||
const List<ConstantInterface>::Element *front = p_ienum.constants.front();
|
||||
int candidate_len = front->get().name.length();
|
||||
const ConstantInterface &front_iconstant = p_ienum.constants.front()->get();
|
||||
Vector<String> front_parts = front_iconstant.name.split("_", /* p_allow_empty: */ true);
|
||||
int candidate_len = front_parts.size() - 1;
|
||||
|
||||
for (const List<ConstantInterface>::Element *E = front->next(); E; E = E->next()) {
|
||||
int j = 0;
|
||||
for (j = 0; j < candidate_len && j < E->get().name.length(); j++) {
|
||||
if (front->get().name[j] != E->get().name[j])
|
||||
break;
|
||||
if (candidate_len == 0)
|
||||
return 0;
|
||||
|
||||
for (const List<ConstantInterface>::Element *E = p_ienum.constants.front()->next(); E; E = E->next()) {
|
||||
const ConstantInterface &iconstant = E->get();
|
||||
|
||||
Vector<String> parts = iconstant.name.split("_", /* p_allow_empty: */ true);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < candidate_len && i < parts.size(); i++) {
|
||||
if (front_parts[i] != parts[i]) {
|
||||
// HARDCODED: Some Flag enums have the prefix 'FLAG_' for everything except 'FLAGS_DEFAULT' (same for 'METHOD_FLAG_' and'METHOD_FLAGS_DEFAULT').
|
||||
bool hardcoded_exc = (i == candidate_len - 1 && ((front_parts[i] == "FLAGS" && parts[i] == "FLAG") || (front_parts[i] == "FLAG" && parts[i] == "FLAGS")));
|
||||
if (!hardcoded_exc)
|
||||
break;
|
||||
}
|
||||
}
|
||||
candidate_len = j;
|
||||
candidate_len = i;
|
||||
|
||||
if (candidate_len == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return front->get().name.substr(0, candidate_len);
|
||||
return candidate_len;
|
||||
}
|
||||
|
||||
void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumInterface &p_ienum, int p_prefix_length) {
|
||||
|
||||
if (p_prefix_length > 0) {
|
||||
for (List<ConstantInterface>::Element *E = p_ienum.constants.front(); E; E = E->next()) {
|
||||
int curr_prefix_length = p_prefix_length;
|
||||
|
||||
ConstantInterface &curr_const = E->get();
|
||||
|
||||
String constant_name = curr_const.name;
|
||||
|
||||
Vector<String> parts = constant_name.split("_", /* p_allow_empty: */ true);
|
||||
|
||||
if (parts.size() <= curr_prefix_length)
|
||||
continue;
|
||||
|
||||
if (parts[curr_prefix_length][0] >= '0' && parts[curr_prefix_length][0] <= '9') {
|
||||
// The name of enum constants may begin with a numeric digit when strip from the enum prefix,
|
||||
// so we make the prefix for this constant one word shorter in those cases.
|
||||
for (curr_prefix_length = curr_prefix_length - 1; curr_prefix_length > 0; curr_prefix_length--) {
|
||||
if (parts[curr_prefix_length][0] < '0' || parts[curr_prefix_length][0] > '9')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
constant_name = "";
|
||||
for (int i = curr_prefix_length; i < parts.size(); i++) {
|
||||
if (i > curr_prefix_length)
|
||||
constant_name += "_";
|
||||
constant_name += parts[i];
|
||||
}
|
||||
|
||||
curr_const.proxy_name = snake_to_pascal_case(constant_name, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
|
||||
|
@ -272,7 +323,7 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
|
|||
}
|
||||
|
||||
p_output.push_back(MEMBER_BEGIN "public const int ");
|
||||
p_output.push_back(iconstant.name);
|
||||
p_output.push_back(iconstant.proxy_name);
|
||||
p_output.push_back(" = ");
|
||||
p_output.push_back(itos(iconstant.value));
|
||||
p_output.push_back(";");
|
||||
|
@ -334,25 +385,8 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
|
|||
p_output.push_back(INDENT2 "/// </summary>\n");
|
||||
}
|
||||
|
||||
String constant_name = iconstant.name;
|
||||
|
||||
if (!ienum.prefix.empty() && constant_name.begins_with(ienum.prefix)) {
|
||||
constant_name = constant_name.substr(ienum.prefix.length(), constant_name.length());
|
||||
}
|
||||
|
||||
if (constant_name[0] >= '0' && constant_name[0] <= '9') {
|
||||
// The name of enum constants may begin with a numeric digit when strip from the enum prefix,
|
||||
// so we make the prefix one word shorter in those cases.
|
||||
int i = 0;
|
||||
for (i = ienum.prefix.length() - 1; i >= 0; i--) {
|
||||
if (ienum.prefix[i] >= 'A' && ienum.prefix[i] <= 'Z')
|
||||
break;
|
||||
}
|
||||
constant_name = ienum.prefix.substr(i, ienum.prefix.length()) + constant_name;
|
||||
}
|
||||
|
||||
p_output.push_back(INDENT2);
|
||||
p_output.push_back(constant_name);
|
||||
p_output.push_back(iconstant.proxy_name);
|
||||
p_output.push_back(" = ");
|
||||
p_output.push_back(itos(iconstant.value));
|
||||
p_output.push_back(E != ienum.constants.back() ? ",\n" : "\n");
|
||||
|
@ -720,7 +754,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
|
|||
}
|
||||
|
||||
output.push_back(MEMBER_BEGIN "public const int ");
|
||||
output.push_back(iconstant.name);
|
||||
output.push_back(iconstant.proxy_name);
|
||||
output.push_back(" = ");
|
||||
output.push_back(itos(iconstant.value));
|
||||
output.push_back(";");
|
||||
|
@ -760,25 +794,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
|
|||
output.push_back(INDENT3 "/// </summary>\n");
|
||||
}
|
||||
|
||||
String constant_name = iconstant.name;
|
||||
|
||||
if (!ienum.prefix.empty() && constant_name.begins_with(ienum.prefix)) {
|
||||
constant_name = constant_name.substr(ienum.prefix.length(), constant_name.length());
|
||||
}
|
||||
|
||||
if (constant_name[0] >= '0' && constant_name[0] <= '9') {
|
||||
// The name of enum constants may begin with a numeric digit when strip from the enum prefix,
|
||||
// so we make the prefix one word shorter in those cases.
|
||||
int i = 0;
|
||||
for (i = ienum.prefix.length() - 1; i >= 0; i--) {
|
||||
if (ienum.prefix[i] >= 'A' && ienum.prefix[i] <= 'Z')
|
||||
break;
|
||||
}
|
||||
constant_name = ienum.prefix.substr(i, ienum.prefix.length()) + constant_name;
|
||||
}
|
||||
|
||||
output.push_back(INDENT3);
|
||||
output.push_back(constant_name);
|
||||
output.push_back(iconstant.proxy_name);
|
||||
output.push_back(" = ");
|
||||
output.push_back(itos(iconstant.value));
|
||||
output.push_back(E != ienum.constants.back() ? ",\n" : "\n");
|
||||
|
@ -1846,11 +1863,13 @@ void BindingsGenerator::_populate_object_type_interfaces() {
|
|||
EnumInterface ienum(enum_proxy_cname);
|
||||
const List<StringName> &constants = enum_map.get(*k);
|
||||
for (const List<StringName>::Element *E = constants.front(); E; E = E->next()) {
|
||||
int *value = class_info->constant_map.getptr(E->get());
|
||||
const StringName &constant_cname = E->get();
|
||||
String constant_name = constant_cname.operator String();
|
||||
int *value = class_info->constant_map.getptr(constant_cname);
|
||||
ERR_FAIL_NULL(value);
|
||||
constant_list.erase(E->get().operator String());
|
||||
constant_list.erase(constant_name);
|
||||
|
||||
ConstantInterface iconstant(snake_to_pascal_case(E->get(), true), *value);
|
||||
ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value);
|
||||
|
||||
iconstant.const_doc = NULL;
|
||||
for (int i = 0; i < itype.class_doc->constants.size(); i++) {
|
||||
|
@ -1865,7 +1884,9 @@ void BindingsGenerator::_populate_object_type_interfaces() {
|
|||
ienum.constants.push_back(iconstant);
|
||||
}
|
||||
|
||||
ienum.prefix = _determine_enum_prefix(ienum);
|
||||
int prefix_length = _determine_enum_prefix(ienum);
|
||||
|
||||
_apply_prefix_to_enum_constants(ienum, prefix_length);
|
||||
|
||||
itype.enums.push_back(ienum);
|
||||
|
||||
|
@ -1879,10 +1900,11 @@ void BindingsGenerator::_populate_object_type_interfaces() {
|
|||
}
|
||||
|
||||
for (const List<String>::Element *E = constant_list.front(); E; E = E->next()) {
|
||||
int *value = class_info->constant_map.getptr(E->get());
|
||||
const String &constant_name = E->get();
|
||||
int *value = class_info->constant_map.getptr(StringName(E->get()));
|
||||
ERR_FAIL_NULL(value);
|
||||
|
||||
ConstantInterface iconstant(snake_to_pascal_case(E->get(), true), *value);
|
||||
ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value);
|
||||
|
||||
iconstant.const_doc = NULL;
|
||||
for (int i = 0; i < itype.class_doc->constants.size(); i++) {
|
||||
|
@ -2265,7 +2287,7 @@ void BindingsGenerator::_populate_global_constants() {
|
|||
int constant_value = GlobalConstants::get_global_constant_value(i);
|
||||
StringName enum_name = GlobalConstants::get_global_constant_enum(i);
|
||||
|
||||
ConstantInterface iconstant(snake_to_pascal_case(constant_name, true), constant_value);
|
||||
ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), constant_value);
|
||||
iconstant.const_doc = const_doc;
|
||||
|
||||
if (enum_name != StringName()) {
|
||||
|
@ -2293,16 +2315,18 @@ void BindingsGenerator::_populate_global_constants() {
|
|||
TypeInterface::postsetup_enum_type(enum_itype);
|
||||
enum_types.insert(enum_itype.cname, enum_itype);
|
||||
|
||||
ienum.prefix = _determine_enum_prefix(ienum);
|
||||
int prefix_length = _determine_enum_prefix(ienum);
|
||||
|
||||
// HARDCODED
|
||||
// HARDCODED: The Error enum have the prefix 'ERR_' for everything except 'OK' and 'FAILED'.
|
||||
if (ienum.cname == name_cache.enum_Error) {
|
||||
if (!ienum.prefix.empty()) { // Just in case it ever changes
|
||||
if (prefix_length > 0) { // Just in case it ever changes
|
||||
ERR_PRINTS("Prefix for enum 'Error' is not empty");
|
||||
}
|
||||
|
||||
ienum.prefix = "Err";
|
||||
prefix_length = 1; // 'ERR_'
|
||||
}
|
||||
|
||||
_apply_prefix_to_enum_constants(ienum, prefix_length);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,20 +43,21 @@ class BindingsGenerator {
|
|||
|
||||
struct ConstantInterface {
|
||||
String name;
|
||||
String proxy_name;
|
||||
int value;
|
||||
const DocData::ConstantDoc *const_doc;
|
||||
|
||||
ConstantInterface() {}
|
||||
|
||||
ConstantInterface(const String &p_name, int p_value) {
|
||||
ConstantInterface(const String &p_name, const String &p_proxy_name, int p_value) {
|
||||
name = p_name;
|
||||
proxy_name = p_proxy_name;
|
||||
value = p_value;
|
||||
}
|
||||
};
|
||||
|
||||
struct EnumInterface {
|
||||
StringName cname;
|
||||
String prefix;
|
||||
List<ConstantInterface> constants;
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const {
|
||||
|
@ -520,7 +521,8 @@ class BindingsGenerator {
|
|||
return p_type.name;
|
||||
}
|
||||
|
||||
String _determine_enum_prefix(const EnumInterface &p_ienum);
|
||||
int _determine_enum_prefix(const EnumInterface &p_ienum);
|
||||
void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
|
||||
|
||||
void _generate_method_icalls(const TypeInterface &p_itype);
|
||||
|
||||
|
|
Loading…
Reference in a new issue