feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -84,6 +84,15 @@ void GDScriptDocGen::_doctype_from_gdtype(const GDType &p_gdtype, String &r_type
return;
}
}
if (p_gdtype.builtin_type == Variant::DICTIONARY && p_gdtype.has_container_element_types()) {
String key, value;
_doctype_from_gdtype(p_gdtype.get_container_element_type_or_variant(0), key, r_enum);
_doctype_from_gdtype(p_gdtype.get_container_element_type_or_variant(1), value, r_enum);
if (key != "Variant" || value != "Variant") {
r_type = "Dictionary[" + key + ", " + value + "]";
return;
}
}
r_type = Variant::get_type_name(p_gdtype.builtin_type);
return;
case GDType::NATIVE:
@ -130,10 +139,11 @@ void GDScriptDocGen::_doctype_from_gdtype(const GDType &p_gdtype, String &r_type
r_type = "int";
r_enum = String(p_gdtype.native_type).replace("::", ".");
if (r_enum.begins_with("res://")) {
r_enum = r_enum.trim_prefix("res://");
int dot_pos = r_enum.rfind(".");
int dot_pos = r_enum.rfind_char('.');
if (dot_pos >= 0) {
r_enum = r_enum.left(dot_pos).quote() + r_enum.substr(dot_pos);
r_enum = _get_script_name(r_enum.left(dot_pos)) + r_enum.substr(dot_pos);
} else {
r_enum = _get_script_name(r_enum);
}
}
return;
@ -155,34 +165,82 @@ String GDScriptDocGen::_docvalue_from_variant(const Variant &p_variant, int p_re
return "<Object>";
case Variant::DICTIONARY: {
const Dictionary dict = p_variant;
String result;
if (dict.is_typed()) {
result += "Dictionary[";
Ref<Script> key_script = dict.get_typed_key_script();
if (key_script.is_valid()) {
if (key_script->get_global_name() != StringName()) {
result += key_script->get_global_name();
} else if (!key_script->get_path().get_file().is_empty()) {
result += key_script->get_path().get_file();
} else {
result += dict.get_typed_key_class_name();
}
} else if (dict.get_typed_key_class_name() != StringName()) {
result += dict.get_typed_key_class_name();
} else if (dict.is_typed_key()) {
result += Variant::get_type_name((Variant::Type)dict.get_typed_key_builtin());
} else {
result += "Variant";
}
result += ", ";
Ref<Script> value_script = dict.get_typed_value_script();
if (value_script.is_valid()) {
if (value_script->get_global_name() != StringName()) {
result += value_script->get_global_name();
} else if (!value_script->get_path().get_file().is_empty()) {
result += value_script->get_path().get_file();
} else {
result += dict.get_typed_value_class_name();
}
} else if (dict.get_typed_value_class_name() != StringName()) {
result += dict.get_typed_value_class_name();
} else if (dict.is_typed_value()) {
result += Variant::get_type_name((Variant::Type)dict.get_typed_value_builtin());
} else {
result += "Variant";
}
result += "](";
}
if (dict.is_empty()) {
return "{}";
}
result += "{}";
} else if (p_recursion_level > MAX_RECURSION_LEVEL) {
result += "{...}";
} else {
result += "{";
if (p_recursion_level > MAX_RECURSION_LEVEL) {
return "{...}";
}
List<Variant> keys;
dict.get_key_list(&keys);
keys.sort_custom<StringLikeVariantOrder>();
List<Variant> keys;
dict.get_key_list(&keys);
keys.sort();
String data;
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
if (E->prev()) {
data += ", ";
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
if (E->prev()) {
result += ", ";
}
result += _docvalue_from_variant(E->get(), p_recursion_level + 1) + ": " + _docvalue_from_variant(dict[E->get()], p_recursion_level + 1);
}
data += _docvalue_from_variant(E->get(), p_recursion_level + 1) + ": " + _docvalue_from_variant(dict[E->get()], p_recursion_level + 1);
result += "}";
}
return "{" + data + "}";
if (dict.is_typed()) {
result += ")";
}
return result;
} break;
case Variant::ARRAY: {
const Array array = p_variant;
String result;
if (array.get_typed_builtin() != Variant::NIL) {
if (array.is_typed()) {
result += "Array[";
Ref<Script> script = array.get_typed_script();
@ -209,16 +267,18 @@ String GDScriptDocGen::_docvalue_from_variant(const Variant &p_variant, int p_re
result += "[...]";
} else {
result += "[";
for (int i = 0; i < array.size(); i++) {
if (i > 0) {
result += ", ";
}
result += _docvalue_from_variant(array[i], p_recursion_level + 1);
}
result += "]";
}
if (array.get_typed_builtin() != Variant::NIL) {
if (array.is_typed()) {
result += ")";
}
@ -229,7 +289,7 @@ String GDScriptDocGen::_docvalue_from_variant(const Variant &p_variant, int p_re
}
}
String GDScriptDocGen::_docvalue_from_expression(const GDP::ExpressionNode *p_expression) {
String GDScriptDocGen::docvalue_from_expression(const GDP::ExpressionNode *p_expression) {
ERR_FAIL_NULL_V(p_expression, String());
if (p_expression->is_constant) {
@ -325,6 +385,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);
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;
@ -348,7 +409,9 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
method_doc.experimental_message = m_func->doc_data.experimental_message;
method_doc.qualifiers = m_func->is_static ? "static" : "";
if (m_func->return_type) {
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) {
@ -363,7 +426,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
arg_doc.name = p->identifier->name;
_doctype_from_gdtype(p->get_datatype(), arg_doc.type, arg_doc.enumeration);
if (p->initializer != nullptr) {
arg_doc.default_value = _docvalue_from_expression(p->initializer);
arg_doc.default_value = docvalue_from_expression(p->initializer);
}
method_doc.arguments.push_back(arg_doc);
}
@ -432,7 +495,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
}
if (m_var->initializer != nullptr) {
prop_doc.default_value = _docvalue_from_expression(m_var->initializer);
prop_doc.default_value = docvalue_from_expression(m_var->initializer);
}
prop_doc.overridden = false;
@ -459,6 +522,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
const_doc.name = val.identifier->name;
const_doc.value = _docvalue_from_variant(val.value);
const_doc.is_value_valid = true;
const_doc.type = "int";
const_doc.enumeration = name;
const_doc.description = val.doc_data.description;
const_doc.is_deprecated = val.doc_data.is_deprecated;
@ -481,6 +545,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
const_doc.name = name;
const_doc.value = _docvalue_from_variant(m_enum_val.value);
const_doc.is_value_valid = true;
const_doc.type = "int";
const_doc.enumeration = "@unnamed_enums";
const_doc.description = m_enum_val.doc_data.description;
const_doc.is_deprecated = m_enum_val.doc_data.is_deprecated;
@ -508,3 +573,14 @@ void GDScriptDocGen::generate_docs(GDScript *p_script, const GDP::ClassNode *p_c
_generate_docs(p_script, p_class);
singletons.clear();
}
// This method is needed for the editor, since during autocompletion the script is not compiled, only analyzed.
void GDScriptDocGen::doctype_from_gdtype(const GDType &p_gdtype, String &r_type, String &r_enum, bool p_is_return) {
for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) {
if (E.value.is_singleton) {
singletons[E.value.path] = E.key;
}
}
_doctype_from_gdtype(p_gdtype, r_type, r_enum, p_is_return);
singletons.clear();
}

View file

@ -45,11 +45,12 @@ class GDScriptDocGen {
static String _get_class_name(const GDP::ClassNode &p_class);
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 String _docvalue_from_expression(const GDP::ExpressionNode *p_expression);
static void _generate_docs(GDScript *p_script, const GDP::ClassNode *p_class);
public:
static void generate_docs(GDScript *p_script, const GDP::ClassNode *p_class);
static void doctype_from_gdtype(const GDType &p_gdtype, String &r_type, String &r_enum, bool p_is_return = false);
static String docvalue_from_expression(const GDP::ExpressionNode *p_expression);
};
#endif // GDSCRIPT_DOCGEN_H

View file

@ -36,6 +36,7 @@
#include "core/config/project_settings.h"
#include "editor/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) {
Dictionary color_map;
@ -93,7 +94,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
in_region = color_region_cache[p_line - 1];
}
const String &str = text_edit->get_line(p_line);
const String &str = text_edit->get_line_with_ime(p_line);
const int line_length = str.length();
Color prev_color;
@ -163,7 +164,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
}
if (from + end_key_length > line_length) {
// If it's key length and there is a '\', dont skip to highlight esc chars.
if (str.find("\\", from) >= 0) {
if (str.find_char('\\', from) >= 0) {
break;
}
}
@ -236,7 +237,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
for (; from < line_length; from++) {
if (line_length - from < end_key_length) {
// Don't break if '\' to highlight esc chars.
if (str.find("\\", from) < 0) {
if (str.find_char('\\', from) < 0) {
break;
}
}
@ -350,15 +351,15 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
// Special cases for numbers.
if (in_number && !is_a_digit) {
if (str[j] == 'b' && str[j - 1] == '0') {
if ((str[j] == 'b' || str[j] == 'B') && str[j - 1] == '0') {
is_bin_notation = true;
} else if (str[j] == 'x' && str[j - 1] == '0') {
} else if ((str[j] == 'x' || str[j] == 'X') && str[j - 1] == '0') {
is_hex_notation = true;
} else if (!((str[j] == '-' || str[j] == '+') && str[j - 1] == 'e' && !prev_is_digit) &&
!(str[j] == '_' && (prev_is_digit || str[j - 1] == 'b' || str[j - 1] == 'x' || str[j - 1] == '.')) &&
!(str[j] == 'e' && (prev_is_digit || str[j - 1] == '_')) &&
} else if (!((str[j] == '-' || str[j] == '+') && (str[j - 1] == 'e' || str[j - 1] == 'E') && !prev_is_digit) &&
!(str[j] == '_' && (prev_is_digit || str[j - 1] == 'b' || str[j - 1] == 'B' || str[j - 1] == 'x' || str[j - 1] == 'X' || str[j - 1] == '.')) &&
!((str[j] == 'e' || str[j] == 'E') && (prev_is_digit || str[j - 1] == '_')) &&
!(str[j] == '.' && (prev_is_digit || (!prev_is_binary_op && (j > 0 && (str[j - 1] == '_' || str[j - 1] == '-' || str[j - 1] == '+' || str[j - 1] == '~'))))) &&
!((str[j] == '-' || str[j] == '+' || str[j] == '~') && !is_binary_op && !prev_is_binary_op && str[j - 1] != 'e')) {
!((str[j] == '-' || str[j] == '+' || str[j] == '~') && !is_binary_op && !prev_is_binary_op && str[j - 1] != 'e' && str[j - 1] != 'E')) {
/* This condition continues number highlighting in special cases.
1st row: '+' or '-' after scientific notation (like 3e-4);
2nd row: '_' as a numeric separator;
@ -560,12 +561,17 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
}
}
// Keep symbol color for binary '&&'. In the case of '&&&' use StringName color for the last ampersand.
// Set color of StringName, keeping symbol color for binary '&&' and '&'.
if (!in_string_name && in_region == -1 && str[j] == '&' && !is_binary_op) {
if (j >= 2 && str[j - 1] == '&' && str[j - 2] != '&' && prev_is_binary_op) {
is_binary_op = true;
} else if (j == 0 || (j > 0 && str[j - 1] != '&') || prev_is_binary_op) {
if (j + 1 <= line_length - 1 && (str[j + 1] == '\'' || str[j + 1] == '"')) {
in_string_name = true;
// Cover edge cases of i.e. '+&""' and '&&&""', so the StringName is properly colored.
if (prev_is_binary_op && j >= 2 && str[j - 1] == '&' && str[j - 2] != '&') {
in_string_name = false;
is_binary_op = true;
}
} else {
is_binary_op = true;
}
} else if (in_region != -1 || is_a_symbol) {
in_string_name = false;
@ -701,7 +707,9 @@ void GDScriptSyntaxHighlighter::_update_cache() {
List<StringName> types;
ClassDB::get_class_list(&types);
for (const StringName &E : types) {
class_names[E] = types_color;
if (ClassDB::is_class_exposed(E)) {
class_names[E] = types_color;
}
}
/* User types. */
@ -813,7 +821,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
if (E.usage & PROPERTY_USAGE_CATEGORY || E.usage & PROPERTY_USAGE_GROUP || E.usage & PROPERTY_USAGE_SUBGROUP) {
continue;
}
if (prop_name.contains("/")) {
if (prop_name.contains_char('/')) {
continue;
}
member_keywords[prop_name] = member_variable_color;
@ -852,6 +860,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
comment_marker_colors[COMMENT_MARKER_NOTICE] = Color(0.24, 0.54, 0.09);
}
// TODO: Move to editor_settings.cpp
EDITOR_DEF("text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color);
EDITOR_DEF("text_editor/theme/highlighting/gdscript/global_function_color", global_function_color);
EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_path_color", node_path_color);

View file

@ -32,7 +32,6 @@
#define GDSCRIPT_HIGHLIGHTER_H
#include "editor/plugins/script_editor_plugin.h"
#include "scene/gui/text_edit.h"
class GDScriptSyntaxHighlighter : public EditorSyntaxHighlighter {
GDCLASS(GDScriptSyntaxHighlighter, EditorSyntaxHighlighter)

View file

@ -39,7 +39,7 @@ void GDScriptEditorTranslationParserPlugin::get_recognized_extensions(List<Strin
GDScriptLanguage::get_singleton()->get_recognized_extensions(r_extensions);
}
Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Vector<String> *r_ids, Vector<Vector<String>> *r_ids_ctx_plural) {
Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Vector<Vector<String>> *r_translations) {
// Extract all translatable strings using the parsed tree from GDScriptParser.
// The strategy is to find all ExpressionNode and AssignmentNode from the tree and extract strings if relevant, i.e
// Search strings in ExpressionNode -> CallNode -> tr(), set_text(), set_placeholder() etc.
@ -49,8 +49,8 @@ Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Ve
Ref<Resource> loaded_res = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err);
ERR_FAIL_COND_V_MSG(err, err, "Failed to load " + p_path);
ids = r_ids;
ids_ctx_plural = r_ids_ctx_plural;
translations = r_translations;
Ref<GDScript> gdscript = loaded_res;
String source_code = gdscript->get_source_code();
@ -62,16 +62,81 @@ Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Ve
err = analyzer.analyze();
ERR_FAIL_COND_V_MSG(err, err, "Failed to analyze GDScript with GDScriptAnalyzer.");
comment_data = &parser.comment_data;
// Traverse through the parsed tree from GDScriptParser.
GDScriptParser::ClassNode *c = parser.get_tree();
_traverse_class(c);
comment_data = nullptr;
return OK;
}
bool GDScriptEditorTranslationParserPlugin::_is_constant_string(const GDScriptParser::ExpressionNode *p_expression) {
ERR_FAIL_NULL_V(p_expression, false);
return p_expression->is_constant && (p_expression->reduced_value.get_type() == Variant::STRING || p_expression->reduced_value.get_type() == Variant::STRING_NAME);
return p_expression->is_constant && p_expression->reduced_value.is_string();
}
String GDScriptEditorTranslationParserPlugin::_parse_comment(int p_line, bool &r_skip) const {
// Parse inline comment.
if (comment_data->has(p_line)) {
const String stripped_comment = comment_data->get(p_line).comment.trim_prefix("#").strip_edges();
if (stripped_comment.begins_with("TRANSLATORS:")) {
return stripped_comment.trim_prefix("TRANSLATORS:").strip_edges(true, false);
}
if (stripped_comment == "NO_TRANSLATE" || stripped_comment.begins_with("NO_TRANSLATE:")) {
r_skip = true;
return String();
}
}
// Parse multiline comment.
String multiline_comment;
for (int line = p_line - 1; comment_data->has(line) && comment_data->get(line).new_line; line--) {
const String stripped_comment = comment_data->get(line).comment.trim_prefix("#").strip_edges();
if (stripped_comment.is_empty()) {
continue;
}
if (multiline_comment.is_empty()) {
multiline_comment = stripped_comment;
} else {
multiline_comment = stripped_comment + "\n" + multiline_comment;
}
if (stripped_comment.begins_with("TRANSLATORS:")) {
return multiline_comment.trim_prefix("TRANSLATORS:").strip_edges(true, false);
}
if (stripped_comment == "NO_TRANSLATE" || stripped_comment.begins_with("NO_TRANSLATE:")) {
r_skip = true;
return String();
}
}
return String();
}
void GDScriptEditorTranslationParserPlugin::_add_id(const String &p_id, int p_line) {
bool skip = false;
const String comment = _parse_comment(p_line, skip);
if (skip) {
return;
}
translations->push_back({ p_id, String(), String(), comment });
}
void GDScriptEditorTranslationParserPlugin::_add_id_ctx_plural(const Vector<String> &p_id_ctx_plural, int p_line) {
bool skip = false;
const String comment = _parse_comment(p_line, skip);
if (skip) {
return;
}
translations->push_back({ p_id_ctx_plural[0], p_id_ctx_plural[1], p_id_ctx_plural[2], comment });
}
void GDScriptEditorTranslationParserPlugin::_traverse_class(const GDScriptParser::ClassNode *p_class) {
@ -253,7 +318,7 @@ void GDScriptEditorTranslationParserPlugin::_assess_assignment(const GDScriptPar
if (assignee_name != StringName() && assignment_patterns.has(assignee_name) && _is_constant_string(p_assignment->assigned_value)) {
// If the assignment is towards one of the extract patterns (text, tooltip_text etc.), and the value is a constant string, we collect the string.
ids->push_back(p_assignment->assigned_value->reduced_value);
_add_id(p_assignment->assigned_value->reduced_value, p_assignment->assigned_value->start_line);
} else if (assignee_name == fd_filters) {
// Extract from `get_node("FileDialog").filters = <filter array>`.
_extract_fd_filter_array(p_assignment->assigned_value);
@ -287,7 +352,7 @@ void GDScriptEditorTranslationParserPlugin::_assess_call(const GDScriptParser::C
}
}
if (extract_id_ctx_plural) {
ids_ctx_plural->push_back(id_ctx_plural);
_add_id_ctx_plural(id_ctx_plural, p_call->start_line);
}
} else if (function_name == trn_func || function_name == atrn_func) {
// Extract from `tr_n(id, plural, n, ctx)` or `atr_n(id, plural, n, ctx)`.
@ -307,20 +372,20 @@ void GDScriptEditorTranslationParserPlugin::_assess_call(const GDScriptParser::C
}
}
if (extract_id_ctx_plural) {
ids_ctx_plural->push_back(id_ctx_plural);
_add_id_ctx_plural(id_ctx_plural, p_call->start_line);
}
} else if (first_arg_patterns.has(function_name)) {
if (!p_call->arguments.is_empty() && _is_constant_string(p_call->arguments[0])) {
ids->push_back(p_call->arguments[0]->reduced_value);
_add_id(p_call->arguments[0]->reduced_value, p_call->arguments[0]->start_line);
}
} else if (second_arg_patterns.has(function_name)) {
if (p_call->arguments.size() > 1 && _is_constant_string(p_call->arguments[1])) {
ids->push_back(p_call->arguments[1]->reduced_value);
_add_id(p_call->arguments[1]->reduced_value, p_call->arguments[1]->start_line);
}
} else if (function_name == fd_add_filter) {
// Extract the 'JPE Images' in this example - get_node("FileDialog").add_filter("*.jpg; JPE Images").
if (!p_call->arguments.is_empty()) {
_extract_fd_filter_string(p_call->arguments[0]);
_extract_fd_filter_string(p_call->arguments[0], p_call->arguments[0]->start_line);
}
} else if (function_name == fd_set_filter) {
// Extract from `get_node("FileDialog").set_filters(<filter array>)`.
@ -330,12 +395,12 @@ void GDScriptEditorTranslationParserPlugin::_assess_call(const GDScriptParser::C
}
}
void GDScriptEditorTranslationParserPlugin::_extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression) {
void GDScriptEditorTranslationParserPlugin::_extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression, int p_line) {
// Extract the name in "extension ; name".
if (_is_constant_string(p_expression)) {
PackedStringArray arr = p_expression->reduced_value.operator String().split(";", true);
ERR_FAIL_COND_MSG(arr.size() != 2, "Argument for setting FileDialog has bad format.");
ids->push_back(arr[1].strip_edges());
_add_id(arr[1].strip_edges(), p_line);
}
}
@ -355,7 +420,7 @@ void GDScriptEditorTranslationParserPlugin::_extract_fd_filter_array(const GDScr
if (array_node) {
for (int i = 0; i < array_node->elements.size(); i++) {
_extract_fd_filter_string(array_node->elements[i]);
_extract_fd_filter_string(array_node->elements[i], array_node->elements[i]->start_line);
}
}
}

View file

@ -32,15 +32,18 @@
#define GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H
#include "../gdscript_parser.h"
#include "../gdscript_tokenizer.h"
#include "core/templates/hash_map.h"
#include "core/templates/hash_set.h"
#include "editor/editor_translation_parser.h"
class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlugin {
GDCLASS(GDScriptEditorTranslationParserPlugin, EditorTranslationParserPlugin);
Vector<String> *ids = nullptr;
Vector<Vector<String>> *ids_ctx_plural = nullptr;
const HashMap<int, GDScriptTokenizer::CommentData> *comment_data = nullptr;
Vector<Vector<String>> *translations = nullptr;
// List of patterns used for extracting translation strings.
StringName tr_func = "tr";
@ -57,6 +60,11 @@ class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlug
static bool _is_constant_string(const GDScriptParser::ExpressionNode *p_expression);
String _parse_comment(int p_line, bool &r_skip) const;
void _add_id(const String &p_id, int p_line);
void _add_id_ctx_plural(const Vector<String> &p_id_ctx_plural, int p_line);
void _traverse_class(const GDScriptParser::ClassNode *p_class);
void _traverse_function(const GDScriptParser::FunctionNode *p_func);
void _traverse_block(const GDScriptParser::SuiteNode *p_suite);
@ -65,11 +73,11 @@ class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlug
void _assess_assignment(const GDScriptParser::AssignmentNode *p_assignment);
void _assess_call(const GDScriptParser::CallNode *p_call);
void _extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression);
void _extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression, int p_line);
void _extract_fd_filter_array(const GDScriptParser::ExpressionNode *p_expression);
public:
virtual Error parse_file(const String &p_path, Vector<String> *r_ids, Vector<Vector<String>> *r_ids_ctx_plural) override;
virtual Error parse_file(const String &p_path, Vector<Vector<String>> *r_translations) override;
virtual void get_recognized_extensions(List<String> *r_extensions) const override;
GDScriptEditorTranslationParserPlugin();

View file

@ -1,16 +1,8 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
import editor.template_builders as build_template_gd
env["BUILDERS"]["MakeGDTemplateBuilder"] = Builder(
action=env.Run(build_template_gd.make_templates),
suffix=".h",
src_suffix=".gd",
)
# Template files
templates_sources = Glob("*/*.gd")
env.Alias("editor_template_gd", [env.MakeGDTemplateBuilder("templates.gen.h", templates_sources)])
env.CommandNoCache("templates.gen.h", Glob("*/*.gd"), env.Run(build_template_gd.make_templates))