Skip to content

Commit

Permalink
Merge pull request #68374 from rune-scape/rune-gdscript-compiler-bugf…
Browse files Browse the repository at this point in the history
…ixes

Fixes #65953
Fixes #68291
Fixes #68561
Fixes #64915
Fixes #61848
Fixes #61268
  • Loading branch information
akien-mga authored Nov 14, 2022
2 parents 30145a9 + bce6f17 commit 963ffd8
Show file tree
Hide file tree
Showing 14 changed files with 283 additions and 281 deletions.
140 changes: 66 additions & 74 deletions modules/gdscript/gdscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,10 +629,6 @@ void GDScript::_update_doc() {
}
}

for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
E.value->_update_doc();
}

_add_doc(doc);
}
#endif
Expand Down Expand Up @@ -674,36 +670,14 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderSc
base_cache = Ref<GDScript>();
}

if (c->extends_used) {
String ext_path = "";
if (String(c->extends_path) != "" && String(c->extends_path) != get_path()) {
ext_path = c->extends_path;
if (ext_path.is_relative_path()) {
String base_path = get_path();
if (base_path.is_empty() || base_path.is_relative_path()) {
ERR_PRINT(("Could not resolve relative path for parent class: " + ext_path).utf8().get_data());
} else {
ext_path = base_path.get_base_dir().path_join(ext_path);
}
}
} else if (c->extends.size() != 0) {
const StringName &base_class = c->extends[0];

if (ScriptServer::is_global_class(base_class)) {
ext_path = ScriptServer::get_global_class_path(base_class);
}
}

if (!ext_path.is_empty()) {
if (ext_path != get_path()) {
Ref<GDScript> bf = ResourceLoader::load(ext_path);

if (bf.is_valid()) {
base_cache = bf;
bf->inheriters_cache.insert(get_instance_id());
}
} else {
ERR_PRINT(("Path extending itself in " + ext_path).utf8().get_data());
GDScriptParser::DataType base_type = parser.get_tree()->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) {
bf = Ref<GDScript>(bf->find_class(base_type.class_type->fqcn));
if (bf.is_valid()) {
base_cache = bf;
bf->inheriters_cache.insert(get_instance_id());
}
}
}
Expand Down Expand Up @@ -825,13 +799,6 @@ void GDScript::update_exports() {
#endif
}

void GDScript::_set_subclass_path(Ref<GDScript> &p_sc, const String &p_path) {
p_sc->path = p_path;
for (KeyValue<StringName, Ref<GDScript>> &E : p_sc->subclasses) {
_set_subclass_path(E.value, p_path);
}
}

String GDScript::_get_debug_path() const {
if (is_built_in() && !get_name().is_empty()) {
return get_name() + " (" + get_path() + ")";
Expand Down Expand Up @@ -860,7 +827,7 @@ Error GDScript::reload(bool p_keep_state) {
basedir = basedir.get_base_dir();
}

// Loading a template, don't parse.
// Loading a template, don't parse.
#ifdef TOOLS_ENABLED
if (EditorPaths::get_singleton() && basedir.begins_with(EditorPaths::get_singleton()->get_project_script_templates_dir())) {
return OK;
Expand Down Expand Up @@ -913,10 +880,6 @@ Error GDScript::reload(bool p_keep_state) {
GDScriptCompiler compiler;
err = compiler.compile(&parser, this, p_keep_state);

#ifdef TOOLS_ENABLED
_update_doc();
#endif

if (err) {
if (can_run) {
if (EngineDebugger::is_active()) {
Expand All @@ -937,14 +900,6 @@ Error GDScript::reload(bool p_keep_state) {
}
#endif

valid = true;

for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) {
_set_subclass_path(E.value, path);
}

_init_rpc_methods_properties();

return OK;
}

Expand Down Expand Up @@ -1051,8 +1006,13 @@ Error GDScript::load_byte_code(const String &p_path) {
}

void GDScript::set_path(const String &p_path, bool p_take_over) {
Script::set_path(p_path, p_take_over);
if (is_root_script()) {
Script::set_path(p_path, p_take_over);
}
this->path = p_path;
for (KeyValue<StringName, Ref<GDScript>> &kv : subclasses) {
kv.value->set_path(p_path, p_take_over);
}
}

Error GDScript::load_source_code(const String &p_path) {
Expand Down Expand Up @@ -1127,6 +1087,52 @@ bool GDScript::inherits_script(const Ref<Script> &p_script) const {
return false;
}

GDScript *GDScript::find_class(const String &p_qualified_name) {
String first = p_qualified_name.get_slice("::", 0);

GDScript *result = nullptr;
if (first.is_empty() || first == name) {
result = this;
} else if (first == get_root_script()->path) {
result = get_root_script();
} else if (HashMap<StringName, Ref<GDScript>>::Iterator E = subclasses.find(first)) {
result = E->value.ptr();
} else if (_owner != nullptr) {
// Check parent scope.
return _owner->find_class(p_qualified_name);
}

int name_count = p_qualified_name.get_slice_count("::");
for (int i = 1; result != nullptr && i < name_count; i++) {
String current_name = p_qualified_name.get_slice("::", i);
if (HashMap<StringName, Ref<GDScript>>::Iterator E = result->subclasses.find(current_name)) {
result = E->value.ptr();
} else {
// Couldn't find inner class.
return nullptr;
}
}

return result;
}

bool GDScript::is_subclass(const GDScript *p_script) {
String fqn = p_script->fully_qualified_name;
if (!fqn.is_empty() && fqn != fully_qualified_name && fqn.begins_with(fully_qualified_name)) {
String fqn_rest = fqn.substr(fully_qualified_name.length());
return find_class(fqn_rest) == p_script;
}
return false;
}

GDScript *GDScript::get_root_script() {
GDScript *result = this;
while (result->_owner) {
result = result->_owner;
}
return result;
}

bool GDScript::has_script_signal(const StringName &p_signal) const {
if (_signals.has(p_signal)) {
return true;
Expand Down Expand Up @@ -1238,25 +1244,11 @@ void GDScript::_init_rpc_methods_properties() {
rpc_config = base->rpc_config.duplicate();
}

GDScript *cscript = this;
HashMap<StringName, Ref<GDScript>>::Iterator sub_E = subclasses.begin();
while (cscript) {
// RPC Methods
for (KeyValue<StringName, GDScriptFunction *> &E : cscript->member_functions) {
Variant config = E.value->get_rpc_config();
if (config.get_type() != Variant::NIL) {
rpc_config[E.value->get_name()] = config;
}
}

if (cscript != this) {
++sub_E;
}

if (sub_E) {
cscript = sub_E->value.ptr();
} else {
cscript = nullptr;
// 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;
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions modules/gdscript/gdscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ class GDScript : public Script {
void _super_implicit_constructor(GDScript *p_script, GDScriptInstance *p_instance, Callable::CallError &r_error);
GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error);

void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path);
String _get_debug_path() const;

#ifdef TOOLS_ENABLED
Expand Down Expand Up @@ -178,6 +177,11 @@ class GDScript : public Script {

bool inherits_script(const Ref<Script> &p_script) const override;

GDScript *find_class(const String &p_qualified_name);
bool is_subclass(const GDScript *p_script);
GDScript *get_root_script();
bool is_root_script() const { return _owner == nullptr; }
String get_fully_qualified_name() const { return fully_qualified_name; }
const HashMap<StringName, Ref<GDScript>> &get_subclasses() const { return subclasses; }
const HashMap<StringName, Variant> &get_constants() const { return constants; }
const HashSet<StringName> &get_members() const { return members; }
Expand Down Expand Up @@ -223,7 +227,6 @@ class GDScript : public Script {
virtual Error reload(bool p_keep_state = false) override;

virtual void set_path(const String &p_path, bool p_take_over = false) override;
void set_script_path(const String &p_path) { path = p_path; } //because subclasses need a path too...
Error load_source_code(const String &p_path);
Error load_byte_code(const String &p_path);

Expand Down
10 changes: 0 additions & 10 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,6 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
return OK;
}

if (p_class == parser->head) {
if (p_class->identifier) {
p_class->fqcn = p_class->identifier->name;
} else {
p_class->fqcn = parser->script_path;
}
} else {
p_class->fqcn = p_class->outer->fqcn + "::" + String(p_class->identifier->name);
}

if (p_class->identifier) {
StringName class_name = p_class->identifier->name;
if (class_exists(class_name)) {
Expand Down
40 changes: 33 additions & 7 deletions modules/gdscript/gdscript_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "core/templates/vector.h"
#include "gdscript.h"
#include "gdscript_analyzer.h"
#include "gdscript_compiler.h"
#include "gdscript_parser.h"

bool GDScriptParserRef::is_valid() const {
Expand Down Expand Up @@ -161,7 +162,7 @@ String GDScriptCache::get_source_code(const String &p_path) {
return source;
}

Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const String &p_owner) {
Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, Error &r_error, const String &p_owner) {
MutexLock lock(singleton->lock);
if (!p_owner.is_empty()) {
singleton->dependencies[p_owner].insert(p_path);
Expand All @@ -173,11 +174,16 @@ Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const Stri
return singleton->shallow_gdscript_cache[p_path];
}

Ref<GDScriptParserRef> parser_ref = get_parser(p_path, GDScriptParserRef::PARSED, r_error);
if (r_error != OK) {
return Ref<GDScript>();
}

Ref<GDScript> script;
script.instantiate();
script->set_path(p_path, true);
script->set_script_path(p_path);
script->load_source_code(p_path);
GDScriptCompiler::make_scripts(script.ptr(), parser_ref->get_parser()->get_tree(), true);

singleton->shallow_gdscript_cache[p_path] = script.ptr();
return script;
Expand All @@ -200,17 +206,21 @@ Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_erro
}

if (script.is_null()) {
script = get_shallow_script(p_path);
ERR_FAIL_COND_V(script.is_null(), Ref<GDScript>());
script = get_shallow_script(p_path, r_error);
if (r_error) {
return script;
}
}

r_error = script->load_source_code(p_path);
if (p_update_from_disk) {
r_error = script->load_source_code(p_path);
}

if (r_error) {
return script;
}

r_error = script->reload();
r_error = script->reload(true);
if (r_error) {
return script;
}
Expand All @@ -221,9 +231,25 @@ Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_erro
return script;
}

Ref<GDScript> GDScriptCache::get_cached_script(const String &p_path) {
MutexLock lock(singleton->lock);

if (singleton->full_gdscript_cache.has(p_path)) {
return singleton->full_gdscript_cache[p_path];
}

if (singleton->shallow_gdscript_cache.has(p_path)) {
return singleton->shallow_gdscript_cache[p_path];
}

return Ref<GDScript>();
}

Error GDScriptCache::finish_compiling(const String &p_owner) {
MutexLock lock(singleton->lock);

// Mark this as compiled.
Ref<GDScript> script = get_shallow_script(p_owner);
Ref<GDScript> script = get_cached_script(p_owner);
singleton->full_gdscript_cache[p_owner] = script.ptr();
singleton->shallow_gdscript_cache.erase(p_owner);

Expand Down
3 changes: 2 additions & 1 deletion modules/gdscript/gdscript_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ class GDScriptCache {
public:
static Ref<GDScriptParserRef> get_parser(const String &p_path, GDScriptParserRef::Status status, Error &r_error, const String &p_owner = String());
static String get_source_code(const String &p_path);
static Ref<GDScript> get_shallow_script(const String &p_path, const String &p_owner = String());
static Ref<GDScript> get_shallow_script(const String &p_path, Error &r_error, const String &p_owner = String());
static Ref<GDScript> get_full_script(const String &p_path, Error &r_error, const String &p_owner = String(), bool p_update_from_disk = false);
static Ref<GDScript> get_cached_script(const String &p_path);
static Error finish_compiling(const String &p_owner);

GDScriptCache();
Expand Down
Loading

0 comments on commit 963ffd8

Please sign in to comment.