summaryrefslogtreecommitdiffstats
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/gdscript.cpp5
-rw-r--r--modules/gdscript/gdscript_compiler.cpp66
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/first_class_callable_and_signal.gd14
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/first_class_callable_and_signal.out5
4 files changed, 58 insertions, 32 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 0bf9f72a2c..42b08f8a68 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -2695,6 +2695,11 @@ Ref<Resource> ResourceFormatLoaderGDScript::load(const String &p_path, const Str
Error err;
Ref<GDScript> scr = GDScriptCache::get_full_script(p_path, err, "", p_cache_mode == CACHE_MODE_IGNORE);
+ if (err && scr.is_valid()) {
+ // If !scr.is_valid(), the error was likely from scr->load_source_code(), which already generates an error.
+ ERR_PRINT_ED(vformat(R"(Failed to load script "%s" with error "%s".)", p_path, error_names[err]));
+ }
+
if (r_error) {
// Don't fail loading because of parsing error.
*r_error = scr.is_valid() ? OK : err;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 2a52db4158..3366fa2eec 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -245,6 +245,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// MEMBERS.
case GDScriptParser::IdentifierNode::MEMBER_VARIABLE:
+ case GDScriptParser::IdentifierNode::MEMBER_FUNCTION:
+ case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
case GDScriptParser::IdentifierNode::INHERITED_VARIABLE: {
// Try class members.
if (_is_class_member_property(codegen, identifier)) {
@@ -271,45 +273,44 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
}
}
}
- } break;
- case GDScriptParser::IdentifierNode::MEMBER_FUNCTION:
- case GDScriptParser::IdentifierNode::MEMBER_SIGNAL: {
- // Try methods and signals (can be Callable and Signal).
- // Search upwards through parent classes:
- const GDScriptParser::ClassNode *base_class = codegen.class_node;
- while (base_class != nullptr) {
- if (base_class->has_member(identifier)) {
- const GDScriptParser::ClassNode::Member &member = base_class->get_member(identifier);
- if (member.type == GDScriptParser::ClassNode::Member::FUNCTION || member.type == GDScriptParser::ClassNode::Member::SIGNAL) {
- // Get like it was a property.
- GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
- GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
-
- gen->write_get_named(temp, identifier, self);
- return temp;
+ // Try methods and signals (can be Callable and Signal).
+ {
+ // Search upwards through parent classes:
+ const GDScriptParser::ClassNode *base_class = codegen.class_node;
+ while (base_class != nullptr) {
+ if (base_class->has_member(identifier)) {
+ const GDScriptParser::ClassNode::Member &member = base_class->get_member(identifier);
+ if (member.type == GDScriptParser::ClassNode::Member::FUNCTION || member.type == GDScriptParser::ClassNode::Member::SIGNAL) {
+ // Get like it was a property.
+ GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
+ GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
+
+ gen->write_get_named(temp, identifier, self);
+ return temp;
+ }
}
+ base_class = base_class->base_type.class_type;
}
- base_class = base_class->base_type.class_type;
- }
- // Try in native base.
- GDScript *scr = codegen.script;
- GDScriptNativeClass *nc = nullptr;
- while (scr) {
- if (scr->native.is_valid()) {
- nc = scr->native.ptr();
+ // Try in native base.
+ GDScript *scr = codegen.script;
+ GDScriptNativeClass *nc = nullptr;
+ while (scr) {
+ if (scr->native.is_valid()) {
+ nc = scr->native.ptr();
+ }
+ scr = scr->_base;
}
- scr = scr->_base;
- }
- if (nc && (ClassDB::has_signal(nc->get_name(), identifier) || ClassDB::has_method(nc->get_name(), identifier))) {
- // Get like it was a property.
- GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
- GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
+ if (nc && (ClassDB::has_signal(nc->get_name(), identifier) || ClassDB::has_method(nc->get_name(), identifier))) {
+ // Get like it was a property.
+ GDScriptCodeGenerator::Address temp = codegen.add_temporary(); // TODO: Get type here.
+ GDScriptCodeGenerator::Address self(GDScriptCodeGenerator::Address::SELF);
- gen->write_get_named(temp, identifier, self);
- return temp;
+ gen->write_get_named(temp, identifier, self);
+ return temp;
+ }
}
} break;
case GDScriptParser::IdentifierNode::MEMBER_CONSTANT:
@@ -319,6 +320,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
while (owner) {
GDScript *scr = owner;
GDScriptNativeClass *nc = nullptr;
+
while (scr) {
if (scr->constants.has(identifier)) {
return codegen.add_constant(scr->constants[identifier]); // TODO: Get type here.
diff --git a/modules/gdscript/tests/scripts/runtime/features/first_class_callable_and_signal.gd b/modules/gdscript/tests/scripts/runtime/features/first_class_callable_and_signal.gd
new file mode 100644
index 0000000000..f17fb9823d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/first_class_callable_and_signal.gd
@@ -0,0 +1,14 @@
+# GH-80157
+
+extends Node
+
+func f():
+ pass
+
+signal s()
+
+func test():
+ print(f)
+ print(s)
+ print(get_child)
+ print(ready)
diff --git a/modules/gdscript/tests/scripts/runtime/features/first_class_callable_and_signal.out b/modules/gdscript/tests/scripts/runtime/features/first_class_callable_and_signal.out
new file mode 100644
index 0000000000..e5e9ff7043
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/first_class_callable_and_signal.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+Node::f
+Node::[signal]s
+Node::get_child
+Node::[signal]ready