summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/tests
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/tests')
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser.gd17
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser.out3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_base1.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_base2.notest.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_script1.notest.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_script1_base.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_script1c.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_script1d.notest.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_script1e.notest.gd0
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_script1f.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_script2.notest.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_parser_script3.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.out9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool_ignored.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool_ignored.out1
-rw-r--r--modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.cfg5
-rw-r--r--modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.gd8
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg (renamed from modules/gdscript/tests/scripts/completion/common/identifiers.cfg)6
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_call.gd18
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg25
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.gd (renamed from modules/gdscript/tests/scripts/completion/common/identifiers.gd)4
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg25
-rw-r--r--modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.gd22
-rw-r--r--modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg26
-rw-r--r--modules/gdscript/tests/scripts/completion/common/no_completion_in_string.gd19
-rw-r--r--modules/gdscript/tests/scripts/completion/common/self.gd1
-rw-r--r--modules/gdscript/tests/scripts/completion/filter/organized_export.gd3
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.gd (renamed from modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/index/array_type.cfg9
-rw-r--r--modules/gdscript/tests/scripts/completion/index/array_type.gd10
-rw-r--r--modules/gdscript/tests/scripts/completion/index/array_value.cfg9
-rw-r--r--modules/gdscript/tests/scripts/completion/index/array_value.gd10
-rw-r--r--modules/gdscript/tests/scripts/completion/index/const_dictionary_keys.cfg11
-rw-r--r--modules/gdscript/tests/scripts/completion/index/const_dictionary_keys.gd13
-rw-r--r--modules/gdscript/tests/scripts/completion/index/dictionary_type.cfg9
-rw-r--r--modules/gdscript/tests/scripts/completion/index/dictionary_type.gd10
-rw-r--r--modules/gdscript/tests/scripts/completion/index/dictionary_value.cfg9
-rw-r--r--modules/gdscript/tests/scripts/completion/index/dictionary_value.gd10
-rw-r--r--modules/gdscript/tests/scripts/completion/index/local_dictionary_keys.cfg11
-rw-r--r--modules/gdscript/tests/scripts/completion/index/local_dictionary_keys.gd13
-rw-r--r--modules/gdscript/tests/scripts/completion/index/property_dictionary_keys.cfg9
-rw-r--r--modules/gdscript/tests/scripts/completion/index/property_dictionary_keys.gd13
-rw-r--r--modules/gdscript/tests/scripts/completion/index/untyped_local.cfg5
-rw-r--r--modules/gdscript/tests/scripts/completion/index/untyped_local.gd10
-rw-r--r--modules/gdscript/tests/scripts/completion/index/untyped_property.cfg5
-rw-r--r--modules/gdscript/tests/scripts/completion/index/untyped_property.gd9
-rw-r--r--modules/gdscript/tests/scripts/completion/types/local/infered.cfg (renamed from modules/gdscript/tests/scripts/completion/types/local/interfered.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/types/local/infered.gd (renamed from modules/gdscript/tests/scripts/completion/types/local/interfered.gd)0
-rw-r--r--modules/gdscript/tests/scripts/completion/types/member/infered.cfg (renamed from modules/gdscript/tests/scripts/completion/types/member/interfered.cfg)0
-rw-r--r--modules/gdscript/tests/scripts/completion/types/member/infered.gd (renamed from modules/gdscript/tests/scripts/completion/types/member/interfered.gd)0
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.gd9
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_wrong_to_typed.out1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/lambda_bind_argument_count.gd18
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/lambda_bind_argument_count.out3
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/lambda_get_method.gd21
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/lambda_get_method.out5
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd20
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.gd11
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.out1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.gd62
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.out26
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.gd13
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.out4
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/single_underscore_node_name.gd15
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/single_underscore_node_name.out1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/typed_array_implicit_cast_param.gd7
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/typed_array_implicit_cast_param.out2
85 files changed, 651 insertions, 7 deletions
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index fbfa4a0a79..025fcbd32a 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -622,7 +622,7 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
enable_stdout();
result.status = GDTEST_COMPILER_ERROR;
result.output = get_text_for_status(result.status) + "\n";
- result.output = compiler.get_error();
+ result.output += compiler.get_error() + "\n";
if (!p_is_generating) {
result.passed = check_output(result.output);
}
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.out b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.out
index 64a6bd417d..878e827d04 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/cyclic_ref_external.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Could not resolve member "v".
+Could not resolve external class member "v".
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser.gd
new file mode 100644
index 0000000000..ad265a7365
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser.gd
@@ -0,0 +1,17 @@
+extends "external_parser_base1.notest.gd"
+
+const External1 = preload("external_parser_script1.notest.gd")
+
+func baz(e1: External1) -> void:
+ print(e1.e1c.bar)
+ print(e1.baz)
+
+func test_external_base_parser_type_resolve(_v: TypeFromBase):
+ pass
+
+func test():
+ var ext := External1.new()
+ print(ext.array[0].test2)
+ print(ext.get_external2().get_external3().test3)
+ # TODO: This actually produces a runtime error, but we're testing the analyzer here
+ #baz(ext)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser.out b/modules/gdscript/tests/scripts/analyzer/features/external_parser.out
new file mode 100644
index 0000000000..26c2527fbc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+test2
+test3
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_base1.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_base1.notest.gd
new file mode 100644
index 0000000000..d27d8cef3b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_base1.notest.gd
@@ -0,0 +1 @@
+extends "external_parser_base2.notest.gd"
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_base2.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_base2.notest.gd
new file mode 100644
index 0000000000..f8de818485
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_base2.notest.gd
@@ -0,0 +1,2 @@
+class TypeFromBase:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1.notest.gd
new file mode 100644
index 0000000000..e1221bb138
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1.notest.gd
@@ -0,0 +1,12 @@
+extends "external_parser_script1_base.notest.gd"
+
+const External2 = preload("external_parser_script2.notest.gd")
+const External1c = preload("external_parser_script1c.notest.gd")
+
+@export var e1c: External1c
+
+var array: Array[External2] = [ External2.new() ]
+var baz: int
+
+func get_external2() -> External2:
+ return External2.new()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1_base.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1_base.notest.gd
new file mode 100644
index 0000000000..4249efa1f9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1_base.notest.gd
@@ -0,0 +1 @@
+extends Resource
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1c.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1c.notest.gd
new file mode 100644
index 0000000000..34a48cba6f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1c.notest.gd
@@ -0,0 +1 @@
+extends "external_parser_script1d.notest.gd"
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1d.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1d.notest.gd
new file mode 100644
index 0000000000..43bc6f3e53
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1d.notest.gd
@@ -0,0 +1,5 @@
+extends "external_parser_script1f.notest.gd"
+
+const External1e = preload("external_parser_script1e.notest.gd")
+
+var bar: Array[External1e]
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1e.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1e.notest.gd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1e.notest.gd
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1f.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1f.notest.gd
new file mode 100644
index 0000000000..4249efa1f9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script1f.notest.gd
@@ -0,0 +1 @@
+extends Resource
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_script2.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script2.notest.gd
new file mode 100644
index 0000000000..885f813503
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script2.notest.gd
@@ -0,0 +1,6 @@
+const External3 = preload("external_parser_script3.notest.gd")
+
+var test2 := "test2"
+
+func get_external3() -> External3:
+ return External3.new()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_parser_script3.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script3.notest.gd
new file mode 100644
index 0000000000..3e62974256
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_parser_script3.notest.gd
@@ -0,0 +1 @@
+var test3 := "test3"
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd
index 13e3edf93f..f3a8661acf 100644
--- a/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/enum_without_default_value.gd
@@ -7,3 +7,17 @@ var has_no_zero: HasNoZero # Warning, because there is no `0` in the enum.
func test():
print(has_zero)
print(has_no_zero)
+
+
+# GH-94634. A parameter is either mandatory or has a default value.
+func test_no_exec(param: HasNoZero) -> void:
+ print(param)
+
+ # Loop iterator always has a value.
+ for i: HasNoZero in HasNoZero.values():
+ print(i)
+
+ match param:
+ # Pattern bind always has a value.
+ var x:
+ print(x)
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.gd b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.gd
new file mode 100644
index 0000000000..95d497c3f3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.gd
@@ -0,0 +1,7 @@
+extends "./non_tool_extends_tool.notest.gd"
+
+class InnerClass extends "./non_tool_extends_tool.notest.gd":
+ pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.notest.gd b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.notest.gd
new file mode 100644
index 0000000000..07427846d1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.notest.gd
@@ -0,0 +1 @@
+@tool
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.out b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.out
new file mode 100644
index 0000000000..f65caf5222
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool.out
@@ -0,0 +1,9 @@
+GDTEST_OK
+>> WARNING
+>> Line: 1
+>> MISSING_TOOL
+>> The base class script has the "@tool" annotation, but this script does not have it.
+>> WARNING
+>> Line: 3
+>> MISSING_TOOL
+>> The base class script has the "@tool" annotation, but this script does not have it.
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool_ignored.gd b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool_ignored.gd
new file mode 100644
index 0000000000..a452307d99
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool_ignored.gd
@@ -0,0 +1,9 @@
+@warning_ignore("missing_tool")
+extends "./non_tool_extends_tool.notest.gd"
+
+@warning_ignore("missing_tool")
+class InnerClass extends "./non_tool_extends_tool.notest.gd":
+ pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool_ignored.out b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool_ignored.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/non_tool_extends_tool_ignored.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.cfg b/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.cfg
new file mode 100644
index 0000000000..be9bd510e1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.cfg
@@ -0,0 +1,5 @@
+[output]
+include=[
+ {"insert_text": "\"property_of_a\""},
+ {"insert_text": "\"name\""},
+]
diff --git a/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.gd b/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.gd
new file mode 100644
index 0000000000..a8e04a62a7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/argument_options/string_literals/argument_options_inside_string_literal.gd
@@ -0,0 +1,8 @@
+extends Node
+
+const A = preload ("res://completion/class_a.notest.gd")
+
+func _ready() -> void:
+ var a := A.new()
+ var tween := get_tree().create_tween()
+ tween.tween_property(a, "➡")
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg
index 871a404e3a..5f08f9c265 100644
--- a/modules/gdscript/tests/scripts/completion/common/identifiers.cfg
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.cfg
@@ -11,11 +11,15 @@ include=[
{"display": "func_of_a"},
{"display": "signal_of_a"},
- ; GDScript: self.gd
+ ; GDScript: identifiers.gd
{"display": "test_signal_1"},
{"display": "test_signal_2"},
{"display": "test_var_1"},
{"display": "test_var_2"},
{"display": "test_func_1"},
{"display": "test_func_2"},
+ {"display": "test_parameter_1"},
+ {"display": "test_parameter_2"},
+ {"display": "local_test_var_1"},
+ {"display": "local_test_var_2"},
]
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.gd b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.gd
new file mode 100644
index 0000000000..91488c25aa
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_call.gd
@@ -0,0 +1,18 @@
+extends "res://completion/class_a.notest.gd"
+
+signal test_signal_1(a)
+signal test_signal_2(a: int)
+
+var test_var_1
+var test_var_2: int
+
+func test_func_1(t):
+ pass
+
+func test_func_2(t: int) -> void:
+ pass
+
+func _init(test_parameter_1, test_parameter_2: String):
+ var local_test_var_1
+ var local_test_var_2: int
+ print(t➡)
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg
new file mode 100644
index 0000000000..5f08f9c265
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.cfg
@@ -0,0 +1,25 @@
+scene="res://completion/get_node/get_node.tscn"
+[output]
+include=[
+ ; Node
+ {"display": "add_child"},
+ {"display": "owner"},
+ {"display": "child_entered_tree"},
+
+ ; GDScript: class_a.notest.gd
+ {"display": "property_of_a"},
+ {"display": "func_of_a"},
+ {"display": "signal_of_a"},
+
+ ; GDScript: identifiers.gd
+ {"display": "test_signal_1"},
+ {"display": "test_signal_2"},
+ {"display": "test_var_1"},
+ {"display": "test_var_2"},
+ {"display": "test_func_1"},
+ {"display": "test_func_2"},
+ {"display": "test_parameter_1"},
+ {"display": "test_parameter_2"},
+ {"display": "local_test_var_1"},
+ {"display": "local_test_var_2"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers.gd b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.gd
index efbafbee8e..a2f5b7bc23 100644
--- a/modules/gdscript/tests/scripts/completion/common/identifiers.gd
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_function_body.gd
@@ -12,5 +12,7 @@ func test_func_1(t):
func test_func_2(t: int) -> void:
pass
-func _init():
+func _init(test_parameter_1, test_parameter_2: String):
+ var local_test_var_1
+ var local_test_var_2: int
t➡
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg
new file mode 100644
index 0000000000..5f08f9c265
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.cfg
@@ -0,0 +1,25 @@
+scene="res://completion/get_node/get_node.tscn"
+[output]
+include=[
+ ; Node
+ {"display": "add_child"},
+ {"display": "owner"},
+ {"display": "child_entered_tree"},
+
+ ; GDScript: class_a.notest.gd
+ {"display": "property_of_a"},
+ {"display": "func_of_a"},
+ {"display": "signal_of_a"},
+
+ ; GDScript: identifiers.gd
+ {"display": "test_signal_1"},
+ {"display": "test_signal_2"},
+ {"display": "test_var_1"},
+ {"display": "test_var_2"},
+ {"display": "test_func_1"},
+ {"display": "test_func_2"},
+ {"display": "test_parameter_1"},
+ {"display": "test_parameter_2"},
+ {"display": "local_test_var_1"},
+ {"display": "local_test_var_2"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.gd b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.gd
new file mode 100644
index 0000000000..fed0b869c4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/identifiers_in_unclosed_call.gd
@@ -0,0 +1,22 @@
+# godotengine/godot#92226
+extends "res://completion/class_a.notest.gd"
+
+signal test_signal_1(a)
+signal test_signal_2(a: int)
+
+var test_var_1
+var test_var_2: int
+
+func test_func_1(t):
+ pass
+
+func test_func_2(t: int) -> void:
+ pass
+
+func _init(test_parameter_1, test_parameter_2: String):
+ var local_test_var_1
+ var local_test_var_2: int
+ print(t➡
+
+ if true:
+ pass
diff --git a/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg
new file mode 100644
index 0000000000..462846c9b2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.cfg
@@ -0,0 +1,26 @@
+scene="res://completion/get_node/get_node.tscn"
+[output]
+exclude=[
+ ; Node
+ {"display": "add_child"},
+ {"display": "owner"},
+ {"display": "child_entered_tree"},
+ {"display": "add_child"},
+
+ ; GDScript: class_a.notest.gd
+ {"display": "property_of_a"},
+ {"display": "func_of_a"},
+ {"display": "signal_of_a"},
+
+ ; GDScript: no_completion_in_string.gd
+ {"display": "test_signal_1"},
+ {"display": "test_signal_2"},
+ {"display": "test_var_1"},
+ {"display": "test_var_2"},
+ {"display": "test_func_1"},
+ {"display": "test_func_2"},
+ {"display": "test_parameter_1"},
+ {"display": "test_parameter_2"},
+ {"display": "local_test_var_1"},
+ {"display": "local_test_var_2"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.gd b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.gd
new file mode 100644
index 0000000000..da52af9fe3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/common/no_completion_in_string.gd
@@ -0,0 +1,19 @@
+# godotengine/godot#62945
+extends "res://completion/class_a.notest.gd"
+
+signal test_signal_1(a)
+signal test_signal_2(a: int)
+
+var test_var_1
+var test_var_2: int
+
+func test_func_1(t):
+ pass
+
+func test_func_2(t: int) -> void:
+ pass
+
+func _init(test_parameter_1, test_parameter_2: String):
+ var local_test_var_1
+ var local_test_var_2: int
+ var a = "➡"
diff --git a/modules/gdscript/tests/scripts/completion/common/self.gd b/modules/gdscript/tests/scripts/completion/common/self.gd
index 9ad2fbea51..ed181af0c5 100644
--- a/modules/gdscript/tests/scripts/completion/common/self.gd
+++ b/modules/gdscript/tests/scripts/completion/common/self.gd
@@ -14,3 +14,4 @@ func test_func_2(t: int) -> void:
func _init():
self.➡
+ pass
diff --git a/modules/gdscript/tests/scripts/completion/filter/organized_export.gd b/modules/gdscript/tests/scripts/completion/filter/organized_export.gd
index 189608904c..9fa9618cee 100644
--- a/modules/gdscript/tests/scripts/completion/filter/organized_export.gd
+++ b/modules/gdscript/tests/scripts/completion/filter/organized_export.gd
@@ -5,4 +5,5 @@ extends CPUParticles2D
@export_subgroup("Test Subgroup")
func _init():
- ➡
+ t➡
+ pass
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg
index ae7d34d87d..ae7d34d87d 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.gd b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.gd
index 7710c2d13b..7710c2d13b 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered/local_interfered.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered/local_infered.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg
index 9c580b711d..9c580b711d 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.gd b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.gd
index 6b29bf5526..6b29bf5526 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/class_local_interfered_scene.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/class_local_infered_scene.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg
index 446198dd35..446198dd35 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.gd b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.gd
index 7710c2d13b..7710c2d13b 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/local_interfered_scene/native_local_interfered_scene.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/local_infered_scene/native_local_infered_scene.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg
index ae7d34d87d..ae7d34d87d 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.gd b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.gd
index 97b288334e..97b288334e 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered/member_interfered.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered/member_infered.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg
index 9c580b711d..9c580b711d 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.gd b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.gd
index 402fd1d275..402fd1d275 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/class_member_interfered_scene.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/class_member_infered_scene.gd
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.cfg b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg
index 446198dd35..446198dd35 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.cfg
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.cfg
diff --git a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.gd b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.gd
index 97b288334e..97b288334e 100644
--- a/modules/gdscript/tests/scripts/completion/get_node/member_interfered_scene/native_member_interfered_scene.gd
+++ b/modules/gdscript/tests/scripts/completion/get_node/member_infered_scene/native_member_infered_scene.gd
diff --git a/modules/gdscript/tests/scripts/completion/index/array_type.cfg b/modules/gdscript/tests/scripts/completion/index/array_type.cfg
new file mode 100644
index 0000000000..5cd5565d00
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/array_type.cfg
@@ -0,0 +1,9 @@
+[output]
+include=[
+ {"display": "outer"},
+ {"display": "inner"},
+]
+exclude=[
+ {"display": "append"},
+ {"display": "\"append\""},
+]
diff --git a/modules/gdscript/tests/scripts/completion/index/array_type.gd b/modules/gdscript/tests/scripts/completion/index/array_type.gd
new file mode 100644
index 0000000000..e0a15da556
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/array_type.gd
@@ -0,0 +1,10 @@
+extends Node
+
+var outer
+
+func _ready() -> void:
+ var inner
+
+ var array: Array
+
+ array[i➡]
diff --git a/modules/gdscript/tests/scripts/completion/index/array_value.cfg b/modules/gdscript/tests/scripts/completion/index/array_value.cfg
new file mode 100644
index 0000000000..5cd5565d00
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/array_value.cfg
@@ -0,0 +1,9 @@
+[output]
+include=[
+ {"display": "outer"},
+ {"display": "inner"},
+]
+exclude=[
+ {"display": "append"},
+ {"display": "\"append\""},
+]
diff --git a/modules/gdscript/tests/scripts/completion/index/array_value.gd b/modules/gdscript/tests/scripts/completion/index/array_value.gd
new file mode 100644
index 0000000000..17451725bc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/array_value.gd
@@ -0,0 +1,10 @@
+extends Node
+
+var outer
+
+func _ready() -> void:
+ var inner
+
+ var array = []
+
+ array[i➡]
diff --git a/modules/gdscript/tests/scripts/completion/index/const_dictionary_keys.cfg b/modules/gdscript/tests/scripts/completion/index/const_dictionary_keys.cfg
new file mode 100644
index 0000000000..ecea284b5d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/const_dictionary_keys.cfg
@@ -0,0 +1,11 @@
+[output]
+include=[
+ {"display": "\"key1\""},
+ {"display": "\"key2\""},
+]
+exclude=[
+ {"display": "keys"},
+ {"display": "\"keys\""},
+ {"display": "key1"},
+ {"display": "key2"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/index/const_dictionary_keys.gd b/modules/gdscript/tests/scripts/completion/index/const_dictionary_keys.gd
new file mode 100644
index 0000000000..06498c57a6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/const_dictionary_keys.gd
@@ -0,0 +1,13 @@
+extends Node
+
+var outer
+
+const dict = {
+ "key1": "value",
+ "key2": null,
+}
+
+func _ready() -> void:
+ var inner
+
+ dict["➡"]
diff --git a/modules/gdscript/tests/scripts/completion/index/dictionary_type.cfg b/modules/gdscript/tests/scripts/completion/index/dictionary_type.cfg
new file mode 100644
index 0000000000..cddf7b8cc8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/dictionary_type.cfg
@@ -0,0 +1,9 @@
+[output]
+include=[
+ {"display": "outer"},
+ {"display": "inner"},
+]
+exclude=[
+ {"display": "keys"},
+ {"display": "\"keys\""},
+]
diff --git a/modules/gdscript/tests/scripts/completion/index/dictionary_type.gd b/modules/gdscript/tests/scripts/completion/index/dictionary_type.gd
new file mode 100644
index 0000000000..b02c62eea5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/dictionary_type.gd
@@ -0,0 +1,10 @@
+extends Node
+
+var outer
+
+func _ready() -> void:
+ var inner
+
+ var dict: Dictionary
+
+ dict[i➡]
diff --git a/modules/gdscript/tests/scripts/completion/index/dictionary_value.cfg b/modules/gdscript/tests/scripts/completion/index/dictionary_value.cfg
new file mode 100644
index 0000000000..cddf7b8cc8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/dictionary_value.cfg
@@ -0,0 +1,9 @@
+[output]
+include=[
+ {"display": "outer"},
+ {"display": "inner"},
+]
+exclude=[
+ {"display": "keys"},
+ {"display": "\"keys\""},
+]
diff --git a/modules/gdscript/tests/scripts/completion/index/dictionary_value.gd b/modules/gdscript/tests/scripts/completion/index/dictionary_value.gd
new file mode 100644
index 0000000000..60bf391716
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/dictionary_value.gd
@@ -0,0 +1,10 @@
+extends Node
+
+var outer
+
+func _ready() -> void:
+ var inner
+
+ var dict = {}
+
+ dict[i➡]
diff --git a/modules/gdscript/tests/scripts/completion/index/local_dictionary_keys.cfg b/modules/gdscript/tests/scripts/completion/index/local_dictionary_keys.cfg
new file mode 100644
index 0000000000..ecea284b5d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/local_dictionary_keys.cfg
@@ -0,0 +1,11 @@
+[output]
+include=[
+ {"display": "\"key1\""},
+ {"display": "\"key2\""},
+]
+exclude=[
+ {"display": "keys"},
+ {"display": "\"keys\""},
+ {"display": "key1"},
+ {"display": "key2"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/index/local_dictionary_keys.gd b/modules/gdscript/tests/scripts/completion/index/local_dictionary_keys.gd
new file mode 100644
index 0000000000..2220cdcc59
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/local_dictionary_keys.gd
@@ -0,0 +1,13 @@
+extends Node
+
+var outer
+
+func _ready() -> void:
+ var inner
+
+ var dict: Dictionary = {
+ "key1": "value",
+ "key2": null,
+ }
+
+ dict["➡"]
diff --git a/modules/gdscript/tests/scripts/completion/index/property_dictionary_keys.cfg b/modules/gdscript/tests/scripts/completion/index/property_dictionary_keys.cfg
new file mode 100644
index 0000000000..8da525bff8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/property_dictionary_keys.cfg
@@ -0,0 +1,9 @@
+[output]
+exclude=[
+ {"display": "keys"},
+ {"display": "\"keys\""},
+ {"display": "key1"},
+ {"display": "key2"},
+ {"display": "\"key1\""},
+ {"display": "\"key2\""},
+]
diff --git a/modules/gdscript/tests/scripts/completion/index/property_dictionary_keys.gd b/modules/gdscript/tests/scripts/completion/index/property_dictionary_keys.gd
new file mode 100644
index 0000000000..ba8d7f76fd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/property_dictionary_keys.gd
@@ -0,0 +1,13 @@
+extends Node
+
+var outer
+
+var dict = {
+ "key1": "value",
+ "key2": null,
+}
+
+func _ready() -> void:
+ var inner
+
+ dict["➡"]
diff --git a/modules/gdscript/tests/scripts/completion/index/untyped_local.cfg b/modules/gdscript/tests/scripts/completion/index/untyped_local.cfg
new file mode 100644
index 0000000000..1173043f94
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/untyped_local.cfg
@@ -0,0 +1,5 @@
+[output]
+include=[
+ {"display": "outer"},
+ {"display": "inner"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/index/untyped_local.gd b/modules/gdscript/tests/scripts/completion/index/untyped_local.gd
new file mode 100644
index 0000000000..1a1157af02
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/untyped_local.gd
@@ -0,0 +1,10 @@
+extends Node
+
+var outer
+
+func _ready() -> void:
+ var inner
+
+ var array
+
+ array[i➡]
diff --git a/modules/gdscript/tests/scripts/completion/index/untyped_property.cfg b/modules/gdscript/tests/scripts/completion/index/untyped_property.cfg
new file mode 100644
index 0000000000..1173043f94
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/untyped_property.cfg
@@ -0,0 +1,5 @@
+[output]
+include=[
+ {"display": "outer"},
+ {"display": "inner"},
+]
diff --git a/modules/gdscript/tests/scripts/completion/index/untyped_property.gd b/modules/gdscript/tests/scripts/completion/index/untyped_property.gd
new file mode 100644
index 0000000000..9fa23da504
--- /dev/null
+++ b/modules/gdscript/tests/scripts/completion/index/untyped_property.gd
@@ -0,0 +1,9 @@
+extends Node
+
+var outer
+var array
+
+func _ready() -> void:
+ var inner
+
+ array[i➡]
diff --git a/modules/gdscript/tests/scripts/completion/types/local/interfered.cfg b/modules/gdscript/tests/scripts/completion/types/local/infered.cfg
index 8b68d51a89..8b68d51a89 100644
--- a/modules/gdscript/tests/scripts/completion/types/local/interfered.cfg
+++ b/modules/gdscript/tests/scripts/completion/types/local/infered.cfg
diff --git a/modules/gdscript/tests/scripts/completion/types/local/interfered.gd b/modules/gdscript/tests/scripts/completion/types/local/infered.gd
index f003c366a4..f003c366a4 100644
--- a/modules/gdscript/tests/scripts/completion/types/local/interfered.gd
+++ b/modules/gdscript/tests/scripts/completion/types/local/infered.gd
diff --git a/modules/gdscript/tests/scripts/completion/types/member/interfered.cfg b/modules/gdscript/tests/scripts/completion/types/member/infered.cfg
index 8b68d51a89..8b68d51a89 100644
--- a/modules/gdscript/tests/scripts/completion/types/member/interfered.cfg
+++ b/modules/gdscript/tests/scripts/completion/types/member/infered.cfg
diff --git a/modules/gdscript/tests/scripts/completion/types/member/interfered.gd b/modules/gdscript/tests/scripts/completion/types/member/infered.gd
index 069abd7891..069abd7891 100644
--- a/modules/gdscript/tests/scripts/completion/types/member/interfered.gd
+++ b/modules/gdscript/tests/scripts/completion/types/member/infered.gd
diff --git a/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.gd b/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.gd
new file mode 100644
index 0000000000..3724c8c713
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.gd
@@ -0,0 +1,9 @@
+# https://github.com/godotengine/godot/issues/90086
+
+class MyObj:
+ var obj: WeakRef
+
+func test():
+ var obj_1 = MyObj.new()
+ var obj_2 = MyObj.new()
+ obj_1.obj = obj_2
diff --git a/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.out b/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.out
new file mode 100644
index 0000000000..dfca5b1eca
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/invalid_property_assignment.gd
+>> 9
+>> Invalid assignment of property or key 'obj' with value of type 'RefCounted (MyObj)' on a base object of type 'RefCounted (MyObj)'.
diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_wrong_to_typed.out b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_wrong_to_typed.out
index 7b9f1066b0..9b38957101 100644
--- a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_wrong_to_typed.out
+++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_wrong_to_typed.out
@@ -1,4 +1,5 @@
GDTEST_RUNTIME_ERROR
>> ERROR
>> Method/function failed.
+>> Unable to convert array index 0 from "Object" to "Object".
not ok
diff --git a/modules/gdscript/tests/scripts/runtime/features/lambda_bind_argument_count.gd b/modules/gdscript/tests/scripts/runtime/features/lambda_bind_argument_count.gd
new file mode 100644
index 0000000000..67225cad6a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/lambda_bind_argument_count.gd
@@ -0,0 +1,18 @@
+# https://github.com/godotengine/godot/issues/93952
+
+func foo():
+ pass
+
+func test():
+ var a: int
+
+ var lambda_self := func (x: int) -> void:
+ foo()
+ print(a, x)
+
+ print(lambda_self.get_argument_count()) # Should print 1.
+
+ var lambda_non_self := func (x: int) -> void:
+ print(a, x)
+
+ print(lambda_non_self.get_argument_count()) # Should print 1.
diff --git a/modules/gdscript/tests/scripts/runtime/features/lambda_bind_argument_count.out b/modules/gdscript/tests/scripts/runtime/features/lambda_bind_argument_count.out
new file mode 100644
index 0000000000..04b4638adf
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/lambda_bind_argument_count.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+1
+1
diff --git a/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.gd b/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.gd
new file mode 100644
index 0000000000..160e43a797
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.gd
@@ -0,0 +1,21 @@
+# https://github.com/godotengine/godot/issues/94074
+
+func foo():
+ pass
+
+func test():
+ var lambda_self := func test() -> void:
+ foo()
+ var anon_lambda_self := func() -> void:
+ foo()
+
+ print(lambda_self.get_method()) # Should print "test".
+ print(anon_lambda_self.get_method()) # Should print "<anonymous lambda>".
+
+ var lambda_non_self := func test() -> void:
+ pass
+ var anon_lambda_non_self := func() -> void:
+ pass
+
+ print(lambda_non_self.get_method()) # Should print "test".
+ print(anon_lambda_non_self.get_method()) # Should print "<anonymous lambda>".
diff --git a/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.out b/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.out
new file mode 100644
index 0000000000..17ee47fca2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/lambda_get_method.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+test
+<anonymous lambda>
+test
+<anonymous lambda>
diff --git a/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd b/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd
index c774ebf83c..df639a7b4d 100644
--- a/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd
@@ -1,6 +1,5 @@
# GH-77666
-
-func test():
+func test_exit_if():
var ref := RefCounted.new()
print(ref.get_reference_count())
@@ -8,3 +7,20 @@ func test():
var _temp := ref
print(ref.get_reference_count())
+
+# GH-94654
+func test_exit_while():
+ var slots_data := []
+
+ while true:
+ @warning_ignore("confusable_local_declaration")
+ var slot = 42
+ slots_data.append(slot)
+ break
+
+ var slot: int = slots_data[0]
+ print(slot)
+
+func test():
+ test_exit_if()
+ test_exit_while()
diff --git a/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out b/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out
index 04b4638adf..164eb24963 100644
--- a/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out
+++ b/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out
@@ -1,3 +1,4 @@
GDTEST_OK
1
1
+42
diff --git a/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.gd b/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.gd
new file mode 100644
index 0000000000..e1aba83507
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.gd
@@ -0,0 +1,11 @@
+# https://github.com/godotengine/godot/issues/90086
+
+class MyObj:
+ var obj : WeakRef
+
+func test():
+ var obj_1 = MyObj.new()
+ var obj_2 = MyObj.new()
+ assert(obj_2.get_reference_count() == 1)
+ obj_1.set(&"obj", obj_2)
+ assert(obj_2.get_reference_count() == 1)
diff --git a/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.out b/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.gd b/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.gd
new file mode 100644
index 0000000000..f70b521e1a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.gd
@@ -0,0 +1,62 @@
+# GH-94667
+
+class Inner:
+ var subprop: Vector2:
+ set(value):
+ prints("subprop setter", value)
+ subprop = value
+ get:
+ print("subprop getter")
+ return subprop
+
+ func _to_string() -> String:
+ return "<Inner>"
+
+var prop1:
+ set(value):
+ prints("prop1 setter", value)
+ prop1 = value
+
+var prop2: Inner:
+ set(value):
+ prints("prop2 setter", value)
+ prop2 = value
+
+var prop3:
+ set(value):
+ prints("prop3 setter", value)
+ prop3 = value
+ get:
+ print("prop3 getter")
+ return prop3
+
+var prop4: Inner:
+ set(value):
+ prints("prop4 setter", value)
+ prop4 = value
+ get:
+ print("prop4 getter")
+ return prop4
+
+func test():
+ print("===")
+ prop1 = Vector2()
+ prop1.x = 1.0
+ print("---")
+ prop1 = Inner.new()
+ prop1.subprop.x = 1.0
+
+ print("===")
+ prop2 = Inner.new()
+ prop2.subprop.x = 1.0
+
+ print("===")
+ prop3 = Vector2()
+ prop3.x = 1.0
+ print("---")
+ prop3 = Inner.new()
+ prop3.subprop.x = 1.0
+
+ print("===")
+ prop4 = Inner.new()
+ prop4.subprop.x = 1.0
diff --git a/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.out b/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.out
new file mode 100644
index 0000000000..c51759f481
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/setter_chain_shared_types.out
@@ -0,0 +1,26 @@
+GDTEST_OK
+===
+prop1 setter (0, 0)
+prop1 setter (1, 0)
+---
+prop1 setter <Inner>
+subprop getter
+subprop setter (1, 0)
+===
+prop2 setter <Inner>
+subprop getter
+subprop setter (1, 0)
+===
+prop3 setter (0, 0)
+prop3 getter
+prop3 setter (1, 0)
+---
+prop3 setter <Inner>
+prop3 getter
+subprop getter
+subprop setter (1, 0)
+===
+prop4 setter <Inner>
+prop4 getter
+subprop getter
+subprop setter (1, 0)
diff --git a/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.gd b/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.gd
new file mode 100644
index 0000000000..9e27a500bf
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.gd
@@ -0,0 +1,13 @@
+# https://github.com/godotengine/godot/issues/85952
+
+var vec: Vector2 = Vector2.ZERO:
+ set(new_vec):
+ prints("setting vec from", vec, "to", new_vec)
+ if new_vec == Vector2(1, 1):
+ vec = new_vec
+
+func test():
+ vec.x = 2
+ vec.y = 2
+
+ prints("vec is", vec)
diff --git a/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.out b/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.out
new file mode 100644
index 0000000000..31b3b3a3a8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/simple_setter_chain_call_setter.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+setting vec from (0, 0) to (2, 0)
+setting vec from (0, 0) to (0, 2)
+vec is (0, 0)
diff --git a/modules/gdscript/tests/scripts/runtime/features/single_underscore_node_name.gd b/modules/gdscript/tests/scripts/runtime/features/single_underscore_node_name.gd
new file mode 100644
index 0000000000..b07c40b6da
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/single_underscore_node_name.gd
@@ -0,0 +1,15 @@
+extends Node
+
+func test() -> void:
+ var node1 := Node.new()
+ node1.name = "_"
+ var node2 := Node.new()
+ node2.name = "Child"
+ var node3 := Node.new()
+ node3.name = "Child"
+
+ add_child(node1)
+ node1.add_child(node2)
+ add_child(node3)
+
+ assert(get_node("_/Child") == $_/Child)
diff --git a/modules/gdscript/tests/scripts/runtime/features/single_underscore_node_name.out b/modules/gdscript/tests/scripts/runtime/features/single_underscore_node_name.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/single_underscore_node_name.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_array_implicit_cast_param.gd b/modules/gdscript/tests/scripts/runtime/features/typed_array_implicit_cast_param.gd
new file mode 100644
index 0000000000..13f2c3b956
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/typed_array_implicit_cast_param.gd
@@ -0,0 +1,7 @@
+# GH-93990
+
+func test_param(array: Array[String]) -> void:
+ print(array.get_typed_builtin() == TYPE_STRING)
+
+func test() -> void:
+ test_param(PackedStringArray())
diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_array_implicit_cast_param.out b/modules/gdscript/tests/scripts/runtime/features/typed_array_implicit_cast_param.out
new file mode 100644
index 0000000000..55482c2b52
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/typed_array_implicit_cast_param.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+true