diff options
Diffstat (limited to 'modules/gdscript/gdscript_editor.cpp')
-rw-r--r-- | modules/gdscript/gdscript_editor.cpp | 99 |
1 files changed, 77 insertions, 22 deletions
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 74d383c57f..fcabb7c4a8 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -754,13 +754,17 @@ static String _make_arguments_hint(const MethodInfo &p_info, int p_arg_idx, bool return arghint; } -static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_function, int p_arg_idx) { +static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_function, int p_arg_idx, bool p_just_args = false) { String arghint; - if (p_function->get_datatype().builtin_type == Variant::NIL) { - arghint = "void " + p_function->identifier->name.operator String() + "("; + if (p_just_args) { + arghint = "("; } else { - arghint = p_function->get_datatype().to_string() + " " + p_function->identifier->name.operator String() + "("; + if (p_function->get_datatype().builtin_type == Variant::NIL) { + arghint = "void " + p_function->identifier->name.operator String() + "("; + } else { + arghint = p_function->get_datatype().to_string() + " " + p_function->identifier->name.operator String() + "("; + } } for (int i = 0; i < p_function->parameters.size(); i++) { @@ -911,6 +915,29 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a option.insert_text = option.display.quote(p_quote_style); r_result.insert(option.display, option); } + } else if (p_annotation->name == SNAME("@export_custom")) { + switch (p_argument) { + case 0: { + static HashMap<StringName, int64_t> items; + if (unlikely(items.is_empty())) { + CoreConstants::get_enum_values(SNAME("PropertyHint"), &items); + } + for (const KeyValue<StringName, int64_t> &item : items) { + ScriptLanguage::CodeCompletionOption option(item.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); + r_result.insert(option.display, option); + } + } break; + case 2: { + static HashMap<StringName, int64_t> items; + if (unlikely(items.is_empty())) { + CoreConstants::get_enum_values(SNAME("PropertyUsageFlags"), &items); + } + for (const KeyValue<StringName, int64_t> &item : items) { + ScriptLanguage::CodeCompletionOption option(item.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); + r_result.insert(option.display, option); + } + } break; + } } else if (p_annotation->name == SNAME("@warning_ignore")) { for (int warning_code = 0; warning_code < GDScriptWarning::WARNING_MAX; warning_code++) { ScriptLanguage::CodeCompletionOption warning(GDScriptWarning::get_name_from_code((GDScriptWarning::Code)warning_code).to_lower(), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); @@ -1695,6 +1722,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, if (full) { // If not fully constant, setting this value is detrimental to the inference. r_type.value = a; + r_type.type.is_constant = true; } r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; r_type.type.kind = GDScriptParser::DataType::BUILTIN; @@ -2064,6 +2092,12 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context, found = false; } + // If the found type was not fully analyzed we analyze it now. + if (found && r_type.type.kind == GDScriptParser::DataType::CLASS && !r_type.type.class_type->resolved_body) { + Error err; + Ref<GDScriptParserRef> r = GDScriptCache::get_parser(r_type.type.script_path, GDScriptParserRef::FULLY_SOLVED, err); + } + // Check type hint last. For collections we want chance to get the actual value first // This way we can detect types from the content of dictionaries and arrays if (!found && p_expression->get_datatype().is_hard_type()) { @@ -2701,6 +2735,25 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c while (base_type.is_set() && !base_type.is_variant()) { switch (base_type.kind) { case GDScriptParser::DataType::CLASS: { + if (base_type.is_meta_type && p_method == SNAME("new")) { + const GDScriptParser::ClassNode *current = base_type.class_type; + + do { + if (current->has_member("_init")) { + const GDScriptParser::ClassNode::Member &member = current->get_member("_init"); + + if (member.type == GDScriptParser::ClassNode::Member::FUNCTION) { + r_arghint = base_type.class_type->get_datatype().to_string() + " new" + _make_arguments_hint(member.function, p_argidx, true); + return; + } + } + current = current->base_type.class_type; + } while (current != nullptr); + + r_arghint = base_type.class_type->get_datatype().to_string() + " new()"; + return; + } + if (base_type.class_type->has_member(p_method)) { const GDScriptParser::ClassNode::Member &member = base_type.class_type->get_member(p_method); @@ -2733,9 +2786,9 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c // Handle user preference. if (opt.is_quoted()) { opt = opt.unquote().quote(quote_style); - if (use_string_names && info.arguments[p_argidx].type == Variant::STRING_NAME) { + if (use_string_names && info.arguments.get(p_argidx).type == Variant::STRING_NAME) { opt = opt.indent("&"); - } else if (use_node_paths && info.arguments[p_argidx].type == Variant::NODE_PATH) { + } else if (use_node_paths && info.arguments.get(p_argidx).type == Variant::NODE_PATH) { opt = opt.indent("^"); } } @@ -2746,7 +2799,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } if (p_argidx < method_args) { - PropertyInfo arg_info = info.arguments[p_argidx]; + const PropertyInfo &arg_info = info.arguments.get(p_argidx); if (arg_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { _find_enumeration_candidates(p_context, arg_info.class_name, r_result); } @@ -3334,19 +3387,17 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } method_hint += "("; - if (mi.arguments.size()) { - for (int i = 0; i < mi.arguments.size(); i++) { - if (i > 0) { - method_hint += ", "; - } - String arg = mi.arguments[i].name; - if (arg.contains(":")) { - arg = arg.substr(0, arg.find(":")); - } - method_hint += arg; - if (use_type_hint) { - method_hint += ": " + _get_visual_datatype(mi.arguments[i], true, class_name); - } + for (List<PropertyInfo>::ConstIterator arg_itr = mi.arguments.begin(); arg_itr != mi.arguments.end(); ++arg_itr) { + if (arg_itr != mi.arguments.begin()) { + method_hint += ", "; + } + String arg = arg_itr->name; + if (arg.contains(":")) { + arg = arg.substr(0, arg.find(":")); + } + method_hint += arg; + if (use_type_hint) { + method_hint += ": " + _get_visual_datatype(*arg_itr, true, class_name); } } method_hint += ")"; @@ -3520,9 +3571,13 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co switch (base_type.kind) { case GDScriptParser::DataType::CLASS: { if (base_type.class_type) { - if (base_type.class_type->has_member(p_symbol)) { + String name = p_symbol; + if (name == "new") { + name = "_init"; + } + if (base_type.class_type->has_member(name)) { r_result.type = ScriptLanguage::LOOKUP_RESULT_SCRIPT_LOCATION; - r_result.location = base_type.class_type->get_member(p_symbol).get_line(); + r_result.location = base_type.class_type->get_member(name).get_line(); r_result.class_path = base_type.script_path; Error err = OK; r_result.script = GDScriptCache::get_shallow_script(r_result.class_path, err); |