summaryrefslogtreecommitdiff
path: root/modules/gdscript/tests
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/tests')
-rw-r--r--modules/gdscript/tests/README.md2
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp96
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.h62
-rw-r--r--modules/gdscript/tests/gdscript_test_runner_suite.h61
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/abstract_class_instantiate.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/abstract_class_instantiate.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/abstract_script_instantiate.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/abstract_script_instantiate.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/annotation_non_constant_parameter.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/annotation_non_constant_parameter.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_enum.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_enum.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_named_enum.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_named_enum.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property_indirectly.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property_indirectly.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assymetric_assignment_bad.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/assymetric_assignment_bad.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/await_signal_no_infer.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/await_signal_no_infer.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constant_array_index_assign.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constant_array_index_assign.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constant_dictionary_index_assign.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constant_dictionary_index_assign.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constant_subscript_type.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constant_subscript_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_bad_method.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_bad_method.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_bad_value.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_bad_value.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_assign_with_wrong_enum_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_init_with_wrong_enum_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_duplicate_bad_method.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_duplicate_bad_method.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_function_parameter_wrong_type.gd8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_function_parameter_wrong_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_function_return_wrong_type.gd8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_function_return_wrong_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_outer_with_wrong_enum_type.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_outer_with_wrong_enum_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_with_wrong_enum_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_init_with_wrong_enum_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_native_bad_value.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_native_bad_value.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_shadows_base_enum.gd8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_shadows_base_enum.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_float.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_float.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_int.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_int.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_enum_value.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_enum_value.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_float.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_float.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_int.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_int.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_iterator.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_iterator.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_string.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_string.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_bool.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_bool.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_int.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_int.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_within_non_node.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_within_non_node.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/incompatible_assignment.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/incompatible_assignment.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_local_variable.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_local_variable.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_member_variable.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_member_variable.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_parameter.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_parameter.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/lambda_no_return.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/lambda_no_return.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/native_type_errors.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/native_type_errors.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node_inner_class.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node_inner_class.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.gd8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.gd8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/ternary_weak_infer.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/ternary_weak_infer.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.gd (renamed from modules/gdscript/tests/scripts/analyzer/typed_array_assignment.gd)0
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.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/typed_array_init_with_unconvertable_in_literal.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.gd3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/allow_get_node_with_onready.gd18
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/allow_get_node_with_onready.out5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.gd20
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.out10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/annotation_constant_expression_parameters.gd10
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/annotation_constant_expression_parameters.out1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/assign_to_native_enum_property.gd13
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/assign_to_native_enum_property.out5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/assymetric_assignment_good.gd16
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/assymetric_assignment_good.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/await_type_inference.gd15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/await_type_inference.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd20
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/const_conversions.gd24
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/const_conversions.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/default_arg_convertable.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/default_arg_convertable.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_access_types.gd29
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_access_types.out13
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd29
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out17
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_duplicate_into_dict.gd13
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_duplicate_into_dict.out7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_from_base.gd13
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_from_base.out (renamed from modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.out)0
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_from_outer.gd (renamed from modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.gd)2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_from_outer.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_function_typecheck.gd112
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_function_typecheck.out55
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_named_no_shadow.gd16
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_named_no_shadow.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_native_access_types.gd19
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_native_access_types.out9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_typecheck_inner_class.gd86
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_typecheck_inner_class.out19
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_unnamed_depend.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/enum_unnamed_depend.out1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/extend_abstract_class.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/extend_abstract_class.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/for_loop_on_variant.gd15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/for_loop_on_variant.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd9
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/hard_variants.gd34
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/hard_variants.out5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lambda_typed.gd12
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lambda_typed.out4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lookup_class.gd50
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lookup_class.out8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lookup_class_external.notest.gd15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lookup_signal.gd41
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lookup_signal.out8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/null_initializer.gd32
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/null_initializer.out5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/onready_on_inner_class_with_non_node_outer.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/onready_on_inner_class_with_non_node_outer.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.gd15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.notest.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.out3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/return_conversions.gd34
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/return_conversions.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/ternary_hard_infer.gd15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/ternary_hard_infer.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.gd17
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.out8
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd211
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/vararg_call.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/vararg_call.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/variant_arg_in_virtual_method.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/variant_arg_in_virtual_method.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/warning_ignore_annotation.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/weak_initializer.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/weak_initializer.out3
-rw-r--r--modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.gd17
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.out22
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/inference_with_variant.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/inference_with_variant.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.out5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/onready_with_export.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/onready_with_export.out6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/overriding_native_method.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/warnings/overriding_native_method.out6
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd6
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/identifier_similar_to_keyword.gd3
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/identifier_similar_to_keyword.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd6
-rw-r--r--modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd62
-rw-r--r--modules/gdscript/tests/scripts/parser/features/allow_id_similar_to_keyword_in_ascii.gd3
-rw-r--r--modules/gdscript/tests/scripts/parser/features/allow_id_similar_to_keyword_in_ascii.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.gd21
-rw-r--r--modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.gd16
-rw-r--r--modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.out6
-rw-r--r--modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd48
-rw-r--r--modules/gdscript/tests/scripts/parser/features/class_name.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_enum.gd15
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_enum.out7
-rw-r--r--modules/gdscript/tests/scripts/parser/features/export_variable.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/lambda_callable.gd6
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match.out1
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_dictionary.gd76
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd40
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd10
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_with_variables.gd22
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_with_variables.out5
-rw-r--r--modules/gdscript/tests/scripts/parser/features/multiline_assert.gd24
-rw-r--r--modules/gdscript/tests/scripts/parser/features/multiline_assert.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/nested_match.gd7
-rw-r--r--modules/gdscript/tests/scripts/parser/features/nested_match.out1
-rw-r--r--modules/gdscript/tests/scripts/parser/features/unicode_identifiers.gd35
-rw-r--r--modules/gdscript/tests/scripts/parser/features/unicode_identifiers.out14
-rw-r--r--modules/gdscript/tests/scripts/parser/features/unnamed_enums_outer_conflicts.gd17
-rw-r--r--modules/gdscript/tests/scripts/parser/features/unnamed_enums_outer_conflicts.out5
-rw-r--r--modules/gdscript/tests/scripts/parser/features/vector_inf.gd6
-rw-r--r--modules/gdscript/tests/scripts/parser/features/vector_inf.out3
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/confusable_identifier.gd12
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/confusable_identifier.out10
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/enum_assign_int_without_casting.out8
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd1
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out6
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/void_assignment.gd6
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/void_assignment.out5
-rw-r--r--modules/gdscript/tests/scripts/runtime/assign_to_read_only_property.gd7
-rw-r--r--modules/gdscript/tests/scripts/runtime/assign_to_read_only_property.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/assign_to_read_only_property_with_variable_index.gd8
-rw-r--r--modules/gdscript/tests/scripts/runtime/assign_to_read_only_property_with_variable_index.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.gd8
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.out8
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.gd6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.gd6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/non_static_method_call_on_native_class.gd6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/non_static_method_call_on_native_class.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.gd7
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.gd7
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd10
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/await_on_void.gd7
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/await_on_void.out2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/constants_are_read_only.gd10
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/constants_are_read_only.out2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.gd19
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out8
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/does_not_override_temp_values.gd17
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/does_not_override_temp_values.out2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_types.gd51
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_types.out14
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/gdscript.gd20
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/gdscript.out3
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd24
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd45
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.out2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.gd6
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.out2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd9
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/typed_assignment.out12
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.gd9
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.out3
-rw-r--r--modules/gdscript/tests/test_gdscript.cpp58
-rw-r--r--modules/gdscript/tests/test_gdscript.h58
332 files changed, 2822 insertions, 383 deletions
diff --git a/modules/gdscript/tests/README.md b/modules/gdscript/tests/README.md
index 6e54085962..361d586d32 100644
--- a/modules/gdscript/tests/README.md
+++ b/modules/gdscript/tests/README.md
@@ -4,5 +4,5 @@ The `scripts/` folder contains integration tests in the form of GDScript files
and output files.
See the
-[Integration tests for GDScript documentation](https://docs.godotengine.org/en/latest/development/cpp/unit_testing.html#integration-tests-for-gdscript)
+[Integration tests for GDScript documentation](https://docs.godotengine.org/en/latest/contributing/development/core_and_modules/unit_testing.html#integration-tests-for-gdscript)
for information about creating and running GDScript integration tests.
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index f59983ca90..57405aa1ce 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* gdscript_test_runner.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* gdscript_test_runner.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "gdscript_test_runner.h"
@@ -132,9 +132,10 @@ void finish_language() {
StringName GDScriptTestRunner::test_function_name;
-GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_language) {
+GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_language, bool p_print_filenames) {
test_function_name = StaticCString::create("test");
do_init_languages = p_init_language;
+ print_filenames = p_print_filenames;
source_dir = p_source_dir;
if (!source_dir.ends_with("/")) {
@@ -145,11 +146,11 @@ GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_l
init_language(p_source_dir);
}
#ifdef DEBUG_ENABLED
- // Enable all warnings for GDScript, so we can test them.
+ // Set all warning levels to "Warn" in order to test them properly, even the ones that default to error.
ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/enable", true);
for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) {
- String warning = GDScriptWarning::get_name_from_code((GDScriptWarning::Code)i).to_lower();
- ProjectSettings::get_singleton()->set_setting("debug/gdscript/warnings/" + warning, true);
+ String warning_setting = GDScriptWarning::get_settings_path_from_code((GDScriptWarning::Code)i);
+ ProjectSettings::get_singleton()->set_setting(warning_setting, (int)GDScriptWarning::WARN);
}
#endif
@@ -194,6 +195,9 @@ int GDScriptTestRunner::run_tests() {
int failed = 0;
for (int i = 0; i < tests.size(); i++) {
GDScriptTest test = tests[i];
+ if (print_filenames) {
+ print_line(test.get_source_relative_filepath());
+ }
GDScriptTest::TestResult result = test.run_test();
String expected = FileAccess::get_file_as_string(test.get_output_file());
@@ -225,8 +229,13 @@ bool GDScriptTestRunner::generate_outputs() {
}
for (int i = 0; i < tests.size(); i++) {
- OS::get_singleton()->print(".");
GDScriptTest test = tests[i];
+ if (print_filenames) {
+ print_line(test.get_source_relative_filepath());
+ } else {
+ OS::get_singleton()->print(".");
+ }
+
bool result = test.generate_output();
if (!result) {
@@ -337,15 +346,10 @@ GDScriptTest::GDScriptTest(const String &p_source_path, const String &p_output_p
void GDScriptTestRunner::handle_cmdline() {
List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
- // TODO: this could likely be ported to use test commands:
- // https://github.com/godotengine/godot/pull/41355
- // Currently requires to startup the whole engine, which is slow.
- String test_cmd = "--gdscript-test";
- String gen_cmd = "--gdscript-generate-tests";
for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) {
String &cmd = E->get();
- if (cmd == test_cmd || cmd == gen_cmd) {
+ if (cmd == "--gdscript-generate-tests") {
if (E->next() == nullptr) {
ERR_PRINT("Needed a path for the test files.");
exit(-1);
@@ -353,14 +357,10 @@ void GDScriptTestRunner::handle_cmdline() {
const String &path = E->next()->get();
- GDScriptTestRunner runner(path, false);
- int failed = 0;
- if (cmd == test_cmd) {
- failed = runner.run_tests();
- } else {
- bool completed = runner.generate_outputs();
- failed = completed ? 0 : -1;
- }
+ GDScriptTestRunner runner(path, false, cmdline_args.find("--print-filenames") != nullptr);
+
+ bool completed = runner.generate_outputs();
+ int failed = completed ? 0 : -1;
exit(failed);
}
}
diff --git a/modules/gdscript/tests/gdscript_test_runner.h b/modules/gdscript/tests/gdscript_test_runner.h
index 033d2fcad1..60b48c6a57 100644
--- a/modules/gdscript/tests/gdscript_test_runner.h
+++ b/modules/gdscript/tests/gdscript_test_runner.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* gdscript_test_runner.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* gdscript_test_runner.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef GDSCRIPT_TEST_RUNNER_H
#define GDSCRIPT_TEST_RUNNER_H
@@ -92,6 +92,7 @@ public:
bool generate_output();
const String &get_source_file() const { return source_file; }
+ const String get_source_relative_filepath() const { return source_file.trim_prefix(base_dir); }
const String &get_output_file() const { return output_file; }
GDScriptTest(const String &p_source_path, const String &p_output_path, const String &p_base_dir);
@@ -105,6 +106,7 @@ class GDScriptTestRunner {
bool is_generating = false;
bool do_init_languages = false;
+ bool print_filenames; // Whether filenames should be printed when generated/running tests
bool make_tests();
bool make_tests_for_dir(const String &p_dir);
@@ -117,7 +119,7 @@ public:
int run_tests();
bool generate_outputs();
- GDScriptTestRunner(const String &p_source_dir, bool p_init_language);
+ GDScriptTestRunner(const String &p_source_dir, bool p_init_language, bool p_print_filenames = false);
~GDScriptTestRunner();
};
diff --git a/modules/gdscript/tests/gdscript_test_runner_suite.h b/modules/gdscript/tests/gdscript_test_runner_suite.h
index 90f6d7f7e8..e27b6218f1 100644
--- a/modules/gdscript/tests/gdscript_test_runner_suite.h
+++ b/modules/gdscript/tests/gdscript_test_runner_suite.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* gdscript_test_runner_suite.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* gdscript_test_runner_suite.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef GDSCRIPT_TEST_RUNNER_SUITE_H
#define GDSCRIPT_TEST_RUNNER_SUITE_H
@@ -41,7 +41,8 @@ TEST_SUITE("[Modules][GDScript]") {
// Allow the tests to fail, but do not ignore errors during development.
// Update the scripts and expected output as needed.
TEST_CASE("Script compilation and runtime") {
- GDScriptTestRunner runner("modules/gdscript/tests/scripts", true);
+ bool print_filenames = OS::get_singleton()->get_cmdline_args().find("--print-filenames") != nullptr;
+ GDScriptTestRunner runner("modules/gdscript/tests/scripts", true, print_filenames);
int fail_count = runner.run_tests();
INFO("Make sure `*.out` files have expected results.");
REQUIRE_MESSAGE(fail_count == 0, "All GDScript tests should pass.");
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/abstract_class_instantiate.gd b/modules/gdscript/tests/scripts/analyzer/errors/abstract_class_instantiate.gd
new file mode 100644
index 0000000000..38c2faa859
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/abstract_class_instantiate.gd
@@ -0,0 +1,2 @@
+func test():
+ CanvasItem.new()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/abstract_class_instantiate.out b/modules/gdscript/tests/scripts/analyzer/errors/abstract_class_instantiate.out
new file mode 100644
index 0000000000..9eff912b59
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/abstract_class_instantiate.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Native class "CanvasItem" cannot be constructed as it is abstract.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/abstract_script_instantiate.gd b/modules/gdscript/tests/scripts/analyzer/errors/abstract_script_instantiate.gd
new file mode 100644
index 0000000000..118e7e8a45
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/abstract_script_instantiate.gd
@@ -0,0 +1,9 @@
+class A extends CanvasItem:
+ func _init():
+ print('no')
+
+class B extends A:
+ pass
+
+func test():
+ B.new()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/abstract_script_instantiate.out b/modules/gdscript/tests/scripts/analyzer/errors/abstract_script_instantiate.out
new file mode 100644
index 0000000000..8b956f5974
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/abstract_script_instantiate.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Class "abstract_script_instantiate.gd::B" cannot be constructed as it is based on abstract native class "CanvasItem".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/annotation_non_constant_parameter.gd b/modules/gdscript/tests/scripts/analyzer/errors/annotation_non_constant_parameter.gd
new file mode 100644
index 0000000000..75524c32ae
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/annotation_non_constant_parameter.gd
@@ -0,0 +1,6 @@
+var num := 1
+
+@export_range(num, 10) var a
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/annotation_non_constant_parameter.out b/modules/gdscript/tests/scripts/analyzer/errors/annotation_non_constant_parameter.out
new file mode 100644
index 0000000000..b4f0e79237
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/annotation_non_constant_parameter.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Argument 1 of annotation "@export_range" isn't a constant expression.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_enum.gd b/modules/gdscript/tests/scripts/analyzer/errors/assign_enum.gd
new file mode 100644
index 0000000000..8123fc53d9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_enum.gd
@@ -0,0 +1,3 @@
+enum { V }
+func test():
+ V = 1
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_enum.out b/modules/gdscript/tests/scripts/analyzer/errors/assign_enum.out
new file mode 100644
index 0000000000..5275183da2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_enum.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a new value to a constant.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_named_enum.gd b/modules/gdscript/tests/scripts/analyzer/errors/assign_named_enum.gd
new file mode 100644
index 0000000000..da2b13d690
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_named_enum.gd
@@ -0,0 +1,3 @@
+enum NamedEnum { V }
+func test():
+ NamedEnum.V = 1
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_named_enum.out b/modules/gdscript/tests/scripts/analyzer/errors/assign_named_enum.out
new file mode 100644
index 0000000000..5275183da2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_named_enum.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a new value to a constant.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property.gd b/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property.gd
new file mode 100644
index 0000000000..2b1c4c9594
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property.gd
@@ -0,0 +1,4 @@
+func test():
+ var tree := SceneTree.new()
+ tree.root = Window.new()
+ tree.free()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property.out b/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property.out
new file mode 100644
index 0000000000..b236d70ec8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a new value to a read-only property.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property_indirectly.gd b/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property_indirectly.gd
new file mode 100644
index 0000000000..c97ee0ea69
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property_indirectly.gd
@@ -0,0 +1,4 @@
+func test():
+ var state := PhysicsDirectBodyState3DExtension.new()
+ state.center_of_mass.x += 1.0
+ state.free()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property_indirectly.out b/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property_indirectly.out
new file mode 100644
index 0000000000..b236d70ec8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assign_to_read_only_property_indirectly.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a new value to a read-only property.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assymetric_assignment_bad.gd b/modules/gdscript/tests/scripts/analyzer/errors/assymetric_assignment_bad.gd
new file mode 100644
index 0000000000..1b22d173c7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assymetric_assignment_bad.gd
@@ -0,0 +1,3 @@
+func test():
+ var var_color: String = Color.RED
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/assymetric_assignment_bad.out b/modules/gdscript/tests/scripts/analyzer/errors/assymetric_assignment_bad.out
new file mode 100644
index 0000000000..cc4b1d86bf
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/assymetric_assignment_bad.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a value of type "Color" as "String".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/await_signal_no_infer.gd b/modules/gdscript/tests/scripts/analyzer/errors/await_signal_no_infer.gd
new file mode 100644
index 0000000000..c787d9e50e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/await_signal_no_infer.gd
@@ -0,0 +1,4 @@
+signal my_signal()
+
+func test():
+ var _a := await my_signal
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/await_signal_no_infer.out b/modules/gdscript/tests/scripts/analyzer/errors/await_signal_no_infer.out
new file mode 100644
index 0000000000..8f8744ad7e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/await_signal_no_infer.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot infer the type of "_a" variable because the value doesn't have a set type.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constant_array_index_assign.gd b/modules/gdscript/tests/scripts/analyzer/errors/constant_array_index_assign.gd
new file mode 100644
index 0000000000..b8603dd4ca
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constant_array_index_assign.gd
@@ -0,0 +1,5 @@
+const array: Array = [0]
+
+func test():
+ var key: int = 0
+ array[key] = 0
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constant_array_index_assign.out b/modules/gdscript/tests/scripts/analyzer/errors/constant_array_index_assign.out
new file mode 100644
index 0000000000..5275183da2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constant_array_index_assign.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a new value to a constant.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constant_dictionary_index_assign.gd b/modules/gdscript/tests/scripts/analyzer/errors/constant_dictionary_index_assign.gd
new file mode 100644
index 0000000000..9b5112b788
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constant_dictionary_index_assign.gd
@@ -0,0 +1,5 @@
+const dictionary := {}
+
+func test():
+ var key: int = 0
+ dictionary[key] = 0
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constant_dictionary_index_assign.out b/modules/gdscript/tests/scripts/analyzer/errors/constant_dictionary_index_assign.out
new file mode 100644
index 0000000000..5275183da2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constant_dictionary_index_assign.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a new value to a constant.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constant_subscript_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/constant_subscript_type.gd
new file mode 100644
index 0000000000..87fbe1229c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constant_subscript_type.gd
@@ -0,0 +1,5 @@
+const base := [0]
+
+func test():
+ var sub := base[0]
+ if sub is String: pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constant_subscript_type.out b/modules/gdscript/tests/scripts/analyzer/errors/constant_subscript_type.out
new file mode 100644
index 0000000000..54c190cf8a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constant_subscript_type.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "int" so it can't be of type "String".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd
new file mode 100644
index 0000000000..251be70088
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd
@@ -0,0 +1,10 @@
+class A:
+ func _init():
+ pass
+
+class B extends A: pass
+class C extends A: pass
+
+func test():
+ var x := B.new()
+ print(x is C)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out
new file mode 100644
index 0000000000..91d5125ec0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "B" so it can't be of type "C".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_method.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_method.gd
new file mode 100644
index 0000000000..2940c03515
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_method.gd
@@ -0,0 +1,4 @@
+enum Enum {V1, V2}
+
+func test():
+ Enum.clear()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_method.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_method.out
new file mode 100644
index 0000000000..9ca86eca9c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_method.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot call non-const Dictionary function "clear()" on enum "Enum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_value.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_value.gd
new file mode 100644
index 0000000000..a66e2714d9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_value.gd
@@ -0,0 +1,4 @@
+enum Enum {V1, V2}
+
+func test():
+ var bad = Enum.V3
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_value.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_value.out
new file mode 100644
index 0000000000..ddbdc17a42
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_bad_value.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot find member "V3" in base "enum_bad_value.gd::Enum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_assign_with_wrong_enum_type.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_assign_with_wrong_enum_type.out
index fde7e92f8c..84958f1aa2 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_assign_with_wrong_enum_type.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_assign_with_wrong_enum_type.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Cannot assign a value of type "MyOtherEnum (enum)" to a target of type "MyEnum (enum)".
+Cannot assign a value of type "enum_class_var_assign_with_wrong_enum_type.gd::MyOtherEnum" as "enum_class_var_assign_with_wrong_enum_type.gd::MyEnum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_init_with_wrong_enum_type.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_init_with_wrong_enum_type.out
index b1710c798d..e294f3496a 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_init_with_wrong_enum_type.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_class_var_init_with_wrong_enum_type.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Value of type "MyOtherEnum (enum)" cannot be assigned to a variable of type "MyEnum (enum)".
+Cannot assign a value of type "enum_class_var_init_with_wrong_enum_type.gd::MyOtherEnum" as "enum_class_var_init_with_wrong_enum_type.gd::MyEnum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_duplicate_bad_method.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_duplicate_bad_method.gd
new file mode 100644
index 0000000000..2c7dfafd06
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_duplicate_bad_method.gd
@@ -0,0 +1,5 @@
+enum Enum {V1, V2}
+
+func test():
+ var Enum2 = Enum
+ Enum2.clear()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_duplicate_bad_method.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_duplicate_bad_method.out
new file mode 100644
index 0000000000..9ca86eca9c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_duplicate_bad_method.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot call non-const Dictionary function "clear()" on enum "Enum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_function_parameter_wrong_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_parameter_wrong_type.gd
new file mode 100644
index 0000000000..62ac1c3108
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_parameter_wrong_type.gd
@@ -0,0 +1,8 @@
+enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
+enum MyOtherEnum { OTHER_ENUM_VALUE_1, OTHER_ENUM_VALUE_2 }
+
+func enum_func(e : MyEnum) -> void:
+ print(e)
+
+func test():
+ enum_func(MyOtherEnum.OTHER_ENUM_VALUE_1)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_function_parameter_wrong_type.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_parameter_wrong_type.out
new file mode 100644
index 0000000000..a91189e2dd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_parameter_wrong_type.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot pass a value of type "enum_function_parameter_wrong_type.gd::MyOtherEnum" as "enum_function_parameter_wrong_type.gd::MyEnum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_function_return_wrong_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_return_wrong_type.gd
new file mode 100644
index 0000000000..18b3ffb0fc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_return_wrong_type.gd
@@ -0,0 +1,8 @@
+enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
+enum MyOtherEnum { OTHER_ENUM_VALUE_1, OTHER_ENUM_VALUE_2 }
+
+func enum_func() -> MyEnum:
+ return MyOtherEnum.OTHER_ENUM_VALUE_1
+
+func test():
+ print(enum_func())
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_function_return_wrong_type.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_return_wrong_type.out
new file mode 100644
index 0000000000..6b4eba3740
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_return_wrong_type.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot return a value of type "enum_function_return_wrong_type.gd::MyOtherEnum" as "enum_function_return_wrong_type.gd::MyEnum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_outer_with_wrong_enum_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_outer_with_wrong_enum_type.gd
new file mode 100644
index 0000000000..2b006f1f69
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_outer_with_wrong_enum_type.gd
@@ -0,0 +1,10 @@
+enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
+
+class InnerClass:
+ enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
+
+func test():
+ var local_var: MyEnum = MyEnum.ENUM_VALUE_1
+ print(local_var)
+ local_var = InnerClass.MyEnum.ENUM_VALUE_2
+ print(local_var)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_outer_with_wrong_enum_type.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_outer_with_wrong_enum_type.out
new file mode 100644
index 0000000000..616358bb61
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_outer_with_wrong_enum_type.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a value of type "enum_local_var_assign_outer_with_wrong_enum_type.gd::InnerClass::MyEnum" as "enum_local_var_assign_outer_with_wrong_enum_type.gd::MyEnum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_with_wrong_enum_type.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_with_wrong_enum_type.out
index fde7e92f8c..af3dde663f 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_with_wrong_enum_type.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_with_wrong_enum_type.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Cannot assign a value of type "MyOtherEnum (enum)" to a target of type "MyEnum (enum)".
+Cannot assign a value of type "enum_local_var_assign_with_wrong_enum_type.gd::MyOtherEnum" as "enum_local_var_assign_with_wrong_enum_type.gd::MyEnum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_init_with_wrong_enum_type.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_init_with_wrong_enum_type.out
index b1710c798d..781b0bc85f 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_init_with_wrong_enum_type.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_init_with_wrong_enum_type.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Value of type "MyOtherEnum (enum)" cannot be assigned to a variable of type "MyEnum (enum)".
+Cannot assign a value of type "enum_local_var_init_with_wrong_enum_type.gd::MyOtherEnum" as "enum_local_var_init_with_wrong_enum_type.gd::MyEnum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_native_bad_value.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_native_bad_value.gd
new file mode 100644
index 0000000000..744c2e47ce
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_native_bad_value.gd
@@ -0,0 +1,2 @@
+func test():
+ var _bad = TileSet.TileShape.THIS_DOES_NOT_EXIST
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_native_bad_value.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_native_bad_value.out
new file mode 100644
index 0000000000..49f041a2dd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_native_bad_value.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot find member "THIS_DOES_NOT_EXIST" in base "TileSet::TileShape".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.gd
new file mode 100644
index 0000000000..81d5d59ae8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.gd
@@ -0,0 +1,7 @@
+enum MyEnum { VALUE_A, VALUE_B, VALUE_C = 42 }
+
+func test():
+ const P = preload("../features/enum_value_from_parent.gd")
+ var local_var: MyEnum
+ local_var = P.VALUE_B
+ print(local_var)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.out
new file mode 100644
index 0000000000..e8c7f86c4f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a value of type "enum_value_from_parent.gd::<anonymous enum>" as "enum_preload_unnamed_assign_to_named.gd::MyEnum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_shadows_base_enum.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_shadows_base_enum.gd
new file mode 100644
index 0000000000..96904c297a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_shadows_base_enum.gd
@@ -0,0 +1,8 @@
+class A:
+ enum { V }
+
+class B extends A:
+ enum { V }
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_shadows_base_enum.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_shadows_base_enum.out
new file mode 100644
index 0000000000..7961a1a481
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_shadows_base_enum.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+The member "V" already exists in parent class A.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.gd
new file mode 100644
index 0000000000..7e749db6b5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.gd
@@ -0,0 +1,7 @@
+enum { ENUM_VALUE_1, ENUM_VALUE_2 }
+
+enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
+
+func test():
+ var local_var: MyEnum = ENUM_VALUE_1
+ print(local_var)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.out
new file mode 100644
index 0000000000..fb18c94d0b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a value of type "enum_unnamed_assign_to_named.gd::<anonymous enum>" as "enum_unnamed_assign_to_named.gd::MyEnum".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_float.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_float.gd
new file mode 100644
index 0000000000..cf56a0a933
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_float.gd
@@ -0,0 +1,6 @@
+const constant_float = 1.0
+
+func test():
+ for x in constant_float:
+ if x is String:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_float.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_float.out
new file mode 100644
index 0000000000..e309831b3e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_float.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "float" so it can't be of type "String".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_int.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_int.gd
new file mode 100644
index 0000000000..5ee8ac19e1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_int.gd
@@ -0,0 +1,6 @@
+const constant_int = 1
+
+func test():
+ for x in constant_int:
+ if x is String:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_int.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_int.out
new file mode 100644
index 0000000000..54c190cf8a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_constant_int.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "int" so it can't be of type "String".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_enum_value.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_enum_value.gd
new file mode 100644
index 0000000000..b3db4f3b49
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_enum_value.gd
@@ -0,0 +1,6 @@
+enum { enum_value = 1 }
+
+func test():
+ for x in enum_value:
+ if x is String:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_enum_value.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_enum_value.out
new file mode 100644
index 0000000000..54c190cf8a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_enum_value.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "int" so it can't be of type "String".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_float.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_float.gd
new file mode 100644
index 0000000000..87c54f7402
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_float.gd
@@ -0,0 +1,6 @@
+func test():
+ var hard_float := 1.0
+
+ for x in hard_float:
+ if x is String:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_float.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_float.out
new file mode 100644
index 0000000000..e309831b3e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_float.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "float" so it can't be of type "String".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_int.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_int.gd
new file mode 100644
index 0000000000..2a43f5a930
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_int.gd
@@ -0,0 +1,6 @@
+func test():
+ var hard_int := 1
+
+ for x in hard_int:
+ if x is String:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_int.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_int.out
new file mode 100644
index 0000000000..54c190cf8a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_int.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "int" so it can't be of type "String".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_iterator.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_iterator.gd
new file mode 100644
index 0000000000..c3920d35b3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_iterator.gd
@@ -0,0 +1,14 @@
+class Iterator:
+ func _iter_init(_count):
+ return true
+ func _iter_next(_count):
+ return false
+ func _iter_get(_count) -> StringName:
+ return &'custom'
+
+func test():
+ var hard_iterator := Iterator.new()
+
+ for x in hard_iterator:
+ if x is int:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_iterator.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_iterator.out
new file mode 100644
index 0000000000..a48591a3b4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_iterator.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "StringName" so it can't be of type "int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_string.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_string.gd
new file mode 100644
index 0000000000..b36d87aabe
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_string.gd
@@ -0,0 +1,6 @@
+func test():
+ var hard_string := 'a'
+
+ for x in hard_string:
+ if x is int:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_string.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_string.out
new file mode 100644
index 0000000000..92c5ebc599
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_hard_string.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "String" so it can't be of type "int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_bool.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_bool.gd
new file mode 100644
index 0000000000..060a8bedf9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_bool.gd
@@ -0,0 +1,3 @@
+func test():
+ for x in true:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_bool.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_bool.out
new file mode 100644
index 0000000000..94cb038885
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_bool.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Unable to iterate on value of type "bool".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_int.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_int.gd
new file mode 100644
index 0000000000..6cfc822482
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_int.gd
@@ -0,0 +1,4 @@
+func test():
+ for x in 1:
+ if x is String:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_int.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_int.out
new file mode 100644
index 0000000000..54c190cf8a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_on_literal_int.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression is of type "int" so it can't be of type "String".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out
index c70a1df10d..508e46742f 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-The function signature doesn't match the parent. Parent signature is "my_function(int = default) -> int".
+The function signature doesn't match the parent. Parent signature is "my_function(int = <default>) -> int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_within_non_node.gd b/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_within_non_node.gd
new file mode 100644
index 0000000000..91f5071fa9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_within_non_node.gd
@@ -0,0 +1,5 @@
+extends RefCounted
+
+func test():
+ var nope := $Node
+ print("Cannot use $ without a Node base")
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_within_non_node.out b/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_within_non_node.out
new file mode 100644
index 0000000000..33365908bf
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/get_node_shorthand_within_non_node.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot use shorthand "get_node()" notation ("$") on a class that isn't a node.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/incompatible_assignment.gd b/modules/gdscript/tests/scripts/analyzer/errors/incompatible_assignment.gd
new file mode 100644
index 0000000000..664e364493
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/incompatible_assignment.gd
@@ -0,0 +1,3 @@
+func test():
+ var foo: bool = true
+ foo += 'bar'
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/incompatible_assignment.out b/modules/gdscript/tests/scripts/analyzer/errors/incompatible_assignment.out
new file mode 100644
index 0000000000..358b096a64
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/incompatible_assignment.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Invalid operands "bool" and "String" for assignment operator.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_local_variable.gd b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_local_variable.gd
new file mode 100644
index 0000000000..6014ee831c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_local_variable.gd
@@ -0,0 +1,3 @@
+func test():
+ var untyped = 1
+ var inferred := untyped
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_local_variable.out b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_local_variable.out
new file mode 100644
index 0000000000..b6dc6d0b01
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_local_variable.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot infer the type of "inferred" variable because the value doesn't have a set type.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_member_variable.gd b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_member_variable.gd
new file mode 100644
index 0000000000..040aa2e82a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_member_variable.gd
@@ -0,0 +1,5 @@
+var untyped = 1
+var inferred := untyped
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_member_variable.out b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_member_variable.out
new file mode 100644
index 0000000000..b6dc6d0b01
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_member_variable.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot infer the type of "inferred" variable because the value doesn't have a set type.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_parameter.gd b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_parameter.gd
new file mode 100644
index 0000000000..80c676488e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_parameter.gd
@@ -0,0 +1,5 @@
+func check(untyped = 1, inferred := untyped):
+ pass
+
+func test():
+ check()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_parameter.out b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_parameter.out
new file mode 100644
index 0000000000..8c9f0c13ae
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/inferring_with_weak_type_parameter.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot infer the type of "inferred" parameter because the value doesn't have a set type.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out
index 6f7f0783f0..015ad756f8 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Cannot get index "true" from "[0, 1]".
+Invalid index type "bool" for a base of type "Array".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/lambda_no_return.gd b/modules/gdscript/tests/scripts/analyzer/errors/lambda_no_return.gd
new file mode 100644
index 0000000000..70973c33d4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/lambda_no_return.gd
@@ -0,0 +1,4 @@
+func test():
+ var lambda := func() -> int:
+ print('no return')
+ lambda.call()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/lambda_no_return.out b/modules/gdscript/tests/scripts/analyzer/errors/lambda_no_return.out
new file mode 100644
index 0000000000..fe1472c54d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/lambda_no_return.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Not all code paths return a value.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.gd b/modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.gd
new file mode 100644
index 0000000000..3c247a5b02
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.gd
@@ -0,0 +1,4 @@
+func test():
+ var lambda := func() -> int:
+ return 'string'
+ print(lambda.call())
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.out b/modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.out
new file mode 100644
index 0000000000..69af0984f7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot return a value of type "String" as "int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.gd b/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.gd
new file mode 100644
index 0000000000..6d92db34c1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.gd
@@ -0,0 +1,5 @@
+func test():
+ var dict = { a = 1 }
+ match 2:
+ dict["a"]:
+ print("not allowed")
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.out b/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.out
new file mode 100644
index 0000000000..b7385a50d5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression in match pattern must be a constant expression, an identifier, or an attribute access ("A.B").
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.gd b/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.gd
new file mode 100644
index 0000000000..4df44d9ea2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.gd
@@ -0,0 +1,5 @@
+func test():
+ var a = 1
+ match 2:
+ a + 2:
+ print("not allowed")
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.out b/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.out
new file mode 100644
index 0000000000..b7385a50d5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression in match pattern must be a constant expression, an identifier, or an attribute access ("A.B").
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd
new file mode 100644
index 0000000000..dd2708b21d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.gd
@@ -0,0 +1,7 @@
+func test():
+ var x = Node.new()
+
+ x.free()
+
+ var ok = x
+ var bad : Node = x
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out
new file mode 100644
index 0000000000..679e51ed81
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/native_freed_instance.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> analyzer/errors/native_freed_instance.gd
+>> 7
+>> Trying to assign invalid previously freed instance.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/native_type_errors.gd b/modules/gdscript/tests/scripts/analyzer/errors/native_type_errors.gd
new file mode 100644
index 0000000000..e1bed94406
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/native_type_errors.gd
@@ -0,0 +1,2 @@
+func test():
+ TileSet.this_does_not_exist # Does not exist
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/native_type_errors.out b/modules/gdscript/tests/scripts/analyzer/errors/native_type_errors.out
new file mode 100644
index 0000000000..06180c3a55
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/native_type_errors.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot find member "this_does_not_exist" in base "TileSet".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node.gd b/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node.gd
new file mode 100644
index 0000000000..e781315266
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node.gd
@@ -0,0 +1,6 @@
+extends RefCounted
+
+@onready var nope := 0
+
+func test():
+ print("Cannot use @onready without a Node base")
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node.out b/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node.out
new file mode 100644
index 0000000000..8088d28329
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+"@onready" can only be used in classes that inherit "Node".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node_inner_class.gd b/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node_inner_class.gd
new file mode 100644
index 0000000000..1639bbbd52
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node_inner_class.gd
@@ -0,0 +1,7 @@
+extends Node
+
+class Inner extends RefCounted:
+ @onready var nope = 0
+
+func test():
+ print("Cannot use @onready without a Node base")
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node_inner_class.out b/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node_inner_class.out
new file mode 100644
index 0000000000..8088d28329
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/onready_within_non_node_inner_class.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+"@onready" can only be used in classes that inherit "Node".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.gd b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.gd
new file mode 100644
index 0000000000..1cf3870a8e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.gd
@@ -0,0 +1,8 @@
+class Outer:
+ const OUTER_CONST: = 0
+ class Inner:
+ pass
+
+func test() -> void:
+ var type: = Outer.Inner
+ print(type.OUTER_CONST)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.out
new file mode 100644
index 0000000000..73a54d7820
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> analyzer/errors/outer_class_constants.gd
+>> 8
+>> Invalid get index 'OUTER_CONST' (on base: 'GDScript').
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.gd b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.gd
new file mode 100644
index 0000000000..c1074df915
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.gd
@@ -0,0 +1,9 @@
+class Outer:
+ const OUTER_CONST: = 0
+ class Inner:
+ pass
+
+func test() -> void:
+ var type: = Outer.Inner
+ var type_v: Variant = type
+ print(type_v.OUTER_CONST)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.out
new file mode 100644
index 0000000000..92e7b9316e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_constants_as_variant.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> analyzer/errors/outer_class_constants_as_variant.gd
+>> 9
+>> Invalid get index 'OUTER_CONST' (on base: 'GDScript').
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.gd b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.gd
new file mode 100644
index 0000000000..2631c3c500
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.gd
@@ -0,0 +1,8 @@
+class Outer:
+ const OUTER_CONST: = 0
+ class Inner:
+ pass
+
+func test() -> void:
+ var instance: = Outer.Inner.new()
+ print(instance.OUTER_CONST)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.out
new file mode 100644
index 0000000000..892f8e2c3f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> analyzer/errors/outer_class_instance_constants.gd
+>> 8
+>> Invalid get index 'OUTER_CONST' (on base: 'RefCounted (Inner)').
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.gd b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.gd
new file mode 100644
index 0000000000..cba788381e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.gd
@@ -0,0 +1,9 @@
+class Outer:
+ const OUTER_CONST: = 0
+ class Inner:
+ pass
+
+func test() -> void:
+ var instance: = Outer.Inner.new()
+ var instance_v: Variant = instance
+ print(instance_v.OUTER_CONST)
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.out b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.out
new file mode 100644
index 0000000000..8257e74f57
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_instance_constants_as_variant.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> analyzer/errors/outer_class_instance_constants_as_variant.gd
+>> 9
+>> Invalid get index 'OUTER_CONST' (on base: 'RefCounted (Inner)').
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
index 65c0d9dabc..200c352223 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
@@ -1,12 +1,12 @@
class A:
- class B:
- func test():
- print(A.B.D)
+ class B:
+ func test():
+ print(A.B.D)
class C:
- class D:
- pass
+ class D:
+ pass
func test():
- var inst = A.B.new()
- inst.test()
+ var inst = A.B.new()
+ inst.test()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.gd b/modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.gd
new file mode 100644
index 0000000000..4e75ded96a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.gd
@@ -0,0 +1,6 @@
+enum LocalNamed { VALUE_A, VALUE_B, VALUE_C = 42 }
+
+func test():
+ const P = preload("../features/enum_from_outer.gd")
+ var x : LocalNamed
+ x = P.Named.VALUE_A
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.out b/modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.out
new file mode 100644
index 0000000000..08a973503f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a value of type "enum_from_outer.gd::Named" as "preload_enum_error.gd::LocalNamed".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.out b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.out
index bbadf1ce27..bf776029b9 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/property_inline_set_type_error.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Cannot assign a value of type "String" to a target of type "int".
+Value of type "String" cannot be assigned to a variable of type "int".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.gd b/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.gd
new file mode 100644
index 0000000000..393b66c9f0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.gd
@@ -0,0 +1,2 @@
+func test() -> void:
+ return null
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.out b/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.out
new file mode 100644
index 0000000000..3c09f44ba9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+A void function cannot return a value.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.gd b/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.gd
new file mode 100644
index 0000000000..6be2730bab
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.gd
@@ -0,0 +1,4 @@
+func test() -> void:
+ var a
+ a = 1
+ return a
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.out b/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.out
new file mode 100644
index 0000000000..3c09f44ba9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+A void function cannot return a value.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd
new file mode 100644
index 0000000000..758fbaccc9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.gd
@@ -0,0 +1,10 @@
+class A extends Node:
+ pass
+
+func test():
+ var x = A.new()
+
+ x.free()
+
+ var ok = x
+ var bad : A = x
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out
new file mode 100644
index 0000000000..dec7090322
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/script_freed_instance.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> analyzer/errors/script_freed_instance.gd
+>> 10
+>> Trying to assign invalid previously freed instance.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.out b/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.out
index 9eb2a42ccd..2857cd53c8 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Value of type "int" cannot be assigned to a variable of type "String".
+Cannot assign a value of type int to variable "x" with specified type String.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/ternary_weak_infer.gd b/modules/gdscript/tests/scripts/analyzer/errors/ternary_weak_infer.gd
new file mode 100644
index 0000000000..fac0e8756c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/ternary_weak_infer.gd
@@ -0,0 +1,6 @@
+func test():
+ var left_hard_int := 1
+ var right_weak_int = 2
+ var result_hm_int := left_hard_int if true else right_weak_int
+
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/ternary_weak_infer.out b/modules/gdscript/tests/scripts/analyzer/errors/ternary_weak_infer.out
new file mode 100644
index 0000000000..71d1e2f8ae
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/ternary_weak_infer.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot infer the type of "result_hm_int" variable because the value doesn't have a set type.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.gd
new file mode 100644
index 0000000000..ce50cccb3c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.gd
@@ -0,0 +1,4 @@
+func test():
+ var differently: Array[float] = [1.0]
+ var typed: Array[int] = differently
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.out
new file mode 100644
index 0000000000..c6d39781ee
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assign_differently_typed.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot assign a value of type Array[float] to variable "typed" with specified type Array[int].
diff --git a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.gd
index 9f86d0531c..9f86d0531c 100644
--- a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.gd
+++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.gd
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.out
new file mode 100644
index 0000000000..8530783673
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_assignment.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot include a value of type "String" as "int".
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
new file mode 100644
index 0000000000..25cde1d40b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.gd
@@ -0,0 +1,4 @@
+func test():
+ var unconvertable := 1
+ var typed: Array[Object] = [unconvertable]
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.out
new file mode 100644
index 0000000000..dfe3443761
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_init_with_unconvertable_in_literal.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot have an element of type "int" in an array of type "Array[Object]".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.gd
new file mode 100644
index 0000000000..1a90bd121e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.gd
@@ -0,0 +1,7 @@
+func expect_typed(typed: Array[int]):
+ print(typed.size())
+
+func test():
+ var differently: Array[float] = [1.0]
+ expect_typed(differently)
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.out
new file mode 100644
index 0000000000..297e1283e8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_array_pass_differently_to_typed.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Invalid argument for "expect_typed()" function: argument 1 should be "Array[int]" but is "Array[float]".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.gd b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.gd
new file mode 100644
index 0000000000..a3450966cc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.gd
@@ -0,0 +1,3 @@
+func test():
+ var builtin := []
+ print(builtin.reverse()) # Built-in type method.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.out b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.out
new file mode 100644
index 0000000000..225c85e9c7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_builtin_method.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot get return value of call to "reverse()" because it returns "void".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.gd b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.gd
new file mode 100644
index 0000000000..2162a181ac
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.gd
@@ -0,0 +1,5 @@
+func foo() -> void:
+ pass
+
+func test():
+ print(foo()) # Custom method.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.out b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.out
new file mode 100644
index 0000000000..2b1a607883
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_custom_method.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot get return value of call to "foo()" because it returns "void".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.gd b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.gd
new file mode 100644
index 0000000000..f3443d985e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.gd
@@ -0,0 +1,2 @@
+func test():
+ print(print_debug()) # GDScript utility function.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.out b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.out
new file mode 100644
index 0000000000..502c18ab9d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_gd_utility.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot get return value of call to "print_debug()" because it returns "void".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.gd b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.gd
new file mode 100644
index 0000000000..b8e81b160a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.gd
@@ -0,0 +1,3 @@
+func test():
+ var obj := Node.new()
+ print(obj.free()) # Native type method.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.out b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.out
new file mode 100644
index 0000000000..88be39345b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_native_method.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot get return value of call to "free()" because it returns "void".
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.gd b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.gd
new file mode 100644
index 0000000000..8eabed4271
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.gd
@@ -0,0 +1,2 @@
+func test():
+ print(print()) # Built-in utility function.
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.out b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.out
new file mode 100644
index 0000000000..ebf43186be
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/use_value_of_void_function_utility.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot get return value of call to "print()" because it returns "void".
diff --git a/modules/gdscript/tests/scripts/analyzer/features/allow_get_node_with_onready.gd b/modules/gdscript/tests/scripts/analyzer/features/allow_get_node_with_onready.gd
new file mode 100644
index 0000000000..a9004a346b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/allow_get_node_with_onready.gd
@@ -0,0 +1,18 @@
+extends Node
+
+@onready var shorthand = $Node
+@onready var call = get_node(^"Node")
+@onready var shorthand_with_cast = $Node as Node
+@onready var call_with_cast = get_node(^"Node") as Node
+
+func _init():
+ var node := Node.new()
+ node.name = "Node"
+ add_child(node)
+
+func test():
+ # Those are expected to be `null` since `_ready()` is never called on tests.
+ prints("shorthand", shorthand)
+ prints("call", call)
+ prints("shorthand_with_cast", shorthand_with_cast)
+ prints("call_with_cast", call_with_cast)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/allow_get_node_with_onready.out b/modules/gdscript/tests/scripts/analyzer/features/allow_get_node_with_onready.out
new file mode 100644
index 0000000000..eddc2deec0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/allow_get_node_with_onready.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+shorthand <null>
+call <null>
+shorthand_with_cast <null>
+call_with_cast <null>
diff --git a/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.gd b/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.gd
new file mode 100644
index 0000000000..df89137f40
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.gd
@@ -0,0 +1,20 @@
+func test():
+ return_call()
+ return_nothing()
+ return_side_effect()
+ var r = return_side_effect.call() # Untyped call to check return value.
+ prints(r, typeof(r) == TYPE_NIL)
+ print("end")
+
+func side_effect(v):
+ print("effect")
+ return v
+
+func return_call() -> void:
+ return print("hello")
+
+func return_nothing() -> void:
+ return
+
+func return_side_effect() -> void:
+ return side_effect("x")
diff --git a/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.out b/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.out
new file mode 100644
index 0000000000..7c0416371f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/allow_void_function_to_return_void.out
@@ -0,0 +1,10 @@
+GDTEST_OK
+>> WARNING
+>> Line: 20
+>> UNSAFE_VOID_RETURN
+>> The method 'return_side_effect()' returns 'void' but it's trying to return a call to 'side_effect()' that can't be ensured to also be 'void'.
+hello
+effect
+effect
+<null> true
+end
diff --git a/modules/gdscript/tests/scripts/analyzer/features/annotation_constant_expression_parameters.gd b/modules/gdscript/tests/scripts/analyzer/features/annotation_constant_expression_parameters.gd
new file mode 100644
index 0000000000..272dce8bbe
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/annotation_constant_expression_parameters.gd
@@ -0,0 +1,10 @@
+const BEFORE = 1
+
+@export_range(-10, 10) var a = 0
+@export_range(1 + 2, absi(-10) + 1) var b = 5
+@export_range(BEFORE + 1, BEFORE + AFTER + 1) var c = 5
+
+const AFTER = 10
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/annotation_constant_expression_parameters.out b/modules/gdscript/tests/scripts/analyzer/features/annotation_constant_expression_parameters.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/annotation_constant_expression_parameters.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gdscript/tests/scripts/analyzer/features/assign_to_native_enum_property.gd b/modules/gdscript/tests/scripts/analyzer/features/assign_to_native_enum_property.gd
new file mode 100644
index 0000000000..02120db868
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/assign_to_native_enum_property.gd
@@ -0,0 +1,13 @@
+# https://github.com/godotengine/godot/issues/72501
+extends Node
+
+func test():
+ prints("before", process_mode)
+ process_mode = PROCESS_MODE_PAUSABLE
+ prints("after", process_mode)
+
+ var node := Node.new()
+ add_child(node)
+ prints("before", node.process_mode)
+ node.process_mode = PROCESS_MODE_PAUSABLE
+ prints("after", node.process_mode)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/assign_to_native_enum_property.out b/modules/gdscript/tests/scripts/analyzer/features/assign_to_native_enum_property.out
new file mode 100644
index 0000000000..1eb045a4e4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/assign_to_native_enum_property.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+before 0
+after 1
+before 0
+after 1
diff --git a/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.gd b/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.gd
new file mode 100644
index 0000000000..595563541f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.gd
@@ -0,0 +1,14 @@
+func test():
+ var two: Variant = 0
+ two += 2
+ print(two)
+
+ var three_0: Variant = 1
+ var three_1: int = 2
+ three_0 += three_1
+ print(three_0)
+
+ var four_0: int = 3
+ var four_1: Variant = 1
+ four_0 += four_1
+ print(four_0)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.out b/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.out
new file mode 100644
index 0000000000..0ddfa4b75f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+2
+3
+4
diff --git a/modules/gdscript/tests/scripts/analyzer/features/assymetric_assignment_good.gd b/modules/gdscript/tests/scripts/analyzer/features/assymetric_assignment_good.gd
new file mode 100644
index 0000000000..efd8ad6edb
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/assymetric_assignment_good.gd
@@ -0,0 +1,16 @@
+const const_color: Color = 'red'
+
+func func_color(arg_color: Color = 'blue') -> bool:
+ return arg_color == Color.BLUE
+
+@warning_ignore("assert_always_true")
+func test():
+ assert(const_color == Color.RED)
+
+ assert(func_color() == true)
+ assert(func_color('blue') == true)
+
+ var var_color: Color = 'green'
+ assert(var_color == Color.GREEN)
+
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/assymetric_assignment_good.out b/modules/gdscript/tests/scripts/analyzer/features/assymetric_assignment_good.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/assymetric_assignment_good.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/await_type_inference.gd b/modules/gdscript/tests/scripts/analyzer/features/await_type_inference.gd
new file mode 100644
index 0000000000..9d8cfc7f99
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/await_type_inference.gd
@@ -0,0 +1,15 @@
+func coroutine() -> int:
+ @warning_ignore("redundant_await")
+ await 0
+ return 1
+
+func not_coroutine() -> int:
+ return 2
+
+func test():
+ var a := await coroutine()
+ @warning_ignore("redundant_await")
+ var b := await not_coroutine()
+ @warning_ignore("redundant_await")
+ var c := await 3
+ prints(a, b, c)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/await_type_inference.out b/modules/gdscript/tests/scripts/analyzer/features/await_type_inference.out
new file mode 100644
index 0000000000..2920e2ce9c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/await_type_inference.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+1 2 3
diff --git a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd
index 7881a0feb6..a94487d989 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd
@@ -11,4 +11,3 @@ func test() -> void:
Extend.InnerClass.InnerInnerClass.test_a_b_c(A.new(), B.new(), C.new())
Extend.InnerClass.InnerInnerClass.test_enum(C.TestEnum.HELLO_WORLD)
Extend.InnerClass.InnerInnerClass.test_a_prime(A.APrime.new())
-
diff --git a/modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd b/modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd
index 30e7deb05a..7c846c59bd 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd
@@ -1,19 +1,19 @@
class A:
- var x = 3
+ var x = 3
class B:
- var x = 4
+ var x = 4
class C:
- var x = 5
+ var x = 5
class Test:
- var a = A.new()
- var b: B = B.new()
- var c := C.new()
+ var a = A.new()
+ var b: B = B.new()
+ var c := C.new()
func test():
- var test_instance := Test.new()
- prints(test_instance.a.x)
- prints(test_instance.b.x)
- prints(test_instance.c.x)
+ var test_instance := Test.new()
+ prints(test_instance.a.x)
+ prints(test_instance.b.x)
+ prints(test_instance.c.x)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/const_conversions.gd b/modules/gdscript/tests/scripts/analyzer/features/const_conversions.gd
new file mode 100644
index 0000000000..bed9dd0e96
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/const_conversions.gd
@@ -0,0 +1,24 @@
+const const_float_int: float = 19
+const const_float_plus: float = 12 + 22
+const const_float_cast: float = 76 as float
+
+const const_packed_empty: PackedFloat64Array = []
+const const_packed_ints: PackedFloat64Array = [52]
+
+@warning_ignore("assert_always_true")
+func test():
+ assert(typeof(const_float_int) == TYPE_FLOAT)
+ assert(str(const_float_int) == '19')
+ assert(typeof(const_float_plus) == TYPE_FLOAT)
+ assert(str(const_float_plus) == '34')
+ assert(typeof(const_float_cast) == TYPE_FLOAT)
+ assert(str(const_float_cast) == '76')
+
+ assert(typeof(const_packed_empty) == TYPE_PACKED_FLOAT64_ARRAY)
+ assert(str(const_packed_empty) == '[]')
+ assert(typeof(const_packed_ints) == TYPE_PACKED_FLOAT64_ARRAY)
+ assert(str(const_packed_ints) == '[52]')
+ assert(typeof(const_packed_ints[0]) == TYPE_FLOAT)
+ assert(str(const_packed_ints[0]) == '52')
+
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/const_conversions.out b/modules/gdscript/tests/scripts/analyzer/features/const_conversions.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/const_conversions.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/default_arg_convertable.gd b/modules/gdscript/tests/scripts/analyzer/features/default_arg_convertable.gd
new file mode 100644
index 0000000000..d0d04897e0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/default_arg_convertable.gd
@@ -0,0 +1,6 @@
+func check(arg: float = 3):
+ return typeof(arg) == typeof(3.0)
+
+func test():
+ if check():
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/default_arg_convertable.out b/modules/gdscript/tests/scripts/analyzer/features/default_arg_convertable.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/default_arg_convertable.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_access_types.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_access_types.gd
new file mode 100644
index 0000000000..9bc08f2dc5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_access_types.gd
@@ -0,0 +1,29 @@
+class_name EnumAccessOuterClass
+
+class InnerClass:
+ enum MyEnum { V0, V2, V1 }
+
+ static func print_enums():
+ print("Inner - Inner")
+ print(MyEnum.V0, MyEnum.V1, MyEnum.V2)
+ print(InnerClass.MyEnum.V0, InnerClass.MyEnum.V1, InnerClass.MyEnum.V2)
+ print(EnumAccessOuterClass.InnerClass.MyEnum.V0, EnumAccessOuterClass.InnerClass.MyEnum.V1, EnumAccessOuterClass.InnerClass.MyEnum.V2)
+
+ print("Inner - Outer")
+ print(EnumAccessOuterClass.MyEnum.V0, EnumAccessOuterClass.MyEnum.V1, EnumAccessOuterClass.MyEnum.V2)
+
+
+enum MyEnum { V0, V1, V2 }
+
+func print_enums():
+ print("Outer - Outer")
+ print(MyEnum.V0, MyEnum.V1, MyEnum.V2)
+ print(EnumAccessOuterClass.MyEnum.V0, EnumAccessOuterClass.MyEnum.V1, EnumAccessOuterClass.MyEnum.V2)
+
+ print("Outer - Inner")
+ print(InnerClass.MyEnum.V0, InnerClass.MyEnum.V1, InnerClass.MyEnum.V2)
+ print(EnumAccessOuterClass.InnerClass.MyEnum.V0, EnumAccessOuterClass.InnerClass.MyEnum.V1, EnumAccessOuterClass.InnerClass.MyEnum.V2)
+
+func test():
+ print_enums()
+ InnerClass.print_enums()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_access_types.out b/modules/gdscript/tests/scripts/analyzer/features/enum_access_types.out
new file mode 100644
index 0000000000..02e2e2b396
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_access_types.out
@@ -0,0 +1,13 @@
+GDTEST_OK
+Outer - Outer
+012
+012
+Outer - Inner
+021
+021
+Inner - Inner
+021
+021
+021
+Inner - Outer
+012
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd
new file mode 100644
index 0000000000..2ce588373b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd
@@ -0,0 +1,29 @@
+class Outer:
+ enum OuterEnum { OuterValue = 3 }
+ const OuterConst := OuterEnum
+
+ class Inner:
+ enum InnerEnum { InnerValue = 7 }
+ const InnerConst := InnerEnum
+
+ static func test() -> void:
+ print(OuterEnum.size());
+ print(OuterEnum.OuterValue);
+ print(OuterConst.size());
+ print(OuterConst.OuterValue);
+ print(Outer.OuterEnum.size());
+ print(Outer.OuterEnum.OuterValue);
+ print(Outer.OuterConst.size());
+ print(Outer.OuterConst.OuterValue);
+
+ print(InnerEnum.size());
+ print(InnerEnum.InnerValue);
+ print(InnerConst.size());
+ print(InnerConst.InnerValue);
+ print(Inner.InnerEnum.size());
+ print(Inner.InnerEnum.InnerValue);
+ print(Inner.InnerConst.size());
+ print(Inner.InnerConst.InnerValue);
+
+func test():
+ Outer.Inner.test()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out
new file mode 100644
index 0000000000..e049f85b6e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out
@@ -0,0 +1,17 @@
+GDTEST_OK
+1
+3
+1
+3
+1
+3
+1
+3
+1
+7
+1
+7
+1
+7
+1
+7
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_duplicate_into_dict.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_duplicate_into_dict.gd
new file mode 100644
index 0000000000..3076e7069f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_duplicate_into_dict.gd
@@ -0,0 +1,13 @@
+enum Enum {V1, V2}
+
+func test():
+ var enumAsDict : Dictionary = Enum.duplicate()
+ var enumAsVariant = Enum.duplicate()
+ print(Enum.has("V1"))
+ print(enumAsDict.has("V1"))
+ print(enumAsVariant.has("V1"))
+ enumAsDict.clear()
+ enumAsVariant.clear()
+ print(Enum.has("V1"))
+ print(enumAsDict.has("V1"))
+ print(enumAsVariant.has("V1"))
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_duplicate_into_dict.out b/modules/gdscript/tests/scripts/analyzer/features/enum_duplicate_into_dict.out
new file mode 100644
index 0000000000..a41924d0c9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_duplicate_into_dict.out
@@ -0,0 +1,7 @@
+GDTEST_OK
+true
+true
+true
+true
+false
+false
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_from_base.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_from_base.gd
new file mode 100644
index 0000000000..b3f9941903
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_from_base.gd
@@ -0,0 +1,13 @@
+class A:
+ enum Named { VALUE_A, VALUE_B, VALUE_C = 42 }
+
+class B extends A:
+ var a = Named.VALUE_A
+ var b = Named.VALUE_B
+ var c = Named.VALUE_C
+
+func test():
+ var test_instance = B.new()
+ prints("a", test_instance.a, test_instance.a == A.Named.VALUE_A)
+ prints("b", test_instance.b, test_instance.b == A.Named.VALUE_B)
+ prints("c", test_instance.c, test_instance.c == B.Named.VALUE_C)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.out b/modules/gdscript/tests/scripts/analyzer/features/enum_from_base.out
index c160839da3..c160839da3 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.out
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_from_base.out
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_from_outer.gd
index 5f57c5b8c2..4d6852a9be 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/enum_from_parent.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_from_outer.gd
@@ -1,5 +1,3 @@
-extends Node
-
enum Named { VALUE_A, VALUE_B, VALUE_C = 42 }
class Test:
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_from_outer.out b/modules/gdscript/tests/scripts/analyzer/features/enum_from_outer.out
new file mode 100644
index 0000000000..c160839da3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_from_outer.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+a 0 true
+b 1 true
+c 42 true
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_function_typecheck.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_function_typecheck.gd
new file mode 100644
index 0000000000..8a4e89d0d6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_function_typecheck.gd
@@ -0,0 +1,112 @@
+class_name EnumFunctionTypecheckOuterClass
+
+enum MyEnum { V0, V1, V2 }
+
+class InnerClass:
+ enum MyEnum { V0, V2, V1 }
+
+ func inner_inner_no_class(e : MyEnum) -> MyEnum:
+ print(e)
+ return e
+
+ func inner_inner_class(e : InnerClass.MyEnum) -> InnerClass.MyEnum:
+ print(e)
+ return e
+
+ func inner_inner_class_class(e : EnumFunctionTypecheckOuterClass.InnerClass.MyEnum) -> EnumFunctionTypecheckOuterClass.InnerClass.MyEnum:
+ print(e)
+ return e
+
+ func inner_outer(e : EnumFunctionTypecheckOuterClass.MyEnum) -> EnumFunctionTypecheckOuterClass.MyEnum:
+ print(e)
+ return e
+
+ func test():
+ var _d
+ print("Inner")
+
+ var o := EnumFunctionTypecheckOuterClass.new()
+
+ _d = o.outer_outer_no_class(EnumFunctionTypecheckOuterClass.MyEnum.V1)
+ print()
+ _d = o.outer_outer_class(EnumFunctionTypecheckOuterClass.MyEnum.V1)
+ print()
+ _d = o.outer_inner_class(MyEnum.V1)
+ _d = o.outer_inner_class(InnerClass.MyEnum.V1)
+ _d = o.outer_inner_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ _d = o.outer_inner_class_class(MyEnum.V1)
+ _d = o.outer_inner_class_class(InnerClass.MyEnum.V1)
+ _d = o.outer_inner_class_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ print()
+
+
+ _d = inner_inner_no_class(MyEnum.V1)
+ _d = inner_inner_no_class(InnerClass.MyEnum.V1)
+ _d = inner_inner_no_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ _d = inner_inner_class(MyEnum.V1)
+ _d = inner_inner_class(InnerClass.MyEnum.V1)
+ _d = inner_inner_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ _d = inner_inner_class_class(MyEnum.V1)
+ _d = inner_inner_class_class(InnerClass.MyEnum.V1)
+ _d = inner_inner_class_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ _d = inner_outer(EnumFunctionTypecheckOuterClass.MyEnum.V1)
+ print()
+ print()
+
+
+func outer_outer_no_class(e : MyEnum) -> MyEnum:
+ print(e)
+ return e
+
+func outer_outer_class(e : EnumFunctionTypecheckOuterClass.MyEnum) -> EnumFunctionTypecheckOuterClass.MyEnum:
+ print(e)
+ return e
+
+func outer_inner_class(e : InnerClass.MyEnum) -> InnerClass.MyEnum:
+ print(e)
+ return e
+
+func outer_inner_class_class(e : EnumFunctionTypecheckOuterClass.InnerClass.MyEnum) -> EnumFunctionTypecheckOuterClass.InnerClass.MyEnum:
+ print(e)
+ return e
+
+func test():
+ var _d
+ print("Outer")
+
+ _d = outer_outer_no_class(MyEnum.V1)
+ _d = outer_outer_no_class(EnumFunctionTypecheckOuterClass.MyEnum.V1)
+ print()
+ _d = outer_outer_class(MyEnum.V1)
+ _d = outer_outer_class(EnumFunctionTypecheckOuterClass.MyEnum.V1)
+ print()
+ _d = outer_inner_class(InnerClass.MyEnum.V1)
+ _d = outer_inner_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ _d = outer_inner_class_class(InnerClass.MyEnum.V1)
+ _d = outer_inner_class_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ print()
+
+ var i := EnumFunctionTypecheckOuterClass.InnerClass.new()
+
+ _d = i.inner_inner_no_class(InnerClass.MyEnum.V1)
+ _d = i.inner_inner_no_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ _d = i.inner_inner_class(InnerClass.MyEnum.V1)
+ _d = i.inner_inner_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ _d = i.inner_inner_class_class(InnerClass.MyEnum.V1)
+ _d = i.inner_inner_class_class(EnumFunctionTypecheckOuterClass.InnerClass.MyEnum.V1)
+ print()
+ _d = i.inner_outer(MyEnum.V1)
+ _d = i.inner_outer(EnumFunctionTypecheckOuterClass.MyEnum.V1)
+ print()
+ print()
+
+ i.test()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_function_typecheck.out b/modules/gdscript/tests/scripts/analyzer/features/enum_function_typecheck.out
new file mode 100644
index 0000000000..2e3ce1aa10
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_function_typecheck.out
@@ -0,0 +1,55 @@
+GDTEST_OK
+Outer
+1
+1
+
+1
+1
+
+2
+2
+
+2
+2
+
+
+2
+2
+
+2
+2
+
+2
+2
+
+1
+1
+
+
+Inner
+1
+
+1
+
+2
+2
+2
+
+2
+2
+2
+
+
+2
+2
+2
+
+2
+2
+2
+
+2
+2
+2
+
+1
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_named_no_shadow.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_named_no_shadow.gd
new file mode 100644
index 0000000000..b97d9bbb6b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_named_no_shadow.gd
@@ -0,0 +1,16 @@
+const A := 1
+enum { B }
+enum NamedEnum { C }
+
+class Parent:
+ const D := 2
+ enum { E }
+ enum NamedEnum2 { F }
+
+class Child extends Parent:
+ enum TestEnum { A, B, C, D, E, F, Node, Object, Child, Parent}
+
+func test():
+ print(A, B, NamedEnum.C, Parent.D, Parent.E, Parent.NamedEnum2.F)
+ print(Child.TestEnum.A, Child.TestEnum.B, Child.TestEnum.C, Child.TestEnum.D, Child.TestEnum.E, Child.TestEnum.F)
+ print(Child.TestEnum.Node, Child.TestEnum.Object, Child.TestEnum.Child, Child.TestEnum.Parent)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_named_no_shadow.out b/modules/gdscript/tests/scripts/analyzer/features/enum_named_no_shadow.out
new file mode 100644
index 0000000000..864ba2a549
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_named_no_shadow.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+100200
+012345
+6789
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_native_access_types.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_native_access_types.gd
new file mode 100644
index 0000000000..6a0a1e1969
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_native_access_types.gd
@@ -0,0 +1,19 @@
+func print_enum(e : TileSet.TileShape) -> TileSet.TileShape:
+ print(e)
+ return e
+
+func test():
+ var v : TileSet.TileShape
+ v = TileSet.TILE_SHAPE_SQUARE
+ v = print_enum(v)
+ v = print_enum(TileSet.TILE_SHAPE_SQUARE)
+ v = TileSet.TileShape.TILE_SHAPE_SQUARE
+ v = print_enum(v)
+ v = print_enum(TileSet.TileShape.TILE_SHAPE_SQUARE)
+
+ v = TileSet.TILE_SHAPE_ISOMETRIC
+ v = print_enum(v)
+ v = print_enum(TileSet.TILE_SHAPE_ISOMETRIC)
+ v = TileSet.TileShape.TILE_SHAPE_ISOMETRIC
+ v = print_enum(v)
+ v = print_enum(TileSet.TileShape.TILE_SHAPE_ISOMETRIC)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_native_access_types.out b/modules/gdscript/tests/scripts/analyzer/features/enum_native_access_types.out
new file mode 100644
index 0000000000..1126dcc6ec
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_native_access_types.out
@@ -0,0 +1,9 @@
+GDTEST_OK
+0
+0
+0
+0
+1
+1
+1
+1
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_typecheck_inner_class.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_typecheck_inner_class.gd
new file mode 100644
index 0000000000..b05ae82048
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_typecheck_inner_class.gd
@@ -0,0 +1,86 @@
+class_name EnumTypecheckOuterClass
+
+enum MyEnum { V0, V1, V2 }
+
+class InnerClass:
+ enum MyEnum { V0, V2, V1 }
+
+ static func test_inner_from_inner():
+ print("Inner - Inner")
+ var e1 : MyEnum
+ var e2 : InnerClass.MyEnum
+ var e3 : EnumTypecheckOuterClass.InnerClass.MyEnum
+
+ print("Self ", e1, e2, e3)
+ e1 = MyEnum.V1
+ e2 = MyEnum.V1
+ e3 = MyEnum.V1
+ print("MyEnum ", e1, e2, e3)
+ e1 = InnerClass.MyEnum.V1
+ e2 = InnerClass.MyEnum.V1
+ e3 = InnerClass.MyEnum.V1
+ print("Inner.MyEnum ", e1, e2, e3)
+ e1 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
+ e2 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
+ e3 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
+ print("Outer.Inner.MyEnum ", e1, e2, e3)
+
+ e1 = e2
+ e1 = e3
+ e2 = e1
+ e2 = e3
+ e3 = e1
+ e3 = e2
+
+ print()
+
+ static func test_outer_from_inner():
+ print("Inner - Outer")
+ var e : EnumTypecheckOuterClass.MyEnum
+
+ e = EnumTypecheckOuterClass.MyEnum.V1
+ print("Outer.MyEnum ", e)
+
+ print()
+
+func test_outer_from_outer():
+ print("Outer - Outer")
+ var e1 : MyEnum
+ var e2 : EnumTypecheckOuterClass.MyEnum
+
+ print("Self ", e1, e2)
+ e1 = MyEnum.V1
+ e2 = MyEnum.V1
+ print("Outer ", e1, e2)
+ e1 = EnumTypecheckOuterClass.MyEnum.V1
+ e2 = EnumTypecheckOuterClass.MyEnum.V1
+ print("Outer.MyEnum ", e1, e2)
+
+ e1 = e2
+ e2 = e1
+
+ print()
+
+func test_inner_from_outer():
+ print("Outer - Inner")
+ var e1 : InnerClass.MyEnum
+ var e2 : EnumTypecheckOuterClass.InnerClass.MyEnum
+
+ print("Inner ", e1, e2)
+ e1 = InnerClass.MyEnum.V1
+ e2 = InnerClass.MyEnum.V1
+ print("Outer.Inner ", e1, e2)
+ e1 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
+ e2 = EnumTypecheckOuterClass.InnerClass.MyEnum.V1
+ print("Outer.Inner.MyEnum ", e1, e2)
+
+ e1 = e2
+ e2 = e1
+
+ print()
+
+func test():
+ test_outer_from_outer()
+ test_inner_from_outer()
+ InnerClass.test_outer_from_inner()
+ InnerClass.test_inner_from_inner()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_typecheck_inner_class.out b/modules/gdscript/tests/scripts/analyzer/features/enum_typecheck_inner_class.out
new file mode 100644
index 0000000000..3b2dcade26
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_typecheck_inner_class.out
@@ -0,0 +1,19 @@
+GDTEST_OK
+Outer - Outer
+Self 00
+Outer 11
+Outer.MyEnum 11
+
+Outer - Inner
+Inner 00
+Outer.Inner 22
+Outer.Inner.MyEnum 22
+
+Inner - Outer
+Outer.MyEnum 1
+
+Inner - Inner
+Self 000
+MyEnum 222
+Inner.MyEnum 222
+Outer.Inner.MyEnum 222
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_unnamed_depend.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_unnamed_depend.gd
new file mode 100644
index 0000000000..f351fc1f7b
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_unnamed_depend.gd
@@ -0,0 +1,7 @@
+enum {
+ V1,
+ V2 = V1,
+}
+
+func test():
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_unnamed_depend.out b/modules/gdscript/tests/scripts/analyzer/features/enum_unnamed_depend.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/enum_unnamed_depend.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gdscript/tests/scripts/analyzer/features/extend_abstract_class.gd b/modules/gdscript/tests/scripts/analyzer/features/extend_abstract_class.gd
new file mode 100644
index 0000000000..95c3268130
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/extend_abstract_class.gd
@@ -0,0 +1,12 @@
+class A extends CanvasItem:
+ func _init():
+ pass
+
+class B extends A:
+ pass
+
+class C extends CanvasItem:
+ pass
+
+func test():
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/extend_abstract_class.out b/modules/gdscript/tests/scripts/analyzer/features/extend_abstract_class.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/extend_abstract_class.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd
index 757744b6f1..0c740935b9 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd
@@ -2,5 +2,5 @@ const External = preload("external_enum_as_constant_external.notest.gd")
const MyEnum = External.MyEnum
func test():
- print(MyEnum.WAITING == 0)
- print(MyEnum.GODOT == 1)
+ print(MyEnum.WAITING == 0)
+ print(MyEnum.GODOT == 1)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd
index 7c090844d0..24c1e41aab 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd
@@ -1,4 +1,4 @@
enum MyEnum {
- WAITING,
- GODOT
+ WAITING,
+ GODOT
}
diff --git a/modules/gdscript/tests/scripts/analyzer/features/for_loop_on_variant.gd b/modules/gdscript/tests/scripts/analyzer/features/for_loop_on_variant.gd
new file mode 100644
index 0000000000..7b74be6f2c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/for_loop_on_variant.gd
@@ -0,0 +1,15 @@
+func test():
+ var variant_int: Variant = 1
+ var weak_int = 1
+
+ for x in variant_int:
+ if x is String:
+ print('never')
+ print(x)
+
+ for x in weak_int:
+ if x is String:
+ print('never')
+ print(x)
+
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/for_loop_on_variant.out b/modules/gdscript/tests/scripts/analyzer/features/for_loop_on_variant.out
new file mode 100644
index 0000000000..7677671cfd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/for_loop_on_variant.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+0
+0
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd
new file mode 100644
index 0000000000..38bb7f6e9c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.gd
@@ -0,0 +1,9 @@
+var Value:int = 8 :
+ get:
+ return Value
+ set(v):
+ Value = v
+
+func test():
+ var f:float = Value
+ print(int(f))
diff --git a/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out
new file mode 100644
index 0000000000..b0cb63ef59
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/getter_return_type.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+8
diff --git a/modules/gdscript/tests/scripts/analyzer/features/hard_variants.gd b/modules/gdscript/tests/scripts/analyzer/features/hard_variants.gd
new file mode 100644
index 0000000000..b447180ea8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/hard_variants.gd
@@ -0,0 +1,34 @@
+func variant() -> Variant: return null
+
+var member_weak = variant()
+var member_typed: Variant = variant()
+@warning_ignore("inference_on_variant")
+var member_inferred := variant()
+
+func param_weak(param = variant()) -> void: print(param)
+func param_typed(param: Variant = variant()) -> void: print(param)
+@warning_ignore("inference_on_variant")
+func param_inferred(param := variant()) -> void: print(param)
+
+func return_untyped(): return variant()
+func return_typed() -> Variant: return variant()
+
+@warning_ignore("unused_variable", "inference_on_variant")
+func test() -> void:
+ var weak = variant()
+ var typed: Variant = variant()
+ var inferred := variant()
+
+ weak = variant()
+ typed = variant()
+ inferred = variant()
+
+ param_weak(typed)
+ param_typed(typed)
+ param_inferred(typed)
+
+ if typed == null: pass
+ if typed != null: pass
+ if typed is Node: pass
+
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/hard_variants.out b/modules/gdscript/tests/scripts/analyzer/features/hard_variants.out
new file mode 100644
index 0000000000..08491efa07
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/hard_variants.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+<null>
+<null>
+<null>
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lambda_typed.gd b/modules/gdscript/tests/scripts/analyzer/features/lambda_typed.gd
new file mode 100644
index 0000000000..114d7f7652
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/lambda_typed.gd
@@ -0,0 +1,12 @@
+func test():
+ var lambda_0 := func() -> void:
+ print(0)
+ lambda_0.call()
+
+ var lambda_1 := func(printed: int) -> void:
+ print(printed)
+ lambda_1.call(1)
+
+ var lambda_2 := func(identity: int) -> int:
+ return identity
+ print(lambda_2.call(2))
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lambda_typed.out b/modules/gdscript/tests/scripts/analyzer/features/lambda_typed.out
new file mode 100644
index 0000000000..63e262aeff
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/lambda_typed.out
@@ -0,0 +1,4 @@
+GDTEST_OK
+0
+1
+2
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lookup_class.gd b/modules/gdscript/tests/scripts/analyzer/features/lookup_class.gd
new file mode 100644
index 0000000000..541da78332
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/lookup_class.gd
@@ -0,0 +1,50 @@
+# Inner-outer class lookup
+class A:
+ const Q: = "right one"
+
+class X:
+ const Q: = "wrong one"
+
+class Y extends X:
+ class B extends A:
+ static func check() -> void:
+ print(Q)
+
+# External class lookup
+const External: = preload("lookup_class_external.notest.gd")
+
+class Internal extends External.A:
+ static func check() -> void:
+ print(TARGET)
+
+ class E extends External.E:
+ static func check() -> void:
+ print(TARGET)
+ print(WAITING)
+
+# Variable lookup
+class C:
+ var Q := 'right one'
+
+class D:
+ const Q := 'wrong one'
+
+class E extends D:
+ class F extends C:
+ func check() -> void:
+ print(Q)
+
+# Test
+func test() -> void:
+ # Inner-outer class lookup
+ Y.B.check()
+ print("---")
+
+ # External class lookup
+ Internal.check()
+ Internal.E.check()
+ print("---")
+
+ # Variable lookup
+ var f: = E.F.new()
+ f.check()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lookup_class.out b/modules/gdscript/tests/scripts/analyzer/features/lookup_class.out
new file mode 100644
index 0000000000..a0983c1438
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/lookup_class.out
@@ -0,0 +1,8 @@
+GDTEST_OK
+right one
+---
+wrong
+right
+godot
+---
+right one
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lookup_class_external.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/lookup_class_external.notest.gd
new file mode 100644
index 0000000000..a2904e20a8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/lookup_class_external.notest.gd
@@ -0,0 +1,15 @@
+class A:
+ const TARGET: = "wrong"
+
+ class B:
+ const TARGET: = "wrong"
+ const WAITING: = "godot"
+
+ class D extends C:
+ pass
+
+class C:
+ const TARGET: = "right"
+
+class E extends A.B.D:
+ pass
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.gd b/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.gd
new file mode 100644
index 0000000000..26cf6c7322
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.gd
@@ -0,0 +1,41 @@
+signal hello
+
+func get_signal() -> Signal:
+ return hello
+
+class A:
+ signal hello
+
+ func get_signal() -> Signal:
+ return hello
+
+ class B:
+ signal hello
+
+ func get_signal() -> Signal:
+ return hello
+
+class C extends A.B:
+ func get_signal() -> Signal:
+ return hello
+
+func test():
+ var a: = A.new()
+ var b: = A.B.new()
+ var c: = C.new()
+
+ var hello_a_result: = hello == a.get_signal()
+ var hello_b_result: = hello == b.get_signal()
+ var hello_c_result: = hello == c.get_signal()
+ var a_b_result: = a.get_signal() == b.get_signal()
+ var a_c_result: = a.get_signal() == c.get_signal()
+ var b_c_result: = b.get_signal() == c.get_signal()
+ var c_c_result: = c.get_signal() == c.get_signal()
+
+ print("hello == A.hello? %s" % hello_a_result)
+ print("hello == A.B.hello? %s" % hello_b_result)
+ print("hello == C.hello? %s" % hello_c_result)
+ print("A.hello == A.B.hello? %s" % a_b_result)
+ print("A.hello == C.hello? %s" % a_c_result)
+ print("A.B.hello == C.hello? %s" % b_c_result)
+ print("C.hello == C.hello? %s" % c_c_result)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.out b/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.out
new file mode 100644
index 0000000000..6b0d32eaf8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.out
@@ -0,0 +1,8 @@
+GDTEST_OK
+hello == A.hello? false
+hello == A.B.hello? false
+hello == C.hello? false
+A.hello == A.B.hello? false
+A.hello == C.hello? false
+A.B.hello == C.hello? false
+C.hello == C.hello? true
diff --git a/modules/gdscript/tests/scripts/analyzer/features/null_initializer.gd b/modules/gdscript/tests/scripts/analyzer/features/null_initializer.gd
new file mode 100644
index 0000000000..5a413e2015
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/null_initializer.gd
@@ -0,0 +1,32 @@
+func check(input: int) -> bool:
+ return input == 1
+
+var recur = null
+var prop = null
+
+func check_arg(arg = null) -> void:
+ if arg != null:
+ print(check(arg))
+
+func check_recur() -> void:
+ if recur != null:
+ print(check(recur))
+ else:
+ recur = 1
+ check_recur()
+
+func test() -> void:
+ check_arg(1)
+
+ check_recur()
+
+ if prop == null:
+ set('prop', 1)
+ print(check(prop))
+ set('prop', null)
+
+ var loop = null
+ while loop != 2:
+ if loop != null:
+ print(check(loop))
+ loop = 1 if loop == null else 2
diff --git a/modules/gdscript/tests/scripts/analyzer/features/null_initializer.out b/modules/gdscript/tests/scripts/analyzer/features/null_initializer.out
new file mode 100644
index 0000000000..f9783e4362
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/null_initializer.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+true
+true
+true
+true
diff --git a/modules/gdscript/tests/scripts/analyzer/features/onready_on_inner_class_with_non_node_outer.gd b/modules/gdscript/tests/scripts/analyzer/features/onready_on_inner_class_with_non_node_outer.gd
new file mode 100644
index 0000000000..1ac03c2181
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/onready_on_inner_class_with_non_node_outer.gd
@@ -0,0 +1,7 @@
+extends RefCounted
+
+func test():
+ print("ok")
+
+class Inner extends Node:
+ @onready var okay = 0
diff --git a/modules/gdscript/tests/scripts/analyzer/features/onready_on_inner_class_with_non_node_outer.out b/modules/gdscript/tests/scripts/analyzer/features/onready_on_inner_class_with_non_node_outer.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/onready_on_inner_class_with_non_node_outer.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.gd
new file mode 100644
index 0000000000..25381035b2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.gd
@@ -0,0 +1,15 @@
+const Preloaded := preload( 'preload_script_native_type.notest.gd' )
+
+func test() -> void:
+ var inferred := Preloaded.new()
+ var inferred_owner := inferred.owner
+
+ var typed: Preloaded
+ typed = Preloaded.new()
+ var typed_owner := typed.owner
+
+ print(typed_owner == inferred_owner)
+
+ inferred.free()
+ typed.free()
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.notest.gd
new file mode 100644
index 0000000000..61510e14cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.notest.gd
@@ -0,0 +1 @@
+extends Node
diff --git a/modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.out b/modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.out
new file mode 100644
index 0000000000..3e24a1e2af
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/preload_script_native_type.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+true
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/return_conversions.gd b/modules/gdscript/tests/scripts/analyzer/features/return_conversions.gd
new file mode 100644
index 0000000000..0b1576e66e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/return_conversions.gd
@@ -0,0 +1,34 @@
+func convert_literal_int_to_float() -> float: return 76
+func convert_arg_int_to_float(arg: int) -> float: return arg
+func convert_var_int_to_float() -> float: var number := 59; return number
+
+func convert_literal_array_to_packed() -> PackedStringArray: return ['46']
+func convert_arg_array_to_packed(arg: Array) -> PackedStringArray: return arg
+func convert_var_array_to_packed() -> PackedStringArray: var array := ['79']; return array
+
+func test():
+ var converted_literal_int := convert_literal_int_to_float()
+ assert(typeof(converted_literal_int) == TYPE_FLOAT)
+ assert(converted_literal_int == 76.0)
+
+ var converted_arg_int := convert_arg_int_to_float(36)
+ assert(typeof(converted_arg_int) == TYPE_FLOAT)
+ assert(converted_arg_int == 36.0)
+
+ var converted_var_int := convert_var_int_to_float()
+ assert(typeof(converted_var_int) == TYPE_FLOAT)
+ assert(converted_var_int == 59.0)
+
+ var converted_literal_array := convert_literal_array_to_packed()
+ assert(typeof(converted_literal_array) == TYPE_PACKED_STRING_ARRAY)
+ assert(str(converted_literal_array) == '["46"]')
+
+ var converted_arg_array := convert_arg_array_to_packed(['91'])
+ assert(typeof(converted_arg_array) == TYPE_PACKED_STRING_ARRAY)
+ assert(str(converted_arg_array) == '["91"]')
+
+ var converted_var_array := convert_var_array_to_packed()
+ assert(typeof(converted_var_array) == TYPE_PACKED_STRING_ARRAY)
+ assert(str(converted_var_array) == '["79"]')
+
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/return_conversions.out b/modules/gdscript/tests/scripts/analyzer/features/return_conversions.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/return_conversions.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.gd b/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.gd
new file mode 100644
index 0000000000..95f04421d1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.gd
@@ -0,0 +1,5 @@
+func variant() -> Variant:
+ return 'variant'
+
+func test():
+ print(variant())
diff --git a/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.out b/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.out
new file mode 100644
index 0000000000..57fe608cc5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+variant
diff --git a/modules/gdscript/tests/scripts/analyzer/features/ternary_hard_infer.gd b/modules/gdscript/tests/scripts/analyzer/features/ternary_hard_infer.gd
new file mode 100644
index 0000000000..44ca5f4dd0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/ternary_hard_infer.gd
@@ -0,0 +1,15 @@
+func test():
+ var left_hard_int := 1
+ var right_hard_int := 2
+ var result_hard_int := left_hard_int if true else right_hard_int
+ assert(result_hard_int == 1)
+
+ @warning_ignore("inference_on_variant")
+ var left_hard_variant := 1 as Variant
+ @warning_ignore("inference_on_variant")
+ var right_hard_variant := 2.0 as Variant
+ @warning_ignore("inference_on_variant")
+ var result_hard_variant := left_hard_variant if true else right_hard_variant
+ assert(result_hard_variant == 1)
+
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/ternary_hard_infer.out b/modules/gdscript/tests/scripts/analyzer/features/ternary_hard_infer.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/ternary_hard_infer.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.gd
new file mode 100644
index 0000000000..fc343377fc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.gd
@@ -0,0 +1,17 @@
+func print_untyped(array = [0]) -> void:
+ print(array)
+ print(array.get_typed_builtin())
+
+func print_inferred(array := [1]) -> void:
+ print(array)
+ print(array.get_typed_builtin())
+
+func print_typed(array: Array[int] = [2]) -> void:
+ print(array)
+ print(array.get_typed_builtin())
+
+func test():
+ print_untyped()
+ print_inferred()
+ print_typed()
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.out b/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.out
new file mode 100644
index 0000000000..2729c5b6c7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.out
@@ -0,0 +1,8 @@
+GDTEST_OK
+[0]
+0
+[1]
+0
+[2]
+2
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd
new file mode 100644
index 0000000000..7416ecd87a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd
@@ -0,0 +1,211 @@
+class A: pass
+class B extends A: pass
+
+enum E { E0 = 391 }
+
+func floats_identity(floats: Array[float]): return floats
+
+class Members:
+ var one: Array[int] = [104]
+ var two: Array[int] = one
+
+ func check_passing() -> bool:
+ assert(str(one) == '[104]')
+ assert(str(two) == '[104]')
+ two.push_back(582)
+ assert(str(one) == '[104, 582]')
+ assert(str(two) == '[104, 582]')
+ two = [486]
+ assert(str(one) == '[104, 582]')
+ assert(str(two) == '[486]')
+ return true
+
+
+@warning_ignore("unsafe_method_access")
+@warning_ignore("assert_always_true")
+@warning_ignore("return_value_discarded")
+func test():
+ var untyped_basic = [459]
+ assert(str(untyped_basic) == '[459]')
+ assert(untyped_basic.get_typed_builtin() == TYPE_NIL)
+
+ var inferred_basic := [366]
+ assert(str(inferred_basic) == '[366]')
+ assert(inferred_basic.get_typed_builtin() == TYPE_NIL)
+
+ var typed_basic: Array = [521]
+ assert(str(typed_basic) == '[521]')
+ assert(typed_basic.get_typed_builtin() == TYPE_NIL)
+
+
+ var empty_floats: Array[float] = []
+ assert(str(empty_floats) == '[]')
+ assert(empty_floats.get_typed_builtin() == TYPE_FLOAT)
+
+ untyped_basic = empty_floats
+ assert(untyped_basic.get_typed_builtin() == TYPE_FLOAT)
+
+ inferred_basic = empty_floats
+ assert(inferred_basic.get_typed_builtin() == TYPE_FLOAT)
+
+ typed_basic = empty_floats
+ assert(typed_basic.get_typed_builtin() == TYPE_FLOAT)
+
+ empty_floats.push_back(705.0)
+ untyped_basic.push_back(430.0)
+ inferred_basic.push_back(263.0)
+ typed_basic.push_back(518.0)
+ assert(str(empty_floats) == '[705, 430, 263, 518]')
+ assert(str(untyped_basic) == '[705, 430, 263, 518]')
+ assert(str(inferred_basic) == '[705, 430, 263, 518]')
+ assert(str(typed_basic) == '[705, 430, 263, 518]')
+
+
+ const constant_float := 950.0
+ const constant_int := 170
+ var typed_float := 954.0
+ var filled_floats: Array[float] = [constant_float, constant_int, typed_float, empty_floats[1] + empty_floats[2]]
+ assert(str(filled_floats) == '[950, 170, 954, 693]')
+ assert(filled_floats.get_typed_builtin() == TYPE_FLOAT)
+
+ var casted_floats := [empty_floats[2] * 2] as Array[float]
+ assert(str(casted_floats) == '[526]')
+ assert(casted_floats.get_typed_builtin() == TYPE_FLOAT)
+
+ var returned_floats = (func () -> Array[float]: return [554]).call()
+ assert(str(returned_floats) == '[554]')
+ assert(returned_floats.get_typed_builtin() == TYPE_FLOAT)
+
+ var passed_floats = floats_identity([663.0 if randf() > 0.5 else 663.0])
+ assert(str(passed_floats) == '[663]')
+ assert(passed_floats.get_typed_builtin() == TYPE_FLOAT)
+
+ var default_floats = (func (floats: Array[float] = [364.0]): return floats).call()
+ assert(str(default_floats) == '[364]')
+ assert(default_floats.get_typed_builtin() == TYPE_FLOAT)
+
+ var typed_int := 556
+ var converted_floats: Array[float] = [typed_int]
+ converted_floats.push_back(498)
+ assert(str(converted_floats) == '[556, 498]')
+ assert(converted_floats.get_typed_builtin() == TYPE_FLOAT)
+
+
+ const constant_basic = [228]
+ assert(str(constant_basic) == '[228]')
+ assert(constant_basic.get_typed_builtin() == TYPE_NIL)
+
+ const constant_floats: Array[float] = [constant_float - constant_basic[0] - constant_int]
+ assert(str(constant_floats) == '[552]')
+ assert(constant_floats.get_typed_builtin() == TYPE_FLOAT)
+
+
+ var source_floats: Array[float] = [999.74]
+ untyped_basic = source_floats
+ var destination_floats: Array[float] = untyped_basic
+ destination_floats[0] -= 0.74
+ assert(str(source_floats) == '[999]')
+ assert(str(untyped_basic) == '[999]')
+ assert(str(destination_floats) == '[999]')
+ assert(destination_floats.get_typed_builtin() == TYPE_FLOAT)
+
+
+ var duplicated_floats := empty_floats.duplicate().slice(2, 3)
+ duplicated_floats[0] *= 3
+ assert(str(duplicated_floats) == '[789]')
+ assert(duplicated_floats.get_typed_builtin() == TYPE_FLOAT)
+
+
+ var b_objects: Array[B] = [B.new(), null]
+ assert(b_objects.size() == 2)
+ assert(b_objects.get_typed_builtin() == TYPE_OBJECT)
+ assert(b_objects.get_typed_script() == B)
+
+ var a_objects: Array[A] = [A.new(), B.new(), null, b_objects[0]]
+ assert(a_objects.size() == 4)
+ assert(a_objects.get_typed_builtin() == TYPE_OBJECT)
+ assert(a_objects.get_typed_script() == A)
+
+ var a_passed = (func check_a_passing(a_objects: Array[A]): return a_objects.size()).call(a_objects)
+ assert(a_passed == 4)
+
+ var b_passed = (func check_b_passing(basic: Array): return basic[0] != null).call(b_objects)
+ assert(b_passed == true)
+
+
+ var empty_strings: Array[String] = []
+ var empty_bools: Array[bool] = []
+ var empty_basic_one := []
+ var empty_basic_two := []
+ assert(empty_strings == empty_bools)
+ assert(empty_basic_one == empty_basic_two)
+ assert(empty_strings.hash() == empty_bools.hash())
+ assert(empty_basic_one.hash() == empty_basic_two.hash())
+
+
+ var assign_source: Array[int] = [527]
+ var assign_target: Array[int] = []
+ assign_target.assign(assign_source)
+ assert(str(assign_source) == '[527]')
+ assert(str(assign_target) == '[527]')
+ assign_source.push_back(657)
+ assert(str(assign_source) == '[527, 657]')
+ assert(str(assign_target) == '[527]')
+
+
+ var defaults_passed = (func check_defaults_passing(one: Array[int] = [], two := one):
+ one.push_back(887)
+ two.push_back(198)
+ assert(str(one) == '[887, 198]')
+ assert(str(two) == '[887, 198]')
+ two = [130]
+ assert(str(one) == '[887, 198]')
+ assert(str(two) == '[130]')
+ return true
+ ).call()
+ assert(defaults_passed == true)
+
+
+ var members := Members.new()
+ var members_passed := members.check_passing()
+ assert(members_passed == true)
+
+
+ var resized_basic: Array = []
+ resized_basic.resize(1)
+ assert(typeof(resized_basic[0]) == TYPE_NIL)
+ assert(resized_basic[0] == null)
+
+ var resized_ints: Array[int] = []
+ resized_ints.resize(1)
+ assert(typeof(resized_ints[0]) == TYPE_INT)
+ assert(resized_ints[0] == 0)
+
+ var resized_arrays: Array[Array] = []
+ resized_arrays.resize(1)
+ assert(typeof(resized_arrays[0]) == TYPE_ARRAY)
+ resized_arrays[0].resize(1)
+ resized_arrays[0][0] = 523
+ assert(str(resized_arrays) == '[[523]]')
+
+ var resized_objects: Array[Object] = []
+ resized_objects.resize(1)
+ assert(typeof(resized_objects[0]) == TYPE_NIL)
+ assert(resized_objects[0] == null)
+
+
+ var typed_enums: Array[E] = []
+ typed_enums.resize(1)
+ assert(str(typed_enums) == '[0]')
+ typed_enums[0] = E.E0
+ assert(str(typed_enums) == '[391]')
+ assert(typed_enums.get_typed_builtin() == TYPE_INT)
+
+
+ var a := A.new()
+ var typed_natives: Array[RefCounted] = [a]
+ var typed_scripts = Array(typed_natives, TYPE_OBJECT, "RefCounted", A)
+ assert(typed_scripts[0] == a)
+
+
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.out b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/vararg_call.gd b/modules/gdscript/tests/scripts/analyzer/features/vararg_call.gd
new file mode 100644
index 0000000000..d444250f1e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/vararg_call.gd
@@ -0,0 +1,6 @@
+signal ok()
+
+@warning_ignore("return_value_discarded")
+func test():
+ ok.connect(func(): print('ok'))
+ emit_signal(&'ok')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/vararg_call.out b/modules/gdscript/tests/scripts/analyzer/features/vararg_call.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/vararg_call.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/analyzer/features/variant_arg_in_virtual_method.gd b/modules/gdscript/tests/scripts/analyzer/features/variant_arg_in_virtual_method.gd
new file mode 100644
index 0000000000..da24c06b2e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/variant_arg_in_virtual_method.gd
@@ -0,0 +1,6 @@
+class Check extends Node:
+ func _set(_property: StringName, _value: Variant) -> bool:
+ return true
+
+func test() -> void:
+ print('OK')
diff --git a/modules/gdscript/tests/scripts/analyzer/features/variant_arg_in_virtual_method.out b/modules/gdscript/tests/scripts/analyzer/features/variant_arg_in_virtual_method.out
new file mode 100644
index 0000000000..1ccb591560
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/variant_arg_in_virtual_method.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+OK
diff --git a/modules/gdscript/tests/scripts/analyzer/features/warning_ignore_annotation.gd b/modules/gdscript/tests/scripts/analyzer/features/warning_ignore_annotation.gd
index 877a4ea221..4c02fd4b0d 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/warning_ignore_annotation.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/warning_ignore_annotation.gd
@@ -1,12 +1,12 @@
-@warning_ignore(unused_private_class_variable)
+@warning_ignore("unused_private_class_variable")
var _unused = 2
-@warning_ignore(unused_variable)
+@warning_ignore("unused_variable")
func test():
print("test")
var unused = 3
- @warning_ignore(redundant_await)
+ @warning_ignore("redundant_await")
print(await regular_func())
print("done")
diff --git a/modules/gdscript/tests/scripts/analyzer/features/weak_initializer.gd b/modules/gdscript/tests/scripts/analyzer/features/weak_initializer.gd
new file mode 100644
index 0000000000..c5f3ccc59e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/weak_initializer.gd
@@ -0,0 +1,5 @@
+func test():
+ var bar = 1
+ var foo: float = bar
+ print(typeof(foo))
+ print(foo is float)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/weak_initializer.out b/modules/gdscript/tests/scripts/analyzer/features/weak_initializer.out
new file mode 100644
index 0000000000..5d798c1f24
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/weak_initializer.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+3
+true
diff --git a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out b/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out
deleted file mode 100644
index 26b6e13d4f..0000000000
--- a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out
+++ /dev/null
@@ -1,2 +0,0 @@
-GDTEST_ANALYZER_ERROR
-Assigned value for constant "arr" has type Array[String] which is not compatible with defined type Array[int].
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.gd b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.gd
new file mode 100644
index 0000000000..71616ea3af
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.gd
@@ -0,0 +1,5 @@
+enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
+enum MyOtherEnum { OTHER_ENUM_VALUE_1, OTHER_ENUM_VALUE_2, OTHER_ENUM_VALUE_3 }
+
+func test():
+ print(MyOtherEnum.OTHER_ENUM_VALUE_3 as MyEnum)
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.out b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.out
new file mode 100644
index 0000000000..6e086a0918
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.out
@@ -0,0 +1,6 @@
+GDTEST_OK
+>> WARNING
+>> Line: 5
+>> INT_AS_ENUM_WITHOUT_MATCH
+>> Cannot cast 2 as Enum "cast_enum_bad_enum.gd::MyEnum": no enum member has matching value.
+2
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.gd b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.gd
new file mode 100644
index 0000000000..60a31fb318
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.gd
@@ -0,0 +1,4 @@
+enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
+
+func test():
+ print(2 as MyEnum)
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.out b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.out
new file mode 100644
index 0000000000..c19d57f98e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.out
@@ -0,0 +1,6 @@
+GDTEST_OK
+>> WARNING
+>> Line: 4
+>> INT_AS_ENUM_WITHOUT_MATCH
+>> Cannot cast 2 as Enum "cast_enum_bad_int.gd::MyEnum": no enum member has matching value.
+2
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
new file mode 100644
index 0000000000..849df0921e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.gd
@@ -0,0 +1,17 @@
+extends Node
+
+var add_node = do_add_node() # Hack to have one node on init and not fail at runtime.
+
+var shorthand = $Node
+var with_self = self.get_node(^"Node")
+var without_self = get_node(^"Node")
+var with_cast = get_node(^"Node") as Node
+var shorthand_with_cast = $Node as Node
+
+func test():
+ print("warn")
+
+func do_add_node():
+ var node = Node.new()
+ node.name = "Node"
+ add_child(node)
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.out b/modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.out
new file mode 100644
index 0000000000..62b3ae291f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/get_node_without_onready.out
@@ -0,0 +1,22 @@
+GDTEST_OK
+>> WARNING
+>> Line: 5
+>> GET_NODE_DEFAULT_WITHOUT_ONREADY
+>> The default value is using "$" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
+>> WARNING
+>> Line: 6
+>> GET_NODE_DEFAULT_WITHOUT_ONREADY
+>> The default value is using "get_node()" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
+>> WARNING
+>> Line: 7
+>> GET_NODE_DEFAULT_WITHOUT_ONREADY
+>> The default value is using "get_node()" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
+>> WARNING
+>> Line: 8
+>> GET_NODE_DEFAULT_WITHOUT_ONREADY
+>> The default value is using "get_node()" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
+>> WARNING
+>> Line: 9
+>> GET_NODE_DEFAULT_WITHOUT_ONREADY
+>> The default value is using "$" which won't return nodes in the scene tree before "_ready()" is called. Use the "@onready" annotation to solve this.
+warn
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/inference_with_variant.gd b/modules/gdscript/tests/scripts/analyzer/warnings/inference_with_variant.gd
new file mode 100644
index 0000000000..024e91b7c6
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/inference_with_variant.gd
@@ -0,0 +1,6 @@
+func test():
+ var inferred_with_variant := return_variant()
+ print(inferred_with_variant)
+
+func return_variant() -> Variant:
+ return "warn"
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/inference_with_variant.out b/modules/gdscript/tests/scripts/analyzer/warnings/inference_with_variant.out
new file mode 100644
index 0000000000..1d4078d2f7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/inference_with_variant.out
@@ -0,0 +1,6 @@
+GDTEST_OK
+>> WARNING
+>> Line: 2
+>> INFERENCE_ON_VARIANT
+>> The variable type is being inferred from a Variant value, so it will be typed as Variant.
+warn
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.gd b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.gd
new file mode 100644
index 0000000000..939496324c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.gd
@@ -0,0 +1,6 @@
+var shadow: int
+
+func test():
+ var lambda := func(shadow: String) -> void:
+ print(shadow)
+ lambda.call('shadow')
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.out b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.out
new file mode 100644
index 0000000000..a98d80514c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_shadowing_arg.out
@@ -0,0 +1,6 @@
+GDTEST_OK
+>> WARNING
+>> Line: 4
+>> SHADOWED_VARIABLE
+>> The local function parameter "shadow" is shadowing an already-declared variable at line 1.
+shadow
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.gd b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.gd
new file mode 100644
index 0000000000..6fc90ea29c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.gd
@@ -0,0 +1,4 @@
+func test():
+ var lambda := func(unused: Variant) -> void:
+ pass
+ lambda.call()
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.out b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.out
new file mode 100644
index 0000000000..32e230fc80
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+>> WARNING
+>> Line: 2
+>> UNUSED_PARAMETER
+>> The parameter 'unused' is never used in the function ''. If this is intended, prefix it with an underscore: '_unused'
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/onready_with_export.gd b/modules/gdscript/tests/scripts/analyzer/warnings/onready_with_export.gd
new file mode 100644
index 0000000000..0b358ca5f2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/onready_with_export.gd
@@ -0,0 +1,6 @@
+extends Node
+
+@onready @export var conflict = ""
+
+func test():
+ print("warn")
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/onready_with_export.out b/modules/gdscript/tests/scripts/analyzer/warnings/onready_with_export.out
new file mode 100644
index 0000000000..ff184f9f04
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/onready_with_export.out
@@ -0,0 +1,6 @@
+GDTEST_OK
+>> WARNING
+>> Line: 3
+>> ONREADY_WITH_EXPORT
+>> The "@onready" annotation will make the default value to be set after the "@export" takes effect and will override it.
+warn
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/overriding_native_method.gd b/modules/gdscript/tests/scripts/analyzer/warnings/overriding_native_method.gd
new file mode 100644
index 0000000000..19d40f8ec8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/overriding_native_method.gd
@@ -0,0 +1,5 @@
+func test():
+ print("warn")
+
+func get(_property: StringName) -> Variant:
+ return null
diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/overriding_native_method.out b/modules/gdscript/tests/scripts/analyzer/warnings/overriding_native_method.out
new file mode 100644
index 0000000000..793faa05d4
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/overriding_native_method.out
@@ -0,0 +1,6 @@
+GDTEST_OK
+>> WARNING
+>> Line: 4
+>> NATIVE_METHOD_OVERRIDE
+>> The method "get" overrides a method from native class "Object". This won't be called by the engine and may not work as expected.
+warn
diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd
index ada6030132..2470fe978e 100644
--- a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd
+++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd
@@ -1,6 +1,6 @@
-# Error here. `class_name` should be used *before* annotations, not after (except @tool).
+# Error here. Annotations should be used before `class_name`, not after.
+class_name WrongAnnotationPlace
@icon("res://path/to/optional/icon.svg")
-class_name HelloWorld
func test():
- pass
+ pass
diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out
index 02b33c8692..5fcf1cbcad 100644
--- a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out
+++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-"class_name" should be used before annotations (except @tool).
+Annotation "@icon" must be at the top of the script, before "extends" and "class_name".
diff --git a/modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd b/modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd
index 92dfb2366d..816783f239 100644
--- a/modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd
+++ b/modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd
@@ -1,2 +1,2 @@
func test():
- var dictionary = { hello = "world",, }
+ var dictionary = { hello = "world",, }
diff --git a/modules/gdscript/tests/scripts/parser/errors/identifier_similar_to_keyword.gd b/modules/gdscript/tests/scripts/parser/errors/identifier_similar_to_keyword.gd
new file mode 100644
index 0000000000..4b1f284070
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/identifier_similar_to_keyword.gd
@@ -0,0 +1,3 @@
+func test():
+ var аs # Using Cyrillic "а".
+ print(аs)
diff --git a/modules/gdscript/tests/scripts/parser/errors/identifier_similar_to_keyword.out b/modules/gdscript/tests/scripts/parser/errors/identifier_similar_to_keyword.out
new file mode 100644
index 0000000000..337dec2f4d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/errors/identifier_similar_to_keyword.out
@@ -0,0 +1,2 @@
+GDTEST_PARSER_ERROR
+Identifier "аs" is visually similar to the GDScript keyword "as" and thus not allowed.
diff --git a/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd
index 4608c778aa..7a745bd995 100644
--- a/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd
+++ b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd
@@ -1,4 +1,4 @@
func test():
- match 1:
- [[[var a]]], 2:
- pass
+ match 1:
+ [[[var a]]], 2:
+ pass
diff --git a/modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd b/modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd
index 43b513045b..a7197bf68f 100644
--- a/modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd
+++ b/modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd
@@ -1,34 +1,34 @@
func foo(x):
- match x:
- 1 + 1:
- print("1+1")
- [1,2,[1,{1:2,2:var z,..}]]:
- print("[1,2,[1,{1:2,2:var z,..}]]")
- print(z)
- 1 if true else 2:
- print("1 if true else 2")
- 1 < 2:
- print("1 < 2")
- 1 or 2 and 1:
- print("1 or 2 and 1")
- 6 | 1:
- print("1 | 1")
- 1 >> 1:
- print("1 >> 1")
- 1, 2 or 3, 4:
- print("1, 2 or 3, 4")
- _:
- print("wildcard")
+ match x:
+ 1 + 1:
+ print("1+1")
+ [1,2,[1,{1:2,2:var z,..}]]:
+ print("[1,2,[1,{1:2,2:var z,..}]]")
+ print(z)
+ 1 if true else 2:
+ print("1 if true else 2")
+ 1 < 2:
+ print("1 < 2")
+ 1 or 2 and 1:
+ print("1 or 2 and 1")
+ 6 | 1:
+ print("1 | 1")
+ 1 >> 1:
+ print("1 >> 1")
+ 1, 2 or 3, 4:
+ print("1, 2 or 3, 4")
+ _:
+ print("wildcard")
func test():
- foo(6 | 1)
- foo(1 >> 1)
- foo(2)
- foo(1)
- foo(1+1)
- foo(1 < 2)
- foo([2, 1])
- foo(4)
- foo([1, 2, [1, {1 : 2, 2:3}]])
- foo([1, 2, [1, {1 : 2, 2:[1,3,5, "123"], 4:2}]])
- foo([1, 2, [1, {1 : 2}]])
+ foo(6 | 1)
+ foo(1 >> 1)
+ foo(2)
+ foo(1)
+ foo(1+1)
+ foo(1 < 2)
+ foo([2, 1])
+ foo(4)
+ foo([1, 2, [1, {1 : 2, 2:3}]])
+ foo([1, 2, [1, {1 : 2, 2:[1,3,5, "123"], 4:2}]])
+ foo([1, 2, [1, {1 : 2}]])
diff --git a/modules/gdscript/tests/scripts/parser/features/allow_id_similar_to_keyword_in_ascii.gd b/modules/gdscript/tests/scripts/parser/features/allow_id_similar_to_keyword_in_ascii.gd
new file mode 100644
index 0000000000..390d314b94
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/allow_id_similar_to_keyword_in_ascii.gd
@@ -0,0 +1,3 @@
+func test():
+ var P1 = "ok" # Technically it is visually similar to keyword "PI" but allowed since it's in ASCII range.
+ print(P1)
diff --git a/modules/gdscript/tests/scripts/parser/features/allow_id_similar_to_keyword_in_ascii.out b/modules/gdscript/tests/scripts/parser/features/allow_id_similar_to_keyword_in_ascii.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/allow_id_similar_to_keyword_in_ascii.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.gd b/modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.gd
new file mode 100644
index 0000000000..3ecd65ad9c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.gd
@@ -0,0 +1,21 @@
+"""
+This is a comment.
+"""
+
+@tool
+
+"""
+This is also a comment.
+"""
+
+extends RefCounted
+
+'''
+This is a comment too.
+'''
+
+func test():
+ """
+ This too is a comment.
+ """
+ print("ok")
diff --git a/modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.out b/modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
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
new file mode 100644
index 0000000000..7e1982597c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.gd
@@ -0,0 +1,16 @@
+func test():
+ # The following keywords are allowed as identifiers:
+ var match = "match"
+ print(match)
+
+ var PI = "PI"
+ print(PI)
+
+ var INF = "INF"
+ print(INF)
+
+ var NAN = "NAN"
+ print(NAN)
+
+ var TAU = "TAU"
+ print(TAU)
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
new file mode 100644
index 0000000000..aae2ae13d5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/allowed_keywords_as_identifiers.out
@@ -0,0 +1,6 @@
+GDTEST_OK
+match
+PI
+INF
+NAN
+TAU
diff --git a/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.gd b/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.gd
index cc78309ae4..a34cc26e67 100644
--- a/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.gd
+++ b/modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.gd
@@ -1,6 +1,6 @@
# https://github.com/godotengine/godot/issues/50285
-@warning_ignore(unused_local_constant)
+@warning_ignore("unused_local_constant")
func test():
const CONST_INNER_DICTIONARY = { "key": true }
const CONST_NESTED_DICTIONARY_OLD_WORKAROUND = {
diff --git a/modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd b/modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd
index 2b46f1e88a..c959c6c6af 100644
--- a/modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd
+++ b/modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd
@@ -1,27 +1,27 @@
func foo(x):
- match x:
- 1:
- print("1")
- 2:
- print("2")
- [1, 2]:
- print("[1, 2]")
- 3 or 4:
- print("3 or 4")
- 4:
- print("4")
- {1 : 2, 2 : 3}:
- print("{1 : 2, 2 : 3}")
- _:
- print("wildcard")
+ match x:
+ 1:
+ print("1")
+ 2:
+ print("2")
+ [1, 2]:
+ print("[1, 2]")
+ 3 or 4:
+ print("3 or 4")
+ 4:
+ print("4")
+ {1 : 2, 2 : 3}:
+ print("{1 : 2, 2 : 3}")
+ _:
+ print("wildcard")
func test():
- foo(0)
- foo(1)
- foo(2)
- foo([1, 2])
- foo(3)
- foo(4)
- foo([4,4])
- foo({1 : 2, 2 : 3})
- foo({1 : 2, 4 : 3})
+ foo(0)
+ foo(1)
+ foo(2)
+ foo([1, 2])
+ foo(3)
+ foo(4)
+ foo([4,4])
+ foo({1 : 2, 2 : 3})
+ foo({1 : 2, 4 : 3})
diff --git a/modules/gdscript/tests/scripts/parser/features/class_name.gd b/modules/gdscript/tests/scripts/parser/features/class_name.gd
index 8bd188e247..19009e433d 100644
--- a/modules/gdscript/tests/scripts/parser/features/class_name.gd
+++ b/modules/gdscript/tests/scripts/parser/features/class_name.gd
@@ -1,5 +1,5 @@
-class_name HelloWorld
@icon("res://path/to/optional/icon.svg")
+class_name HelloWorld
func test():
pass
diff --git a/modules/gdscript/tests/scripts/parser/features/export_enum.gd b/modules/gdscript/tests/scripts/parser/features/export_enum.gd
new file mode 100644
index 0000000000..9b2c22dea1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/export_enum.gd
@@ -0,0 +1,15 @@
+@export_enum("Red", "Green", "Blue") var untyped
+
+@export_enum("Red", "Green", "Blue") var weak_int = 0
+@export_enum("Red", "Green", "Blue") var weak_string = ""
+
+@export_enum("Red", "Green", "Blue") var hard_int: int
+@export_enum("Red", "Green", "Blue") var hard_string: String
+
+@export_enum("Red:10", "Green:20", "Blue:30") var with_values
+
+func test():
+ for property in get_property_list():
+ if property.name in ["untyped", "weak_int", "weak_string", "hard_int",
+ "hard_string", "with_values"]:
+ prints(property.name, property.type, property.hint_string)
diff --git a/modules/gdscript/tests/scripts/parser/features/export_enum.out b/modules/gdscript/tests/scripts/parser/features/export_enum.out
new file mode 100644
index 0000000000..330b7eaf01
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/export_enum.out
@@ -0,0 +1,7 @@
+GDTEST_OK
+untyped 2 Red,Green,Blue
+weak_int 2 Red,Green,Blue
+weak_string 4 Red,Green,Blue
+hard_int 2 Red,Green,Blue
+hard_string 4 Red,Green,Blue
+with_values 2 Red:10,Green:20,Blue:30
diff --git a/modules/gdscript/tests/scripts/parser/features/export_variable.gd b/modules/gdscript/tests/scripts/parser/features/export_variable.gd
index 1e072728fc..acf9ff2e21 100644
--- a/modules/gdscript/tests/scripts/parser/features/export_variable.gd
+++ b/modules/gdscript/tests/scripts/parser/features/export_variable.gd
@@ -5,7 +5,7 @@
@export var color: Color
@export_color_no_alpha var color_no_alpha: Color
-@export_node_path(Sprite2D, Sprite3D, Control, Node) var nodepath := ^"hello"
+@export_node_path("Sprite2D", "Sprite3D", "Control", "Node") var nodepath := ^"hello"
func test():
diff --git a/modules/gdscript/tests/scripts/parser/features/lambda_callable.gd b/modules/gdscript/tests/scripts/parser/features/lambda_callable.gd
index c3b2506156..17d00bce3c 100644
--- a/modules/gdscript/tests/scripts/parser/features/lambda_callable.gd
+++ b/modules/gdscript/tests/scripts/parser/features/lambda_callable.gd
@@ -1,4 +1,4 @@
func test():
- var my_lambda = func(x):
- print(x)
- my_lambda.call("hello")
+ var my_lambda = func(x):
+ print(x)
+ my_lambda.call("hello")
diff --git a/modules/gdscript/tests/scripts/parser/features/match.gd b/modules/gdscript/tests/scripts/parser/features/match.gd
index 4d05490aa5..59b5ba2426 100644
--- a/modules/gdscript/tests/scripts/parser/features/match.gd
+++ b/modules/gdscript/tests/scripts/parser/features/match.gd
@@ -3,8 +3,6 @@ func test():
match i:
"Hello":
print("hello")
- # This will fall through to the default case below.
- continue
"Good bye":
print("bye")
_:
diff --git a/modules/gdscript/tests/scripts/parser/features/match.out b/modules/gdscript/tests/scripts/parser/features/match.out
index 732885c7a2..a2cb94399c 100644
--- a/modules/gdscript/tests/scripts/parser/features/match.out
+++ b/modules/gdscript/tests/scripts/parser/features/match.out
@@ -1,4 +1,3 @@
GDTEST_OK
hello
-default
This will match
diff --git a/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd b/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
index 377dd25e9e..75857fb8ff 100644
--- a/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
+++ b/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
@@ -1,43 +1,43 @@
func foo(x):
- match x:
- {"key1": "value1", "key2": "value2"}:
- print('{"key1": "value1", "key2": "value2"}')
- {"key1": "value1", "key2"}:
- print('{"key1": "value1", "key2"}')
- {"key1", "key2": "value2"}:
- print('{"key1", "key2": "value2"}')
- {"key1", "key2"}:
- print('{"key1", "key2"}')
- {"key1": "value1"}:
- print('{"key1": "value1"}')
- {"key1"}:
- print('{"key1"}')
- _:
- print("wildcard")
+ match x:
+ {"key1": "value1", "key2": "value2"}:
+ print('{"key1": "value1", "key2": "value2"}')
+ {"key1": "value1", "key2"}:
+ print('{"key1": "value1", "key2"}')
+ {"key1", "key2": "value2"}:
+ print('{"key1", "key2": "value2"}')
+ {"key1", "key2"}:
+ print('{"key1", "key2"}')
+ {"key1": "value1"}:
+ print('{"key1": "value1"}')
+ {"key1"}:
+ print('{"key1"}')
+ _:
+ print("wildcard")
func bar(x):
- match x:
- {0}:
- print("0")
- {1}:
- print("1")
- {2}:
- print("2")
- _:
- print("wildcard")
+ match x:
+ {0}:
+ print("0")
+ {1}:
+ print("1")
+ {2}:
+ print("2")
+ _:
+ print("wildcard")
func test():
- foo({"key1": "value1", "key2": "value2"})
- foo({"key1": "value1", "key2": ""})
- foo({"key1": "", "key2": "value2"})
- foo({"key1": "", "key2": ""})
- foo({"key1": "value1"})
- foo({"key1": ""})
- foo({"key1": "value1", "key2": "value2", "key3": "value3"})
- foo({"key1": "value1", "key3": ""})
- foo({"key2": "value2"})
- foo({"key3": ""})
- bar({0: "0"})
- bar({1: "1"})
- bar({2: "2"})
- bar({3: "3"})
+ foo({"key1": "value1", "key2": "value2"})
+ foo({"key1": "value1", "key2": ""})
+ foo({"key1": "", "key2": "value2"})
+ foo({"key1": "", "key2": ""})
+ foo({"key1": "value1"})
+ foo({"key1": ""})
+ foo({"key1": "value1", "key2": "value2", "key3": "value3"})
+ foo({"key1": "value1", "key3": ""})
+ foo({"key2": "value2"})
+ foo({"key3": ""})
+ bar({0: "0"})
+ bar({1: "1"})
+ bar({2: "2"})
+ bar({3: "3"})
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
index dbe223f5f5..a278ea1154 100644
--- a/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
@@ -1,26 +1,26 @@
func foo(x):
- match x:
- 1, [2]:
- print('1, [2]')
- _:
- print('wildcard')
+ match x:
+ 1, [2]:
+ print('1, [2]')
+ _:
+ print('wildcard')
func bar(x):
- match x:
- [1], [2], [3]:
- print('[1], [2], [3]')
- [4]:
- print('[4]')
- _:
- print('wildcard')
+ match x:
+ [1], [2], [3]:
+ print('[1], [2], [3]')
+ [4]:
+ print('[4]')
+ _:
+ print('wildcard')
func test():
- foo(1)
- foo([2])
- foo(2)
- bar([1])
- bar([2])
- bar([3])
- bar([4])
- bar([5])
+ foo(1)
+ foo([2])
+ foo(2)
+ bar([1])
+ bar([2])
+ bar([3])
+ bar([4])
+ bar([5])
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd
index a0ae7fb17c..0a71f33c25 100644
--- a/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd
@@ -1,6 +1,6 @@
func test():
- match [1, 2, 3]:
- [var a, var b, var c]:
- print(a == 1)
- print(b == 2)
- print(c == 3)
+ match [1, 2, 3]:
+ [var a, var b, var c]:
+ print(a == 1)
+ print(b == 2)
+ print(c == 3)
diff --git a/modules/gdscript/tests/scripts/parser/features/match_with_variables.gd b/modules/gdscript/tests/scripts/parser/features/match_with_variables.gd
new file mode 100644
index 0000000000..aa38c3bf41
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_with_variables.gd
@@ -0,0 +1,22 @@
+func test():
+ var a = 1
+ match 1:
+ a:
+ print("reach 1")
+
+ var dict = { b = 2 }
+ match 2:
+ dict.b:
+ print("reach 2")
+
+ var nested_dict = {
+ sub = { c = 3 }
+ }
+ match 3:
+ nested_dict.sub.c:
+ print("reach 3")
+
+ var sub_pattern = { d = 4 }
+ match [4]:
+ [sub_pattern.d]:
+ print("reach 4")
diff --git a/modules/gdscript/tests/scripts/parser/features/match_with_variables.out b/modules/gdscript/tests/scripts/parser/features/match_with_variables.out
new file mode 100644
index 0000000000..de1dcb0d40
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_with_variables.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+reach 1
+reach 2
+reach 3
+reach 4
diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_assert.gd b/modules/gdscript/tests/scripts/parser/features/multiline_assert.gd
new file mode 100644
index 0000000000..8c699c604d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/multiline_assert.gd
@@ -0,0 +1,24 @@
+func test():
+ var x := 5
+
+ assert(x > 0)
+ assert(x > 0,)
+ assert(x > 0, 'message')
+ assert(x > 0, 'message',)
+
+ assert(
+ x > 0
+ )
+ assert(
+ x > 0,
+ )
+ assert(
+ x > 0,
+ 'message'
+ )
+ assert(
+ x > 0,
+ 'message',
+ )
+
+ print('OK')
diff --git a/modules/gdscript/tests/scripts/parser/features/multiline_assert.out b/modules/gdscript/tests/scripts/parser/features/multiline_assert.out
new file mode 100644
index 0000000000..1ccb591560
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/multiline_assert.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+OK
diff --git a/modules/gdscript/tests/scripts/parser/features/nested_match.gd b/modules/gdscript/tests/scripts/parser/features/nested_match.gd
index aaddcc7e83..491d917a8e 100644
--- a/modules/gdscript/tests/scripts/parser/features/nested_match.gd
+++ b/modules/gdscript/tests/scripts/parser/features/nested_match.gd
@@ -8,11 +8,10 @@ func test():
1234:
print("2")
match number:
- 1234:
- print("3")
- continue
+ 4321:
+ print("Should not be printed")
_:
- print("Should also be printed")
+ print("3")
match number:
1234:
print("4")
diff --git a/modules/gdscript/tests/scripts/parser/features/nested_match.out b/modules/gdscript/tests/scripts/parser/features/nested_match.out
index 651d76cc59..c2d2e29a06 100644
--- a/modules/gdscript/tests/scripts/parser/features/nested_match.out
+++ b/modules/gdscript/tests/scripts/parser/features/nested_match.out
@@ -2,7 +2,6 @@ GDTEST_OK
1
2
3
-Should also be printed
4
5
6
diff --git a/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.gd b/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.gd
new file mode 100644
index 0000000000..523959a016
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.gd
@@ -0,0 +1,35 @@
+const π = PI
+var ㄥ = π
+
+func test():
+ var փորձարկում = "test"
+ prints("փորձարկում", փորձարկում)
+ var امتحان = "test"
+ prints("امتحان", امتحان)
+ var পরীক্ষা = "test"
+ prints("পরীক্ষা", পরীক্ষা)
+ var тест = "test"
+ prints("тест", тест)
+ var जाँच = "test"
+ prints("जाँच", जाँच)
+ var 기준 = "test"
+ prints("기준", 기준)
+ var 测试 = "test"
+ prints("测试", 测试)
+ var テスト = "test"
+ prints("テスト", テスト)
+ var 試験 = "test"
+ prints("試験", 試験)
+ var പരീക്ഷ = "test"
+ prints("പരീക്ഷ", പരീക്ഷ)
+ var ทดสอบ = "test"
+ prints("ทดสอบ", ทดสอบ)
+ var δοκιμή = "test"
+ prints("δοκιμή", δοκιμή)
+
+ const d = 1.1
+ _process(d)
+ print(is_equal_approx(ㄥ, PI + (d * PI)))
+
+func _process(Δ: float) -> void:
+ ㄥ += Δ * π
diff --git a/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.out b/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.out
new file mode 100644
index 0000000000..c071380a8f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/unicode_identifiers.out
@@ -0,0 +1,14 @@
+GDTEST_OK
+փորձարկում test
+امتحان test
+পরীক্ষা test
+тест test
+जाँच test
+기준 test
+测试 test
+テスト test
+試験 test
+പരീക്ഷ test
+ทดสอบ test
+δοκιμή test
+true
diff --git a/modules/gdscript/tests/scripts/parser/features/unnamed_enums_outer_conflicts.gd b/modules/gdscript/tests/scripts/parser/features/unnamed_enums_outer_conflicts.gd
new file mode 100644
index 0000000000..4cbb464f59
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/unnamed_enums_outer_conflicts.gd
@@ -0,0 +1,17 @@
+class A:
+ enum { X = 1 }
+
+ class B:
+ enum { X = 2 }
+
+class C:
+ const X = 3
+
+ class D:
+ enum { X = 4 }
+
+func test():
+ print(A.X)
+ print(A.B.X)
+ print(C.X)
+ print(C.D.X)
diff --git a/modules/gdscript/tests/scripts/parser/features/unnamed_enums_outer_conflicts.out b/modules/gdscript/tests/scripts/parser/features/unnamed_enums_outer_conflicts.out
new file mode 100644
index 0000000000..7536c38490
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/unnamed_enums_outer_conflicts.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+1
+2
+3
+4
diff --git a/modules/gdscript/tests/scripts/parser/features/vector_inf.gd b/modules/gdscript/tests/scripts/parser/features/vector_inf.gd
new file mode 100644
index 0000000000..039d51d9ed
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/vector_inf.gd
@@ -0,0 +1,6 @@
+func test():
+ var vec2: = Vector2.INF
+ var vec3: = Vector3.INF
+
+ print(vec2.x == INF)
+ print(vec3.z == INF)
diff --git a/modules/gdscript/tests/scripts/parser/features/vector_inf.out b/modules/gdscript/tests/scripts/parser/features/vector_inf.out
new file mode 100644
index 0000000000..9d111a8322
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/vector_inf.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+true
+true
diff --git a/modules/gdscript/tests/scripts/parser/warnings/confusable_identifier.gd b/modules/gdscript/tests/scripts/parser/warnings/confusable_identifier.gd
new file mode 100644
index 0000000000..41b38c4bba
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/confusable_identifier.gd
@@ -0,0 +1,12 @@
+extends Node
+
+func test():
+ var port = 0 # Only latin characters.
+ var pοrt = 1 # The "ο" is Greek omicron.
+
+ prints(port, pοrt)
+
+# Do not call this since nodes aren't in the tree. It is just a parser check.
+func nodes():
+ var _node1 = $port # Only latin characters.
+ var _node2 = $pοrt # The "ο" is Greek omicron.
diff --git a/modules/gdscript/tests/scripts/parser/warnings/confusable_identifier.out b/modules/gdscript/tests/scripts/parser/warnings/confusable_identifier.out
new file mode 100644
index 0000000000..c189204285
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/warnings/confusable_identifier.out
@@ -0,0 +1,10 @@
+GDTEST_OK
+>> WARNING
+>> Line: 5
+>> CONFUSABLE_IDENTIFIER
+>> The identifier "pοrt" has misleading characters and might be confused with something else.
+>> WARNING
+>> Line: 12
+>> CONFUSABLE_IDENTIFIER
+>> The identifier "pοrt" has misleading characters and might be confused with something else.
+0 1
diff --git a/modules/gdscript/tests/scripts/parser/warnings/enum_assign_int_without_casting.out b/modules/gdscript/tests/scripts/parser/warnings/enum_assign_int_without_casting.out
index eef13bbff8..b8e243769f 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/enum_assign_int_without_casting.out
+++ b/modules/gdscript/tests/scripts/parser/warnings/enum_assign_int_without_casting.out
@@ -1,19 +1,19 @@
GDTEST_OK
>> WARNING
>> Line: 5
->> INT_ASSIGNED_TO_ENUM
+>> INT_AS_ENUM_WITHOUT_CAST
>> Integer used when an enum value is expected. If this is intended cast the integer to the enum type.
>> WARNING
>> Line: 9
->> INT_ASSIGNED_TO_ENUM
+>> INT_AS_ENUM_WITHOUT_CAST
>> Integer used when an enum value is expected. If this is intended cast the integer to the enum type.
>> WARNING
>> Line: 12
->> INT_ASSIGNED_TO_ENUM
+>> INT_AS_ENUM_WITHOUT_CAST
>> Integer used when an enum value is expected. If this is intended cast the integer to the enum type.
>> WARNING
>> Line: 14
->> INT_ASSIGNED_TO_ENUM
+>> INT_AS_ENUM_WITHOUT_CAST
>> Integer used when an enum value is expected. If this is intended cast the integer to the enum type.
0
1
diff --git a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd
index 18ea260fa2..dc4223ec2d 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd
+++ b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd
@@ -1,6 +1,5 @@
func test():
# The following statements should all be reported as standalone expressions:
- "This is a standalone expression"
1234
0.0 + 0.0
Color(1, 1, 1)
diff --git a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out
index 99ec87438e..a2c67a6e51 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out
+++ b/modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out
@@ -8,14 +8,10 @@ GDTEST_OK
>> STANDALONE_EXPRESSION
>> Standalone expression (the line has no effect).
>> WARNING
->> Line: 5
+>> Line: 6
>> STANDALONE_EXPRESSION
>> Standalone expression (the line has no effect).
>> WARNING
>> Line: 7
>> STANDALONE_EXPRESSION
>> Standalone expression (the line has no effect).
->> WARNING
->> Line: 8
->> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
diff --git a/modules/gdscript/tests/scripts/parser/warnings/void_assignment.gd b/modules/gdscript/tests/scripts/parser/warnings/void_assignment.gd
deleted file mode 100644
index b4a42b3e3d..0000000000
--- a/modules/gdscript/tests/scripts/parser/warnings/void_assignment.gd
+++ /dev/null
@@ -1,6 +0,0 @@
-func i_return_void() -> void:
- return
-
-
-func test():
- var __ = i_return_void()
diff --git a/modules/gdscript/tests/scripts/parser/warnings/void_assignment.out b/modules/gdscript/tests/scripts/parser/warnings/void_assignment.out
deleted file mode 100644
index 84c9598f9a..0000000000
--- a/modules/gdscript/tests/scripts/parser/warnings/void_assignment.out
+++ /dev/null
@@ -1,5 +0,0 @@
-GDTEST_OK
->> WARNING
->> Line: 6
->> VOID_ASSIGNMENT
->> Assignment operation, but the function 'i_return_void()' returns void.
diff --git a/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property.gd b/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property.gd
new file mode 100644
index 0000000000..19c4186622
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property.gd
@@ -0,0 +1,7 @@
+func test():
+ var state = PhysicsDirectBodyState3DExtension.new()
+ assign(state)
+ state.free()
+
+func assign(state):
+ state.center_of_mass.x -= 1.0
diff --git a/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property.out b/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property.out
new file mode 100644
index 0000000000..c181c5dd02
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: assign()
+>> runtime/assign_to_read_only_property.gd
+>> 7
+>> Cannot set value into property "center_of_mass" (on base "PhysicsDirectBodyState3DExtension") because it is read-only.
diff --git a/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property_with_variable_index.gd b/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property_with_variable_index.gd
new file mode 100644
index 0000000000..f15f580272
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property_with_variable_index.gd
@@ -0,0 +1,8 @@
+func test():
+ var state = PhysicsDirectBodyState3DExtension.new()
+ var prop = &"center_of_mass"
+ assign(state, prop)
+ state.free()
+
+func assign(state, prop):
+ state[prop].x = 1.0
diff --git a/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property_with_variable_index.out b/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property_with_variable_index.out
new file mode 100644
index 0000000000..2cdc81aacc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/assign_to_read_only_property_with_variable_index.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: assign()
+>> runtime/assign_to_read_only_property_with_variable_index.gd
+>> 8
+>> Cannot set value into property "center_of_mass" (on base "PhysicsDirectBodyState3DExtension") because it is read-only.
diff --git a/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.gd b/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.gd
new file mode 100644
index 0000000000..a72ac9b5ee
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.gd
@@ -0,0 +1,8 @@
+var weakling = 'not float'
+func weak(x: float = weakling):
+ print(x)
+ print('typeof x is', typeof(x))
+
+func test():
+ print(typeof(weak()))
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.out b/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.out
new file mode 100644
index 0000000000..8543cf976e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/bad_conversion_for_default_parameter.out
@@ -0,0 +1,8 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: weak()
+>> runtime/errors/bad_conversion_for_default_parameter.gd
+>> 2
+>> Trying to assign value of type 'String' to a variable of type 'float'.
+0
+not ok
diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.gd b/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.gd
new file mode 100644
index 0000000000..a5ecaba38d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.gd
@@ -0,0 +1,6 @@
+const array: Array = [{}]
+
+func test():
+ var dictionary := array[0]
+ var key: int = 0
+ dictionary[key] = 0
diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.out b/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.out
new file mode 100644
index 0000000000..2a97eaea44
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/constant_array_is_deep.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/constant_array_is_deep.gd
+>> 6
+>> Invalid set index '0' (on base: 'Dictionary') with value of type 'int'
diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.gd b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.gd
new file mode 100644
index 0000000000..4763210a7f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.gd
@@ -0,0 +1,6 @@
+const dictionary := {0: [0]}
+
+func test():
+ var array := dictionary[0]
+ var key: int = 0
+ array[key] = 0
diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.out b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.out
new file mode 100644
index 0000000000..c807db6b0c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_is_deep.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/constant_dictionary_is_deep.gd
+>> 6
+>> Invalid set index '0' (on base: 'Array') with value of type 'int'
diff --git a/modules/gdscript/tests/scripts/runtime/errors/non_static_method_call_on_native_class.gd b/modules/gdscript/tests/scripts/runtime/errors/non_static_method_call_on_native_class.gd
new file mode 100644
index 0000000000..0c15701364
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/non_static_method_call_on_native_class.gd
@@ -0,0 +1,6 @@
+# https://github.com/godotengine/godot/issues/66675
+func test():
+ example(Node2D)
+
+func example(thing):
+ print(thing.has_method('asdf'))
diff --git a/modules/gdscript/tests/scripts/runtime/errors/non_static_method_call_on_native_class.out b/modules/gdscript/tests/scripts/runtime/errors/non_static_method_call_on_native_class.out
new file mode 100644
index 0000000000..3a90f98d99
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/non_static_method_call_on_native_class.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: example()
+>> runtime/errors/non_static_method_call_on_native_class.gd
+>> 6
+>> Invalid call. Nonexistent function 'has_method' in base 'Node2D'.
diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.gd
new file mode 100644
index 0000000000..e9dbc1b640
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.gd
@@ -0,0 +1,4 @@
+func test():
+ var basic := [1]
+ var typed: Array[int] = basic
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.out b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.out
new file mode 100644
index 0000000000..bca700b4ec
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_basic_to_typed.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/typed_array_assign_basic_to_typed.gd
+>> 3
+>> Trying to assign an array of type "Array" to a variable of type "Array[int]".
diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.gd
new file mode 100644
index 0000000000..920352a6ea
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.gd
@@ -0,0 +1,4 @@
+func test():
+ var differently: Variant = [1.0] as Array[float]
+ var typed: Array[int] = differently
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.out b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.out
new file mode 100644
index 0000000000..402ab38fb3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_assign_differently_typed.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/typed_array_assign_differently_typed.gd
+>> 3
+>> Trying to assign an array of type "Array[float]" to a variable of type "Array[int]".
diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.gd
new file mode 100644
index 0000000000..e1fd0f7168
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.gd
@@ -0,0 +1,7 @@
+func expect_typed(typed: Array[int]):
+ print(typed.size())
+
+func test():
+ var basic := [1]
+ expect_typed(basic)
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.out b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.out
new file mode 100644
index 0000000000..6f210e944e
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_basic_to_typed.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/typed_array_pass_basic_to_typed.gd
+>> 6
+>> Invalid type in function 'expect_typed' in base 'RefCounted ()'. The array of argument 1 (Array) does not have the same element type as the expected typed array argument.
diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.gd b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.gd
new file mode 100644
index 0000000000..e2d2721e8c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.gd
@@ -0,0 +1,7 @@
+func expect_typed(typed: Array[int]):
+ print(typed.size())
+
+func test():
+ var differently: Variant = [1.0] as Array[float]
+ expect_typed(differently)
+ print('not ok')
diff --git a/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.out b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.out
new file mode 100644
index 0000000000..3cd4e25bd8
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/typed_array_pass_differently_to_typed.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/typed_array_pass_differently_to_typed.gd
+>> 6
+>> Invalid type in function 'expect_typed' in base 'RefCounted ()'. The array of argument 1 (Array[float]) does not have the same element type as the expected typed array argument.
diff --git a/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.gd b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.gd
new file mode 100644
index 0000000000..a3daf70627
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.gd
@@ -0,0 +1,4 @@
+func test():
+ var obj
+ obj = Node.new()
+ print(obj.free())
diff --git a/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.out b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.out
new file mode 100644
index 0000000000..5edaf19442
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_free_call.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/use_return_value_of_free_call.gd
+>> 4
+>> Trying to get a return value of a method that returns "void"
diff --git a/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.gd b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.gd
new file mode 100644
index 0000000000..49fb76ad1f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.gd
@@ -0,0 +1,4 @@
+func test():
+ var value
+ value = []
+ print(value.reverse())
diff --git a/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.out b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.out
new file mode 100644
index 0000000000..128356ff8a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_builtin_method_call.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/use_return_value_of_void_builtin_method_call.gd
+>> 4
+>> Trying to get a return value of a method that returns "void"
diff --git a/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.gd b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.gd
new file mode 100644
index 0000000000..44f9aa467a
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.gd
@@ -0,0 +1,4 @@
+func test():
+ var obj
+ obj = RefCounted.new()
+ print(obj.notify_property_list_changed())
diff --git a/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.out b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.out
new file mode 100644
index 0000000000..e02c206778
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/use_return_value_of_void_native_method_call.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/use_return_value_of_void_native_method_call.gd
+>> 4
+>> Trying to get a return value of a method that returns "void"
diff --git a/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd
index 5303fb04e2..bd38259cec 100644
--- a/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd
@@ -9,16 +9,16 @@ func test():
array_sname.push_back(&"godot")
print("String in Array: ", "godot" in array_sname)
- # Not equal because the values are different types.
+ # Not equal because the values are different types.
print("Arrays not equal: ", array_str != array_sname)
var string_array: Array[String] = []
var stringname_array: Array[StringName] = []
- assert(!string_array.push_back(&"abc"))
+ string_array.push_back(&"abc")
print("Array[String] insert converted: ", typeof(string_array[0]) == TYPE_STRING)
- assert(!stringname_array.push_back("abc"))
+ stringname_array.push_back("abc")
print("Array[StringName] insert converted: ", typeof(stringname_array[0]) == TYPE_STRING_NAME)
print("StringName in Array[String]: ", &"abc" in string_array)
@@ -28,8 +28,8 @@ func test():
assert(!packed_string_array.push_back("abc"))
print("StringName in PackedStringArray: ", &"abc" in packed_string_array)
- assert(!string_array.push_back("abc"))
+ string_array.push_back("abc")
print("StringName finds String in Array: ", string_array.find(&"abc"))
- assert(!stringname_array.push_back(&"abc"))
+ stringname_array.push_back(&"abc")
print("String finds StringName in Array: ", stringname_array.find("abc"))
diff --git a/modules/gdscript/tests/scripts/runtime/features/await_on_void.gd b/modules/gdscript/tests/scripts/runtime/features/await_on_void.gd
new file mode 100644
index 0000000000..1490a164c9
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/await_on_void.gd
@@ -0,0 +1,7 @@
+func wait() -> void:
+ pass
+
+func test():
+ @warning_ignore("redundant_await")
+ await wait()
+ print("end")
diff --git a/modules/gdscript/tests/scripts/runtime/features/await_on_void.out b/modules/gdscript/tests/scripts/runtime/features/await_on_void.out
new file mode 100644
index 0000000000..5bc3dcf2db
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/await_on_void.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+end
diff --git a/modules/gdscript/tests/scripts/runtime/features/constants_are_read_only.gd b/modules/gdscript/tests/scripts/runtime/features/constants_are_read_only.gd
new file mode 100644
index 0000000000..d1746979be
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/constants_are_read_only.gd
@@ -0,0 +1,10 @@
+const array: Array = [0]
+const dictionary := {1: 2}
+
+@warning_ignore("assert_always_true")
+func test():
+ assert(array.is_read_only() == true)
+ assert(str(array) == '[0]')
+ assert(dictionary.is_read_only() == true)
+ assert(str(dictionary) == '{ 1: 2 }')
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/runtime/features/constants_are_read_only.out b/modules/gdscript/tests/scripts/runtime/features/constants_are_read_only.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/constants_are_read_only.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.gd b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.gd
new file mode 100644
index 0000000000..9d0c6317b3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.gd
@@ -0,0 +1,19 @@
+func literal(x: float = 1):
+ print('x is ', x)
+ print('typeof x is ', typeof(x))
+
+var inferring := 2
+func inferred(x: float = inferring):
+ print('x is ', x)
+ print('typeof x is ', typeof(x))
+
+var weakling = 3
+func weak(x: float = weakling):
+ print('x is ', x)
+ print('typeof x is ', typeof(x))
+
+func test():
+ literal()
+ inferred()
+ weak()
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out
new file mode 100644
index 0000000000..a9ef4919cf
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/conversion_for_default_parameter.out
@@ -0,0 +1,8 @@
+GDTEST_OK
+x is 1
+typeof x is 3
+x is 2
+typeof x is 3
+x is 3
+typeof x is 3
+ok
diff --git a/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd
index 1f15026f17..94bac1974f 100644
--- a/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd
@@ -13,5 +13,5 @@ func test():
print("String gets StringName: ", stringname_dict.get("abc"))
stringname_dict[&"abc"] = 42
- # They compare equal because StringName keys are converted to String.
+ # They compare equal because StringName keys are converted to String.
print("String Dictionary == StringName Dictionary: ", string_dict == stringname_dict)
diff --git a/modules/gdscript/tests/scripts/runtime/features/does_not_override_temp_values.gd b/modules/gdscript/tests/scripts/runtime/features/does_not_override_temp_values.gd
new file mode 100644
index 0000000000..48af734317
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/does_not_override_temp_values.gd
@@ -0,0 +1,17 @@
+# https://github.com/godotengine/godot/issues/71177
+
+func test():
+ builtin_method()
+ builtin_method_static()
+ print("done")
+
+func builtin_method():
+ var pba := PackedByteArray()
+ @warning_ignore("return_value_discarded")
+ pba.resize(1) # Built-in validated.
+
+
+func builtin_method_static():
+ var _pba := PackedByteArray()
+ @warning_ignore("return_value_discarded")
+ Vector2.from_angle(PI) # Static built-in validated.
diff --git a/modules/gdscript/tests/scripts/runtime/features/does_not_override_temp_values.out b/modules/gdscript/tests/scripts/runtime/features/does_not_override_temp_values.out
new file mode 100644
index 0000000000..8e68c97774
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/does_not_override_temp_values.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+done
diff --git a/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_types.gd b/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_types.gd
new file mode 100644
index 0000000000..81355e0255
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_types.gd
@@ -0,0 +1,51 @@
+const constant_float = 1.0
+const constant_int = 1
+enum { enum_value = 1 }
+
+class Iterator:
+ func _iter_init(_count):
+ return true
+ func _iter_next(_count):
+ return false
+ func _iter_get(_count) -> StringName:
+ return &'custom'
+
+func test():
+ var hard_float := 1.0
+ var hard_int := 1
+ var hard_string := '0'
+ var hard_iterator := Iterator.new()
+
+ var variant_float: Variant = hard_float
+ var variant_int: Variant = hard_int
+ var variant_string: Variant = hard_string
+ var variant_iterator: Variant = hard_iterator
+
+ for i in 1.0:
+ print(typeof(i) == TYPE_FLOAT)
+ for i in 1:
+ print(typeof(i) == TYPE_INT)
+ for i in 'a':
+ print(typeof(i) == TYPE_STRING)
+ for i in Iterator.new():
+ print(typeof(i) == TYPE_STRING_NAME)
+
+ for i in hard_float:
+ print(typeof(i) == TYPE_FLOAT)
+ for i in hard_int:
+ print(typeof(i) == TYPE_INT)
+ for i in hard_string:
+ print(typeof(i) == TYPE_STRING)
+ for i in hard_iterator:
+ print(typeof(i) == TYPE_STRING_NAME)
+
+ for i in variant_float:
+ print(typeof(i) == TYPE_FLOAT)
+ for i in variant_int:
+ print(typeof(i) == TYPE_INT)
+ for i in variant_string:
+ print(typeof(i) == TYPE_STRING)
+ for i in variant_iterator:
+ print(typeof(i) == TYPE_STRING_NAME)
+
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_types.out b/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_types.out
new file mode 100644
index 0000000000..b3e82d52ef
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/for_loop_iterator_types.out
@@ -0,0 +1,14 @@
+GDTEST_OK
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+ok
diff --git a/modules/gdscript/tests/scripts/runtime/features/gdscript.gd b/modules/gdscript/tests/scripts/runtime/features/gdscript.gd
new file mode 100644
index 0000000000..e686cffc48
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/gdscript.gd
@@ -0,0 +1,20 @@
+func test():
+ var gdscr: = GDScript.new()
+ gdscr.source_code = '''
+extends Resource
+
+func test() -> void:
+ prints("Outer")
+ var inner = InnerClass.new()
+
+class InnerClass:
+ func _init() -> void:
+ prints("Inner")
+'''
+ @warning_ignore("return_value_discarded")
+ gdscr.reload()
+
+ var inst = gdscr.new()
+
+ @warning_ignore("unsafe_method_access")
+ inst.test()
diff --git a/modules/gdscript/tests/scripts/runtime/features/gdscript.out b/modules/gdscript/tests/scripts/runtime/features/gdscript.out
new file mode 100644
index 0000000000..16114f57f7
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/gdscript.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+Outer
+Inner
diff --git a/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd
index f33ba7dffd..252e100bda 100644
--- a/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd
@@ -3,23 +3,23 @@
var a: int = 1
func shadow_regular_assignment(a: Variant, b: Variant) -> void:
- print(a)
- print(self.a)
- a = b
- print(a)
- print(self.a)
+ print(a)
+ print(self.a)
+ a = b
+ print(a)
+ print(self.a)
var v := Vector2(0.0, 0.0)
func shadow_subscript_assignment(v: Vector2, x: float) -> void:
- print(v)
- print(self.v)
- v.x += x
- print(v)
- print(self.v)
+ print(v)
+ print(self.v)
+ v.x += x
+ print(v)
+ print(self.v)
func test():
- shadow_regular_assignment('a', 'b')
- shadow_subscript_assignment(Vector2(1.0, 1.0), 5.0)
+ shadow_regular_assignment('a', 'b')
+ shadow_subscript_assignment(Vector2(1.0, 1.0), 5.0)
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
new file mode 100644
index 0000000000..2f55059334
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd
@@ -0,0 +1,45 @@
+# https://github.com/godotengine/godot/issues/70964
+
+func test():
+ test_construct(0, false)
+ test_utility(0, false)
+ test_builtin_call(Vector2.UP, false)
+ test_builtin_call_validated(Vector2.UP, false)
+ test_object_call(RefCounted.new(), false)
+ test_object_call_method_bind(Resource.new(), false)
+ test_object_call_ptrcall(RefCounted.new(), false)
+
+ print("end")
+
+func test_construct(v, f):
+ Vector2(v, v) # Built-in type construct.
+ assert(not f) # Test unary operator reading from `nil`.
+
+func test_utility(v, f):
+ abs(v) # Utility function.
+ assert(not f) # Test unary operator reading from `nil`.
+
+func test_builtin_call(v, f):
+ @warning_ignore("unsafe_method_access")
+ v.angle() # Built-in method call.
+ assert(not f) # Test unary operator reading from `nil`.
+
+func test_builtin_call_validated(v: Vector2, f):
+ @warning_ignore("return_value_discarded")
+ v.abs() # Built-in method call validated.
+ assert(not f) # Test unary operator reading from `nil`.
+
+func test_object_call(v, f):
+ @warning_ignore("unsafe_method_access")
+ v.get_reference_count() # Native type method call.
+ assert(not f) # Test unary operator reading from `nil`.
+
+func test_object_call_method_bind(v: Resource, f):
+ @warning_ignore("return_value_discarded")
+ v.duplicate() # Native type method call with MethodBind.
+ assert(not f) # Test unary operator reading from `nil`.
+
+func test_object_call_ptrcall(v: RefCounted, f):
+ @warning_ignore("return_value_discarded")
+ v.get_reference_count() # Native type method call with ptrcall.
+ assert(not f) # Test unary operator reading from `nil`.
diff --git a/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.out b/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.out
new file mode 100644
index 0000000000..5bc3dcf2db
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+end
diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.gd b/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.gd
new file mode 100644
index 0000000000..ec444b4ffa
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.gd
@@ -0,0 +1,6 @@
+func test():
+ var untyped: Variant = 32
+ var typed: Array[int] = [untyped]
+ assert(typed.get_typed_builtin() == TYPE_INT)
+ assert(str(typed) == '[32]')
+ print('ok')
diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.out b/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.out
new file mode 100644
index 0000000000..1b47ed10dc
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/typed_array_init_with_untyped_in_literal.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+ok
diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd
new file mode 100644
index 0000000000..22e54cf91c
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd
@@ -0,0 +1,9 @@
+func test():
+ var x: int = 2
+ var y = 3.14
+ var z := 2.72
+ print(typeof(x))
+ x = y
+ print(typeof(x))
+ x = z
+ print(typeof(x))
diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_assignment.out b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.out
new file mode 100644
index 0000000000..4a268dd8e0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.out
@@ -0,0 +1,12 @@
+GDTEST_OK
+>> WARNING
+>> Line: 6
+>> NARROWING_CONVERSION
+>> Narrowing conversion (float is converted to int and loses precision).
+>> WARNING
+>> Line: 8
+>> NARROWING_CONVERSION
+>> Narrowing conversion (float is converted to int and loses precision).
+2
+2
+2
diff --git a/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.gd b/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.gd
new file mode 100644
index 0000000000..efa8270526
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.gd
@@ -0,0 +1,9 @@
+# https://github.com/godotengine/godot/issues/71172
+
+func test():
+ @warning_ignore("narrowing_conversion")
+ var foo: int = 0.0
+ print(typeof(foo) == TYPE_INT)
+ var dict : Dictionary = {"a":0.0}
+ foo = dict.get("a")
+ print(typeof(foo) == TYPE_INT)
diff --git a/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.out b/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.out
new file mode 100644
index 0000000000..9d111a8322
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+true
+true
diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp
index cbcd7b2955..ad38312abe 100644
--- a/modules/gdscript/tests/test_gdscript.cpp
+++ b/modules/gdscript/tests/test_gdscript.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* test_gdscript.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* test_gdscript.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "test_gdscript.h"
diff --git a/modules/gdscript/tests/test_gdscript.h b/modules/gdscript/tests/test_gdscript.h
index b6b1f26203..d719e3d94a 100644
--- a/modules/gdscript/tests/test_gdscript.h
+++ b/modules/gdscript/tests/test_gdscript.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* test_gdscript.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* test_gdscript.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef TEST_GDSCRIPT_H
#define TEST_GDSCRIPT_H