diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 9de697b32c3..32e3c9a02c7 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -1714,6 +1714,12 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode * static_context = p_function->is_static; } + MethodInfo method_info; + method_info.name = function_name; + if (p_function->is_static) { + method_info.flags |= MethodFlags::METHOD_FLAG_STATIC; + } + GDScriptParser::DataType prev_datatype = p_function->get_datatype(); GDScriptParser::DataType resolving_datatype; @@ -1733,6 +1739,7 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode * for (int i = 0; i < p_function->parameters.size(); i++) { resolve_parameter(p_function->parameters[i]); + method_info.arguments.push_back(p_function->parameters[i]->get_datatype().to_property_info(p_function->parameters[i]->identifier->name)); #ifdef DEBUG_ENABLED if (p_function->parameters[i]->usages == 0 && !String(p_function->parameters[i]->identifier->name).begins_with("_")) { parser->push_warning(p_function->parameters[i]->identifier, GDScriptWarning::UNUSED_PARAMETER, function_visible_name, p_function->parameters[i]->identifier->name); @@ -1883,6 +1890,10 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode * } #endif + method_info.default_arguments.append_array(p_function->default_arg_values); + method_info.return_val = p_function->get_datatype().to_property_info(""); + p_function->info = method_info; + if (p_function->get_datatype().is_resolving()) { p_function->set_datatype(prev_datatype); } diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 092a2043b1b..ba00f9e6b42 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -1091,9 +1091,9 @@ static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite, } } -static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, bool p_types_only, HashMap &r_result, int p_recursion_depth); +static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, bool p_types_only, bool p_add_braces, HashMap &r_result, int p_recursion_depth); -static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, bool p_only_functions, bool p_types_only, bool p_static, bool p_parent_only, HashMap &r_result, int p_recursion_depth) { +static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, bool p_only_functions, bool p_types_only, bool p_static, bool p_parent_only, bool p_add_braces, HashMap &r_result, int p_recursion_depth) { ERR_FAIL_COND(p_recursion_depth > COMPLETION_RECURSION_LIMIT); if (!p_parent_only) { @@ -1147,12 +1147,14 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, continue; } option = ScriptLanguage::CodeCompletionOption(member.function->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (member.function->parameters.size() > 0 || (member.function->info.flags & METHOD_FLAG_VARARG)) { - option.insert_text += "("; - option.display += U"(\u2026)"; - } else { - option.insert_text += "()"; - option.display += "()"; + if (p_add_braces) { + if (member.function->parameters.size() > 0 || (member.function->info.flags & METHOD_FLAG_VARARG)) { + option.insert_text += "("; + option.display += U"(\u2026)"; + } else { + option.insert_text += "()"; + option.display += "()"; + } } break; case GDScriptParser::ClassNode::Member::SIGNAL: @@ -1183,25 +1185,27 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, base_type.type = p_class->base_type; base_type.type.is_meta_type = p_static; - _find_identifiers_in_base(base_type, p_only_functions, p_types_only, r_result, p_recursion_depth + 1); + _find_identifiers_in_base(base_type, p_only_functions, p_types_only, p_add_braces, r_result, p_recursion_depth + 1); } -static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, bool p_types_only, HashMap &r_result, int p_recursion_depth) { +static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base, bool p_only_functions, bool p_types_only, bool p_add_braces, HashMap &r_result, int p_recursion_depth) { ERR_FAIL_COND(p_recursion_depth > COMPLETION_RECURSION_LIMIT); GDScriptParser::DataType base_type = p_base.type; if (!p_types_only && base_type.is_meta_type && base_type.kind != GDScriptParser::DataType::BUILTIN && base_type.kind != GDScriptParser::DataType::ENUM) { ScriptLanguage::CodeCompletionOption option("new", ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, ScriptLanguage::LOCATION_LOCAL); - option.insert_text += "("; - option.display += U"(\u2026)"; + if (p_add_braces) { + option.insert_text += "("; + option.display += U"(\u2026)"; + } r_result.insert(option.display, option); } while (!base_type.has_no_type()) { switch (base_type.kind) { case GDScriptParser::DataType::CLASS: { - _find_identifiers_in_class(base_type.class_type, p_only_functions, p_types_only, base_type.is_meta_type, false, r_result, p_recursion_depth); + _find_identifiers_in_class(base_type.class_type, p_only_functions, p_types_only, base_type.is_meta_type, false, p_add_braces, r_result, p_recursion_depth); // This already finds all parent identifiers, so we are done. base_type = GDScriptParser::DataType(); } break; @@ -1252,12 +1256,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base } int location = p_recursion_depth + _get_method_location(scr->get_class_name(), E.name); ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { - option.insert_text += "("; - option.display += U"(\u2026)"; - } else { - option.insert_text += "()"; - option.display += "()"; + if (p_add_braces) { + if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { + option.insert_text += "("; + option.display += U"(\u2026)"; + } else { + option.insert_text += "()"; + option.display += "()"; + } } r_result.insert(option.display, option); } @@ -1340,12 +1346,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base } int location = p_recursion_depth + _get_method_location(type, E.name); ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { - option.insert_text += "("; - option.display += U"(\u2026)"; - } else { - option.insert_text += "()"; - option.display += "()"; + if (p_add_braces) { + if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { + option.insert_text += "("; + option.display += U"(\u2026)"; + } else { + option.insert_text += "()"; + option.display += "()"; + } } r_result.insert(option.display, option); } @@ -1413,12 +1421,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base continue; } ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location); - if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { - option.insert_text += "("; - option.display += U"(\u2026)"; - } else { - option.insert_text += "()"; - option.display += "()"; + if (p_add_braces) { + if (E.arguments.size() || (E.flags & METHOD_FLAG_VARARG)) { + option.insert_text += "("; + option.display += U"(\u2026)"; + } else { + option.insert_text += "()"; + option.display += "()"; + } } r_result.insert(option.display, option); } @@ -1432,14 +1442,14 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base } } -static void _find_identifiers(const GDScriptParser::CompletionContext &p_context, bool p_only_functions, HashMap &r_result, int p_recursion_depth) { +static void _find_identifiers(const GDScriptParser::CompletionContext &p_context, bool p_only_functions, bool p_add_braces, HashMap &r_result, int p_recursion_depth) { if (!p_only_functions && p_context.current_suite) { // This includes function parameters, since they are also locals. _find_identifiers_in_suite(p_context.current_suite, r_result); } if (p_context.current_class) { - _find_identifiers_in_class(p_context.current_class, p_only_functions, false, (!p_context.current_function || p_context.current_function->is_static), false, r_result, p_recursion_depth); + _find_identifiers_in_class(p_context.current_class, p_only_functions, false, (!p_context.current_function || p_context.current_function->is_static), false, p_add_braces, r_result, p_recursion_depth); } List functions; @@ -1448,12 +1458,14 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context for (const StringName &E : functions) { MethodInfo function = GDScriptUtilityFunctions::get_function_info(E); ScriptLanguage::CodeCompletionOption option(String(E), ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); - if (function.arguments.size() || (function.flags & METHOD_FLAG_VARARG)) { - option.insert_text += "("; - option.display += U"(\u2026)"; - } else { - option.insert_text += "()"; - option.display += "()"; + if (p_add_braces) { + if (function.arguments.size() || (function.flags & METHOD_FLAG_VARARG)) { + option.insert_text += "("; + option.display += U"(\u2026)"; + } else { + option.insert_text += "()"; + option.display += "()"; + } } r_result.insert(option.display, option); } @@ -1499,8 +1511,10 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context const char **kwa = _keywords_with_args; while (*kwa) { ScriptLanguage::CodeCompletionOption option(*kwa, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); - option.insert_text += "("; - option.display += U"(\u2026)"; + if (p_add_braces) { + option.insert_text += "("; + option.display += U"(\u2026)"; + } r_result.insert(option.display, option); kwa++; } @@ -1511,7 +1525,10 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context for (const StringName &util_func_name : utility_func_names) { ScriptLanguage::CodeCompletionOption option(util_func_name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); option.insert_text += "("; - option.display += U"(\u2026)"; // As all utility functions contain an argument or more, this is hardcoded here. + if (p_add_braces) { + option.insert_text += "("; + option.display += U"(\u2026)"; // As all utility functions contain an argument or more, this is hardcoded here. + } r_result.insert(option.display, option); } @@ -1621,6 +1638,16 @@ static GDScriptCompletionIdentifier _type_from_property(const PropertyInfo &p_pr return ci; } +static GDScriptCompletionIdentifier _callable_type_from_method_info(const MethodInfo &p_method) { + GDScriptCompletionIdentifier ci; + ci.type.kind = GDScriptParser::DataType::BUILTIN; + ci.type.builtin_type = Variant::CALLABLE; + ci.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; + ci.type.is_constant = true; + ci.type.method_info = p_method; + return ci; +} + #define MAX_COMPLETION_RECURSION 100 struct RecursionCheck { int *counter; @@ -2458,14 +2485,13 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; r_type.type.kind = GDScriptParser::DataType::BUILTIN; r_type.type.builtin_type = Variant::SIGNAL; + r_type.type.method_info = member.signal->method_info; return true; case GDScriptParser::ClassNode::Member::FUNCTION: if (is_static && !member.function->is_static) { return false; } - r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; - r_type.type.kind = GDScriptParser::DataType::BUILTIN; - r_type.type.builtin_type = Variant::CALLABLE; + r_type = _callable_type_from_method_info(member.function->info); return true; case GDScriptParser::ClassNode::Member::CLASS: r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; @@ -2505,6 +2531,12 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & } } + if (scr->has_method(p_identifier)) { + MethodInfo mi = scr->get_method_info(p_identifier); + r_type = _callable_type_from_method_info(mi); + return true; + } + Ref