Skip to content

Commit 6102c01

Browse files
committed
GDScript: Add support for variadic functions
1 parent bdf625b commit 6102c01

32 files changed

+419
-60
lines changed

core/doc_data.h

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

editor/connections_dialog.cpp

+23-13
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,16 @@ List<MethodInfo> ConnectDialog::_filter_method_list(const List<MethodInfo> &p_me
307307
}
308308

309309
if (check_signal) {
310-
if (mi.arguments.size() != effective_args.size()) {
310+
const int min_argc = mi.arguments.size() - mi.default_arguments.size();
311+
const int max_argc = (mi.flags & METHOD_FLAG_VARARG) ? INT_MAX : mi.arguments.size();
312+
313+
if (effective_args.size() < min_argc || effective_args.size() > max_argc) {
311314
continue;
312315
}
313316

314317
bool type_mismatch = false;
315318
const List<Pair<Variant::Type, StringName>>::Element *E = effective_args.front();
316-
for (const List<PropertyInfo>::Element *F = mi.arguments.front(); F; F = F->next(), E = E->next()) {
319+
for (const List<PropertyInfo>::Element *F = mi.arguments.front(); F && E; F = F->next(), E = E->next()) {
317320
Variant::Type stype = E->get().first;
318321
Variant::Type mtype = F->get().type;
319322

@@ -603,10 +606,17 @@ String ConnectDialog::get_signature(const MethodInfo &p_method, PackedStringArra
603606
String arg_name = pi.name.is_empty() ? "arg" + itos(i) : pi.name;
604607
signature.append(arg_name + ": " + type_name);
605608
if (r_arg_names) {
606-
r_arg_names->push_back(arg_name + ":" + type_name);
609+
r_arg_names->push_back(arg_name + ": " + type_name);
607610
}
608611
}
609612

613+
if (p_method.flags & METHOD_FLAG_VARARG) {
614+
if (!p_method.arguments.is_empty()) {
615+
signature.append(", ");
616+
}
617+
signature.append("...");
618+
}
619+
610620
signature.append(")");
611621
return String().join(signature);
612622
}
@@ -988,7 +998,7 @@ void ConnectionsDock::_make_or_edit_connection() {
988998
PackedStringArray script_function_args = connect_dialog->get_signal_args();
989999
script_function_args.resize(script_function_args.size() - cd.unbinds);
9901000
for (int i = 0; i < cd.binds.size(); i++) {
991-
script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cd.binds[i].get_type()));
1001+
script_function_args.push_back("extra_arg_" + itos(i) + ": " + Variant::get_type_name(cd.binds[i].get_type()));
9921002
}
9931003

9941004
EditorNode::get_singleton()->emit_signal(SNAME("script_add_function_request"), target, cd.method, script_function_args);
@@ -1126,9 +1136,9 @@ bool ConnectionsDock::_is_connection_inherited(Connection &p_connection) {
11261136
* Open connection dialog with TreeItem data to CREATE a brand-new connection.
11271137
*/
11281138
void ConnectionsDock::_open_connection_dialog(TreeItem &p_item) {
1129-
Dictionary sinfo = p_item.get_metadata(0);
1130-
String signal_name = sinfo["name"];
1131-
PackedStringArray signal_args = sinfo["args"];
1139+
const Dictionary sinfo = p_item.get_metadata(0);
1140+
const StringName signal_name = sinfo["name"];
1141+
const PackedStringArray signal_args = sinfo["args"];
11321142

11331143
Node *dst_node = selected_node->get_owner() ? selected_node->get_owner() : selected_node;
11341144
if (!dst_node || dst_node->get_script().is_null()) {
@@ -1137,12 +1147,12 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &p_item) {
11371147

11381148
ConnectDialog::ConnectionData cd;
11391149
cd.source = selected_node;
1140-
cd.signal = StringName(signal_name);
1150+
cd.signal = signal_name;
11411151
cd.target = dst_node;
11421152
cd.method = ConnectDialog::generate_method_callback_name(cd.source, signal_name, cd.target);
11431153
connect_dialog->init(cd, signal_args);
11441154
connect_dialog->set_title(TTR("Connect a Signal to a Method"));
1145-
connect_dialog->popup_dialog(signal_name + "(" + String(", ").join(signal_args) + ")");
1155+
connect_dialog->popup_dialog(signal_name.operator String() + "(" + String(", ").join(signal_args) + ")");
11461156
}
11471157

11481158
/*
@@ -1159,12 +1169,12 @@ void ConnectionsDock::_open_edit_connection_dialog(TreeItem &p_item) {
11591169
Node *dst = Object::cast_to<Node>(cd.target);
11601170

11611171
if (src && dst) {
1162-
const String &signal_name_ref = cd.signal;
1163-
PackedStringArray signal_args = signal_item->get_metadata(0).operator Dictionary()["args"];
1172+
const StringName &signal_name = cd.signal;
1173+
const PackedStringArray signal_args = signal_item->get_metadata(0).operator Dictionary()["args"];
11641174

1165-
connect_dialog->set_title(vformat(TTR("Edit Connection: '%s'"), cd.signal));
1166-
connect_dialog->popup_dialog(signal_name_ref);
11671175
connect_dialog->init(cd, signal_args, true);
1176+
connect_dialog->set_title(vformat(TTR("Edit Connection: '%s'"), cd.signal));
1177+
connect_dialog->popup_dialog(signal_name.operator String() + "(" + String(", ").join(signal_args) + ")");
11681178
}
11691179
}
11701180

editor/editor_help.cpp

+86-16
Original file line numberDiff line numberDiff line change
@@ -604,14 +604,20 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
604604
for (int j = 0; j < p_method.arguments.size(); j++) {
605605
const DocData::ArgumentDoc &argument = p_method.arguments[j];
606606

607-
class_desc->push_color(theme_cache.text_color);
608-
609607
if (j > 0) {
608+
class_desc->push_color(theme_cache.symbol_color);
610609
class_desc->add_text(", ");
610+
class_desc->pop(); // color
611611
}
612612

613+
class_desc->push_color(theme_cache.text_color);
613614
class_desc->add_text(argument.name);
615+
class_desc->pop(); // color
616+
617+
class_desc->push_color(theme_cache.symbol_color);
614618
class_desc->add_text(colon_nbsp);
619+
class_desc->pop(); // color
620+
615621
_add_type(argument.type, argument.enumeration, argument.is_bitfield);
616622

617623
if (!argument.default_value.is_empty()) {
@@ -623,20 +629,34 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
623629
class_desc->add_text(_fix_constant(argument.default_value));
624630
class_desc->pop(); // color
625631
}
626-
627-
class_desc->pop(); // color
628632
}
629633

630634
if (is_vararg) {
631635
if (!p_method.arguments.is_empty()) {
632-
class_desc->push_color(theme_cache.text_color);
636+
class_desc->push_color(theme_cache.symbol_color);
633637
class_desc->add_text(", ");
634638
class_desc->pop(); // color
635639
}
636640

637641
class_desc->push_color(theme_cache.symbol_color);
638642
class_desc->add_text("...");
639643
class_desc->pop(); // color
644+
645+
const DocData::ArgumentDoc &rest_argument = p_method.rest_argument;
646+
647+
class_desc->push_color(theme_cache.text_color);
648+
class_desc->add_text(rest_argument.name.is_empty() ? "args" : rest_argument.name);
649+
class_desc->pop(); // color
650+
651+
class_desc->push_color(theme_cache.symbol_color);
652+
class_desc->add_text(colon_nbsp);
653+
class_desc->pop(); // color
654+
655+
if (rest_argument.type.is_empty()) {
656+
_add_type("Array");
657+
} else {
658+
_add_type(rest_argument.type, rest_argument.enumeration, rest_argument.is_bitfield);
659+
}
640660
}
641661

642662
class_desc->push_color(theme_cache.symbol_color);
@@ -1568,14 +1588,20 @@ void EditorHelp::_update_doc() {
15681588
for (int j = 0; j < signal.arguments.size(); j++) {
15691589
const DocData::ArgumentDoc &argument = signal.arguments[j];
15701590

1571-
class_desc->push_color(theme_cache.text_color);
1572-
15731591
if (j > 0) {
1592+
class_desc->push_color(theme_cache.symbol_color);
15741593
class_desc->add_text(", ");
1594+
class_desc->pop(); // color
15751595
}
15761596

1597+
class_desc->push_color(theme_cache.text_color);
15771598
class_desc->add_text(argument.name);
1599+
class_desc->pop(); // color
1600+
1601+
class_desc->push_color(theme_cache.symbol_color);
15781602
class_desc->add_text(colon_nbsp);
1603+
class_desc->pop(); // color
1604+
15791605
_add_type(argument.type, argument.enumeration, argument.is_bitfield);
15801606

15811607
// Signals currently do not support default argument values, neither the core nor GDScript.
@@ -1589,8 +1615,6 @@ void EditorHelp::_update_doc() {
15891615
class_desc->add_text(_fix_constant(argument.default_value));
15901616
class_desc->pop(); // color
15911617
}
1592-
1593-
class_desc->pop(); // color
15941618
}
15951619

15961620
class_desc->push_color(theme_cache.symbol_color);
@@ -2012,14 +2036,20 @@ void EditorHelp::_update_doc() {
20122036
for (int j = 0; j < annotation.arguments.size(); j++) {
20132037
const DocData::ArgumentDoc &argument = annotation.arguments[j];
20142038

2015-
class_desc->push_color(theme_cache.text_color);
2016-
20172039
if (j > 0) {
2040+
class_desc->push_color(theme_cache.symbol_color);
20182041
class_desc->add_text(", ");
2042+
class_desc->pop(); // color
20192043
}
20202044

2045+
class_desc->push_color(theme_cache.text_color);
20212046
class_desc->add_text(argument.name);
2047+
class_desc->pop(); // color
2048+
2049+
class_desc->push_color(theme_cache.symbol_color);
20222050
class_desc->add_text(colon_nbsp);
2051+
class_desc->pop(); // color
2052+
20232053
_add_type(argument.type, argument.enumeration, argument.is_bitfield);
20242054

20252055
if (!argument.default_value.is_empty()) {
@@ -2031,20 +2061,34 @@ void EditorHelp::_update_doc() {
20312061
class_desc->add_text(_fix_constant(argument.default_value));
20322062
class_desc->pop(); // color
20332063
}
2034-
2035-
class_desc->pop(); // color
20362064
}
20372065

20382066
if (annotation.qualifiers.contains("vararg")) {
20392067
if (!annotation.arguments.is_empty()) {
2040-
class_desc->push_color(theme_cache.text_color);
2068+
class_desc->push_color(theme_cache.symbol_color);
20412069
class_desc->add_text(", ");
20422070
class_desc->pop(); // color
20432071
}
20442072

20452073
class_desc->push_color(theme_cache.symbol_color);
20462074
class_desc->add_text("...");
20472075
class_desc->pop(); // color
2076+
2077+
const DocData::ArgumentDoc &rest_argument = annotation.rest_argument;
2078+
2079+
class_desc->push_color(theme_cache.text_color);
2080+
class_desc->add_text(rest_argument.name.is_empty() ? "args" : rest_argument.name);
2081+
class_desc->pop(); // color
2082+
2083+
class_desc->push_color(theme_cache.symbol_color);
2084+
class_desc->add_text(colon_nbsp);
2085+
class_desc->pop(); // color
2086+
2087+
if (rest_argument.type.is_empty()) {
2088+
_add_type("Array");
2089+
} else {
2090+
_add_type(rest_argument.type, rest_argument.enumeration, rest_argument.is_bitfield);
2091+
}
20482092
}
20492093

20502094
class_desc->push_color(theme_cache.symbol_color);
@@ -3519,10 +3563,13 @@ EditorHelpBit::HelpData EditorHelpBit::_get_method_help_data(const StringName &p
35193563
}
35203564
current.doc_type = { method.return_type, method.return_enum, method.return_is_bitfield };
35213565
for (const DocData::ArgumentDoc &argument : method.arguments) {
3522-
const DocType argument_type = { argument.type, argument.enumeration, argument.is_bitfield };
3523-
current.arguments.push_back({ argument.name, argument_type, argument.default_value });
3566+
const DocType argument_doc_type = { argument.type, argument.enumeration, argument.is_bitfield };
3567+
current.arguments.push_back({ argument.name, argument_doc_type, argument.default_value });
35243568
}
35253569
current.qualifiers = method.qualifiers;
3570+
const DocData::ArgumentDoc &rest_argument = method.rest_argument;
3571+
const DocType rest_argument_doc_type = { rest_argument.type, rest_argument.enumeration, rest_argument.is_bitfield };
3572+
current.rest_argument = { rest_argument.name, rest_argument_doc_type, rest_argument.default_value };
35263573

35273574
if (method.name == p_method_name) {
35283575
result = current;
@@ -3684,6 +3731,7 @@ void EditorHelpBit::_update_labels() {
36843731

36853732
title->pop(); // font
36863733

3734+
const Color text_color = get_theme_color(SNAME("text_color"), SNAME("EditorHelp"));
36873735
const Color symbol_color = get_theme_color(SNAME("symbol_color"), SNAME("EditorHelp"));
36883736
const Color value_color = get_theme_color(SNAME("value_color"), SNAME("EditorHelp"));
36893737
const Color qualifier_color = get_theme_color(SNAME("qualifier_color"), SNAME("EditorHelp"));
@@ -3759,10 +3807,14 @@ void EditorHelpBit::_update_labels() {
37593807
const ArgumentData &argument = help_data.arguments[i];
37603808

37613809
if (i > 0) {
3810+
title->push_color(symbol_color);
37623811
title->add_text(", ");
3812+
title->pop(); // color
37633813
}
37643814

3815+
title->push_color(text_color);
37653816
title->add_text(argument.name);
3817+
title->pop(); // color
37663818

37673819
title->push_color(symbol_color);
37683820
title->add_text(colon_nbsp);
@@ -3783,12 +3835,30 @@ void EditorHelpBit::_update_labels() {
37833835

37843836
if (help_data.qualifiers.contains("vararg")) {
37853837
if (!help_data.arguments.is_empty()) {
3838+
title->push_color(symbol_color);
37863839
title->add_text(", ");
3840+
title->pop(); // color
37873841
}
37883842

37893843
title->push_color(symbol_color);
37903844
title->add_text("...");
37913845
title->pop(); // color
3846+
3847+
const ArgumentData &rest_argument = help_data.rest_argument;
3848+
3849+
title->push_color(text_color);
3850+
title->add_text(rest_argument.name.is_empty() ? "args" : rest_argument.name);
3851+
title->pop(); // color
3852+
3853+
title->push_color(symbol_color);
3854+
title->add_text(colon_nbsp);
3855+
title->pop(); // color
3856+
3857+
if (rest_argument.doc_type.type.is_empty()) {
3858+
_add_type_to_title({ "Array", "", false });
3859+
} else {
3860+
_add_type_to_title(rest_argument.doc_type);
3861+
}
37923862
}
37933863

37943864
title->push_color(symbol_color);

editor/editor_help.h

+1
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ class EditorHelpBit : public VBoxContainer {
276276
DocType doc_type;
277277
String value;
278278
Vector<ArgumentData> arguments;
279+
ArgumentData rest_argument;
279280
String qualifiers;
280281
};
281282

editor/property_selector.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,19 @@ void PropertySelector::_update_search() {
286286
}
287287
}
288288

289+
if (mi.flags & METHOD_FLAG_VARARG) {
290+
if (!mi.arguments.is_empty()) {
291+
desc += ", ";
292+
}
293+
desc += "...";
294+
}
295+
289296
desc += ")";
290297

298+
if (mi.flags & METHOD_FLAG_VARARG) {
299+
desc += " vararg";
300+
}
301+
291302
if (mi.flags & METHOD_FLAG_CONST) {
292303
desc += " const";
293304
}

modules/gdscript/editor/gdscript_docgen.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,20 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
407407
method_doc.deprecated_message = m_func->doc_data.deprecated_message;
408408
method_doc.is_experimental = m_func->doc_data.is_experimental;
409409
method_doc.experimental_message = m_func->doc_data.experimental_message;
410-
method_doc.qualifiers = m_func->is_static ? "static" : "";
410+
if (m_func->is_vararg()) {
411+
if (!method_doc.qualifiers.is_empty()) {
412+
method_doc.qualifiers += " ";
413+
}
414+
method_doc.qualifiers += "vararg";
415+
method_doc.rest_argument.name = m_func->rest_parameter->identifier->name;
416+
_doctype_from_gdtype(m_func->rest_parameter->get_datatype(), method_doc.rest_argument.type, method_doc.rest_argument.enumeration);
417+
}
418+
if (m_func->is_static) {
419+
if (!method_doc.qualifiers.is_empty()) {
420+
method_doc.qualifiers += " ";
421+
}
422+
method_doc.qualifiers += "static";
423+
}
411424

412425
if (func_name == "_init") {
413426
method_doc.return_type = "void";

modules/gdscript/editor/gdscript_highlighter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
483483
k--;
484484
}
485485

486-
if (str[k] == '.') {
486+
if (str[k] == '.' && (k < 1 || str[k - 1] != '.')) {
487487
in_member_variable = true;
488488
}
489489
}

0 commit comments

Comments
 (0)