GDScript: Fix: update member cache of subclasses

Currently, the member cache for subclasses (sometimes called inner classes in the codebase)
is not updated. This causes users being unable to see exported
properties inherited from an inner class in the editor.
This commit is contained in:
yannick-was-taken 2024-07-25 16:38:30 +02:00
parent e343dbbcc1
commit 9ca9fb3c2f
No known key found for this signature in database
GPG Key ID: 4A80145C01F8A10A
4 changed files with 48 additions and 7 deletions

View File

@ -451,11 +451,18 @@ void GDScript::set_source_code(const String &p_code) {
}
source = p_code;
#ifdef TOOLS_ENABLED
source_changed_cache = true;
mark_source_changed();
#endif
}
#ifdef TOOLS_ENABLED
void GDScript::mark_source_changed() {
_source_changed_cache = true;
for (KeyValue<StringName, Ref<GDScript>> &inner : subclasses) {
inner.value->mark_source_changed();
}
}
void GDScript::_update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames) {
for (const KeyValue<StringName, Variant> &E : member_default_values_cache) {
values[E.key] = E.value;
@ -505,8 +512,9 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
bool changed = p_base_exports_changed;
if (source_changed_cache) {
source_changed_cache = false;
if (_source_changed_cache) {
// Only set to false for this instance: subclasses have to update themselves
_source_changed_cache = false;
changed = true;
String basedir = path;
@ -521,17 +529,27 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
GDScriptParser parser;
GDScriptAnalyzer analyzer(&parser);
Error err = parser.parse(source, path, false);
const String *s = &source;
if (!is_root_script()) {
// Subclasses are contained in their root script's source
s = &get_root_script()->source;
}
Error err = parser.parse(*s, path, false);
if (err == OK && analyzer.analyze() == OK) {
const GDScriptParser::ClassNode *c = parser.get_tree();
if (!is_root_script()) {
// get_tree() would return outer class. We are in that tree somewhere!
c = c->find_class(fully_qualified_name);
}
if (base_cache.is_valid()) {
base_cache->inheriters_cache.erase(get_instance_id());
base_cache = Ref<GDScript>();
}
GDScriptParser::DataType base_type = parser.get_tree()->base_type;
GDScriptParser::DataType base_type = c->base_type;
if (base_type.kind == GDScriptParser::DataType::CLASS) {
Ref<GDScript> bf = GDScriptCache::get_full_script(base_type.script_path, err, path);
if (err == OK) {
@ -1110,7 +1128,7 @@ Error GDScript::load_source_code(const String &p_path) {
path = p_path;
path_valid = true;
#ifdef TOOLS_ENABLED
source_changed_cache = true;
mark_source_changed();
set_edited(false);
set_last_modified_time(FileAccess::get_modified_time(path));
#endif // TOOLS_ENABLED

View File

@ -153,7 +153,8 @@ private:
HashMap<StringName, Variant> member_default_values_cache;
Ref<GDScript> base_cache;
HashSet<ObjectID> inheriters_cache;
bool source_changed_cache = false;
bool _source_changed_cache = false;
void mark_source_changed();
bool placeholder_fallback_enabled = false;
void _update_exports_values(HashMap<StringName, Variant> &values, List<PropertyInfo> &propnames);

View File

@ -3086,6 +3086,11 @@ void GDScriptCompiler::make_scripts(GDScript *p_script, const GDScriptParser::Cl
make_scripts(subclass.ptr(), inner_class, p_keep_state);
}
#ifdef TOOLS_ENABLED
// Mark all newly created subclasses as having changed source
p_script->mark_source_changed();
#endif // TOOLS_ENABLED
}
GDScriptCompiler::FunctionLambdaInfo GDScriptCompiler::_get_function_replacement_info(GDScriptFunction *p_func, int p_index, int p_depth, GDScriptFunction *p_parent_func) {

View File

@ -757,6 +757,23 @@ public:
ERR_FAIL_INDEX(members_indices[p_name], members.size());
members.write[members_indices[p_name]].enum_value.doc_data = p_doc_data;
}
const ClassNode *find_class(const String &p_fqcn) const {
if (fqcn == p_fqcn) {
return this;
}
for (const Member &member : members) {
if (member.type == Member::CLASS) {
const ClassNode *c = member.m_class->find_class(p_fqcn);
if (c != nullptr) {
return c;
}
}
}
return nullptr;
}
#endif // TOOLS_ENABLED
bool resolved_interface = false;