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

GDScript: Fix subclass methods not inheriting RPC info #81201

Merged
merged 1 commit into from
Sep 12, 2023
Merged
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
16 changes: 0 additions & 16 deletions modules/gdscript/gdscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1399,22 +1399,6 @@ void GDScript::_save_orphaned_subclasses(ClearData *p_clear_data) {
}
}

void GDScript::_init_rpc_methods_properties() {
// Copy the base rpc methods so we don't mask their IDs.
rpc_config.clear();
if (base.is_valid()) {
rpc_config = base->rpc_config.duplicate();
}

// RPC Methods
for (KeyValue<StringName, GDScriptFunction *> &E : member_functions) {
Variant config = E.value->get_rpc_config();
if (config.get_type() != Variant::NIL) {
rpc_config[E.value->get_name()] = config;
}
}
}

#ifdef DEBUG_ENABLED
String GDScript::debug_get_script_name(const Ref<Script> &p_script) {
if (p_script.is_valid()) {
Expand Down
1 change: 0 additions & 1 deletion modules/gdscript/gdscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ class GDScript : public Script {
bool _update_exports(bool *r_err = nullptr, bool p_recursive_call = false, PlaceHolderScriptInstance *p_instance_to_update = nullptr);

void _save_orphaned_subclasses(GDScript::ClearData *p_clear_data);
void _init_rpc_methods_properties();

void _get_script_property_list(List<PropertyInfo> *r_list, bool p_include_base) const;
void _get_script_method_list(List<MethodInfo> *r_list, bool p_include_base) const;
Expand Down
32 changes: 24 additions & 8 deletions modules/gdscript/gdscript_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2503,7 +2503,10 @@ Error GDScriptCompiler::_parse_setter_getter(GDScript *p_script, const GDScriptP
return err;
}

Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
// Prepares given script, and inner class scripts, for compilation. It populates class members and initializes method
// RPC info for its base classes first, then for itself, then for inner classes.
// Warning: this function cannot initiate compilation of other classes, or it will result in cyclic dependency issues.
Error GDScriptCompiler::_prepare_compilation(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
if (parsed_classes.has(p_script)) {
return OK;
}
Expand Down Expand Up @@ -2562,6 +2565,7 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
p_script->implicit_initializer = nullptr;
p_script->implicit_ready = nullptr;
p_script->static_initializer = nullptr;
p_script->rpc_config.clear();

p_script->clearing = false;

Expand Down Expand Up @@ -2592,7 +2596,7 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
}

if (main_script->has_class(base.ptr())) {
Error err = _populate_class_members(base.ptr(), p_class->base_type.class_type, p_keep_state);
Error err = _prepare_compilation(base.ptr(), p_class->base_type.class_type, p_keep_state);
if (err) {
return err;
}
Expand All @@ -2611,7 +2615,7 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
return ERR_COMPILATION_FAILED;
}

err = _populate_class_members(base.ptr(), p_class->base_type.class_type, p_keep_state);
err = _prepare_compilation(base.ptr(), p_class->base_type.class_type, p_keep_state);
if (err) {
_set_error(vformat(R"(Could not populate class members of base class "%s" in "%s".)", base->fully_qualified_name, base->path), nullptr);
return err;
Expand All @@ -2628,6 +2632,12 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
} break;
}

// Duplicate RPC information from base GDScript
// Base script isn't valid because it should not have been compiled yet, but the reference contains relevant info.
if (base_type.kind == GDScriptDataType::GDSCRIPT && p_script->base.is_valid()) {
p_script->rpc_config = p_script->base->rpc_config.duplicate();
}

for (int i = 0; i < p_class->members.size(); i++) {
const GDScriptParser::ClassNode::Member &member = p_class->members[i];
switch (member.type) {
Expand Down Expand Up @@ -2746,6 +2756,14 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
p_script->members.insert(Variant());
} break;

case GDScriptParser::ClassNode::Member::FUNCTION: {
const GDScriptParser::FunctionNode *function_n = member.function;

Variant config = function_n->rpc_config;
if (config.get_type() != Variant::NIL) {
p_script->rpc_config[function_n->identifier->name] = config;
}
} break;
default:
break; // Nothing to do here.
}
Expand All @@ -2756,7 +2774,7 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
parsed_classes.insert(p_script);
parsing_classes.erase(p_script);

// Populate sub-classes.
// Populate inner classes.
for (int i = 0; i < p_class->members.size(); i++) {
const GDScriptParser::ClassNode::Member &member = p_class->members[i];
if (member.type != member.CLASS) {
Expand All @@ -2769,7 +2787,7 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri

// Subclass might still be parsing, just skip it
if (!parsing_classes.has(subclass_ptr)) {
Error err = _populate_class_members(subclass_ptr, inner_class, p_keep_state);
Error err = _prepare_compilation(subclass_ptr, inner_class, p_keep_state);
if (err) {
return err;
}
Expand Down Expand Up @@ -2905,8 +2923,6 @@ Error GDScriptCompiler::_compile_class(GDScript *p_script, const GDScriptParser:
has_static_data = has_static_data || inner_class->has_static_data;
}

p_script->_init_rpc_methods_properties();

p_script->valid = true;
return OK;
}
Expand Down Expand Up @@ -2979,7 +2995,7 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri
make_scripts(p_script, root, p_keep_state);

main_script->_owner = nullptr;
Error err = _populate_class_members(main_script, parser->get_tree(), p_keep_state);
Error err = _prepare_compilation(main_script, parser->get_tree(), p_keep_state);

if (err) {
return err;
Expand Down
2 changes: 1 addition & 1 deletion modules/gdscript/gdscript_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class GDScriptCompiler {
GDScriptFunction *_parse_function(Error &r_error, GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false, bool p_for_lambda = false);
GDScriptFunction *_make_static_initializer(Error &r_error, GDScript *p_script, const GDScriptParser::ClassNode *p_class);
Error _parse_setter_getter(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::VariableNode *p_variable, bool p_is_setter);
Error _populate_class_members(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
Error _prepare_compilation(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
Error _compile_class(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state);
int err_line = 0;
int err_column = 0;
Expand Down
Loading