diff options
Diffstat (limited to 'modules/gdscript')
| -rw-r--r-- | modules/gdscript/SCsub | 5 | ||||
| -rw-r--r-- | modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd (renamed from modules/gdscript/editor_templates/CharacterBody2D/basic_movement.gd) | 0 | ||||
| -rw-r--r-- | modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd (renamed from modules/gdscript/editor_templates/CharacterBody3D/basic_movement.gd) | 0 | ||||
| -rw-r--r-- | modules/gdscript/editor/script_templates/EditorPlugin/plugin.gd (renamed from modules/gdscript/editor_templates/EditorPlugin/plugin.gd) | 0 | ||||
| -rw-r--r-- | modules/gdscript/editor/script_templates/EditorScript/basic_editor_script.gd (renamed from modules/gdscript/editor_templates/EditorScript/basic_editor_script.gd) | 0 | ||||
| -rw-r--r-- | modules/gdscript/editor/script_templates/Node/default.gd (renamed from modules/gdscript/editor_templates/Node/default.gd) | 0 | ||||
| -rw-r--r-- | modules/gdscript/editor/script_templates/Object/empty.gd (renamed from modules/gdscript/editor_templates/Object/empty.gd) | 0 | ||||
| -rw-r--r-- | modules/gdscript/editor/script_templates/SCsub (renamed from modules/gdscript/editor_templates/SCsub) | 0 | ||||
| -rw-r--r-- | modules/gdscript/editor/script_templates/VisualShaderNodeCustom/basic.gd (renamed from modules/gdscript/editor_templates/VisualShaderNodeCustom/basic.gd) | 0 | ||||
| -rw-r--r-- | modules/gdscript/gdscript.cpp | 2 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_analyzer.cpp | 14 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_editor.cpp | 106 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 8 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_parser.h | 2 |
14 files changed, 98 insertions, 39 deletions
diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub index c6121ec7fe..2f507db548 100644 --- a/modules/gdscript/SCsub +++ b/modules/gdscript/SCsub @@ -10,6 +10,8 @@ env_gdscript.add_source_files(env.modules_sources, "*.cpp") if env["tools"]: env_gdscript.add_source_files(env.modules_sources, "./editor/*.cpp") + SConscript("editor/script_templates/SCsub") + # Those two modules are required for the language server protocol if env["module_jsonrpc_enabled"] and env["module_websocket_enabled"]: env_gdscript.add_source_files(env.modules_sources, "./language_server/*.cpp") @@ -18,8 +20,7 @@ if env["tools"]: # in regular builds where all modules are enabled. env_gdscript.Append(CPPDEFINES=["GDSCRIPT_NO_LSP"]) + if env["tests"]: env_gdscript.Append(CPPDEFINES=["TESTS_ENABLED"]) env_gdscript.add_source_files(env.modules_sources, "./tests/*.cpp") - -SConscript("editor_templates/SCsub") diff --git a/modules/gdscript/editor_templates/CharacterBody2D/basic_movement.gd b/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd index a379d915a9..a379d915a9 100644 --- a/modules/gdscript/editor_templates/CharacterBody2D/basic_movement.gd +++ b/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd diff --git a/modules/gdscript/editor_templates/CharacterBody3D/basic_movement.gd b/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd index 360b199e56..360b199e56 100644 --- a/modules/gdscript/editor_templates/CharacterBody3D/basic_movement.gd +++ b/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd diff --git a/modules/gdscript/editor_templates/EditorPlugin/plugin.gd b/modules/gdscript/editor/script_templates/EditorPlugin/plugin.gd index b27b3e5655..b27b3e5655 100644 --- a/modules/gdscript/editor_templates/EditorPlugin/plugin.gd +++ b/modules/gdscript/editor/script_templates/EditorPlugin/plugin.gd diff --git a/modules/gdscript/editor_templates/EditorScript/basic_editor_script.gd b/modules/gdscript/editor/script_templates/EditorScript/basic_editor_script.gd index fdb8550d43..fdb8550d43 100644 --- a/modules/gdscript/editor_templates/EditorScript/basic_editor_script.gd +++ b/modules/gdscript/editor/script_templates/EditorScript/basic_editor_script.gd diff --git a/modules/gdscript/editor_templates/Node/default.gd b/modules/gdscript/editor/script_templates/Node/default.gd index cb96a21537..cb96a21537 100644 --- a/modules/gdscript/editor_templates/Node/default.gd +++ b/modules/gdscript/editor/script_templates/Node/default.gd diff --git a/modules/gdscript/editor_templates/Object/empty.gd b/modules/gdscript/editor/script_templates/Object/empty.gd index 387786b0a4..387786b0a4 100644 --- a/modules/gdscript/editor_templates/Object/empty.gd +++ b/modules/gdscript/editor/script_templates/Object/empty.gd diff --git a/modules/gdscript/editor_templates/SCsub b/modules/gdscript/editor/script_templates/SCsub index 2266ef2d01..2266ef2d01 100644 --- a/modules/gdscript/editor_templates/SCsub +++ b/modules/gdscript/editor/script_templates/SCsub diff --git a/modules/gdscript/editor_templates/VisualShaderNodeCustom/basic.gd b/modules/gdscript/editor/script_templates/VisualShaderNodeCustom/basic.gd index 283a95d3b4..283a95d3b4 100644 --- a/modules/gdscript/editor_templates/VisualShaderNodeCustom/basic.gd +++ b/modules/gdscript/editor/script_templates/VisualShaderNodeCustom/basic.gd diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index d415684d10..3a0e320e9b 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -824,7 +824,7 @@ Error GDScript::reload(bool p_keep_state) { // Loading a template, don't parse. #ifdef TOOLS_ENABLED - if (basedir.begins_with(EditorSettings::get_singleton()->get_project_script_templates_dir())) { + if (EditorSettings::get_singleton() && basedir.begins_with(EditorSettings::get_singleton()->get_project_script_templates_dir())) { return OK; } #endif diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 27e1520ab8..00931961b7 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -647,7 +647,7 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas } } - // Check if initalizer is an unset identifier (ie: a variable within scope, but declared below) + // Check if initializer is an unset identifier (ie: a variable within scope, but declared below) if (member.variable->initializer && !member.variable->initializer->get_datatype().is_set()) { if (member.variable->initializer->type == GDScriptParser::Node::IDENTIFIER) { GDScriptParser::IdentifierNode *initializer_identifier = static_cast<GDScriptParser::IdentifierNode *>(member.variable->initializer); @@ -2426,6 +2426,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a base_type = parser->current_class->base_type; base_type.is_meta_type = false; is_self = true; + + if (p_call->callee == nullptr && !lambda_stack.is_empty()) { + push_error("Cannot use `super()` inside a lambda.", p_call); + } } else if (callee_type == GDScriptParser::Node::IDENTIFIER) { base_type = parser->current_class->get_datatype(); base_type.is_meta_type = false; @@ -2494,12 +2498,12 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a } if (is_self && parser->current_function != nullptr && parser->current_function->is_static && !is_static) { - push_error(vformat(R"*(Cannot call non-static function "%s()" from static function "%s()".)*", p_call->function_name, parser->current_function->identifier->name), p_call->callee); + push_error(vformat(R"*(Cannot call non-static function "%s()" from static function "%s()".)*", p_call->function_name, parser->current_function->identifier->name), p_call); } else if (!is_self && base_type.is_meta_type && !is_static) { base_type.is_meta_type = false; // For `to_string()`. - push_error(vformat(R"*(Cannot call non-static function "%s()" on the class "%s" directly. Make an instance instead.)*", p_call->function_name, base_type.to_string()), p_call->callee); + push_error(vformat(R"*(Cannot call non-static function "%s()" on the class "%s" directly. Make an instance instead.)*", p_call->function_name, base_type.to_string()), p_call); } else if (is_self && !is_static && !lambda_stack.is_empty()) { - push_error(vformat(R"*(Cannot call non-static function "%s()" from a lambda function.)*", p_call->function_name), p_call->callee); + push_error(vformat(R"*(Cannot call non-static function "%s()" from a lambda function.)*", p_call->function_name), p_call); } call_type = return_type; @@ -2539,7 +2543,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a } if (call_type.is_coroutine && !p_is_await && !p_is_root) { - push_error(vformat(R"*(Function "%s()" is a coroutine, so it must be called with "await".)*", p_call->function_name), p_call->callee); + push_error(vformat(R"*(Function "%s()" is a coroutine, so it must be called with "await".)*", p_call->function_name), p_call); } p_call->set_datatype(call_type); diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 92b0241f51..7f0ffb4586 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -33,7 +33,6 @@ #include "core/config/engine.h" #include "core/core_constants.h" #include "core/io/file_access.h" -#include "editor_templates/templates.gen.h" #include "gdscript_analyzer.h" #include "gdscript_compiler.h" #include "gdscript_parser.h" @@ -44,6 +43,7 @@ #include "core/config/project_settings.h" #include "editor/editor_file_system.h" #include "editor/editor_settings.h" +#include "editor/script_templates/templates.gen.h" #endif void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const { @@ -64,8 +64,11 @@ Ref<Script> GDScriptLanguage::make_template(const String &p_template, const Stri Ref<GDScript> script; script.instantiate(); String processed_template = p_template; + bool type_hints = false; #ifdef TOOLS_ENABLED - if (!EDITOR_GET("text_editor/completion/add_type_hints")) { + type_hints = EDITOR_GET("text_editor/completion/add_type_hints"); +#endif + if (!type_hints) { processed_template = processed_template.replace(": int", "") .replace(": String", "") .replace(": Array[String]", "") @@ -75,16 +78,6 @@ Ref<Script> GDScriptLanguage::make_template(const String &p_template, const Stri .replace(" -> int", "") .replace(" -> void", ""); } -#else - processed_template = processed_template.replace(": int", "") - .replace(": String", "") - .replace(": Array[String]", "") - .replace(": float", "") - .replace(":=", "=") - .replace(" -> String", "") - .replace(" -> int", "") - .replace(" -> void", ""); -#endif processed_template = processed_template.replace("_BASE_", p_base_class_name) .replace("_CLASS_", p_class_name) @@ -95,11 +88,13 @@ Ref<Script> GDScriptLanguage::make_template(const String &p_template, const Stri Vector<ScriptLanguage::ScriptTemplate> GDScriptLanguage::get_built_in_templates(StringName p_object) { Vector<ScriptLanguage::ScriptTemplate> templates; +#ifdef TOOLS_ENABLED for (int i = 0; i < TEMPLATES_ARRAY_SIZE; i++) { if (TEMPLATES[i].inherit == p_object) { templates.append(TEMPLATES[i]); } } +#endif return templates; } @@ -2495,7 +2490,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c r_arghint = _make_arguments_hint(info, p_argidx); return; } else if (GDScriptParser::get_builtin_type(call->function_name) < Variant::VARIANT_MAX) { - // Complete constructor + // Complete constructor. List<MethodInfo> constructors; Variant::get_constructor_list(GDScriptParser::get_builtin_type(call->function_name), &constructors); @@ -2521,6 +2516,32 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c } else if (callee_type == GDScriptParser::Node::SUBSCRIPT) { const GDScriptParser::SubscriptNode *subscript = static_cast<const GDScriptParser::SubscriptNode *>(call->callee); + if (subscript->base != nullptr && subscript->base->type == GDScriptParser::Node::IDENTIFIER) { + const GDScriptParser::IdentifierNode *base_identifier = static_cast<const GDScriptParser::IdentifierNode *>(subscript->base); + + Variant::Type method_type = GDScriptParser::get_builtin_type(base_identifier->name); + if (method_type < Variant::VARIANT_MAX) { + Variant v; + Callable::CallError err; + Variant::construct(method_type, v, nullptr, 0, err); + if (err.error != Callable::CallError::CALL_OK) { + return; + } + List<MethodInfo> methods; + v.get_method_list(&methods); + + for (MethodInfo &E : methods) { + if (p_argidx >= E.arguments.size()) { + continue; + } + if (E.name == call->function_name) { + r_arghint += _make_arguments_hint(E, p_argidx); + return; + } + } + } + } + if (subscript->is_attribute) { GDScriptCompletionIdentifier ci; if (_guess_expression_type(p_context, subscript->base, ci)) { @@ -2583,17 +2604,36 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c _find_annotation_arguments(annotation, completion_context.current_argument, quote_style, options); r_forced = true; } break; - case GDScriptParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: { - List<StringName> constants; - Variant::get_constants_for_type(completion_context.builtin_type, &constants); - for (const StringName &E : constants) { - ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); - bool valid = false; - Variant default_value = Variant::get_constant_value(completion_context.builtin_type, E, &valid); - if (valid) { - option.default_value = default_value; + case GDScriptParser::COMPLETION_BUILT_IN_TYPE_CONSTANT_OR_STATIC_METHOD: { + // Constants. + { + List<StringName> constants; + Variant::get_constants_for_type(completion_context.builtin_type, &constants); + for (const StringName &E : constants) { + ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); + bool valid = false; + Variant default_value = Variant::get_constant_value(completion_context.builtin_type, E, &valid); + if (valid) { + option.default_value = default_value; + } + options.insert(option.display, option); + } + } + // Methods. + { + List<StringName> methods; + Variant::get_builtin_method_list(completion_context.builtin_type, &methods); + for (const StringName &E : methods) { + if (Variant::is_builtin_method_static(completion_context.builtin_type, E)) { + ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); + if (Variant::get_builtin_method_argument_count(completion_context.builtin_type, E) > 0 || Variant::is_builtin_method_vararg(completion_context.builtin_type, E)) { + option.insert_text += "("; + } else { + option.insert_text += "()"; + } + options.insert(option.display, option); + } } - options.insert(option.display, option); } } break; case GDScriptParser::COMPLETION_INHERIT_TYPE: { @@ -3147,11 +3187,21 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co bool is_function = false; switch (context.type) { - case GDScriptParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: { - r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_CONSTANT; - r_result.class_name = Variant::get_type_name(context.builtin_type); - r_result.class_member = p_symbol; - return OK; + case GDScriptParser::COMPLETION_BUILT_IN_TYPE_CONSTANT_OR_STATIC_METHOD: { + if (!Variant::has_builtin_method(context.builtin_type, StringName(p_symbol))) { + // A constant. + r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_CONSTANT; + r_result.class_name = Variant::get_type_name(context.builtin_type); + r_result.class_member = p_symbol; + return OK; + } + // A method. + GDScriptParser::DataType base_type; + base_type.kind = GDScriptParser::DataType::BUILTIN; + base_type.builtin_type = context.builtin_type; + if (_lookup_symbol_from_base(base_type, p_symbol, true, r_result) == OK) { + return OK; + } } break; case GDScriptParser::COMPLETION_SUPER_METHOD: case GDScriptParser::COMPLETION_METHOD: { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 10709d3667..67d778f932 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2685,7 +2685,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_attribute(ExpressionNode * const IdentifierNode *id = static_cast<const IdentifierNode *>(p_previous_operand); Variant::Type builtin_type = get_builtin_type(id->name); if (builtin_type < Variant::VARIANT_MAX) { - make_completion_context(COMPLETION_BUILT_IN_TYPE_CONSTANT, builtin_type, true); + make_completion_context(COMPLETION_BUILT_IN_TYPE_CONSTANT_OR_STATIC_METHOD, builtin_type, true); is_builtin = true; } } @@ -2752,7 +2752,11 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre pop_multiline(); return nullptr; } - call->function_name = current_function->identifier->name; + if (current_function->identifier) { + call->function_name = current_function->identifier->name; + } else { + call->function_name = SNAME("<anonymous>"); + } } else { consume(GDScriptTokenizer::Token::PERIOD, R"(Expected "." or "(" after "super".)"); make_completion_context(COMPLETION_SUPER_METHOD, call, true); diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index c09b07282f..0da1896936 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -1146,7 +1146,7 @@ public: COMPLETION_ASSIGN, // Assignment based on type (e.g. enum values). COMPLETION_ATTRIBUTE, // After id.| to look for members. COMPLETION_ATTRIBUTE_METHOD, // After id.| to look for methods. - COMPLETION_BUILT_IN_TYPE_CONSTANT, // Constants inside a built-in type (e.g. Color.blue). + COMPLETION_BUILT_IN_TYPE_CONSTANT_OR_STATIC_METHOD, // Constants inside a built-in type (e.g. Color.BLUE) or static methods (e.g. Color.html). COMPLETION_CALL_ARGUMENTS, // Complete with nodes, input actions, enum values (or usual expressions). // TODO: COMPLETION_DECLARATION, // Potential declaration (var, const, func). COMPLETION_GET_NODE, // Get node with $ notation. |