Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Signal parameters' type will now be correctly displayed in the node signal preview box. #65812

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions modules/gdscript/gdscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,10 +711,15 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
} break;
case GDScriptParser::ClassNode::Member::SIGNAL: {
// TODO: Cache this in parser to avoid loops like this.
Vector<StringName> parameters_names;
Vector<Pair<StringName, GDScriptParser::DataType>> parameters_names;
parameters_names.resize(member.signal->parameters.size());
for (int j = 0; j < member.signal->parameters.size(); j++) {
parameters_names.write[j] = member.signal->parameters[j]->identifier->name;
Pair<StringName, GDScriptParser::DataType> &current_parameter = parameters_names.write[j];

current_parameter.first = member.signal->parameters[j]->identifier->name;
if (member.signal->parameters[j]->datatype_specifier && member.signal->parameters[j]->datatype_specifier->type_chain.size() == 1) {
current_parameter.second = member.signal->parameters[j]->get_datatype();
}
}
_signals[member.signal->identifier->name] = parameters_names;
} break;
Expand Down Expand Up @@ -1244,12 +1249,32 @@ bool GDScript::has_script_signal(const StringName &p_signal) const {
}

void GDScript::_get_script_signal_list(List<MethodInfo> *r_list, bool p_include_base) const {
for (const KeyValue<StringName, Vector<StringName>> &E : _signals) {
for (const KeyValue<StringName, Vector<Pair<StringName, GDScriptParser::DataType>>> &E : _signals) {
MethodInfo mi;
mi.name = E.key;

for (int i = 0; i < E.value.size(); i++) {
const Pair<StringName, GDScriptParser::DataType> &parameter = E.value[i];

PropertyInfo arg;
arg.name = E.value[i];
arg.name = parameter.first;
arg.type = Variant::NIL;

if (parameter.second.is_set()) {
if (parameter.second.kind == GDScriptParser::DataType::BUILTIN) {
arg.type = parameter.second.builtin_type;
} else if (parameter.second.kind == GDScriptParser::DataType::NATIVE) {
arg.type = Variant::OBJECT;
arg.class_name = parameter.second.native_type;
} else if (parameter.second.kind == GDScriptParser::DataType::SCRIPT) {
arg.type = Variant::OBJECT;
arg.class_name = parameter.second.script_type->get_instance_base_type();
} else if (parameter.second.kind == GDScriptParser::DataType::CLASS) {
arg.type = Variant::OBJECT;
arg.class_name = parameter.second.class_type->identifier->name;
}
}

mi.arguments.push_back(arg);
}
r_list->push_back(mi);
Expand Down Expand Up @@ -1602,7 +1627,7 @@ bool GDScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
// Signals.
const GDScript *sl = sptr;
while (sl) {
HashMap<StringName, Vector<StringName>>::ConstIterator E = sl->_signals.find(p_name);
HashMap<StringName, Vector<Pair<StringName, GDScriptParser::DataType>>>::ConstIterator E = sl->_signals.find(p_name);
if (E) {
r_ret = Signal(this->owner, E->key);
return true; //index found
Expand Down
3 changes: 2 additions & 1 deletion modules/gdscript/gdscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "core/object/script_language.h"
#include "core/templates/rb_set.h"
#include "gdscript_function.h"
#include "gdscript_parser.h"

class GDScriptNativeClass : public RefCounted {
GDCLASS(GDScriptNativeClass, RefCounted);
Expand Down Expand Up @@ -96,7 +97,7 @@ class GDScript : public Script {
HashMap<StringName, GDScriptFunction *> member_functions;
HashMap<StringName, MemberInfo> member_indices; //members are just indices to the instantiated script.
HashMap<StringName, Ref<GDScript>> subclasses;
HashMap<StringName, Vector<StringName>> _signals;
HashMap<StringName, Vector<Pair<StringName, GDScriptParser::DataType>>> _signals;
Dictionary rpc_config;

#ifdef TOOLS_ENABLED
Expand Down
38 changes: 38 additions & 0 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3023,6 +3023,44 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
update_array_literal_element_type(E.value, par_types[index].get_container_element_type());
}
}

if (is_vararg) {
StringName signal_name;
// signal_name.emit(args...)
if (
p_call->function_name == "emit" &&
p_call->arguments.size() > 0 &&
p_call->callee->type == GDScriptParser::Node::SUBSCRIPT &&
static_cast<GDScriptParser::SubscriptNode *>(p_call->callee)->base->type == GDScriptParser::Node::IDENTIFIER) {
signal_name = static_cast<GDScriptParser::IdentifierNode*>(static_cast<GDScriptParser::SubscriptNode *>(p_call->callee)->base)->name;
}
// emit_signal(signal_name, args...)
else if (
p_call->function_name == "emit_signal" &&
p_call->arguments.size() >= 1 &&
p_call->arguments[0]->type == GDScriptParser::Node::LITERAL
) {
signal_name = static_cast<const GDScriptParser::LiteralNode *>(p_call->arguments[0])->value;
}

if (signal_name) {
if (!parser->current_class->has_member(signal_name)) {
push_error(vformat(R"*(Invalid "emit_signal" call", no such a signal named "%s".)*", signal_name), p_call);
} else {
const GDScriptParser::ClassNode::Member &current_signal_member = parser->current_class->get_member(signal_name);

if (current_signal_member.type != GDScriptParser::ClassNode::Member::SIGNAL) {
push_error(vformat(R"*(Invalid "emit_signal" call", "%s" is not a signal.)*", signal_name), p_call);
} else {
const GDScriptParser::SignalNode *current_signal = current_signal_member.signal;
for (int i = 0; i < current_signal->parameters.size(); ++i) {
par_types.push_back(current_signal->parameters[i]->get_datatype());
}
}
}
}
}

validate_call_arg(par_types, default_arg_count, is_vararg, p_call);

if (base_type.kind == GDScriptParser::DataType::ENUM && base_type.is_meta_type) {
Expand Down
1 change: 1 addition & 0 deletions modules/gdscript/gdscript_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "gdscript.h"
#include "scene/resources/packed_scene.h"

class GDScript;
class GDScriptAnalyzer;
class GDScriptParser;

Expand Down
13 changes: 9 additions & 4 deletions modules/gdscript/gdscript_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2431,10 +2431,15 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
const GDScriptParser::SignalNode *signal = member.signal;
StringName name = signal->identifier->name;

Vector<StringName> parameters_names;
parameters_names.resize(signal->parameters.size());
for (int j = 0; j < signal->parameters.size(); j++) {
parameters_names.write[j] = signal->parameters[j]->identifier->name;
Vector<Pair<StringName, GDScriptParser::DataType>> parameters_names;
parameters_names.resize(member.signal->parameters.size());
for (int j = 0; j < member.signal->parameters.size(); j++) {
Pair<StringName, GDScriptParser::DataType> &current_parameter = parameters_names.write[j];

current_parameter.first = member.signal->parameters[j]->identifier->name;
if (member.signal->parameters[j]->datatype_specifier && member.signal->parameters[j]->datatype_specifier->type_chain.size() == 1) {
current_parameter.second = member.signal->parameters[j]->get_datatype();
}
}
p_script->_signals[name] = parameters_names;
#ifdef TOOLS_ENABLED
Expand Down
16 changes: 13 additions & 3 deletions modules/gdscript/language_server/gdscript_extend_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,12 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
if (j > 0) {
symbol.detail += ", ";
}
symbol.detail += m.signal->parameters[j]->identifier->name;
const ParameterNode &this_parameter = *m.signal->parameters[j];
symbol.detail += this_parameter.identifier->name;
if (this_parameter.datatype_specifier && this_parameter.datatype_specifier->type_chain.size() == 1) {
symbol.detail += ": ";
symbol.detail += this_parameter.datatype_specifier->type_chain[0]->name;
}
}
symbol.detail += ")";

Expand Down Expand Up @@ -796,9 +801,14 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
case ClassNode::Member::SIGNAL: {
Dictionary api;
api["name"] = m.signal->identifier->name;
Array pars;
Dictionary pars;
for (int j = 0; j < m.signal->parameters.size(); j++) {
pars.append(String(m.signal->parameters[i]->identifier->name));
const GDScriptParser::ParameterNode &this_parameter = *m.signal->parameters[i];
if (this_parameter.datatype_specifier && this_parameter.datatype_specifier->type_chain.size() == 1) {
pars[this_parameter.identifier->name] = this_parameter.datatype_specifier->type_chain[0]->name;
} else {
pars[this_parameter.identifier->name] = Variant::NIL;
}
}
api["arguments"] = pars;
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.signal->start_line))) {
Expand Down