diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index b97bcb6e77f..24f215f83e4 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -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(8) +#define BINDINGS_GENERATOR_VERSION UINT32_C(9) const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n"); @@ -1464,7 +1464,13 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte p_output.append("\n" INDENT2 OPEN_BLOCK); if (getter) { - p_output.append(INDENT3 "get\n" OPEN_BLOCK_L3); + p_output.append(INDENT3 "get\n" + + // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that) + "#pragma warning disable CS0618 // Disable warning about obsolete method\n" + + OPEN_BLOCK_L3); + p_output.append("return "); p_output.append(getter->proxy_name + "("); if (p_iprop.index != -1) { @@ -1478,11 +1484,22 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte p_output.append(itos(p_iprop.index)); } } - p_output.append(");\n" CLOSE_BLOCK_L3); + p_output.append(");\n" + + CLOSE_BLOCK_L3 + + // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that) + "#pragma warning restore CS0618\n"); } if (setter) { - p_output.append(INDENT3 "set\n" OPEN_BLOCK_L3); + p_output.append(INDENT3 "set\n" + + // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that) + "#pragma warning disable CS0618 // Disable warning about obsolete method\n" + + OPEN_BLOCK_L3); + p_output.append(setter->proxy_name + "("); if (p_iprop.index != -1) { const ArgumentInterface &idx_arg = setter->arguments.front()->get(); @@ -1495,7 +1512,12 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte p_output.append(itos(p_iprop.index) + ", "); } } - p_output.append("value);\n" CLOSE_BLOCK_L3); + p_output.append("value);\n" + + CLOSE_BLOCK_L3 + + // TODO Remove this once we make accessor methods private/internal (they will no longer be marked as obsolete after that) + "#pragma warning restore CS0618\n"); } p_output.append(CLOSE_BLOCK_L2); @@ -1623,6 +1645,15 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf p_output.append("\")]"); } + if (p_imethod.is_deprecated) { + if (p_imethod.deprecation_message.empty()) + WARN_PRINTS("An empty deprecation message is discouraged. Method: " + p_imethod.proxy_name); + + p_output.append(MEMBER_BEGIN "[Obsolete(\""); + p_output.append(p_imethod.deprecation_message); + p_output.append("\")]"); + } + p_output.append(MEMBER_BEGIN); p_output.append(p_imethod.is_internal ? "internal " : "public "); @@ -2147,10 +2178,12 @@ void BindingsGenerator::_populate_object_type_interfaces() { itype.im_type_in = "IntPtr"; itype.im_type_out = itype.proxy_name; + // Populate properties + List property_list; ClassDB::get_property_list(type_cname, &property_list, true); - // Populate properties + Map accessor_methods; for (const List::Element *E = property_list.front(); E; E = E->next()) { const PropertyInfo &property = E->get(); @@ -2163,6 +2196,11 @@ void BindingsGenerator::_populate_object_type_interfaces() { iprop.setter = ClassDB::get_property_setter(type_cname, iprop.cname); iprop.getter = ClassDB::get_property_getter(type_cname, iprop.cname); + if (iprop.setter != StringName()) + accessor_methods[iprop.setter] = iprop.cname; + if (iprop.getter != StringName()) + accessor_methods[iprop.getter] = iprop.cname; + bool valid = false; iprop.index = ClassDB::get_property_index(type_cname, iprop.cname, &valid); ERR_FAIL_COND(!valid); @@ -2307,6 +2345,16 @@ void BindingsGenerator::_populate_object_type_interfaces() { imethod.proxy_name += "_"; } + Map::Element *accessor = accessor_methods.find(imethod.cname); + if (accessor) { + const PropertyInterface *accessor_property = itype.find_property_by_name(accessor->value()); + + // We only deprecate an accessor method if it's in the same class as the property. It's easier this way, but also + // we don't know if an accessor method in a different class could have other purposes, so better leave those untouched. + imethod.is_deprecated = true; + imethod.deprecation_message = imethod.proxy_name + " is deprecated. Use the " + accessor_property->proxy_name + " property instead."; + } + if (itype.class_doc) { for (int i = 0; i < itype.class_doc->methods.size(); i++) { if (itype.class_doc->methods[i].name == imethod.name) { diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 7599c6edeec..d84315c7df6 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -159,6 +159,9 @@ class BindingsGenerator { const DocData::MethodDoc *method_doc; + bool is_deprecated; + String deprecation_message; + void add_argument(const ArgumentInterface &argument) { arguments.push_back(argument); } @@ -169,6 +172,7 @@ class BindingsGenerator { requires_object_call = false; is_internal = false; method_doc = NULL; + is_deprecated = false; } };