| 5748 | } |
| 5749 | |
| 5750 | bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bool p_is_constructor, GDScriptParser::DataType p_base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, BitField<MethodFlags> &r_method_flags, StringName *r_native_class) { |
| 5751 | r_method_flags = METHOD_FLAGS_DEFAULT; |
| 5752 | r_default_arg_count = 0; |
| 5753 | if (r_native_class) { |
| 5754 | *r_native_class = StringName(); |
| 5755 | } |
| 5756 | StringName function_name = p_function; |
| 5757 | |
| 5758 | bool was_enum = false; |
| 5759 | if (p_base_type.kind == GDScriptParser::DataType::ENUM) { |
| 5760 | was_enum = true; |
| 5761 | if (p_base_type.is_meta_type) { |
| 5762 | // Enum type can be treated as a dictionary value. |
| 5763 | p_base_type.kind = GDScriptParser::DataType::BUILTIN; |
| 5764 | p_base_type.is_meta_type = false; |
| 5765 | } else { |
| 5766 | push_error("Cannot call function on enum value.", p_source); |
| 5767 | return false; |
| 5768 | } |
| 5769 | } |
| 5770 | |
| 5771 | if (p_base_type.kind == GDScriptParser::DataType::BUILTIN) { |
| 5772 | // Construct a base type to get methods. |
| 5773 | Callable::CallError err; |
| 5774 | Variant dummy; |
| 5775 | Variant::construct(p_base_type.builtin_type, dummy, nullptr, 0, err); |
| 5776 | if (err.error != Callable::CallError::CALL_OK) { |
| 5777 | ERR_FAIL_V_MSG(false, "Could not construct base Variant type."); |
| 5778 | } |
| 5779 | List<MethodInfo> methods; |
| 5780 | dummy.get_method_list(&methods); |
| 5781 | |
| 5782 | for (const MethodInfo &E : methods) { |
| 5783 | if (E.name == p_function) { |
| 5784 | function_signature_from_info(E, r_return_type, r_par_types, r_default_arg_count, r_method_flags); |
| 5785 | // Cannot use non-const methods on enums. |
| 5786 | if (!r_method_flags.has_flag(METHOD_FLAG_STATIC) && was_enum && !(E.flags & METHOD_FLAG_CONST)) { |
| 5787 | push_error(vformat(R"*(Cannot call non-const Dictionary function "%s()" on enum "%s".)*", p_function, p_base_type.enum_type), p_source); |
| 5788 | } |
| 5789 | return true; |
| 5790 | } |
| 5791 | } |
| 5792 | |
| 5793 | return false; |
| 5794 | } |
| 5795 | |
| 5796 | StringName base_native = p_base_type.native_type; |
| 5797 | if (base_native != StringName()) { |
| 5798 | // Empty native class might happen in some Script implementations. |
| 5799 | // Just ignore it. |
| 5800 | if (!class_exists(base_native)) { |
| 5801 | push_error(vformat("Native class %s used in script doesn't exist or isn't exposed.", base_native), p_source); |
| 5802 | return false; |
| 5803 | } else if (p_is_constructor && ClassDB::is_abstract(base_native)) { |
| 5804 | if (p_base_type.kind == GDScriptParser::DataType::CLASS) { |
| 5805 | push_error(vformat(R"(Class "%s" cannot be constructed as it is based on abstract native class "%s".)", p_base_type.class_type->fqcn.get_file(), base_native), p_source); |
| 5806 | } else if (p_base_type.kind == GDScriptParser::DataType::SCRIPT) { |
| 5807 | push_error(vformat(R"(Script "%s" cannot be constructed as it is based on abstract native class "%s".)", p_base_type.script_path.get_file(), base_native), p_source); |
nothing calls this directly
no test coverage detected