summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/tests/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/tests/scripts')
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/call_not_existing_static_method.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/call_not_existing_static_method.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/engine_singleton_instantiate.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/engine_singleton_instantiate.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/extend_engine_singleton.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/extend_engine_singleton.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_array.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_array.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_1.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_1.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_2.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_2.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_3.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_3.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_1.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_1.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_2.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_2.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_3.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_3.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_4.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_4.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_in_static_function.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_in_static_function.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_call_arg.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_call_arg.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_param.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_param.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_before_declared.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_before_declared.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_const.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_const.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_type.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_guard_invalid_expression.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_guard_invalid_expression.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/object_invalid_constructor.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/object_invalid_constructor.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd17
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out11
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/function_param_type_contravariance.gd20
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/function_param_type_contravariance.out1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/function_return_type_covariance.gd32
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/function_return_type_covariance.out1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/hard_variants.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_class_access_from_inside.gd21
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_class_access_from_inside.out5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lambda_cyclic_ref_body.gd34
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lambda_cyclic_ref_body.out5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.gd41
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.notest.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.out11
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/null_initializer.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/typed_array_dont_make_literal_typed_with_weak_type.gd22
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/typed_array_dont_make_literal_typed_with_weak_type.out7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.gd21
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.out3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out22
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/unsafe_call_argument.gd37
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/unsafe_call_argument.out33
-rw-r--r--modules/gdscript/tests/scripts/lsp/class.notest.gd132
-rw-r--r--modules/gdscript/tests/scripts/lsp/enums.notest.gd26
-rw-r--r--modules/gdscript/tests/scripts/lsp/indentation.notest.gd28
-rw-r--r--modules/gdscript/tests/scripts/lsp/lambdas.notest.gd91
-rw-r--r--modules/gdscript/tests/scripts/lsp/local_variables.notest.gd25
-rw-r--r--modules/gdscript/tests/scripts/lsp/properties.notest.gd65
-rw-r--r--modules/gdscript/tests/scripts/lsp/scopes.notest.gd106
-rw-r--r--modules/gdscript/tests/scripts/lsp/shadowing_initializer.notest.gd56
-rw-r--r--modules/gdscript/tests/scripts/parser/.editorconfig2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/bad_r_string_1.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/bad_r_string_1.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/bad_r_string_2.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/bad_r_string_2.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/bad_r_string_3.gd3
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/bad_r_string_3.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/match_guard_with_assignment.gd5
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/match_guard_with_assignment.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.gd4
-rw-r--r--modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.out1
-rw-r--r--modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd5
-rw-r--r--modules/gdscript/tests/scripts/parser/features/dollar_node_paths.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/lambda_ends_with_new_line.gd1
-rw-r--r--modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines.gd20
-rw-r--r--modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines.out4
-rw-r--r--modules/gdscript/tests/scripts/parser/features/nested_function_calls.gd1
-rw-r--r--modules/gdscript/tests/scripts/parser/features/r_strings.gd22
-rw-r--r--modules/gdscript/tests/scripts/parser/features/r_strings.out22
-rw-r--r--modules/gdscript/tests/scripts/parser/features/super.gd1
-rw-r--r--modules/gdscript/tests/scripts/parser/features/unicode_identifiers.gd1
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/for_loop_iterator_type_not_match_specified.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/for_loop_iterator_type_not_match_specified.out6
-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
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_specified_types.gd40
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_specified_types.out29
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/match_with_pattern_guards.gd71
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/match_with_pattern_guards.out10
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/member_info.gd72
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/member_info.out45
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd45
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.out24
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/metatypes.gd36
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/metatypes.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/metatypes.out13
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/object_constructor.gd6
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/object_constructor.out2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/static_variables.gd1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/stringify.gd3
-rw-r--r--modules/gdscript/tests/scripts/utils.notest.gd281
117 files changed, 1878 insertions, 12 deletions
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/call_not_existing_static_method.gd b/modules/gdscript/tests/scripts/analyzer/errors/call_not_existing_static_method.gd
new file mode 100644
index 0000000000..87d1b9ea18
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/call_not_existing_static_method.gd
@@ -0,0 +1,7 @@
+# GH-73283
+
+class MyClass:
+ pass
+
+func test():
+ MyClass.not_existing_method()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/call_not_existing_static_method.out b/modules/gdscript/tests/scripts/analyzer/errors/call_not_existing_static_method.out
new file mode 100644
index 0000000000..7340058dd4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/call_not_existing_static_method.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Static function "not_existing_method()" not found in base "MyClass".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/engine_singleton_instantiate.gd b/modules/gdscript/tests/scripts/analyzer/errors/engine_singleton_instantiate.gd
new file mode 100644
index 0000000000..7e1efb8d1b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/engine_singleton_instantiate.gd
@@ -0,0 +1,2 @@
+func test():
+ Time.new()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/engine_singleton_instantiate.out b/modules/gdscript/tests/scripts/analyzer/errors/engine_singleton_instantiate.out
new file mode 100644
index 0000000000..bc4875d908
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/engine_singleton_instantiate.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot construct native class "Time" because it is an engine singleton.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/extend_engine_singleton.gd b/modules/gdscript/tests/scripts/analyzer/errors/extend_engine_singleton.gd
new file mode 100644
index 0000000000..a46b6d8658
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/extend_engine_singleton.gd
@@ -0,0 +1,6 @@
+# GH-82081
+
+extends Time
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/extend_engine_singleton.out b/modules/gdscript/tests/scripts/analyzer/errors/extend_engine_singleton.out
new file mode 100644
index 0000000000..7c26dea56e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/extend_engine_singleton.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot inherit native class "Time" because it is an engine singleton.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type.gd
new file mode 100644
index 0000000000..7e3b6e3c39
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type.gd
@@ -0,0 +1,4 @@
+func test():
+ var a: Array[Resource] = []
+ for node: Node in a:
+ print(node)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type.out
new file mode 100644
index 0000000000..8f8a368f9a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Unable to iterate on value of type "Array[Resource]" with variable of type "Node".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_array.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_array.gd
new file mode 100644
index 0000000000..db3f3f4c72
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_array.gd
@@ -0,0 +1,5 @@
+# GH-82021
+
+func test():
+ for x: String in [1, 2, 3]:
+ print(x)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_array.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_array.out
new file mode 100644
index 0000000000..0bb654e7e2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_array.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot include a value of type "int" as "String".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_1.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_1.gd
new file mode 100644
index 0000000000..fdf22f6843
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_1.gd
@@ -0,0 +1,10 @@
+class A:
+ func f(_p: Object):
+ pass
+
+class B extends A:
+ func f(_p: Node):
+ pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_1.out b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_1.out
new file mode 100644
index 0000000000..c6a7e40e8c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_1.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The function signature doesn't match the parent. Parent signature is "f(Object) -> Variant".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_2.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_2.gd
new file mode 100644
index 0000000000..e4094f1d76
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_2.gd
@@ -0,0 +1,10 @@
+class A:
+ func f(_p: Variant):
+ pass
+
+class B extends A:
+ func f(_p: Node): # No `is_type_compatible()` misuse.
+ pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_2.out b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_2.out
new file mode 100644
index 0000000000..52a6efc6fc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_2.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The function signature doesn't match the parent. Parent signature is "f(Variant) -> Variant".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_3.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_3.gd
new file mode 100644
index 0000000000..17663da4f6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_3.gd
@@ -0,0 +1,10 @@
+class A:
+ func f(_p: int):
+ pass
+
+class B extends A:
+ func f(_p: float): # No implicit conversion.
+ pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_3.out b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_3.out
new file mode 100644
index 0000000000..7a6207fd45
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_param_type_invalid_contravariance_3.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The function signature doesn't match the parent. Parent signature is "f(int) -> Variant".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_1.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_1.gd
new file mode 100644
index 0000000000..6dfa75ecbc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_1.gd
@@ -0,0 +1,10 @@
+class A:
+ func f() -> Node:
+ return null
+
+class B extends A:
+ func f() -> Object:
+ return null
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_1.out b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_1.out
new file mode 100644
index 0000000000..e680b2bd77
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_1.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The function signature doesn't match the parent. Parent signature is "f() -> Node".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_2.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_2.gd
new file mode 100644
index 0000000000..366494b94f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_2.gd
@@ -0,0 +1,10 @@
+class A:
+ func f() -> Node:
+ return null
+
+class B extends A:
+ func f() -> Variant: # No `is_type_compatible()` misuse.
+ return null
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_2.out b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_2.out
new file mode 100644
index 0000000000..e680b2bd77
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_2.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The function signature doesn't match the parent. Parent signature is "f() -> Node".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_3.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_3.gd
new file mode 100644
index 0000000000..2cb4e7c616
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_3.gd
@@ -0,0 +1,10 @@
+class A:
+ func f() -> Node:
+ return null
+
+class B extends A:
+ func f() -> void: # No `is_type_compatible()` misuse.
+ return
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_3.out b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_3.out
new file mode 100644
index 0000000000..e680b2bd77
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_3.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The function signature doesn't match the parent. Parent signature is "f() -> Node".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_4.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_4.gd
new file mode 100644
index 0000000000..2cabce46f5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_4.gd
@@ -0,0 +1,10 @@
+class A:
+ func f() -> float:
+ return 0.0
+
+class B extends A:
+ func f() -> int: # No implicit conversion.
+ return 0
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_4.out b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_4.out
new file mode 100644
index 0000000000..72f2c493d4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_return_type_invalid_covariance_4.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The function signature doesn't match the parent. Parent signature is "f() -> float".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_in_static_function.gd b/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_in_static_function.gd
new file mode 100644
index 0000000000..caeea46977
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_in_static_function.gd
@@ -0,0 +1,9 @@
+# GH-75645
+
+extends Node
+
+static func static_func():
+ var a = $Node
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_in_static_function.out b/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_in_static_function.out
new file mode 100644
index 0000000000..1910b3e66b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_in_static_function.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot use shorthand "get_node()" notation ("$") in a static function.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_call_arg.gd b/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_call_arg.gd
new file mode 100644
index 0000000000..4b72fb9daa
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_call_arg.gd
@@ -0,0 +1,5 @@
+var f = (func (_a): return 0).call(x)
+var x = f
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_call_arg.out b/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_call_arg.out
new file mode 100644
index 0000000000..6bca25b330
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_call_arg.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not resolve member "f": Cyclic reference.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_param.gd b/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_param.gd
new file mode 100644
index 0000000000..115e8be50a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_param.gd
@@ -0,0 +1,5 @@
+var f = func (_a = x): return 0
+var x = f
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_param.out b/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_param.out
new file mode 100644
index 0000000000..6bca25b330
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/lambda_cyclic_ref_param.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Could not resolve member "f": Cyclic reference.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_before_declared.gd b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_before_declared.gd
new file mode 100644
index 0000000000..7cdc14685f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_before_declared.gd
@@ -0,0 +1,5 @@
+enum MyEnum {}
+
+func test():
+ var e: E
+ const E = MyEnum
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_before_declared.out b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_before_declared.out
new file mode 100644
index 0000000000..e1d5837f32
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_before_declared.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Local constant "E" is not resolved at this point.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_const.gd b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_const.gd
new file mode 100644
index 0000000000..68cf5efd8b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_const.gd
@@ -0,0 +1,5 @@
+enum MyEnum {}
+
+func test():
+ var E = MyEnum
+ var e: E
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_const.out b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_const.out
new file mode 100644
index 0000000000..b1f4e7a2c8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_const.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Local variable "E" cannot be used as a type.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_type.gd
new file mode 100644
index 0000000000..ac446183cb
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_type.gd
@@ -0,0 +1,5 @@
+enum MyEnum {A}
+
+func test():
+ const E = MyEnum.A
+ var e: E
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_type.out b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_type.out
new file mode 100644
index 0000000000..c3c2c8ca2f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/local_const_as_type_use_not_type.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Local constant "E" is not a valid type.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_guard_invalid_expression.gd b/modules/gdscript/tests/scripts/analyzer/errors/match_guard_invalid_expression.gd
new file mode 100644
index 0000000000..1dcb9fc36a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_guard_invalid_expression.gd
@@ -0,0 +1,4 @@
+func test():
+ match 0:
+ _ when a == 0:
+ print("a does not exist")
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_guard_invalid_expression.out b/modules/gdscript/tests/scripts/analyzer/errors/match_guard_invalid_expression.out
new file mode 100644
index 0000000000..c5f0a90d6a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_guard_invalid_expression.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Identifier "a" not declared in the current scope.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/object_invalid_constructor.gd b/modules/gdscript/tests/scripts/analyzer/errors/object_invalid_constructor.gd
new file mode 100644
index 0000000000..1600c3001f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/object_invalid_constructor.gd
@@ -0,0 +1,4 @@
+# GH-73213
+
+func test():
+ print(Object())
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/object_invalid_constructor.out b/modules/gdscript/tests/scripts/analyzer/errors/object_invalid_constructor.out
new file mode 100644
index 0000000000..27668fcd48
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/object_invalid_constructor.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Invalid constructor "Object()", use "Object.new()" instead.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.gd
index 25cde1d40b..7cc5aaf44f 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.gd
+++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.gd
@@ -1,4 +1,4 @@
func test():
- var unconvertable := 1
- var typed: Array[Object] = [unconvertable]
+ var unconvertible := 1
+ var typed: Array[Object] = [unconvertible]
print('not ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.gd b/modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.gd
new file mode 100644
index 0000000000..57dfffdbee
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.gd
@@ -0,0 +1,5 @@
+func _init():
+ super()
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.out b/modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.out
new file mode 100644
index 0000000000..e68759223c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot call the parent class' virtual function "_init()" because it hasn't been defined.
diff --git a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd
new file mode 100644
index 0000000000..dafd2ec0c8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.gd
@@ -0,0 +1,17 @@
+class_name TestExportEnumAsDictionary
+
+enum MyEnum {A, B, C}
+
+const Utils = preload("../../utils.notest.gd")
+
+@export var x1 = MyEnum
+@export var x2 = MyEnum.A
+@export var x3 := MyEnum
+@export var x4 := MyEnum.A
+@export var x5: MyEnum
+
+func test():
+ for property in get_property_list():
+ if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE:
+ print(Utils.get_property_signature(property))
+ print(" ", Utils.get_property_additional_info(property))
diff --git a/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out
new file mode 100644
index 0000000000..f1a13f1045
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/export_enum_as_dictionary.out
@@ -0,0 +1,11 @@
+GDTEST_OK
+@export var x1: Dictionary
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
+@export var x2: TestExportEnumAsDictionary.MyEnum
+ hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
+@export var x3: Dictionary
+ hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
+@export var x4: TestExportEnumAsDictionary.MyEnum
+ hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
+@export var x5: TestExportEnumAsDictionary.MyEnum
+ hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_param_type_contravariance.gd b/modules/gdscript/tests/scripts/analyzer/features/function_param_type_contravariance.gd
new file mode 100644
index 0000000000..a43c233625
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/function_param_type_contravariance.gd
@@ -0,0 +1,20 @@
+class A:
+ func int_to_variant(_p: int): pass
+ func node_to_variant(_p: Node): pass
+ func node_2d_to_node(_p: Node2D): pass
+
+ func variant_to_untyped(_p: Variant): pass
+ func int_to_untyped(_p: int): pass
+ func node_to_untyped(_p: Node): pass
+
+class B extends A:
+ func int_to_variant(_p: Variant): pass
+ func node_to_variant(_p: Variant): pass
+ func node_2d_to_node(_p: Node): pass
+
+ func variant_to_untyped(_p): pass
+ func int_to_untyped(_p): pass
+ func node_to_untyped(_p): pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_param_type_contravariance.out b/modules/gdscript/tests/scripts/analyzer/features/function_param_type_contravariance.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/function_param_type_contravariance.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_return_type_covariance.gd b/modules/gdscript/tests/scripts/analyzer/features/function_return_type_covariance.gd
new file mode 100644
index 0000000000..4de50b6731
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/function_return_type_covariance.gd
@@ -0,0 +1,32 @@
+class A:
+ func variant_to_int() -> Variant: return 0
+ func variant_to_node() -> Variant: return null
+ func node_to_node_2d() -> Node: return null
+
+ func untyped_to_void(): pass
+ func untyped_to_variant(): pass
+ func untyped_to_int(): pass
+ func untyped_to_node(): pass
+
+ func void_to_untyped() -> void: pass
+ func variant_to_untyped() -> Variant: return null
+ func int_to_untyped() -> int: return 0
+ func node_to_untyped() -> Node: return null
+
+class B extends A:
+ func variant_to_int() -> int: return 0
+ func variant_to_node() -> Node: return null
+ func node_to_node_2d() -> Node2D: return null
+
+ func untyped_to_void() -> void: pass
+ func untyped_to_variant() -> Variant: return null
+ func untyped_to_int() -> int: return 0
+ func untyped_to_node() -> Node: return null
+
+ func void_to_untyped(): pass
+ func variant_to_untyped(): pass
+ func int_to_untyped(): pass
+ func node_to_untyped(): pass
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_return_type_covariance.out b/modules/gdscript/tests/scripts/analyzer/features/function_return_type_covariance.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/function_return_type_covariance.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gdscript/tests/scripts/analyzer/features/hard_variants.gd b/modules/gdscript/tests/scripts/analyzer/features/hard_variants.gd
index b447180ea8..d0f895d784 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/hard_variants.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/hard_variants.gd
@@ -23,6 +23,7 @@ func test() -> void:
typed = variant()
inferred = variant()
+ @warning_ignore("unsafe_call_argument") # TODO: Hard vs Weak vs Unknown.
param_weak(typed)
param_typed(typed)
param_inferred(typed)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_access_from_inside.gd b/modules/gdscript/tests/scripts/analyzer/features/inner_class_access_from_inside.gd
new file mode 100644
index 0000000000..51c589b8e0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_access_from_inside.gd
@@ -0,0 +1,21 @@
+# GH-80508
+
+class A:
+ func a():
+ return A.new()
+ func b():
+ return B.new()
+
+class B:
+ func a():
+ return A.new()
+ func b():
+ return B.new()
+
+func test():
+ var a := A.new()
+ var b := B.new()
+ print(a.a() is A)
+ print(a.b() is B)
+ print(b.a() is A)
+ print(b.b() is B)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_access_from_inside.out b/modules/gdscript/tests/scripts/analyzer/features/inner_class_access_from_inside.out
new file mode 100644
index 0000000000..f9783e4362
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_access_from_inside.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+true
+true
+true
+true
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lambda_cyclic_ref_body.gd b/modules/gdscript/tests/scripts/analyzer/features/lambda_cyclic_ref_body.gd
new file mode 100644
index 0000000000..e2f41a652c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/lambda_cyclic_ref_body.gd
@@ -0,0 +1,34 @@
+# GH-70592
+
+var f: Callable = func ():
+ x = 2
+ return 1
+
+var x: int = f.call()
+
+var g: Array[Callable] = [
+ func ():
+ y += 10
+ return 1,
+ func ():
+ y += 20
+ return 2,
+]
+
+var y: int = g[0].call() + g[1].call()
+
+func test():
+ print(x)
+ f.call()
+ print(x)
+
+ print(y)
+ g[0].call()
+ g[1].call()
+ print(y)
+
+ # This prevents memory leak in CI. TODO: Investigate it.
+ # Also you cannot run the `EditorScript` twice without the cleaning. Error:
+ # Condition "!p_keep_state && has_instances" is true. Returning: ERR_ALREADY_IN_USE
+ f = Callable()
+ g.clear()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lambda_cyclic_ref_body.out b/modules/gdscript/tests/scripts/analyzer/features/lambda_cyclic_ref_body.out
new file mode 100644
index 0000000000..6917fa7c2c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/lambda_cyclic_ref_body.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+1
+2
+3
+33
diff --git a/modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.gd b/modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.gd
new file mode 100644
index 0000000000..90c7f893b1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.gd
@@ -0,0 +1,41 @@
+class InnerClass:
+ enum InnerEnum {A = 2}
+ const INNER_CONST = "INNER_CONST"
+
+enum Enum {A = 1}
+
+const Other = preload("./local_const_as_type.notest.gd")
+
+func test():
+ const IC = InnerClass
+ const IE = IC.InnerEnum
+ const E = Enum
+ # Doesn't work in CI, but works in the editor. Looks like an unrelated bug. TODO: Investigate it.
+ # Error: Invalid call. Nonexistent function 'new' in base 'GDScript'.
+ var a1: IC = null # IC.new()
+ var a2: IE = IE.A
+ var a3: IC.InnerEnum = IE.A
+ var a4: E = E.A
+ print(a1.INNER_CONST)
+ print(a2)
+ print(a3)
+ print(a4)
+
+ const O = Other
+ const OV: Variant = Other # Removes metatype.
+ const OIC = O.InnerClass
+ const OIE = OIC.InnerEnum
+ const OE = O.Enum
+ var b: O = O.new()
+ @warning_ignore("unsafe_method_access")
+ var bv: OV = OV.new()
+ var b1: OIC = OIC.new()
+ var b2: OIE = OIE.A
+ var b3: O.InnerClass.InnerEnum = OIE.A
+ var b4: OE = OE.A
+ print(b.CONST)
+ print(bv.CONST)
+ print(b1.INNER_CONST)
+ print(b2)
+ print(b3)
+ print(b4)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.notest.gd
new file mode 100644
index 0000000000..f16cdc18d8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.notest.gd
@@ -0,0 +1,6 @@
+class InnerClass:
+ enum InnerEnum {A = 20}
+ const INNER_CONST = "OTHER_INNER_CONST"
+
+enum Enum {A = 10}
+const CONST = "OTHER_CONST"
diff --git a/modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.out b/modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.out
new file mode 100644
index 0000000000..b00024de2c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/local_const_as_type.out
@@ -0,0 +1,11 @@
+GDTEST_OK
+INNER_CONST
+2
+2
+1
+OTHER_CONST
+OTHER_CONST
+OTHER_INNER_CONST
+20
+20
+10
diff --git a/modules/gdscript/tests/scripts/analyzer/features/null_initializer.gd b/modules/gdscript/tests/scripts/analyzer/features/null_initializer.gd
index 5a413e2015..08e7dc590e 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/null_initializer.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/null_initializer.gd
@@ -6,10 +6,12 @@ var prop = null
func check_arg(arg = null) -> void:
if arg != null:
+ @warning_ignore("unsafe_call_argument")
print(check(arg))
func check_recur() -> void:
if recur != null:
+ @warning_ignore("unsafe_call_argument")
print(check(recur))
else:
recur = 1
@@ -22,11 +24,13 @@ func test() -> void:
if prop == null:
set('prop', 1)
+ @warning_ignore("unsafe_call_argument")
print(check(prop))
set('prop', null)
var loop = null
while loop != 2:
if loop != null:
+ @warning_ignore("unsafe_call_argument")
print(check(loop))
loop = 1 if loop == null else 2
diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_dont_make_literal_typed_with_weak_type.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_array_dont_make_literal_typed_with_weak_type.gd
new file mode 100644
index 0000000000..e1a1f07e47
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_dont_make_literal_typed_with_weak_type.gd
@@ -0,0 +1,22 @@
+var _typed_array: Array[int]
+
+func weak_param_func(weak_param = _typed_array):
+ weak_param = [11] # Don't treat the literal as typed!
+ return weak_param
+
+func hard_param_func(hard_param := _typed_array):
+ hard_param = [12]
+ return hard_param
+
+func test():
+ var weak_var = _typed_array
+ print(weak_var.is_typed())
+ weak_var = [21] # Don't treat the literal as typed!
+ print(weak_var.is_typed())
+ print(weak_param_func().is_typed())
+
+ var hard_var := _typed_array
+ print(hard_var.is_typed())
+ hard_var = [22]
+ print(hard_var.is_typed())
+ print(hard_param_func().is_typed())
diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_dont_make_literal_typed_with_weak_type.out b/modules/gdscript/tests/scripts/analyzer/features/typed_array_dont_make_literal_typed_with_weak_type.out
new file mode 100644
index 0000000000..34b18dbe7c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_dont_make_literal_typed_with_weak_type.out
@@ -0,0 +1,7 @@
+GDTEST_OK
+true
+false
+false
+true
+true
+true
diff --git a/modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.gd b/modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.gd
new file mode 100644
index 0000000000..a8641e4f3b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.gd
@@ -0,0 +1,21 @@
+class BaseClass:
+ func _get_property_list():
+ return {"property" : "definition"}
+
+class SuperClassMethodsRecognized extends BaseClass:
+ func _init():
+ # Recognizes super class methods.
+ var _x = _get_property_list()
+
+class SuperMethodsRecognized extends BaseClass:
+ func _get_property_list():
+ # Recognizes super method.
+ var result = super()
+ result["new"] = "new"
+ return result
+
+func test():
+ var test1 = SuperClassMethodsRecognized.new()
+ print(test1._get_property_list()) # Calls base class's method.
+ var test2 = SuperMethodsRecognized.new()
+ print(test2._get_property_list())
diff --git a/modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.out b/modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.out
new file mode 100644
index 0000000000..ccff660117
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+{ "property": "definition" }
+{ "property": "definition", "new": "new" }
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.gd b/modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.gd
index 849df0921e..c1776fe1b4 100644
--- a/modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.gd
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.gd
@@ -14,4 +14,5 @@ func test():
func do_add_node():
var node = Node.new()
node.name = "Node"
+ @warning_ignore("unsafe_call_argument")
add_child(node)
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd b/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd
index 29239a19da..939e787ea5 100644
--- a/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.gd
@@ -1,3 +1,5 @@
+class_name ShadowedClass
+
var member: int = 0
var print_debug := 'print_debug'
@@ -12,5 +14,6 @@ func test():
var sqrt := 'sqrt'
var member := 'member'
var reference := 'reference'
+ var ShadowedClass := 'ShadowedClass'
print('warn')
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out b/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out
index accc791d8a..8297eed4b8 100644
--- a/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/shadowning.out
@@ -1,30 +1,34 @@
GDTEST_OK
>> WARNING
->> Line: 3
+>> Line: 5
>> SHADOWED_GLOBAL_IDENTIFIER
>> The variable "print_debug" has the same name as a built-in function.
>> WARNING
->> Line: 9
+>> Line: 11
>> SHADOWED_GLOBAL_IDENTIFIER
>> The variable "Array" has the same name as a built-in type.
>> WARNING
->> Line: 10
+>> Line: 12
>> SHADOWED_GLOBAL_IDENTIFIER
->> The variable "Node" has the same name as a global class.
+>> The variable "Node" has the same name as a native class.
>> WARNING
->> Line: 11
+>> Line: 13
>> SHADOWED_GLOBAL_IDENTIFIER
>> The variable "is_same" has the same name as a built-in function.
>> WARNING
->> Line: 12
+>> Line: 14
>> SHADOWED_GLOBAL_IDENTIFIER
>> The variable "sqrt" has the same name as a built-in function.
>> WARNING
->> Line: 13
+>> Line: 15
>> SHADOWED_VARIABLE
->> The local variable "member" is shadowing an already-declared variable at line 1.
+>> The local variable "member" is shadowing an already-declared variable at line 3.
>> WARNING
->> Line: 14
+>> Line: 16
>> SHADOWED_VARIABLE_BASE_CLASS
>> The local variable "reference" is shadowing an already-declared method at the base class "RefCounted".
+>> WARNING
+>> Line: 17
+>> SHADOWED_GLOBAL_IDENTIFIER
+>> The variable "ShadowedClass" has the same name as a global class defined in "shadowning.gd".
warn
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/unsafe_call_argument.gd b/modules/gdscript/tests/scripts/analyzer/warnings/unsafe_call_argument.gd
new file mode 100644
index 0000000000..573060ae0f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/unsafe_call_argument.gd
@@ -0,0 +1,37 @@
+func variant_func(x: Variant) -> void:
+ print(x)
+
+func int_func(x: int) -> void:
+ print(x)
+
+func float_func(x: float) -> void:
+ print(x)
+
+# We don't want to execute it because of errors, just analyze.
+func no_exec_test():
+ var untyped_int = 42
+ var untyped_string = "abc"
+ var variant_int: Variant = 42
+ var variant_string: Variant = "abc"
+ var typed_int: int = 42
+
+ variant_func(untyped_int) # No warning.
+ variant_func(untyped_string) # No warning.
+ variant_func(variant_int) # No warning.
+ variant_func(variant_string) # No warning.
+ variant_func(typed_int) # No warning.
+
+ int_func(untyped_int)
+ int_func(untyped_string)
+ int_func(variant_int)
+ int_func(variant_string)
+ int_func(typed_int) # No warning.
+
+ float_func(untyped_int)
+ float_func(untyped_string)
+ float_func(variant_int)
+ float_func(variant_string)
+ float_func(typed_int) # No warning.
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/unsafe_call_argument.out b/modules/gdscript/tests/scripts/analyzer/warnings/unsafe_call_argument.out
new file mode 100644
index 0000000000..b8fcb67158
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/unsafe_call_argument.out
@@ -0,0 +1,33 @@
+GDTEST_OK
+>> WARNING
+>> Line: 24
+>> UNSAFE_CALL_ARGUMENT
+>> The argument 1 of the function "int_func()" requires the subtype "int" but the supertype "Variant" was provided.
+>> WARNING
+>> Line: 25
+>> UNSAFE_CALL_ARGUMENT
+>> The argument 1 of the function "int_func()" requires the subtype "int" but the supertype "Variant" was provided.
+>> WARNING
+>> Line: 26
+>> UNSAFE_CALL_ARGUMENT
+>> The argument 1 of the function "int_func()" requires the subtype "int" but the supertype "Variant" was provided.
+>> WARNING
+>> Line: 27
+>> UNSAFE_CALL_ARGUMENT
+>> The argument 1 of the function "int_func()" requires the subtype "int" but the supertype "Variant" was provided.
+>> WARNING
+>> Line: 30
+>> UNSAFE_CALL_ARGUMENT
+>> The argument 1 of the function "float_func()" requires the subtype "float" but the supertype "Variant" was provided.
+>> WARNING
+>> Line: 31
+>> UNSAFE_CALL_ARGUMENT
+>> The argument 1 of the function "float_func()" requires the subtype "float" but the supertype "Variant" was provided.
+>> WARNING
+>> Line: 32
+>> UNSAFE_CALL_ARGUMENT
+>> The argument 1 of the function "float_func()" requires the subtype "float" but the supertype "Variant" was provided.
+>> WARNING
+>> Line: 33
+>> UNSAFE_CALL_ARGUMENT
+>> The argument 1 of the function "float_func()" requires the subtype "float" but the supertype "Variant" was provided.
diff --git a/modules/gdscript/tests/scripts/lsp/class.notest.gd b/modules/gdscript/tests/scripts/lsp/class.notest.gd
new file mode 100644
index 0000000000..53d0b14d72
--- /dev/null
+++ b/modules/gdscript/tests/scripts/lsp/class.notest.gd
@@ -0,0 +1,132 @@
+extends Node
+
+class Inner1 extends Node:
+# ^^^^^^ class1 -> class1
+ var member1 := 42
+ # ^^^^^^^ class1:member1 -> class1:member1
+ var member2 : int = 13
+ # ^^^^^^^ class1:member2 -> class1:member2
+ var member3 = 1337
+ # ^^^^^^^ class1:member3 -> class1:member3
+
+ signal changed(old, new)
+ # ^^^^^^^ class1:signal -> class1:signal
+ func my_func(arg1: int, arg2: String, arg3):
+ # | | | | | | ^^^^ class1:func:arg3 -> class1:func:arg3
+ # | | | | ^^^^ class1:func:arg2 -> class1:func:arg2
+ # | | ^^^^ class1:func:arg1 -> class1:func:arg1
+ # ^^^^^^^ class1:func -> class1:func
+ print(arg1, arg2, arg3)
+ # | | | | ^^^^ -> class1:func:arg3
+ # | | ^^^^ -> class1:func:arg2
+ # ^^^^ -> class1:func:arg1
+ changed.emit(arg1, arg3)
+ # | | | ^^^^ -> class1:func:arg3
+ # | ^^^^ -> class1:func:arg1
+ #<^^^^^ -> class1:signal
+ return arg1 + arg2.length() + arg3
+ # | | | | ^^^^ -> class1:func:arg3
+ # | | ^^^^ -> class1:func:arg2
+ # ^^^^ -> class1:func:arg1
+
+class Inner2:
+# ^^^^^^ class2 -> class2
+ var member1 := 42
+ # ^^^^^^^ class2:member1 -> class2:member1
+ var member2 : int = 13
+ # ^^^^^^^ class2:member2 -> class2:member2
+ var member3 = 1337
+ # ^^^^^^^ class2:member3 -> class2:member3
+
+ signal changed(old, new)
+ # ^^^^^^^ class2:signal -> class2:signal
+ func my_func(arg1: int, arg2: String, arg3):
+ # | | | | | | ^^^^ class2:func:arg3 -> class2:func:arg3
+ # | | | | ^^^^ class2:func:arg2 -> class2:func:arg2
+ # | | ^^^^ class2:func:arg1 -> class2:func:arg1
+ # ^^^^^^^ class2:func -> class2:func
+ print(arg1, arg2, arg3)
+ # | | | | ^^^^ -> class2:func:arg3
+ # | | ^^^^ -> class2:func:arg2
+ # ^^^^ -> class2:func:arg1
+ changed.emit(arg1, arg3)
+ # | | | ^^^^ -> class2:func:arg3
+ # | ^^^^ -> class2:func:arg1
+ #<^^^^^ -> class2:signal
+ return arg1 + arg2.length() + arg3
+ # | | | | ^^^^ -> class2:func:arg3
+ # | | ^^^^ -> class2:func:arg2
+ # ^^^^ -> class2:func:arg1
+
+class Inner3 extends Inner2:
+# | | ^^^^^^ -> class2
+# ^^^^^^ class3 -> class3
+ var whatever = "foo"
+ # ^^^^^^^^ class3:whatever -> class3:whatever
+
+ func _init():
+ # ^^^^^ class3:init
+ # Note: no self-ref check here: resolves to `Object._init`.
+ # usages of `Inner3.new()` DO resolve to this `_init`
+ pass
+
+ class NestedInInner3:
+ # ^^^^^^^^^^^^^^ class3:nested1 -> class3:nested1
+ var some_value := 42
+ # ^^^^^^^^^^ class3:nested1:some_value -> class3:nested1:some_value
+
+ class AnotherNestedInInner3 extends NestedInInner3:
+ #! | | ^^^^^^^^^^^^^^ -> class3:nested1
+ # ^^^^^^^^^^^^^^^^^^^^^ class3:nested2 -> class3:nested2
+ var another_value := 13
+ # ^^^^^^^^^^^^^ class3:nested2:another_value -> class3:nested2:another_value
+
+func _ready():
+ var inner1 = Inner1.new()
+ # | | ^^^^^^ -> class1
+ # ^^^^^^ func:class1 -> func:class1
+ var value1 = inner1.my_func(1,"",3)
+ # | | | | ^^^^^^^ -> class1:func
+ # | | ^^^^^^ -> func:class1
+ # ^^^^^^ func:class1:value1 -> func:class1:value1
+ var value2 = inner1.member3
+ # | | | | ^^^^^^^ -> class1:member3
+ # | | ^^^^^^ -> func:class1
+ # ^^^^^^ func:class1:value2 -> func:class1:value2
+ print(value1, value2)
+ # | | ^^^^^^ -> func:class1:value2
+ # ^^^^^^ -> func:class1:value1
+
+ var inner3 = Inner3.new()
+ # | | | | ^^^ -> class3:init
+ # | | ^^^^^^ -> class3
+ # ^^^^^^ func:class3 -> func:class3
+ print(inner3)
+ # ^^^^^^ -> func:class3
+
+ var nested1 = Inner3.NestedInInner3.new()
+ # | | | | ^^^^^^^^^^^^^^ -> class3:nested1
+ # | | ^^^^^^ -> class3
+ # ^^^^^^^ func:class3:nested1 -> func:class3:nested1
+ var value_nested1 = nested1.some_value
+ # | | | | ^^^^^^^^^^ -> class3:nested1:some_value
+ # | | ^^^^^^^ -> func:class3:nested1
+ # ^^^^^^^^^^^^^ func:class3:nested1:value
+ print(value_nested1)
+ # ^^^^^^^^^^^^^ -> func:class3:nested1:value
+
+ var nested2 = Inner3.AnotherNestedInInner3.new()
+ # | | | | ^^^^^^^^^^^^^^^^^^^^^ -> class3:nested2
+ # | | ^^^^^^ -> class3
+ # ^^^^^^^ func:class3:nested2 -> func:class3:nested2
+ var value_nested2 = nested2.some_value
+ # | | | | ^^^^^^^^^^ -> class3:nested1:some_value
+ # | | ^^^^^^^ -> func:class3:nested2
+ # ^^^^^^^^^^^^^ func:class3:nested2:value
+ var another_value_nested2 = nested2.another_value
+ # | | | | ^^^^^^^^^^^^^ -> class3:nested2:another_value
+ # | | ^^^^^^^ -> func:class3:nested2
+ # ^^^^^^^^^^^^^^^^^^^^^ func:class3:nested2:another_value_nested
+ print(value_nested2, another_value_nested2)
+ # | | ^^^^^^^^^^^^^^^^^^^^^ -> func:class3:nested2:another_value_nested
+ # ^^^^^^^^^^^^^ -> func:class3:nested2:value
diff --git a/modules/gdscript/tests/scripts/lsp/enums.notest.gd b/modules/gdscript/tests/scripts/lsp/enums.notest.gd
new file mode 100644
index 0000000000..38b9ec110a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/lsp/enums.notest.gd
@@ -0,0 +1,26 @@
+extends Node
+
+enum {UNIT_NEUTRAL, UNIT_ENEMY, UNIT_ALLY}
+# | | | | ^^^^^^^^^ enum:unnamed:ally -> enum:unnamed:ally
+# | | ^^^^^^^^^^ enum:unnamed:enemy -> enum:unnamed:enemy
+# ^^^^^^^^^^^^ enum:unnamed:neutral -> enum:unnamed:neutral
+enum Named {THING_1, THING_2, ANOTHER_THING = -1}
+# | | | | | | ^^^^^^^^^^^^^ enum:named:thing3 -> enum:named:thing3
+# | | | | ^^^^^^^ enum:named:thing2 -> enum:named:thing2
+# | | ^^^^^^^ enum:named:thing1 -> enum:named:thing1
+# ^^^^^ enum:named -> enum:named
+
+func f(arg):
+ match arg:
+ UNIT_ENEMY: print(UNIT_ENEMY)
+ # | ^^^^^^^^^^ -> enum:unnamed:enemy
+ #<^^^^^^^^ -> enum:unnamed:enemy
+ Named.THING_2: print(Named.THING_2)
+ #! | | | | | ^^^^^^^ -> enum:named:thing2
+ # | | | ^^^^^ -> enum:named
+ #! | ^^^^^^^ -> enum:named:thing2
+ #<^^^ -> enum:named
+ _: print(UNIT_ENEMY, Named.ANOTHER_THING)
+ #! | | | | ^^^^^^^^^^^^^ -> enum:named:thing3
+ # | | ^^^^^ -> enum:named
+ # ^^^^^^^^^^ -> enum:unnamed:enemy
diff --git a/modules/gdscript/tests/scripts/lsp/indentation.notest.gd b/modules/gdscript/tests/scripts/lsp/indentation.notest.gd
new file mode 100644
index 0000000000..c25d73a719
--- /dev/null
+++ b/modules/gdscript/tests/scripts/lsp/indentation.notest.gd
@@ -0,0 +1,28 @@
+extends Node
+
+var root = 0
+# ^^^^ 0_indent -> 0_indent
+
+func a():
+ var alpha: int = root + 42
+ # | | ^^^^ -> 0_indent
+ # ^^^^^ 1_indent -> 1_indent
+ if alpha > 42:
+ # ^^^^^ -> 1_indent
+ var beta := alpha + 13
+ # | | ^^^^ -> 1_indent
+ # ^^^^ 2_indent -> 2_indent
+ if beta > alpha:
+ # | | ^^^^^ -> 1_indent
+ # ^^^^ -> 2_indent
+ var gamma = beta + 1
+ # | | ^^^^ -> 2_indent
+ # ^^^^^ 3_indent -> 3_indent
+ print(gamma)
+ # ^^^^^ -> 3_indent
+ print(beta)
+ # ^^^^ -> 2_indent
+ print(alpha)
+ # ^^^^^ -> 1_indent
+ print(root)
+ # ^^^^ -> 0_indent
diff --git a/modules/gdscript/tests/scripts/lsp/lambdas.notest.gd b/modules/gdscript/tests/scripts/lsp/lambdas.notest.gd
new file mode 100644
index 0000000000..6f5d468eea
--- /dev/null
+++ b/modules/gdscript/tests/scripts/lsp/lambdas.notest.gd
@@ -0,0 +1,91 @@
+extends Node
+
+var lambda_member1 := func(alpha: int, beta): return alpha + beta
+# | | | | | | | | ^^^^ -> \1:beta
+# | | | | | | ^^^^^ -> \1:alpha
+# | | | | ^^^^ \1:beta -> \1:beta
+# | | ^^^^^ \1:alpha -> \1:alpha
+# ^^^^^^^^^^^^^^ \1 -> \1
+
+var lambda_member2 := func(alpha, beta: int) -> int:
+# | | | | | |
+# | | | | | |
+# | | | | ^^^^ \2:beta -> \2:beta
+# | | ^^^^^ \2:alpha -> \2:alpha
+# ^^^^^^^^^^^^^^ \2 -> \2
+ return alpha + beta
+ # | | ^^^^ -> \2:beta
+ # ^^^^^ -> \2:alpha
+
+var lambda_member3 := func add_values(alpha, beta): return alpha + beta
+# | | | | | | | | ^^^^ -> \3:beta
+# | | | | | | ^^^^^ -> \3:alpha
+# | | | | ^^^^ \3:beta -> \3:beta
+# | | ^^^^^ \3:alpha -> \3:alpha
+# ^^^^^^^^^^^^^^ \3 -> \3
+
+var lambda_multiline = func(alpha: int, beta: int) -> int:
+# | | | | | |
+# | | | | | |
+# | | | | ^^^^ \multi:beta -> \multi:beta
+# | | ^^^^^ \multi:alpha -> \multi:alpha
+# ^^^^^^^^^^^^^^^^ \multi -> \multi
+ print(alpha + beta)
+ # | | ^^^^ -> \multi:beta
+ # ^^^^^ -> \multi:alpha
+ var tmp = alpha + beta + 42
+ # | | | | ^^^^ -> \multi:beta
+ # | | ^^^^^ -> \multi:alpha
+ # ^^^ \multi:tmp -> \multi:tmp
+ print(tmp)
+ # ^^^ -> \multi:tmp
+ if tmp > 50:
+ # ^^^ -> \multi:tmp
+ tmp += alpha
+ # | ^^^^^ -> \multi:alpha
+ #<^ -> \multi:tmp
+ else:
+ tmp -= beta
+ # | ^^^^ -> \multi:beta
+ #<^ -> \multi:tmp
+ print(tmp)
+ # ^^^ -> \multi:tmp
+ return beta + tmp + alpha
+ # | | | | ^^^^^ -> \multi:alpha
+ # | | ^^^ -> \multi:tmp
+ # ^^^^ -> \multi:beta
+
+
+var some_name := "foo bar"
+# ^^^^^^^^^ member:some_name -> member:some_name
+
+func _ready() -> void:
+ var a = lambda_member1.call(1,2)
+ # ^^^^^^^^^^^^^^ -> \1
+ var b = lambda_member2.call(1,2)
+ # ^^^^^^^^^^^^^^ -> \2
+ var c = lambda_member3.call(1,2)
+ # ^^^^^^^^^^^^^^ -> \3
+ var d = lambda_multiline.call(1,2)
+ # ^^^^^^^^^^^^^^^^ -> \multi
+ print(a,b,c,d)
+
+ var lambda_local = func(alpha, beta): return alpha + beta
+ # | | | | | | | | ^^^^ -> \local:beta
+ # | | | | | | ^^^^^ -> \local:alpha
+ # | | | | ^^^^ \local:beta -> \local:beta
+ # | | ^^^^^ \local:alpha -> \local:alpha
+ # ^^^^^^^^^^^^ \local -> \local
+
+ var value := 42
+ # ^^^^^ local:value -> local:value
+ var lambda_capture = func(): return value + some_name.length()
+ # | | | | ^^^^^^^^^ -> member:some_name
+ # | | ^^^^^ -> local:value
+ # ^^^^^^^^^^^^^^ \capture -> \capture
+
+ var z = lambda_local.call(1,2)
+ # ^^^^^^^^^^^^ -> \local
+ var x = lambda_capture.call()
+ # ^^^^^^^^^^^^^^ -> \capture
+ print(z,x)
diff --git a/modules/gdscript/tests/scripts/lsp/local_variables.notest.gd b/modules/gdscript/tests/scripts/lsp/local_variables.notest.gd
new file mode 100644
index 0000000000..b6cc46f7da
--- /dev/null
+++ b/modules/gdscript/tests/scripts/lsp/local_variables.notest.gd
@@ -0,0 +1,25 @@
+extends Node
+
+var member := 2
+# ^^^^^^ member -> member
+
+func test_member() -> void:
+ var test := member + 42
+ # | | ^^^^^^ -> member
+ # ^^^^ test -> test
+ test += 3
+ #<^^ -> test
+ member += 5
+ #<^^^^ -> member
+ test = return_arg(test)
+ # | ^^^^ -> test
+ #<^^ -> test
+ print(test)
+ # ^^^^ -> test
+
+func return_arg(arg: int) -> int:
+# ^^^ arg -> arg
+ arg += 2
+ #<^ -> arg
+ return arg
+ # ^^^ -> arg \ No newline at end of file
diff --git a/modules/gdscript/tests/scripts/lsp/properties.notest.gd b/modules/gdscript/tests/scripts/lsp/properties.notest.gd
new file mode 100644
index 0000000000..8dfaee2e5b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/lsp/properties.notest.gd
@@ -0,0 +1,65 @@
+extends Node
+
+var prop1 := 42
+# ^^^^^ prop1 -> prop1
+var prop2 : int = 42
+# ^^^^^ prop2 -> prop2
+var prop3 := 42:
+# ^^^^^ prop3 -> prop3
+ get:
+ return prop3 + 13
+ # ^^^^^ -> prop3
+ set(value):
+ # ^^^^^ prop3:value -> prop3:value
+ prop3 = value - 13
+ # | ^^^^^ -> prop3:value
+ #<^^^ -> prop3
+var prop4: int:
+# ^^^^^ prop4 -> prop4
+ get:
+ return 42
+var prop5 := 42:
+# ^^^^^ prop5 -> prop5
+ set(value):
+ # ^^^^^ prop5:value -> prop5:value
+ prop5 = value - 13
+ # | ^^^^^ -> prop5:value
+ #<^^^ -> prop5
+
+var prop6:
+# ^^^^^ prop6 -> prop6
+ get = get_prop6,
+ # ^^^^^^^^^ -> get_prop6
+ set = set_prop6
+ # ^^^^^^^^^ -> set_prop6
+func get_prop6():
+# ^^^^^^^^^ get_prop6 -> get_prop6
+ return 42
+func set_prop6(value):
+# | | ^^^^^ set_prop6:value -> set_prop6:value
+# ^^^^^^^^^ set_prop6 -> set_prop6
+ print(value)
+ # ^^^^^ -> set_prop6:value
+
+var prop7:
+# ^^^^^ prop7 -> prop7
+ get = get_prop7
+ # ^^^^^^^^^ -> get_prop7
+func get_prop7():
+# ^^^^^^^^^ get_prop7 -> get_prop7
+ return 42
+
+var prop8:
+# ^^^^^ prop8 -> prop8
+ set = set_prop8
+ # ^^^^^^^^^ -> set_prop8
+func set_prop8(value):
+# | | ^^^^^ set_prop8:value -> set_prop8:value
+# ^^^^^^^^^ set_prop8 -> set_prop8
+ print(value)
+ # ^^^^^ -> set_prop8:value
+
+const const_var := 42
+# ^^^^^^^^^ const_var -> const_var
+static var static_var := 42
+# ^^^^^^^^^^ static_var -> static_var
diff --git a/modules/gdscript/tests/scripts/lsp/scopes.notest.gd b/modules/gdscript/tests/scripts/lsp/scopes.notest.gd
new file mode 100644
index 0000000000..20b8fb9bd7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/lsp/scopes.notest.gd
@@ -0,0 +1,106 @@
+extends Node
+
+var member := 2
+# ^^^^^^ public -> public
+
+signal some_changed(new_value)
+# | | ^^^^^^^^^ signal:parameter -> signal:parameter
+# ^^^^^^^^^^^^ signal -> signal
+var some_value := 42:
+# ^^^^^^^^^^ property -> property
+ get:
+ return some_value
+ # ^^^^^^^^^^ -> property
+ set(value):
+ # ^^^^^ property:set:value -> property:set:value
+ some_changed.emit(value)
+ # | ^^^^^ -> property:set:value
+ #<^^^^^^^^^^ -> signal
+ some_value = value
+ # | ^^^^^ -> property:set:value
+ #<^^^^^^^^ -> property
+
+func v():
+ var value := member + 2
+ # | | ^^^^^^ -> public
+ # ^^^^^ v:value -> v:value
+ print(value)
+ # ^^^^^ -> v:value
+ if value > 0:
+ # ^^^^^ -> v:value
+ var beta := value + 2
+ # | | ^^^^^ -> v:value
+ # ^^^^ v:if:beta -> v:if:beta
+ print(beta)
+ # ^^^^ -> v:if:beta
+
+ for counter in beta:
+ # | | ^^^^ -> v:if:beta
+ # ^^^^^^^ v:if:counter -> v:if:counter
+ print (counter)
+ # ^^^^^^^ -> v:if:counter
+
+ else:
+ for counter in value:
+ # | | ^^^^^ -> v:value
+ # ^^^^^^^ v:else:counter -> v:else:counter
+ print(counter)
+ # ^^^^^^^ -> v:else:counter
+
+func f():
+ var func1 = func(value): print(value + 13)
+ # | | | | ^^^^^ -> f:func1:value
+ # | | ^^^^^ f:func1:value -> f:func1:value
+ # ^^^^^ f:func1 -> f:func1
+ var func2 = func(value): print(value + 42)
+ # | | | | ^^^^^ -> f:func2:value
+ # | | ^^^^^ f:func2:value -> f:func2:value
+ # ^^^^^ f:func2 -> f:func2
+
+ func1.call(1)
+ #<^^^ -> f:func1
+ func2.call(2)
+ #<^^^ -> f:func2
+
+func m():
+ var value = 42
+ # ^^^^^ m:value -> m:value
+
+ match value:
+ # ^^^^^ -> m:value
+ 13:
+ print(value)
+ # ^^^^^ -> m:value
+ [var start, _, var end]:
+ # | | ^^^ m:match:array:end -> m:match:array:end
+ # ^^^^^ m:match:array:start -> m:match:array:start
+ print(start + end)
+ # | | ^^^ -> m:match:array:end
+ # ^^^^^ -> m:match:array:start
+ { "name": var name }:
+ # ^^^^ m:match:dict:var -> m:match:dict:var
+ print(name)
+ # ^^^^ -> m:match:dict:var
+ var whatever:
+ # ^^^^^^^^ m:match:var -> m:match:var
+ print(whatever)
+ # ^^^^^^^^ -> m:match:var
+
+func m2():
+ var value = 42
+ # ^^^^^ m2:value -> m2:value
+
+ match value:
+ # ^^^^^ -> m2:value
+ { "name": var name }:
+ # ^^^^ m2:match:dict:var -> m2:match:dict:var
+ print(name)
+ # ^^^^ -> m2:match:dict:var
+ [var name, ..]:
+ # ^^^^ m2:match:array:var -> m2:match:array:var
+ print(name)
+ # ^^^^ -> m2:match:array:var
+ var name:
+ # ^^^^ m2:match:var -> m2:match:var
+ print(name)
+ # ^^^^ -> m2:match:var
diff --git a/modules/gdscript/tests/scripts/lsp/shadowing_initializer.notest.gd b/modules/gdscript/tests/scripts/lsp/shadowing_initializer.notest.gd
new file mode 100644
index 0000000000..338000fa0e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/lsp/shadowing_initializer.notest.gd
@@ -0,0 +1,56 @@
+extends Node
+
+var value := 42
+# ^^^^^ member:value -> member:value
+
+func variable():
+ var value = value + 42
+ #! | | ^^^^^ -> member:value
+ # ^^^^^ variable:value -> variable:value
+ print(value)
+ # ^^^^^ -> variable:value
+
+func array():
+ var value = [1,value,3,value+4]
+ #! | | | | ^^^^^ -> member:value
+ #! | | ^^^^^ -> member:value
+ # ^^^^^ array:value -> array:value
+ print(value)
+ # ^^^^^ -> array:value
+
+func dictionary():
+ var value = {
+ # ^^^^^ dictionary:value -> dictionary:value
+ "key1": value,
+ #! ^^^^^ -> member:value
+ "key2": 1 + value + 3,
+ #! ^^^^^ -> member:value
+ }
+ print(value)
+ # ^^^^^ -> dictionary:value
+
+func for_loop():
+ for value in value:
+ # | | ^^^^^ -> member:value
+ # ^^^^^ for:value -> for:value
+ print(value)
+ # ^^^^^ -> for:value
+
+func for_range():
+ for value in range(5, value):
+ # | | ^^^^^ -> member:value
+ # ^^^^^ for:range:value -> for:range:value
+ print(value)
+ # ^^^^^ -> for:range:value
+
+func matching():
+ match value:
+ # ^^^^^ -> member:value
+ 42: print(value)
+ # ^^^^^ -> member:value
+ [var value, ..]: print(value)
+ # | | ^^^^^ -> match:array:value
+ # ^^^^^ match:array:value -> match:array:value
+ var value: print(value)
+ # | | ^^^^^ -> match:var:value
+ # ^^^^^ match:var:value -> match:var:value
diff --git a/modules/gdscript/tests/scripts/parser/.editorconfig b/modules/gdscript/tests/scripts/parser/.editorconfig
new file mode 100644
index 0000000000..fa43b3ad78
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/.editorconfig
@@ -0,0 +1,2 @@
+[*.{gd,out}]
+trim_trailing_whitespace = false
diff --git a/modules/gdscript/tests/scripts/parser/errors/bad_r_string_1.gd b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_1.gd
new file mode 100644
index 0000000000..e5eecbb819
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_1.gd
@@ -0,0 +1,2 @@
+func test():
+ print(r"\")
diff --git a/modules/gdscript/tests/scripts/parser/errors/bad_r_string_1.out b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_1.out
new file mode 100644
index 0000000000..c8e843b0d7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_1.out
@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+Unterminated string.
diff --git a/modules/gdscript/tests/scripts/parser/errors/bad_r_string_2.gd b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_2.gd
new file mode 100644
index 0000000000..9168b69f86
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_2.gd
@@ -0,0 +1,2 @@
+func test():
+ print(r"\\"")
diff --git a/modules/gdscript/tests/scripts/parser/errors/bad_r_string_2.out b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_2.out
new file mode 100644
index 0000000000..c8e843b0d7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_2.out
@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+Unterminated string.
diff --git a/modules/gdscript/tests/scripts/parser/errors/bad_r_string_3.gd b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_3.gd
new file mode 100644
index 0000000000..37dc910e5f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_3.gd
@@ -0,0 +1,3 @@
+func test():
+ # v
+ print(r"['"]*")
diff --git a/modules/gdscript/tests/scripts/parser/errors/bad_r_string_3.out b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_3.out
new file mode 100644
index 0000000000..dcb5c2f289
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/bad_r_string_3.out
@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+Closing "]" doesn't have an opening counterpart.
diff --git a/modules/gdscript/tests/scripts/parser/errors/match_guard_with_assignment.gd b/modules/gdscript/tests/scripts/parser/errors/match_guard_with_assignment.gd
new file mode 100644
index 0000000000..d88b4a37c4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/match_guard_with_assignment.gd
@@ -0,0 +1,5 @@
+func test():
+ var a = 0
+ match a:
+ 0 when a = 1:
+ print("assignment not allowed on pattern guard")
diff --git a/modules/gdscript/tests/scripts/parser/errors/match_guard_with_assignment.out b/modules/gdscript/tests/scripts/parser/errors/match_guard_with_assignment.out
new file mode 100644
index 0000000000..e8f9130706
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/match_guard_with_assignment.out
@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+Assignment is not allowed inside an expression.
diff --git a/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.gd b/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.gd
index 7e1982597c..0c8a5d1367 100644
--- a/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.gd
+++ b/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.gd
@@ -14,3 +14,7 @@ func test():
var TAU = "TAU"
print(TAU)
+
+ # New keyword for pattern guards.
+ var when = "when"
+ print(when)
diff --git a/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.out b/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.out
index aae2ae13d5..8ac8e92ef7 100644
--- a/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.out
+++ b/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.out
@@ -4,3 +4,4 @@ PI
INF
NAN
TAU
+when
diff --git a/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd
index f04f4de08d..19f6e08285 100644
--- a/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd
+++ b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd
@@ -3,27 +3,32 @@ extends Node
func test():
var child = Node.new()
child.name = "Child"
+ @warning_ignore("unsafe_call_argument")
add_child(child)
child.owner = self
var hey = Node.new()
hey.name = "Hey"
+ @warning_ignore("unsafe_call_argument")
child.add_child(hey)
hey.owner = self
hey.unique_name_in_owner = true
var fake_hey = Node.new()
fake_hey.name = "Hey"
+ @warning_ignore("unsafe_call_argument")
add_child(fake_hey)
fake_hey.owner = self
var sub_child = Node.new()
sub_child.name = "SubChild"
+ @warning_ignore("unsafe_call_argument")
hey.add_child(sub_child)
sub_child.owner = self
var howdy = Node.new()
howdy.name = "Howdy"
+ @warning_ignore("unsafe_call_argument")
sub_child.add_child(howdy)
howdy.owner = self
howdy.unique_name_in_owner = true
diff --git a/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.gd b/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.gd
index 8ba558e91d..3d9404b20b 100644
--- a/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.gd
+++ b/modules/gdscript/tests/scripts/parser/features/dollar_node_paths.gd
@@ -5,9 +5,11 @@ func test():
# Create the required node structure.
var hello = Node.new()
hello.name = "Hello"
+ @warning_ignore("unsafe_call_argument")
add_child(hello)
var world = Node.new()
world.name = "World"
+ @warning_ignore("unsafe_call_argument")
hello.add_child(world)
# All the ways of writing node paths below with the `$` operator are valid.
diff --git a/modules/gdscript/tests/scripts/parser/features/lambda_ends_with_new_line.gd b/modules/gdscript/tests/scripts/parser/features/lambda_ends_with_new_line.gd
index df6001c7e2..f16c768f7f 100644
--- a/modules/gdscript/tests/scripts/parser/features/lambda_ends_with_new_line.gd
+++ b/modules/gdscript/tests/scripts/parser/features/lambda_ends_with_new_line.gd
@@ -26,6 +26,7 @@ func test():
if true: (v as Callable).call()
print()
+ @warning_ignore("unsafe_call_argument")
other(v)
print()
diff --git a/modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines.gd b/modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines.gd
new file mode 100644
index 0000000000..7ee2708999
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines.gd
@@ -0,0 +1,20 @@
+# Empty line:
+
+
+# Comment line:
+ # Comment.
+
+func test():
+ print(1)
+
+ if true:
+
+ # Empty line:
+
+
+ print(2)
+
+ # Comment line:
+ # Comment.
+
+ print(3)
diff --git a/modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines.out b/modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines.out
new file mode 100644
index 0000000000..c40e402ba3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+1
+2
+3
diff --git a/modules/gdscript/tests/scripts/parser/features/nested_function_calls.gd b/modules/gdscript/tests/scripts/parser/features/nested_function_calls.gd
index 59cdc7d6c2..31de73813f 100644
--- a/modules/gdscript/tests/scripts/parser/features/nested_function_calls.gd
+++ b/modules/gdscript/tests/scripts/parser/features/nested_function_calls.gd
@@ -2,4 +2,5 @@ func foo(x):
return x + 1
func test():
+ @warning_ignore("unsafe_call_argument")
print(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(foo(0)))))))))))))))))))))))))
diff --git a/modules/gdscript/tests/scripts/parser/features/r_strings.gd b/modules/gdscript/tests/scripts/parser/features/r_strings.gd
new file mode 100644
index 0000000000..6f546f28be
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/r_strings.gd
@@ -0,0 +1,22 @@
+func test():
+ print(r"test ' \' \" \\ \n \t \u2023 test")
+ print(r"\n\\[\t ]*(\w+)")
+ print(r"")
+ print(r"\"")
+ print(r"\\\"")
+ print(r"\\")
+ print(r"\" \\\" \\\\\"")
+ print(r"\ \\ \\\ \\\\ \\\\\ \\")
+ print(r'"')
+ print(r'"(?:\\.|[^"])*"')
+ print(r"""""")
+ print(r"""test \t "test"="" " \" \\\" \ \\ \\\ test""")
+ print(r'''r"""test \t "test"="" " \" \\\" \ \\ \\\ test"""''')
+ print(r"\t
+ \t")
+ print(r"\t \
+ \t")
+ print(r"""\t
+ \t""")
+ print(r"""\t \
+ \t""")
diff --git a/modules/gdscript/tests/scripts/parser/features/r_strings.out b/modules/gdscript/tests/scripts/parser/features/r_strings.out
new file mode 100644
index 0000000000..114ef0a6c3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/r_strings.out
@@ -0,0 +1,22 @@
+GDTEST_OK
+test ' \' \" \\ \n \t \u2023 test
+\n\\[\t ]*(\w+)
+
+\"
+\\\"
+\\
+\" \\\" \\\\\"
+\ \\ \\\ \\\\ \\\\\ \\
+"
+"(?:\\.|[^"])*"
+
+test \t "test"="" " \" \\\" \ \\ \\\ test
+r"""test \t "test"="" " \" \\\" \ \\ \\\ test"""
+\t
+ \t
+\t \
+ \t
+\t
+ \t
+\t \
+ \t
diff --git a/modules/gdscript/tests/scripts/parser/features/super.gd b/modules/gdscript/tests/scripts/parser/features/super.gd
index f5ae2a74a7..33accd92a9 100644
--- a/modules/gdscript/tests/scripts/parser/features/super.gd
+++ b/modules/gdscript/tests/scripts/parser/features/super.gd
@@ -36,6 +36,7 @@ class SayNothing extends Say:
print("howdy, see above")
func say(name):
+ @warning_ignore("unsafe_call_argument")
super(name + " super'd")
print(prefix, " say nothing... or not? ", name)
diff --git a/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.gd b/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.gd
index 523959a016..20cc0cee2e 100644
--- a/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.gd
+++ b/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.gd
@@ -29,6 +29,7 @@ func test():
const d = 1.1
_process(d)
+ @warning_ignore("unsafe_call_argument")
print(is_equal_approx(ㄥ, PI + (d * PI)))
func _process(Δ: float) -> void:
diff --git a/modules/gdscript/tests/scripts/runtime/errors/for_loop_iterator_type_not_match_specified.gd b/modules/gdscript/tests/scripts/runtime/errors/for_loop_iterator_type_not_match_specified.gd
new file mode 100644
index 0000000000..cdc278ecf5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/for_loop_iterator_type_not_match_specified.gd
@@ -0,0 +1,4 @@
+func test():
+ var a: Array = [Resource.new()]
+ for node: Node in a:
+ print(node)
diff --git a/modules/gdscript/tests/scripts/runtime/errors/for_loop_iterator_type_not_match_specified.out b/modules/gdscript/tests/scripts/runtime/errors/for_loop_iterator_type_not_match_specified.out
new file mode 100644
index 0000000000..b7ef07afb2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/for_loop_iterator_type_not_match_specified.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/for_loop_iterator_type_not_match_specified.gd
+>> 3
+>> Trying to assign value of type 'Resource' to a variable of type 'Node'.
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
diff --git a/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_specified_types.gd b/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_specified_types.gd
new file mode 100644
index 0000000000..bc899a3a6f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_specified_types.gd
@@ -0,0 +1,40 @@
+func test():
+ print("Test range.")
+ for e: float in range(2, 5):
+ var elem := e
+ prints(var_to_str(e), var_to_str(elem))
+
+ print("Test int.")
+ for e: float in 3:
+ var elem := e
+ prints(var_to_str(e), var_to_str(elem))
+
+ print("Test untyped int array.")
+ var a1 := [10, 20, 30]
+ for e: float in a1:
+ var elem := e
+ prints(var_to_str(e), var_to_str(elem))
+
+ print("Test typed int array.")
+ var a2: Array[int] = [10, 20, 30]
+ for e: float in a2:
+ var elem := e
+ prints(var_to_str(e), var_to_str(elem))
+
+ # GH-82021
+ print("Test implicitly typed array literal.")
+ for e: float in [100, 200, 300]:
+ var elem := e
+ prints(var_to_str(e), var_to_str(elem))
+
+ print("Test String-keys dictionary.")
+ var d1 := {a = 1, b = 2, c = 3}
+ for k: StringName in d1:
+ var key := k
+ prints(var_to_str(k), var_to_str(key))
+
+ print("Test RefCounted-keys dictionary.")
+ var d2 := {RefCounted.new(): 1, Resource.new(): 2, ConfigFile.new(): 3}
+ for k: RefCounted in d2:
+ var key := k
+ prints(k.get_class(), key.get_class())
diff --git a/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_specified_types.out b/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_specified_types.out
new file mode 100644
index 0000000000..eeebdc4be5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_specified_types.out
@@ -0,0 +1,29 @@
+GDTEST_OK
+Test range.
+2.0 2.0
+3.0 3.0
+4.0 4.0
+Test int.
+0.0 0.0
+1.0 1.0
+2.0 2.0
+Test untyped int array.
+10.0 10.0
+20.0 20.0
+30.0 30.0
+Test typed int array.
+10.0 10.0
+20.0 20.0
+30.0 30.0
+Test implicitly typed array literal.
+100.0 100.0
+200.0 200.0
+300.0 300.0
+Test String-keys dictionary.
+&"a" &"a"
+&"b" &"b"
+&"c" &"c"
+Test RefCounted-keys dictionary.
+RefCounted RefCounted
+Resource Resource
+ConfigFile ConfigFile
diff --git a/modules/gdscript/tests/scripts/runtime/features/match_with_pattern_guards.gd b/modules/gdscript/tests/scripts/runtime/features/match_with_pattern_guards.gd
new file mode 100644
index 0000000000..4cb51f8512
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/match_with_pattern_guards.gd
@@ -0,0 +1,71 @@
+var global := 0
+
+func test():
+ var a = 0
+ var b = 1
+
+ match a:
+ 0 when b == 0:
+ print("does not run" if true else "")
+ 0 when b == 1:
+ print("guards work")
+ _:
+ print("does not run")
+
+ match a:
+ var a_bind when b == 0:
+ prints("a is", a_bind, "and b is 0")
+ var a_bind when b == 1:
+ prints("a is", a_bind, "and b is 1")
+ _:
+ print("does not run")
+
+ match a:
+ var a_bind when a_bind < 0:
+ print("a is less than zero")
+ var a_bind when a_bind == 0:
+ print("a is equal to zero")
+ _:
+ print("a is more than zero")
+
+ match [1, 2, 3]:
+ [1, 2, var element] when element == 0:
+ print("does not run")
+ [1, 2, var element] when element == 3:
+ print("3rd element is 3")
+
+ match a:
+ _ when b == 0:
+ print("does not run")
+ _ when b == 1:
+ print("works with wildcard too.")
+ _:
+ print("does not run")
+
+ match a:
+ 0, 1 when b == 0:
+ print("does not run")
+ 0, 1 when b == 1:
+ print("guard with multiple patterns")
+ _:
+ print("does not run")
+
+ match a:
+ 0 when b == 0:
+ print("does not run")
+ 0:
+ print("regular pattern after guard mismatch")
+
+ match a:
+ 1 when side_effect():
+ print("should not run the side effect call")
+ 0 when side_effect():
+ print("will run the side effect call, but not this")
+ _:
+ assert(global == 1)
+ print("side effect only ran once")
+
+func side_effect():
+ print("side effect")
+ global += 1
+ return false
diff --git a/modules/gdscript/tests/scripts/runtime/features/match_with_pattern_guards.out b/modules/gdscript/tests/scripts/runtime/features/match_with_pattern_guards.out
new file mode 100644
index 0000000000..452d1ff4bf
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/match_with_pattern_guards.out
@@ -0,0 +1,10 @@
+GDTEST_OK
+guards work
+a is 0 and b is 1
+a is equal to zero
+3rd element is 3
+works with wildcard too.
+guard with multiple patterns
+regular pattern after guard mismatch
+side effect
+side effect only ran once
diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info.gd b/modules/gdscript/tests/scripts/runtime/features/member_info.gd
new file mode 100644
index 0000000000..805ea42455
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/member_info.gd
@@ -0,0 +1,72 @@
+class_name TestMemberInfo
+
+class MyClass:
+ pass
+
+enum MyEnum {}
+
+const Utils = preload("../../utils.notest.gd")
+
+static var test_static_var_untyped
+static var test_static_var_weak_null = null
+static var test_static_var_weak_int = 1
+static var test_static_var_hard_int: int
+
+var test_var_untyped
+var test_var_weak_null = null
+var test_var_weak_int = 1
+@export var test_var_weak_int_exported = 1
+var test_var_weak_variant_type = TYPE_NIL
+@export var test_var_weak_variant_type_exported = TYPE_NIL
+var test_var_hard_variant: Variant
+var test_var_hard_int: int
+var test_var_hard_variant_type: Variant.Type
+@export var test_var_hard_variant_type_exported: Variant.Type
+var test_var_hard_node_process_mode: Node.ProcessMode
+var test_var_hard_my_enum: MyEnum
+var test_var_hard_array: Array
+var test_var_hard_array_int: Array[int]
+var test_var_hard_array_variant_type: Array[Variant.Type]
+var test_var_hard_array_node_process_mode: Array[Node.ProcessMode]
+var test_var_hard_array_my_enum: Array[MyEnum]
+var test_var_hard_array_resource: Array[Resource]
+var test_var_hard_array_this: Array[TestMemberInfo]
+var test_var_hard_array_my_class: Array[MyClass]
+var test_var_hard_resource: Resource
+var test_var_hard_this: TestMemberInfo
+var test_var_hard_my_class: MyClass
+
+static func test_static_func(): pass
+
+func test_func_implicit_void(): pass
+func test_func_explicit_void() -> void: pass
+func test_func_weak_null(): return null
+func test_func_weak_int(): return 1
+func test_func_hard_variant() -> Variant: return null
+func test_func_hard_int() -> int: return 1
+func test_func_args_1(_a: int, _b: Array[int], _c: int = 1, _d = 2): pass
+func test_func_args_2(_a = 1, _b = _a, _c = [2], _d = 3): pass
+
+signal test_signal_1()
+signal test_signal_2(a: Variant, b)
+signal test_signal_3(a: int, b: Array[int])
+signal test_signal_4(a: Variant.Type, b: Array[Variant.Type])
+signal test_signal_5(a: MyEnum, b: Array[MyEnum])
+signal test_signal_6(a: Resource, b: Array[Resource])
+signal test_signal_7(a: TestMemberInfo, b: Array[TestMemberInfo])
+signal test_signal_8(a: MyClass, b: Array[MyClass])
+
+func test():
+ var script: Script = get_script()
+ for property in script.get_property_list():
+ if str(property.name).begins_with("test_"):
+ print(Utils.get_property_signature(property, true))
+ for property in get_property_list():
+ if str(property.name).begins_with("test_"):
+ print(Utils.get_property_signature(property))
+ for method in get_method_list():
+ if str(method.name).begins_with("test_"):
+ print(Utils.get_method_signature(method))
+ for method in get_signal_list():
+ if str(method.name).begins_with("test_"):
+ print(Utils.get_method_signature(method, true))
diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info.out b/modules/gdscript/tests/scripts/runtime/features/member_info.out
new file mode 100644
index 0000000000..3a91507da9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/member_info.out
@@ -0,0 +1,45 @@
+GDTEST_OK
+static var test_static_var_untyped: Variant
+static var test_static_var_weak_null: Variant
+static var test_static_var_weak_int: Variant
+static var test_static_var_hard_int: int
+var test_var_untyped: Variant
+var test_var_weak_null: Variant
+var test_var_weak_int: Variant
+@export var test_var_weak_int_exported: int
+var test_var_weak_variant_type: Variant
+@export var test_var_weak_variant_type_exported: Variant.Type
+var test_var_hard_variant: Variant
+var test_var_hard_int: int
+var test_var_hard_variant_type: Variant.Type
+@export var test_var_hard_variant_type_exported: Variant.Type
+var test_var_hard_node_process_mode: Node.ProcessMode
+var test_var_hard_my_enum: TestMemberInfo.MyEnum
+var test_var_hard_array: Array
+var test_var_hard_array_int: Array[int]
+var test_var_hard_array_variant_type: Array[Variant.Type]
+var test_var_hard_array_node_process_mode: Array[Node.ProcessMode]
+var test_var_hard_array_my_enum: Array[TestMemberInfo.MyEnum]
+var test_var_hard_array_resource: Array[Resource]
+var test_var_hard_array_this: Array[TestMemberInfo]
+var test_var_hard_array_my_class: Array[RefCounted]
+var test_var_hard_resource: Resource
+var test_var_hard_this: TestMemberInfo
+var test_var_hard_my_class: RefCounted
+static func test_static_func() -> void
+func test_func_implicit_void() -> void
+func test_func_explicit_void() -> void
+func test_func_weak_null() -> Variant
+func test_func_weak_int() -> Variant
+func test_func_hard_variant() -> Variant
+func test_func_hard_int() -> int
+func test_func_args_1(_a: int, _b: Array[int], _c: int = 1, _d: Variant = 2) -> void
+func test_func_args_2(_a: Variant = 1, _b: Variant = null, _c: Variant = null, _d: Variant = 3) -> void
+signal test_signal_1()
+signal test_signal_2(a: Variant, b: Variant)
+signal test_signal_3(a: int, b: Array[int])
+signal test_signal_4(a: Variant.Type, b: Array[Variant.Type])
+signal test_signal_5(a: TestMemberInfo.MyEnum, b: Array[TestMemberInfo.MyEnum])
+signal test_signal_6(a: Resource, b: Array[Resource])
+signal test_signal_7(a: TestMemberInfo, b: Array[TestMemberInfo])
+signal test_signal_8(a: RefCounted, b: Array[RefCounted])
diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd
new file mode 100644
index 0000000000..d0cbeeab85
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.gd
@@ -0,0 +1,45 @@
+# GH-82169
+
+const Utils = preload("../../utils.notest.gd")
+
+class A:
+ static var test_static_var_a1
+ static var test_static_var_a2
+ var test_var_a1
+ var test_var_a2
+ static func test_static_func_a1(): pass
+ static func test_static_func_a2(): pass
+ func test_func_a1(): pass
+ func test_func_a2(): pass
+ signal test_signal_a1()
+ signal test_signal_a2()
+
+class B extends A:
+ static var test_static_var_b1
+ static var test_static_var_b2
+ var test_var_b1
+ var test_var_b2
+ static func test_static_func_b1(): pass
+ static func test_static_func_b2(): pass
+ func test_func_b1(): pass
+ func test_func_b2(): pass
+ signal test_signal_b1()
+ signal test_signal_b2()
+
+func test():
+ var b := B.new()
+ for property in (B as GDScript).get_property_list():
+ if str(property.name).begins_with("test_"):
+ print(Utils.get_property_signature(property, true))
+ print("---")
+ for property in b.get_property_list():
+ if str(property.name).begins_with("test_"):
+ print(Utils.get_property_signature(property))
+ print("---")
+ for method in b.get_method_list():
+ if str(method.name).begins_with("test_"):
+ print(Utils.get_method_signature(method))
+ print("---")
+ for method in b.get_signal_list():
+ if str(method.name).begins_with("test_"):
+ print(Utils.get_method_signature(method, true))
diff --git a/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.out b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.out
new file mode 100644
index 0000000000..f294b66ef9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/member_info_inheritance.out
@@ -0,0 +1,24 @@
+GDTEST_OK
+static var test_static_var_a1: Variant
+static var test_static_var_a2: Variant
+static var test_static_var_b1: Variant
+static var test_static_var_b2: Variant
+---
+var test_var_b1: Variant
+var test_var_b2: Variant
+var test_var_a1: Variant
+var test_var_a2: Variant
+---
+static func test_static_func_b1() -> void
+static func test_static_func_b2() -> void
+func test_func_b1() -> void
+func test_func_b2() -> void
+static func test_static_func_a1() -> void
+static func test_static_func_a2() -> void
+func test_func_a1() -> void
+func test_func_a2() -> void
+---
+signal test_signal_b1()
+signal test_signal_b2()
+signal test_signal_a1()
+signal test_signal_a2()
diff --git a/modules/gdscript/tests/scripts/runtime/features/metatypes.gd b/modules/gdscript/tests/scripts/runtime/features/metatypes.gd
new file mode 100644
index 0000000000..6c5df32ffe
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/metatypes.gd
@@ -0,0 +1,36 @@
+class MyClass:
+ const TEST = 10
+
+enum MyEnum {A, B, C}
+
+const Utils = preload("../../utils.notest.gd")
+const Other = preload("./metatypes.notest.gd")
+
+var test_native := JSON
+var test_script := Other
+var test_class := MyClass
+var test_enum := MyEnum
+
+func check_gdscript_native_class(value: Variant) -> void:
+ print(var_to_str(value).get_slice(",", 0).trim_prefix("Object("))
+
+func check_gdscript(value: GDScript) -> void:
+ print(value.get_class())
+
+func check_enum(value: Dictionary) -> void:
+ print(value)
+
+func test():
+ for property in get_property_list():
+ if str(property.name).begins_with("test_"):
+ print(Utils.get_property_signature(property))
+
+ check_gdscript_native_class(test_native)
+ check_gdscript(test_script)
+ check_gdscript(test_class)
+ check_enum(test_enum)
+
+ print(test_native.stringify([]))
+ print(test_script.TEST)
+ print(test_class.TEST)
+ print(test_enum.keys())
diff --git a/modules/gdscript/tests/scripts/runtime/features/metatypes.notest.gd b/modules/gdscript/tests/scripts/runtime/features/metatypes.notest.gd
new file mode 100644
index 0000000000..e6a591b927
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/metatypes.notest.gd
@@ -0,0 +1 @@
+const TEST = 100
diff --git a/modules/gdscript/tests/scripts/runtime/features/metatypes.out b/modules/gdscript/tests/scripts/runtime/features/metatypes.out
new file mode 100644
index 0000000000..352d1caa59
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/metatypes.out
@@ -0,0 +1,13 @@
+GDTEST_OK
+var test_native: GDScriptNativeClass
+var test_script: GDScript
+var test_class: GDScript
+var test_enum: Dictionary
+GDScriptNativeClass
+GDScript
+GDScript
+{ "A": 0, "B": 1, "C": 2 }
+[]
+100
+10
+["A", "B", "C"]
diff --git a/modules/gdscript/tests/scripts/runtime/features/object_constructor.gd b/modules/gdscript/tests/scripts/runtime/features/object_constructor.gd
new file mode 100644
index 0000000000..b875efef56
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/object_constructor.gd
@@ -0,0 +1,6 @@
+# GH-73213
+
+func test():
+ var object := Object.new() # Not `Object()`.
+ print(object.get_class())
+ object.free()
diff --git a/modules/gdscript/tests/scripts/runtime/features/object_constructor.out b/modules/gdscript/tests/scripts/runtime/features/object_constructor.out
new file mode 100644
index 0000000000..3673881576
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/object_constructor.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+Object
diff --git a/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd b/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd
index 2f55059334..fd1460a48f 100644
--- a/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd
@@ -12,6 +12,7 @@ func test():
print("end")
func test_construct(v, f):
+ @warning_ignore("unsafe_call_argument")
Vector2(v, v) # Built-in type construct.
assert(not f) # Test unary operator reading from `nil`.
diff --git a/modules/gdscript/tests/scripts/runtime/features/static_variables.gd b/modules/gdscript/tests/scripts/runtime/features/static_variables.gd
index 8da8bb7e53..7fa76ca4b0 100644
--- a/modules/gdscript/tests/scripts/runtime/features/static_variables.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/static_variables.gd
@@ -44,6 +44,7 @@ func test():
@warning_ignore("unsafe_method_access")
var path = get_script().get_path().get_base_dir()
+ @warning_ignore("unsafe_call_argument")
var other = load(path + "/static_variables_load.gd")
prints("load.perm:", other.perm)
diff --git a/modules/gdscript/tests/scripts/runtime/features/stringify.gd b/modules/gdscript/tests/scripts/runtime/features/stringify.gd
index fead2df854..1e66d8f34a 100644
--- a/modules/gdscript/tests/scripts/runtime/features/stringify.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/stringify.gd
@@ -24,7 +24,8 @@ func test():
print(StringName("hello"))
print(NodePath("hello/world"))
var node := Node.new()
- print(RID(node))
+ @warning_ignore("unsafe_call_argument")
+ print(RID(node)) # TODO: Why is the constructor (or implicit cast) not documented?
print(node.get_name)
print(node.property_list_changed)
node.free()
diff --git a/modules/gdscript/tests/scripts/utils.notest.gd b/modules/gdscript/tests/scripts/utils.notest.gd
new file mode 100644
index 0000000000..fb20817117
--- /dev/null
+++ b/modules/gdscript/tests/scripts/utils.notest.gd
@@ -0,0 +1,281 @@
+static func get_type(property: Dictionary, is_return: bool = false) -> String:
+ match property.type:
+ TYPE_NIL:
+ if property.usage & PROPERTY_USAGE_NIL_IS_VARIANT:
+ return "Variant"
+ return "void" if is_return else "null"
+ TYPE_INT:
+ if property.usage & PROPERTY_USAGE_CLASS_IS_ENUM:
+ if property.class_name == &"":
+ return "<unknown enum>"
+ return property.class_name
+ TYPE_ARRAY:
+ if property.hint == PROPERTY_HINT_ARRAY_TYPE:
+ if str(property.hint_string).is_empty():
+ return "Array[<unknown type>]"
+ return "Array[%s]" % property.hint_string
+ TYPE_OBJECT:
+ if not str(property.class_name).is_empty():
+ return property.class_name
+ return variant_get_type_name(property.type)
+
+
+static func get_property_signature(property: Dictionary, is_static: bool = false) -> String:
+ var result: String = ""
+ if not (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE):
+ printerr("Missing `PROPERTY_USAGE_SCRIPT_VARIABLE` flag.")
+ if property.usage & PROPERTY_USAGE_DEFAULT:
+ result += "@export "
+ if is_static:
+ result += "static "
+ result += "var " + property.name + ": " + get_type(property)
+ return result
+
+
+static func get_property_additional_info(property: Dictionary) -> String:
+ return 'hint=%s hint_string="%s" usage=%s' % [
+ get_property_hint_name(property.hint).trim_prefix("PROPERTY_HINT_"),
+ str(property.hint_string).c_escape(),
+ get_property_usage_string(property.usage).replace("PROPERTY_USAGE_", ""),
+ ]
+
+
+static func get_method_signature(method: Dictionary, is_signal: bool = false) -> String:
+ var result: String = ""
+ if method.flags & METHOD_FLAG_STATIC:
+ result += "static "
+ result += ("signal " if is_signal else "func ") + method.name + "("
+
+ var args: Array[Dictionary] = method.args
+ var default_args: Array = method.default_args
+ var mandatory_argc: int = args.size() - default_args.size()
+ for i in args.size():
+ if i > 0:
+ result += ", "
+ var arg: Dictionary = args[i]
+ result += arg.name + ": " + get_type(arg)
+ if i >= mandatory_argc:
+ result += " = " + var_to_str(default_args[i - mandatory_argc])
+
+ result += ")"
+ if is_signal:
+ if get_type(method.return, true) != "void":
+ printerr("Signal return type must be `void`.")
+ else:
+ result += " -> " + get_type(method.return, true)
+ return result
+
+
+static func variant_get_type_name(type: Variant.Type) -> String:
+ match type:
+ TYPE_NIL:
+ return "Nil" # `Nil` in core, `null` in GDScript.
+ TYPE_BOOL:
+ return "bool"
+ TYPE_INT:
+ return "int"
+ TYPE_FLOAT:
+ return "float"
+ TYPE_STRING:
+ return "String"
+ TYPE_VECTOR2:
+ return "Vector2"
+ TYPE_VECTOR2I:
+ return "Vector2i"
+ TYPE_RECT2:
+ return "Rect2"
+ TYPE_RECT2I:
+ return "Rect2i"
+ TYPE_VECTOR3:
+ return "Vector3"
+ TYPE_VECTOR3I:
+ return "Vector3i"
+ TYPE_TRANSFORM2D:
+ return "Transform2D"
+ TYPE_VECTOR4:
+ return "Vector4"
+ TYPE_VECTOR4I:
+ return "Vector4i"
+ TYPE_PLANE:
+ return "Plane"
+ TYPE_QUATERNION:
+ return "Quaternion"
+ TYPE_AABB:
+ return "AABB"
+ TYPE_BASIS:
+ return "Basis"
+ TYPE_TRANSFORM3D:
+ return "Transform3D"
+ TYPE_PROJECTION:
+ return "Projection"
+ TYPE_COLOR:
+ return "Color"
+ TYPE_STRING_NAME:
+ return "StringName"
+ TYPE_NODE_PATH:
+ return "NodePath"
+ TYPE_RID:
+ return "RID"
+ TYPE_OBJECT:
+ return "Object"
+ TYPE_CALLABLE:
+ return "Callable"
+ TYPE_SIGNAL:
+ return "Signal"
+ TYPE_DICTIONARY:
+ return "Dictionary"
+ TYPE_ARRAY:
+ return "Array"
+ TYPE_PACKED_BYTE_ARRAY:
+ return "PackedByteArray"
+ TYPE_PACKED_INT32_ARRAY:
+ return "PackedInt32Array"
+ TYPE_PACKED_INT64_ARRAY:
+ return "PackedInt64Array"
+ TYPE_PACKED_FLOAT32_ARRAY:
+ return "PackedFloat32Array"
+ TYPE_PACKED_FLOAT64_ARRAY:
+ return "PackedFloat64Array"
+ TYPE_PACKED_STRING_ARRAY:
+ return "PackedStringArray"
+ TYPE_PACKED_VECTOR2_ARRAY:
+ return "PackedVector2Array"
+ TYPE_PACKED_VECTOR3_ARRAY:
+ return "PackedVector3Array"
+ TYPE_PACKED_COLOR_ARRAY:
+ return "PackedColorArray"
+ push_error("Argument `type` is invalid. Use `TYPE_*` constants.")
+ return "<invalid type>"
+
+
+static func get_property_hint_name(hint: PropertyHint) -> String:
+ match hint:
+ PROPERTY_HINT_NONE:
+ return "PROPERTY_HINT_NONE"
+ PROPERTY_HINT_RANGE:
+ return "PROPERTY_HINT_RANGE"
+ PROPERTY_HINT_ENUM:
+ return "PROPERTY_HINT_ENUM"
+ PROPERTY_HINT_ENUM_SUGGESTION:
+ return "PROPERTY_HINT_ENUM_SUGGESTION"
+ PROPERTY_HINT_EXP_EASING:
+ return "PROPERTY_HINT_EXP_EASING"
+ PROPERTY_HINT_LINK:
+ return "PROPERTY_HINT_LINK"
+ PROPERTY_HINT_FLAGS:
+ return "PROPERTY_HINT_FLAGS"
+ PROPERTY_HINT_LAYERS_2D_RENDER:
+ return "PROPERTY_HINT_LAYERS_2D_RENDER"
+ PROPERTY_HINT_LAYERS_2D_PHYSICS:
+ return "PROPERTY_HINT_LAYERS_2D_PHYSICS"
+ PROPERTY_HINT_LAYERS_2D_NAVIGATION:
+ return "PROPERTY_HINT_LAYERS_2D_NAVIGATION"
+ PROPERTY_HINT_LAYERS_3D_RENDER:
+ return "PROPERTY_HINT_LAYERS_3D_RENDER"
+ PROPERTY_HINT_LAYERS_3D_PHYSICS:
+ return "PROPERTY_HINT_LAYERS_3D_PHYSICS"
+ PROPERTY_HINT_LAYERS_3D_NAVIGATION:
+ return "PROPERTY_HINT_LAYERS_3D_NAVIGATION"
+ PROPERTY_HINT_LAYERS_AVOIDANCE:
+ return "PROPERTY_HINT_LAYERS_AVOIDANCE"
+ PROPERTY_HINT_FILE:
+ return "PROPERTY_HINT_FILE"
+ PROPERTY_HINT_DIR:
+ return "PROPERTY_HINT_DIR"
+ PROPERTY_HINT_GLOBAL_FILE:
+ return "PROPERTY_HINT_GLOBAL_FILE"
+ PROPERTY_HINT_GLOBAL_DIR:
+ return "PROPERTY_HINT_GLOBAL_DIR"
+ PROPERTY_HINT_RESOURCE_TYPE:
+ return "PROPERTY_HINT_RESOURCE_TYPE"
+ PROPERTY_HINT_MULTILINE_TEXT:
+ return "PROPERTY_HINT_MULTILINE_TEXT"
+ PROPERTY_HINT_EXPRESSION:
+ return "PROPERTY_HINT_EXPRESSION"
+ PROPERTY_HINT_PLACEHOLDER_TEXT:
+ return "PROPERTY_HINT_PLACEHOLDER_TEXT"
+ PROPERTY_HINT_COLOR_NO_ALPHA:
+ return "PROPERTY_HINT_COLOR_NO_ALPHA"
+ PROPERTY_HINT_OBJECT_ID:
+ return "PROPERTY_HINT_OBJECT_ID"
+ PROPERTY_HINT_TYPE_STRING:
+ return "PROPERTY_HINT_TYPE_STRING"
+ PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE:
+ return "PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE"
+ PROPERTY_HINT_OBJECT_TOO_BIG:
+ return "PROPERTY_HINT_OBJECT_TOO_BIG"
+ PROPERTY_HINT_NODE_PATH_VALID_TYPES:
+ return "PROPERTY_HINT_NODE_PATH_VALID_TYPES"
+ PROPERTY_HINT_SAVE_FILE:
+ return "PROPERTY_HINT_SAVE_FILE"
+ PROPERTY_HINT_GLOBAL_SAVE_FILE:
+ return "PROPERTY_HINT_GLOBAL_SAVE_FILE"
+ PROPERTY_HINT_INT_IS_OBJECTID:
+ return "PROPERTY_HINT_INT_IS_OBJECTID"
+ PROPERTY_HINT_INT_IS_POINTER:
+ return "PROPERTY_HINT_INT_IS_POINTER"
+ PROPERTY_HINT_ARRAY_TYPE:
+ return "PROPERTY_HINT_ARRAY_TYPE"
+ PROPERTY_HINT_LOCALE_ID:
+ return "PROPERTY_HINT_LOCALE_ID"
+ PROPERTY_HINT_LOCALIZABLE_STRING:
+ return "PROPERTY_HINT_LOCALIZABLE_STRING"
+ PROPERTY_HINT_NODE_TYPE:
+ return "PROPERTY_HINT_NODE_TYPE"
+ PROPERTY_HINT_HIDE_QUATERNION_EDIT:
+ return "PROPERTY_HINT_HIDE_QUATERNION_EDIT"
+ PROPERTY_HINT_PASSWORD:
+ return "PROPERTY_HINT_PASSWORD"
+ push_error("Argument `hint` is invalid. Use `PROPERTY_HINT_*` constants.")
+ return "<invalid hint>"
+
+
+static func get_property_usage_string(usage: int) -> String:
+ if usage == PROPERTY_USAGE_NONE:
+ return "PROPERTY_USAGE_NONE"
+
+ const FLAGS: Array[Array] = [
+ [PROPERTY_USAGE_DEFAULT, "PROPERTY_USAGE_DEFAULT"],
+ [PROPERTY_USAGE_STORAGE, "PROPERTY_USAGE_STORAGE"],
+ [PROPERTY_USAGE_EDITOR, "PROPERTY_USAGE_EDITOR"],
+ [PROPERTY_USAGE_INTERNAL, "PROPERTY_USAGE_INTERNAL"],
+ [PROPERTY_USAGE_CHECKABLE, "PROPERTY_USAGE_CHECKABLE"],
+ [PROPERTY_USAGE_CHECKED, "PROPERTY_USAGE_CHECKED"],
+ [PROPERTY_USAGE_GROUP, "PROPERTY_USAGE_GROUP"],
+ [PROPERTY_USAGE_CATEGORY, "PROPERTY_USAGE_CATEGORY"],
+ [PROPERTY_USAGE_SUBGROUP, "PROPERTY_USAGE_SUBGROUP"],
+ [PROPERTY_USAGE_CLASS_IS_BITFIELD, "PROPERTY_USAGE_CLASS_IS_BITFIELD"],
+ [PROPERTY_USAGE_NO_INSTANCE_STATE, "PROPERTY_USAGE_NO_INSTANCE_STATE"],
+ [PROPERTY_USAGE_RESTART_IF_CHANGED, "PROPERTY_USAGE_RESTART_IF_CHANGED"],
+ [PROPERTY_USAGE_SCRIPT_VARIABLE, "PROPERTY_USAGE_SCRIPT_VARIABLE"],
+ [PROPERTY_USAGE_STORE_IF_NULL, "PROPERTY_USAGE_STORE_IF_NULL"],
+ [PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED, "PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED"],
+ [PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE, "PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE"],
+ [PROPERTY_USAGE_CLASS_IS_ENUM, "PROPERTY_USAGE_CLASS_IS_ENUM"],
+ [PROPERTY_USAGE_NIL_IS_VARIANT, "PROPERTY_USAGE_NIL_IS_VARIANT"],
+ [PROPERTY_USAGE_ARRAY, "PROPERTY_USAGE_ARRAY"],
+ [PROPERTY_USAGE_ALWAYS_DUPLICATE, "PROPERTY_USAGE_ALWAYS_DUPLICATE"],
+ [PROPERTY_USAGE_NEVER_DUPLICATE, "PROPERTY_USAGE_NEVER_DUPLICATE"],
+ [PROPERTY_USAGE_HIGH_END_GFX, "PROPERTY_USAGE_HIGH_END_GFX"],
+ [PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT, "PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT"],
+ [PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT, "PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT"],
+ [PROPERTY_USAGE_KEYING_INCREMENTS, "PROPERTY_USAGE_KEYING_INCREMENTS"],
+ [PROPERTY_USAGE_DEFERRED_SET_RESOURCE, "PROPERTY_USAGE_DEFERRED_SET_RESOURCE"],
+ [PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT, "PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT"],
+ [PROPERTY_USAGE_EDITOR_BASIC_SETTING, "PROPERTY_USAGE_EDITOR_BASIC_SETTING"],
+ [PROPERTY_USAGE_READ_ONLY, "PROPERTY_USAGE_READ_ONLY"],
+ [PROPERTY_USAGE_SECRET, "PROPERTY_USAGE_SECRET"],
+ ]
+
+ var result: String = ""
+
+ for flag in FLAGS:
+ if usage & flag[0]:
+ result += flag[1] + "|"
+ usage &= ~flag[0]
+
+ if usage != PROPERTY_USAGE_NONE:
+ push_error("Argument `usage` is invalid. Use `PROPERTY_USAGE_*` constants.")
+ return "<invalid usage flags>"
+
+ return result.left(-1)