feat: updated engine

This commit is contained in:
Sara Gerretsen 2026-07-10 17:04:34 +02:00
parent cbe99774ff
commit f4cf6b3999
6607 changed files with 910135 additions and 430025 deletions

View file

@ -33,6 +33,7 @@
#include "../gdscript.h"
#include "core/config/project_settings.h"
#include "core/doc_data.h"
HashMap<String, String> GDScriptDocGen::singletons;
@ -61,6 +62,20 @@ String GDScriptDocGen::_get_class_name(const GDP::ClassNode &p_class) {
return full_name;
}
String GDScriptDocGen::_get_gdscript_name(const GDScript *p_script) {
if (p_script->local_name.is_empty()) {
// This is an outer unnamed class.
return _get_script_name(p_script->get_script_path());
} else {
// This is an inner or global outer class.
String name = p_script->local_name;
if (p_script->_owner) {
name = _get_gdscript_name(p_script->_owner) + "." + name;
}
return name;
}
}
void GDScriptDocGen::_doctype_from_gdtype(const GDType &p_gdtype, String &r_type, String &r_enum, bool p_is_return) {
if (!p_gdtype.is_hard_type()) {
r_type = "Variant";
@ -304,7 +319,7 @@ String GDScriptDocGen::docvalue_from_expression(const GDP::ExpressionNode *p_exp
case GDP::Node::CALL: {
const GDP::CallNode *call = static_cast<const GDP::CallNode *>(p_expression);
if (call->get_callee_type() == GDP::Node::IDENTIFIER) {
return call->function_name.operator String() + (call->arguments.is_empty() ? "()" : "(...)");
return call->function_name.string() + (call->arguments.is_empty() ? "()" : "(...)");
}
} break;
case GDP::Node::DICTIONARY: {
@ -315,6 +330,11 @@ String GDScriptDocGen::docvalue_from_expression(const GDP::ExpressionNode *p_exp
const GDP::IdentifierNode *id = static_cast<const GDP::IdentifierNode *>(p_expression);
return id->name;
} break;
case GDP::Node::LAMBDA: {
const GDP::LambdaNode *lambda = static_cast<const GDP::LambdaNode *>(p_expression);
const GDP::IdentifierNode *id = lambda->function->identifier;
return id != nullptr ? id->name : "<anonymous lambda>";
} break;
default: {
// Nothing to do.
} break;
@ -330,27 +350,16 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
doc.is_script_doc = true;
if (p_script->local_name == StringName()) {
// This is an outer unnamed class.
doc.name = _get_script_name(p_script->get_script_path());
} else {
// This is an inner or global outer class.
doc.name = p_script->local_name;
if (p_script->_owner) {
doc.name = p_script->_owner->doc.name + "." + doc.name;
}
}
doc.name = _get_gdscript_name(p_script);
doc.script_path = p_script->get_script_path();
if (p_script->base.is_valid() && p_script->base->is_valid()) {
if (!p_script->base->doc.name.is_empty()) {
doc.inherits = p_script->base->doc.name;
} else {
doc.inherits = p_script->base->get_instance_base_type();
}
} else if (p_script->native.is_valid()) {
doc.inherits = p_script->native->get_name();
if (p_script->base.is_valid() && p_script->base->is_script_valid()) {
// See GH-105926. Evaluate the doc name of the base class instead of using `p_script->base->doc.name`
// to avoid load/compile order issues in case of complex circular dependencies.
doc.inherits = _get_gdscript_name(p_script->base.ptr());
} else {
doc.inherits = p_script->get_instance_base_type();
}
doc.brief_description = p_class->doc_data.brief;
@ -389,7 +398,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
const_doc.name = const_name;
const_doc.value = _docvalue_from_variant(m_const->initializer->reduced_value);
const_doc.is_value_valid = true;
_doctype_from_gdtype(m_const->get_datatype(), const_doc.type, const_doc.enumeration);
_doctype_from_gdtype(m_const->type_constraint, const_doc.type, const_doc.enumeration);
const_doc.description = m_const->doc_data.description;
const_doc.is_deprecated = m_const->doc_data.is_deprecated;
const_doc.deprecated_message = m_const->doc_data.deprecated_message;
@ -418,7 +427,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
}
method_doc.qualifiers += "vararg";
method_doc.rest_argument.name = m_func->rest_parameter->identifier->name;
_doctype_from_gdtype(m_func->rest_parameter->get_datatype(), method_doc.rest_argument.type, method_doc.rest_argument.enumeration);
_doctype_from_gdtype(m_func->rest_parameter->type_constraint, method_doc.rest_argument.type, method_doc.rest_argument.enumeration);
}
if (m_func->is_abstract) {
if (!method_doc.qualifiers.is_empty()) {
@ -433,14 +442,10 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
method_doc.qualifiers += "static";
}
if (func_name == "_init") {
method_doc.return_type = "void";
} else if (m_func->return_type) {
// `m_func->return_type->get_datatype()` is a metatype.
_doctype_from_gdtype(m_func->get_datatype(), method_doc.return_type, method_doc.return_enum, true);
} else if (!m_func->body->has_return) {
// If no `return` statement, then return type is `void`, not `Variant`.
if (func_name == "_init" || func_name == "_static_init") {
method_doc.return_type = "void";
} else if (!m_func->return_type_constraint.is_variant()) {
_doctype_from_gdtype(m_func->return_type_constraint, method_doc.return_type, method_doc.return_enum, true);
} else {
method_doc.return_type = "Variant";
}
@ -448,7 +453,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
for (const GDP::ParameterNode *p : m_func->parameters) {
DocData::ArgumentDoc arg_doc;
arg_doc.name = p->identifier->name;
_doctype_from_gdtype(p->get_datatype(), arg_doc.type, arg_doc.enumeration);
_doctype_from_gdtype(p->type_constraint, arg_doc.type, arg_doc.enumeration);
if (p->initializer != nullptr) {
arg_doc.default_value = docvalue_from_expression(p->initializer);
}
@ -475,7 +480,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
for (const GDP::ParameterNode *p : m_signal->parameters) {
DocData::ArgumentDoc arg_doc;
arg_doc.name = p->identifier->name;
_doctype_from_gdtype(p->get_datatype(), arg_doc.type, arg_doc.enumeration);
_doctype_from_gdtype(p->type_constraint, arg_doc.type, arg_doc.enumeration);
signal_doc.arguments.push_back(arg_doc);
}
@ -495,7 +500,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
prop_doc.deprecated_message = m_var->doc_data.deprecated_message;
prop_doc.is_experimental = m_var->doc_data.is_experimental;
prop_doc.experimental_message = m_var->doc_data.experimental_message;
_doctype_from_gdtype(m_var->get_datatype(), prop_doc.type, prop_doc.enumeration);
_doctype_from_gdtype(m_var->type_constraint, prop_doc.type, prop_doc.enumeration);
switch (m_var->property) {
case GDP::VariableNode::PROP_NONE:

View file

@ -32,8 +32,6 @@
#include "../gdscript_parser.h"
#include "core/doc_data.h"
class GDScriptDocGen {
using GDP = GDScriptParser;
using GDType = GDP::DataType;
@ -42,8 +40,11 @@ class GDScriptDocGen {
static String _get_script_name(const String &p_path);
static String _get_class_name(const GDP::ClassNode &p_class);
static String _get_gdscript_name(const GDScript *p_script);
static void _doctype_from_gdtype(const GDType &p_gdtype, String &r_type, String &r_enum, bool p_is_return = false);
static String _docvalue_from_variant(const Variant &p_variant, int p_recursion_level = 1);
static void _generate_docs(GDScript *p_script, const GDP::ClassNode *p_class);
public:

View file

@ -0,0 +1,54 @@
/**************************************************************************/
/* gdscript_editor_language.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/object/editor_language.h"
class GDScriptEditorLanguage final : public EditorLanguage {
static GDScriptEditorLanguage *singleton;
public:
_FORCE_INLINE_ static GDScriptEditorLanguage *get_singleton() { return singleton; }
virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptLanguage::CodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) override;
virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) override;
GDScriptEditorLanguage() {
ERR_FAIL_COND(singleton != nullptr);
singleton = this;
}
~GDScriptEditorLanguage() {
if (singleton == this) {
singleton = nullptr;
}
}
};

View file

@ -35,8 +35,8 @@
#include "core/config/project_settings.h"
#include "core/core_constants.h"
#include "core/object/class_db.h"
#include "editor/settings/editor_settings.h"
#include "editor/themes/editor_theme_manager.h"
#include "scene/gui/text_edit.h"
Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_line) {
@ -947,7 +947,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
HashMap<StringName, Variant> scr_constant_list;
scr_class->get_constants(&scr_constant_list);
for (const KeyValue<StringName, Variant> &E : scr_constant_list) {
member_keywords[E.key.operator String()] = member_variable_color;
member_keywords[E.key.string()] = member_variable_color;
}
scr_class = scr_class->get_base_script();
}

View file

@ -30,7 +30,7 @@
#pragma once
#include "editor/script/script_editor_plugin.h"
#include "editor/script/syntax_highlighters.h"
class GDScriptSyntaxHighlighter : public EditorSyntaxHighlighter {
GDCLASS(GDScriptSyntaxHighlighter, EditorSyntaxHighlighter)

View file

@ -450,6 +450,7 @@ GDScriptEditorTranslationParserPlugin::GDScriptEditorTranslationParserPlugin() {
first_arg_patterns.insert("add_radio_check_item");
first_arg_patterns.insert("add_separator");
first_arg_patterns.insert("add_submenu_item");
first_arg_patterns.insert("add_submenu_node_item");
second_arg_patterns.insert("set_tab_title");
second_arg_patterns.insert("add_icon_check_item");

View file

@ -38,7 +38,7 @@
#include "editor/translations/editor_translation_parser.h"
class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlugin {
GDCLASS(GDScriptEditorTranslationParserPlugin, EditorTranslationParserPlugin);
GDSOFTCLASS(GDScriptEditorTranslationParserPlugin, EditorTranslationParserPlugin);
const HashMap<int, GDScriptTokenizer::CommentData> *comment_data = nullptr;