Skip to content

Commit 0f05e91

Browse files
committed
Merge pull request #82808 from dalexeev/gds-vararg
GDScript: Add support for variadic functions
2 parents 7584546 + ee121ef commit 0f05e91

33 files changed

+416
-65
lines changed

core/doc_data.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ class DocData {
107107
bool is_experimental = false;
108108
String experimental_message;
109109
Vector<ArgumentDoc> arguments;
110+
// NOTE: Only for GDScript for now. The rest argument is not saved to the XML file.
111+
ArgumentDoc rest_argument;
110112
Vector<int> errors_returned;
111113
String keywords;
112114
bool operator<(const MethodDoc &p_method) const {

editor/connections_dialog.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,15 @@ List<MethodInfo> ConnectDialog::_filter_method_list(const List<MethodInfo> &p_me
314314
}
315315

316316
if (check_signal) {
317-
if (mi.arguments.size() != effective_args.size()) {
317+
const unsigned min_argc = mi.arguments.size() - mi.default_arguments.size();
318+
const unsigned max_argc = (mi.flags & METHOD_FLAG_VARARG) ? UINT_MAX : mi.arguments.size();
319+
320+
if (effective_args.size() < min_argc || effective_args.size() > max_argc) {
318321
continue;
319322
}
320323

321324
bool type_mismatch = false;
322-
for (int64_t i = 0; i < mi.arguments.size(); ++i) {
325+
for (int64_t i = 0; i < effective_args.size() && i < mi.arguments.size(); ++i) {
323326
Variant::Type stype = effective_args[i].first;
324327
Variant::Type mtype = mi.arguments[i].type;
325328

@@ -609,10 +612,14 @@ String ConnectDialog::get_signature(const MethodInfo &p_method, PackedStringArra
609612
String arg_name = pi.name.is_empty() ? "arg" + itos(i) : pi.name;
610613
signature.append(arg_name + ": " + type_name);
611614
if (r_arg_names) {
612-
r_arg_names->push_back(arg_name + ":" + type_name);
615+
r_arg_names->push_back(arg_name + ": " + type_name);
613616
}
614617
}
615618

619+
if (p_method.flags & METHOD_FLAG_VARARG) {
620+
signature.append(p_method.arguments.is_empty() ? "..." : ", ...");
621+
}
622+
616623
signature.append(")");
617624
return String().join(signature);
618625
}
@@ -1044,7 +1051,7 @@ void ConnectionsDock::_make_or_edit_connection() {
10441051
}
10451052

10461053
for (int i = 0; i < cd.binds.size(); i++) {
1047-
script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cd.binds[i].get_type()));
1054+
script_function_args.push_back("extra_arg_" + itos(i) + ": " + Variant::get_type_name(cd.binds[i].get_type()));
10481055
}
10491056

10501057
EditorNode::get_singleton()->emit_signal(SNAME("script_add_function_request"), target, cd.method, script_function_args);
@@ -1182,9 +1189,9 @@ bool ConnectionsDock::_is_connection_inherited(Connection &p_connection) {
11821189
* Open connection dialog with TreeItem data to CREATE a brand-new connection.
11831190
*/
11841191
void ConnectionsDock::_open_connection_dialog(TreeItem &p_item) {
1185-
Dictionary sinfo = p_item.get_metadata(0);
1186-
String signal_name = sinfo["name"];
1187-
PackedStringArray signal_args = sinfo["args"];
1192+
const Dictionary sinfo = p_item.get_metadata(0);
1193+
const StringName signal_name = sinfo["name"];
1194+
const PackedStringArray signal_args = sinfo["args"];
11881195

11891196
Node *dst_node = selected_node->get_owner() ? selected_node->get_owner() : selected_node;
11901197
if (!dst_node || dst_node->get_script().is_null()) {
@@ -1193,12 +1200,12 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &p_item) {
11931200

11941201
ConnectDialog::ConnectionData cd;
11951202
cd.source = selected_node;
1196-
cd.signal = StringName(signal_name);
1203+
cd.signal = signal_name;
11971204
cd.target = dst_node;
11981205
cd.method = ConnectDialog::generate_method_callback_name(cd.source, signal_name, cd.target);
11991206
connect_dialog->init(cd, signal_args);
12001207
connect_dialog->set_title(TTR("Connect a Signal to a Method"));
1201-
connect_dialog->popup_dialog(signal_name + "(" + String(", ").join(signal_args) + ")");
1208+
connect_dialog->popup_dialog(signal_name.operator String() + "(" + String(", ").join(signal_args) + ")");
12021209
}
12031210

12041211
/*
@@ -1215,12 +1222,12 @@ void ConnectionsDock::_open_edit_connection_dialog(TreeItem &p_item) {
12151222
Node *dst = Object::cast_to<Node>(cd.target);
12161223

12171224
if (src && dst) {
1218-
const String &signal_name_ref = cd.signal;
1219-
PackedStringArray signal_args = signal_item->get_metadata(0).operator Dictionary()["args"];
1225+
const StringName &signal_name = cd.signal;
1226+
const PackedStringArray signal_args = signal_item->get_metadata(0).operator Dictionary()["args"];
12201227

1221-
connect_dialog->set_title(vformat(TTR("Edit Connection: '%s'"), cd.signal));
1222-
connect_dialog->popup_dialog(signal_name_ref);
12231228
connect_dialog->init(cd, signal_args, true);
1229+
connect_dialog->set_title(vformat(TTR("Edit Connection: '%s'"), cd.signal));
1230+
connect_dialog->popup_dialog(signal_name.operator String() + "(" + String(", ").join(signal_args) + ")");
12241231
}
12251232
}
12261233

editor/editor_help.cpp

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -582,14 +582,20 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
582582
for (int j = 0; j < p_method.arguments.size(); j++) {
583583
const DocData::ArgumentDoc &argument = p_method.arguments[j];
584584

585-
class_desc->push_color(theme_cache.text_color);
586-
587585
if (j > 0) {
586+
class_desc->push_color(theme_cache.symbol_color);
588587
class_desc->add_text(", ");
588+
class_desc->pop(); // color
589589
}
590590

591+
class_desc->push_color(theme_cache.text_color);
591592
class_desc->add_text(argument.name);
593+
class_desc->pop(); // color
594+
595+
class_desc->push_color(theme_cache.symbol_color);
592596
class_desc->add_text(colon_nbsp);
597+
class_desc->pop(); // color
598+
593599
_add_type(argument.type, argument.enumeration, argument.is_bitfield);
594600

595601
if (!argument.default_value.is_empty()) {
@@ -601,20 +607,34 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
601607
class_desc->add_text(_fix_constant(argument.default_value));
602608
class_desc->pop(); // color
603609
}
604-
605-
class_desc->pop(); // color
606610
}
607611

608612
if (is_vararg) {
609613
if (!p_method.arguments.is_empty()) {
610-
class_desc->push_color(theme_cache.text_color);
614+
class_desc->push_color(theme_cache.symbol_color);
611615
class_desc->add_text(", ");
612616
class_desc->pop(); // color
613617
}
614618

615619
class_desc->push_color(theme_cache.symbol_color);
616620
class_desc->add_text("...");
617621
class_desc->pop(); // color
622+
623+
const DocData::ArgumentDoc &rest_argument = p_method.rest_argument;
624+
625+
class_desc->push_color(theme_cache.text_color);
626+
class_desc->add_text(rest_argument.name.is_empty() ? "args" : rest_argument.name);
627+
class_desc->pop(); // color
628+
629+
class_desc->push_color(theme_cache.symbol_color);
630+
class_desc->add_text(colon_nbsp);
631+
class_desc->pop(); // color
632+
633+
if (rest_argument.type.is_empty()) {
634+
_add_type("Array");
635+
} else {
636+
_add_type(rest_argument.type, rest_argument.enumeration, rest_argument.is_bitfield);
637+
}
618638
}
619639

620640
class_desc->push_color(theme_cache.symbol_color);
@@ -1558,14 +1578,20 @@ void EditorHelp::_update_doc() {
15581578
for (int j = 0; j < signal.arguments.size(); j++) {
15591579
const DocData::ArgumentDoc &argument = signal.arguments[j];
15601580

1561-
class_desc->push_color(theme_cache.text_color);
1562-
15631581
if (j > 0) {
1582+
class_desc->push_color(theme_cache.symbol_color);
15641583
class_desc->add_text(", ");
1584+
class_desc->pop(); // color
15651585
}
15661586

1587+
class_desc->push_color(theme_cache.text_color);
15671588
class_desc->add_text(argument.name);
1589+
class_desc->pop(); // color
1590+
1591+
class_desc->push_color(theme_cache.symbol_color);
15681592
class_desc->add_text(colon_nbsp);
1593+
class_desc->pop(); // color
1594+
15691595
_add_type(argument.type, argument.enumeration, argument.is_bitfield);
15701596

15711597
// Signals currently do not support default argument values, neither the core nor GDScript.
@@ -1579,8 +1605,6 @@ void EditorHelp::_update_doc() {
15791605
class_desc->add_text(_fix_constant(argument.default_value));
15801606
class_desc->pop(); // color
15811607
}
1582-
1583-
class_desc->pop(); // color
15841608
}
15851609

15861610
class_desc->push_color(theme_cache.symbol_color);
@@ -2002,14 +2026,20 @@ void EditorHelp::_update_doc() {
20022026
for (int j = 0; j < annotation.arguments.size(); j++) {
20032027
const DocData::ArgumentDoc &argument = annotation.arguments[j];
20042028

2005-
class_desc->push_color(theme_cache.text_color);
2006-
20072029
if (j > 0) {
2030+
class_desc->push_color(theme_cache.symbol_color);
20082031
class_desc->add_text(", ");
2032+
class_desc->pop(); // color
20092033
}
20102034

2035+
class_desc->push_color(theme_cache.text_color);
20112036
class_desc->add_text(argument.name);
2037+
class_desc->pop(); // color
2038+
2039+
class_desc->push_color(theme_cache.symbol_color);
20122040
class_desc->add_text(colon_nbsp);
2041+
class_desc->pop(); // color
2042+
20132043
_add_type(argument.type, argument.enumeration, argument.is_bitfield);
20142044

20152045
if (!argument.default_value.is_empty()) {
@@ -2021,20 +2051,34 @@ void EditorHelp::_update_doc() {
20212051
class_desc->add_text(_fix_constant(argument.default_value));
20222052
class_desc->pop(); // color
20232053
}
2024-
2025-
class_desc->pop(); // color
20262054
}
20272055

20282056
if (annotation.qualifiers.contains("vararg")) {
20292057
if (!annotation.arguments.is_empty()) {
2030-
class_desc->push_color(theme_cache.text_color);
2058+
class_desc->push_color(theme_cache.symbol_color);
20312059
class_desc->add_text(", ");
20322060
class_desc->pop(); // color
20332061
}
20342062

20352063
class_desc->push_color(theme_cache.symbol_color);
20362064
class_desc->add_text("...");
20372065
class_desc->pop(); // color
2066+
2067+
const DocData::ArgumentDoc &rest_argument = annotation.rest_argument;
2068+
2069+
class_desc->push_color(theme_cache.text_color);
2070+
class_desc->add_text(rest_argument.name.is_empty() ? "args" : rest_argument.name);
2071+
class_desc->pop(); // color
2072+
2073+
class_desc->push_color(theme_cache.symbol_color);
2074+
class_desc->add_text(colon_nbsp);
2075+
class_desc->pop(); // color
2076+
2077+
if (rest_argument.type.is_empty()) {
2078+
_add_type("Array");
2079+
} else {
2080+
_add_type(rest_argument.type, rest_argument.enumeration, rest_argument.is_bitfield);
2081+
}
20382082
}
20392083

20402084
class_desc->push_color(theme_cache.symbol_color);
@@ -3730,10 +3774,13 @@ EditorHelpBit::HelpData EditorHelpBit::_get_method_help_data(const StringName &p
37303774
}
37313775
current.doc_type = { method.return_type, method.return_enum, method.return_is_bitfield };
37323776
for (const DocData::ArgumentDoc &argument : method.arguments) {
3733-
const DocType argument_type = { argument.type, argument.enumeration, argument.is_bitfield };
3734-
current.arguments.push_back({ argument.name, argument_type, argument.default_value });
3777+
const DocType argument_doc_type = { argument.type, argument.enumeration, argument.is_bitfield };
3778+
current.arguments.push_back({ argument.name, argument_doc_type, argument.default_value });
37353779
}
37363780
current.qualifiers = method.qualifiers;
3781+
const DocData::ArgumentDoc &rest_argument = method.rest_argument;
3782+
const DocType rest_argument_doc_type = { rest_argument.type, rest_argument.enumeration, rest_argument.is_bitfield };
3783+
current.rest_argument = { rest_argument.name, rest_argument_doc_type, rest_argument.default_value };
37373784

37383785
if (method.name == p_method_name) {
37393786
result = current;
@@ -3895,6 +3942,7 @@ void EditorHelpBit::_update_labels() {
38953942

38963943
title->pop(); // font
38973944

3945+
const Color text_color = get_theme_color(SNAME("text_color"), SNAME("EditorHelp"));
38983946
const Color symbol_color = get_theme_color(SNAME("symbol_color"), SNAME("EditorHelp"));
38993947
const Color value_color = get_theme_color(SNAME("value_color"), SNAME("EditorHelp"));
39003948
const Color qualifier_color = get_theme_color(SNAME("qualifier_color"), SNAME("EditorHelp"));
@@ -3970,10 +4018,14 @@ void EditorHelpBit::_update_labels() {
39704018
const ArgumentData &argument = help_data.arguments[i];
39714019

39724020
if (i > 0) {
4021+
title->push_color(symbol_color);
39734022
title->add_text(", ");
4023+
title->pop(); // color
39744024
}
39754025

4026+
title->push_color(text_color);
39764027
title->add_text(argument.name);
4028+
title->pop(); // color
39774029

39784030
title->push_color(symbol_color);
39794031
title->add_text(colon_nbsp);
@@ -3994,12 +4046,30 @@ void EditorHelpBit::_update_labels() {
39944046

39954047
if (help_data.qualifiers.contains("vararg")) {
39964048
if (!help_data.arguments.is_empty()) {
4049+
title->push_color(symbol_color);
39974050
title->add_text(", ");
4051+
title->pop(); // color
39984052
}
39994053

40004054
title->push_color(symbol_color);
40014055
title->add_text("...");
40024056
title->pop(); // color
4057+
4058+
const ArgumentData &rest_argument = help_data.rest_argument;
4059+
4060+
title->push_color(text_color);
4061+
title->add_text(rest_argument.name.is_empty() ? "args" : rest_argument.name);
4062+
title->pop(); // color
4063+
4064+
title->push_color(symbol_color);
4065+
title->add_text(colon_nbsp);
4066+
title->pop(); // color
4067+
4068+
if (rest_argument.doc_type.type.is_empty()) {
4069+
_add_type_to_title({ "Array", "", false });
4070+
} else {
4071+
_add_type_to_title(rest_argument.doc_type);
4072+
}
40034073
}
40044074

40054075
title->push_color(symbol_color);

editor/editor_help.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ class EditorHelpBit : public VBoxContainer {
302302
DocType doc_type;
303303
String value;
304304
Vector<ArgumentData> arguments;
305+
ArgumentData rest_argument;
305306
String qualifiers;
306307
String resource_path;
307308
};

editor/property_selector.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,16 @@ void PropertySelector::_update_search() {
287287
}
288288
}
289289

290+
if (mi.flags & METHOD_FLAG_VARARG) {
291+
desc += mi.arguments.is_empty() ? "..." : ", ...";
292+
}
293+
290294
desc += ")";
291295

296+
if (mi.flags & METHOD_FLAG_VARARG) {
297+
desc += " vararg";
298+
}
299+
292300
if (mi.flags & METHOD_FLAG_CONST) {
293301
desc += " const";
294302
}

modules/gdscript/editor/gdscript_docgen.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,25 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
408408
method_doc.is_experimental = m_func->doc_data.is_experimental;
409409
method_doc.experimental_message = m_func->doc_data.experimental_message;
410410

411-
// Currently, an abstract function cannot be static.
411+
if (m_func->is_vararg()) {
412+
if (!method_doc.qualifiers.is_empty()) {
413+
method_doc.qualifiers += " ";
414+
}
415+
method_doc.qualifiers += "vararg";
416+
method_doc.rest_argument.name = m_func->rest_parameter->identifier->name;
417+
_doctype_from_gdtype(m_func->rest_parameter->get_datatype(), method_doc.rest_argument.type, method_doc.rest_argument.enumeration);
418+
}
412419
if (m_func->is_abstract) {
413-
method_doc.qualifiers = "abstract";
414-
} else if (m_func->is_static) {
415-
method_doc.qualifiers = "static";
416-
} else {
417-
method_doc.qualifiers = "";
420+
if (!method_doc.qualifiers.is_empty()) {
421+
method_doc.qualifiers += " ";
422+
}
423+
method_doc.qualifiers += "abstract";
424+
}
425+
if (m_func->is_static) {
426+
if (!method_doc.qualifiers.is_empty()) {
427+
method_doc.qualifiers += " ";
428+
}
429+
method_doc.qualifiers += "static";
418430
}
419431

420432
if (func_name == "_init") {

modules/gdscript/editor/gdscript_highlighter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
492492
k--;
493493
}
494494

495-
if (str[k] == '.') {
495+
if (str[k] == '.' && (k < 1 || str[k - 1] != '.')) {
496496
in_member_variable = true;
497497
}
498498
}

0 commit comments

Comments
 (0)