summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/doc_classes/GDScript.xml2
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp42
-rw-r--r--modules/gdscript/gdscript_cache.cpp8
-rw-r--r--modules/gdscript/gdscript_parser.cpp2
-rw-r--r--modules/gdscript/gdscript_vm.cpp1
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp13
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.gd11
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/local_inference_is_weak.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/local_inference_is_weak.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/subscript_self.gd8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/subscript_self.out3
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/lua_assign.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/lua_assign.out2
15 files changed, 89 insertions, 29 deletions
diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml
index d45202bd40..0a448ed88c 100644
--- a/modules/gdscript/doc_classes/GDScript.xml
+++ b/modules/gdscript/doc_classes/GDScript.xml
@@ -8,7 +8,7 @@
[method new] creates a new instance of the script. [method Object.set_script] extends an existing object, if that object's class matches one of the script's base classes.
</description>
<tutorials>
- <link title="GDScript tutorial index">https://docs.godotengine.org/en/latest/getting_started/scripting/gdscript/index.html</link>
+ <link title="GDScript documentation index">https://docs.godotengine.org/en/latest/tutorials/scripting/gdscript/index.html</link>
</tutorials>
<methods>
<method name="get_as_byte_code" qualifiers="const">
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index ac031baa8c..2dafc85f45 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -244,6 +244,7 @@ Error GDScriptAnalyzer::resolve_inheritance(GDScriptParser::ClassNode *p_class,
class_type.kind = GDScriptParser::DataType::CLASS;
class_type.class_type = p_class;
class_type.script_path = parser->script_path;
+ class_type.builtin_type = Variant::OBJECT;
p_class->set_datatype(class_type);
if (!p_class->extends_used) {
@@ -1742,7 +1743,7 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
push_error("Cannot assign a new value to a constant.", p_assignment->assignee);
}
- if (!assignee_type.is_variant() && !assigned_value_type.is_variant()) {
+ if (!assignee_type.is_variant() && assigned_value_type.is_hard_type()) {
bool compatible = true;
GDScriptParser::DataType op_type = assigned_value_type;
if (p_assignment->operation != GDScriptParser::AssignmentNode::OP_NONE) {
@@ -1794,27 +1795,24 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
case GDScriptParser::IdentifierNode::FUNCTION_PARAMETER: {
GDScriptParser::DataType id_type = identifier->parameter_source->get_datatype();
if (!id_type.is_hard_type()) {
- id_type = assigned_value_type;
- id_type.type_source = GDScriptParser::DataType::INFERRED;
- id_type.is_constant = false;
+ id_type.kind = GDScriptParser::DataType::VARIANT;
+ id_type.type_source = GDScriptParser::DataType::UNDETECTED;
identifier->parameter_source->set_datatype(id_type);
}
} break;
case GDScriptParser::IdentifierNode::LOCAL_VARIABLE: {
GDScriptParser::DataType id_type = identifier->variable_source->get_datatype();
if (!id_type.is_hard_type()) {
- id_type = assigned_value_type;
- id_type.type_source = GDScriptParser::DataType::INFERRED;
- id_type.is_constant = false;
+ id_type.kind = GDScriptParser::DataType::VARIANT;
+ id_type.type_source = GDScriptParser::DataType::UNDETECTED;
identifier->variable_source->set_datatype(id_type);
}
} break;
case GDScriptParser::IdentifierNode::LOCAL_ITERATOR: {
GDScriptParser::DataType id_type = identifier->bind_source->get_datatype();
if (!id_type.is_hard_type()) {
- id_type = assigned_value_type;
- id_type.type_source = GDScriptParser::DataType::INFERRED;
- id_type.is_constant = false;
+ id_type.kind = GDScriptParser::DataType::VARIANT;
+ id_type.type_source = GDScriptParser::DataType::UNDETECTED;
identifier->variable_source->set_datatype(id_type);
}
} break;
@@ -2610,10 +2608,13 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
const StringName &native = base.native_type;
if (class_exists(native)) {
- PropertyInfo prop_info;
MethodInfo method_info;
- if (ClassDB::get_property_info(native, name, &prop_info)) {
- p_identifier->set_datatype(type_from_property(prop_info));
+ if (ClassDB::has_property(native, name)) {
+ StringName getter_name = ClassDB::get_property_getter(native, name);
+ MethodBind *getter = ClassDB::get_method(native, getter_name);
+ if (getter != nullptr) {
+ p_identifier->set_datatype(type_from_property(getter->get_return_info()));
+ }
return;
}
if (ClassDB::get_method_info(native, name, &method_info)) {
@@ -2941,7 +2942,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
} else {
GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
- if (base_type.is_variant()) {
+ if (base_type.is_variant() || !base_type.is_hard_type()) {
result_type.kind = GDScriptParser::DataType::VARIANT;
mark_node_unsafe(p_subscript);
} else {
@@ -3064,6 +3065,9 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
result_type.kind = GDScriptParser::DataType::BUILTIN;
result_type.type_source = base_type.is_hard_type() ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
+ if (base_type.kind != GDScriptParser::DataType::BUILTIN) {
+ base_type.builtin_type = Variant::OBJECT;
+ }
switch (base_type.builtin_type) {
// Can't index at all.
case Variant::RID:
@@ -3124,6 +3128,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
case Variant::PLANE:
case Variant::COLOR:
case Variant::DICTIONARY:
+ case Variant::OBJECT:
result_type.kind = GDScriptParser::DataType::VARIANT;
result_type.type_source = GDScriptParser::DataType::UNDETECTED;
break;
@@ -3138,7 +3143,6 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
}
break;
// Here for completeness.
- case Variant::OBJECT:
case Variant::VARIANT_MAX:
break;
}
@@ -3305,7 +3309,13 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
current = current->_owner;
}
- Ref<GDScriptParserRef> ref = get_parser_for(current->path);
+ Ref<GDScriptParserRef> ref = get_parser_for(current->get_path());
+ if (ref.is_null()) {
+ push_error("Could not find script in path.", p_source);
+ GDScriptParser::DataType error_type;
+ error_type.kind = GDScriptParser::DataType::VARIANT;
+ return error_type;
+ }
ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED);
GDScriptParser::ClassNode *found = ref->get_parser()->head;
diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp
index 8121053245..bb0d9e9e9b 100644
--- a/modules/gdscript/gdscript_cache.cpp
+++ b/modules/gdscript/gdscript_cache.cpp
@@ -58,27 +58,27 @@ Error GDScriptParserRef::raise_status(Status p_new_status) {
while (p_new_status > status) {
switch (status) {
case EMPTY:
- result = parser->parse(GDScriptCache::get_source_code(path), path, false);
status = PARSED;
+ result = parser->parse(GDScriptCache::get_source_code(path), path, false);
break;
case PARSED: {
analyzer = memnew(GDScriptAnalyzer(parser));
- Error inheritance_result = analyzer->resolve_inheritance();
status = INHERITANCE_SOLVED;
+ Error inheritance_result = analyzer->resolve_inheritance();
if (result == OK) {
result = inheritance_result;
}
} break;
case INHERITANCE_SOLVED: {
- Error interface_result = analyzer->resolve_interface();
status = INTERFACE_SOLVED;
+ Error interface_result = analyzer->resolve_interface();
if (result == OK) {
result = interface_result;
}
} break;
case INTERFACE_SOLVED: {
- Error body_result = analyzer->resolve_body();
status = FULLY_SOLVED;
+ Error body_result = analyzer->resolve_body();
if (result == OK) {
result = body_result;
}
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index ad75e8174c..93a5f7d493 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -3500,7 +3500,7 @@ bool GDScriptParser::network_annotations(const AnnotationNode *p_annotation, Nod
} else if (mode == "unreliable_ordered") {
rpc_config.transfer_mode = Multiplayer::TRANSFER_MODE_UNRELIABLE_ORDERED;
} else {
- push_error(R"(Invalid RPC argument. Must be one of: 'call_local'/'no_call_local' (local calls), 'any_peer'/'authority' (permission), 'reliable'/'unreliable'/'unreliable_ordered' (transfer mode).)", p_annotation);
+ push_error(R"(Invalid RPC argument. Must be one of: 'call_local'/'call_remote' (local calls), 'any_peer'/'authority' (permission), 'reliable'/'unreliable'/'unreliable_ordered' (transfer mode).)", p_annotation);
}
}
}
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index c89cf2f25c..1bc7ae086f 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -1719,6 +1719,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#define OPCODE_CALL_PTR(m_type) \
OPCODE(OPCODE_CALL_PTRCALL_##m_type) { \
CHECK_SPACE(3 + instr_arg_count); \
+ ip += instr_arg_count; \
int argc = _code_ptr[ip + 1]; \
GET_INSTRUCTION_ARG(base, argc); \
MethodBind *method = _methods_ptr[_code_ptr[ip + 2]]; \
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index c383830c82..50c1f68440 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -133,13 +133,12 @@ GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_l
if (do_init_languages) {
init_language(p_source_dir);
-
- // Enable all warnings for GDScript, so we can test them.
- ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/enable", true);
- for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
- String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
- ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/" + warning, true);
- }
+ }
+ // Enable all warnings for GDScript, so we can test them.
+ ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/enable", true);
+ for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
+ String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
+ ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/" + warning, true);
}
// Enable printing to show results
diff --git a/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out
index 0e9f482af4..481016138a 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out
+++ b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out
@@ -1,2 +1,6 @@
GDTEST_OK
+>> WARNING
+>> Line: 6
+>> UNSAFE_METHOD_ACCESS
+>> The method 'free' is not present on the inferred type 'Variant' (but may be present on a subtype).
Ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.gd b/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.gd
new file mode 100644
index 0000000000..630b20c282
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.gd
@@ -0,0 +1,11 @@
+# https://github.com/godotengine/godot/issues/43503
+
+var test_var = null
+
+
+func test():
+ print(test_var.x)
+
+
+func _init():
+ test_var = Vector3()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.out b/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.out
new file mode 100644
index 0000000000..94e2ec2af8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/class_inference_is_weak.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+0
diff --git a/modules/gdscript/tests/scripts/analyzer/features/local_inference_is_weak.gd b/modules/gdscript/tests/scripts/analyzer/features/local_inference_is_weak.gd
new file mode 100644
index 0000000000..b3784dffa3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/local_inference_is_weak.gd
@@ -0,0 +1,14 @@
+# https://github.com/godotengine/godot/issues/41064
+var x = true
+
+func test():
+ var int_var: int = 0
+ var dyn_var = 2
+
+ if x:
+ dyn_var = 5
+ else:
+ dyn_var = Node.new()
+
+ int_var = dyn_var
+ print(int_var)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/local_inference_is_weak.out b/modules/gdscript/tests/scripts/analyzer/features/local_inference_is_weak.out
new file mode 100644
index 0000000000..952029f665
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/local_inference_is_weak.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+5
diff --git a/modules/gdscript/tests/scripts/analyzer/features/subscript_self.gd b/modules/gdscript/tests/scripts/analyzer/features/subscript_self.gd
new file mode 100644
index 0000000000..f9a8b23b92
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/subscript_self.gd
@@ -0,0 +1,8 @@
+# https://github.com/godotengine/godot/issues/43221
+extends Node
+
+func test():
+ name = "Node"
+ print(self["name"])
+ self["name"] = "Changed"
+ print(name)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/subscript_self.out b/modules/gdscript/tests/scripts/analyzer/features/subscript_self.out
new file mode 100644
index 0000000000..6417f4f8da
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/subscript_self.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+Node
+Changed
diff --git a/modules/gdscript/tests/scripts/runtime/features/lua_assign.gd b/modules/gdscript/tests/scripts/runtime/features/lua_assign.gd
new file mode 100644
index 0000000000..c9b5f8481e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/lua_assign.gd
@@ -0,0 +1,4 @@
+func test():
+ var dict = {}
+ dict.test = 1
+ print(dict.test)
diff --git a/modules/gdscript/tests/scripts/runtime/features/lua_assign.out b/modules/gdscript/tests/scripts/runtime/features/lua_assign.out
new file mode 100644
index 0000000000..a7f1357bb2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/lua_assign.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+1