summaryrefslogtreecommitdiff
path: root/modules/gdscript/tests
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/tests')
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp38
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.h4
-rw-r--r--modules/gdscript/tests/gdscript_test_runner_suite.h3
-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_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/cast_enum_bad_enum.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_int.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_function_parameter_wrong_type.out2
-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.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_preload_unnamed_assign_to_named.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.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/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_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/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/preload_enum_error.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/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/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.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.out1
-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/const_conversions.gd24
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/const_conversions.out2
-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/native_typed_assign_null.gd15
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/native_typed_assign_null.out7
-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/return_conversions.gd34
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/return_conversions.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.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd215
-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/warning_ignore_annotation.gd6
-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.gd (renamed from modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_enum.gd)0
-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.gd (renamed from modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_int.gd)0
-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_unused_arg.out2
-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.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out2
-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/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/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/match.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match.out1
-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/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/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/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/constant_array_push_back.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/constant_array_push_back.out7
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.out7
-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/features/await_on_void.gd2
-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/does_not_override_temp_values.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/gdscript.gd4
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd10
-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/use_conversion_assign_with_variant_value.gd2
160 files changed, 1081 insertions, 106 deletions
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index d2c8b5c317..57405aa1ce 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -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 b097f1b485..60b48c6a57 100644
--- a/modules/gdscript/tests/gdscript_test_runner.h
+++ b/modules/gdscript/tests/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 aed0ac2baf..e27b6218f1 100644
--- a/modules/gdscript/tests/gdscript_test_runner_suite.h
+++ b/modules/gdscript/tests/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/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_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/cast_enum_bad_enum.out b/modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_enum.out
deleted file mode 100644
index 3a8d2a205a..0000000000
--- a/modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_enum.out
+++ /dev/null
@@ -1,2 +0,0 @@
-GDTEST_ANALYZER_ERROR
-Invalid cast. Enum "cast_enum_bad_enum.gd::MyEnum" does not have value corresponding to "MyOtherEnum.OTHER_ENUM_VALUE_3" (2).
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_int.out b/modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_int.out
deleted file mode 100644
index bc0d8b7834..0000000000
--- a/modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_int.out
+++ /dev/null
@@ -1,2 +0,0 @@
-GDTEST_ANALYZER_ERROR
-Invalid cast. Enum "cast_enum_bad_int.gd::MyEnum" does not have enum value 2.
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 02c4633586..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
-Value of type "enum_class_var_assign_with_wrong_enum_type.gd::MyOtherEnum" cannot be assigned to a variable of type "enum_class_var_assign_with_wrong_enum_type.gd::MyEnum".
+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 441cccbf7b..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
-Cannot assign a value of type enum_class_var_init_with_wrong_enum_type.gd::MyOtherEnum to variable "class_var" with specified type enum_class_var_init_with_wrong_enum_type.gd::MyEnum.
+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_function_parameter_wrong_type.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_parameter_wrong_type.out
index e85f7d6f9f..a91189e2dd 100644
--- 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
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Invalid argument for "enum_func()" function: argument 1 should be "enum_function_parameter_wrong_type.gd::MyEnum" but is "enum_function_parameter_wrong_type.gd::MyOtherEnum".
+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.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_function_return_wrong_type.out
index f7ea3267fa..6b4eba3740 100644
--- 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
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Cannot return value of type "enum_function_return_wrong_type.gd::MyOtherEnum" because the function return type is "enum_function_return_wrong_type.gd::MyEnum".
+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.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_local_var_assign_outer_with_wrong_enum_type.out
index 38df5a0cd8..616358bb61 100644
--- 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
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Value of type "enum_local_var_assign_outer_with_wrong_enum_type.gd::InnerClass::MyEnum" cannot be assigned to a variable of type "enum_local_var_assign_outer_with_wrong_enum_type.gd::MyEnum".
+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 2adcbd9edf..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
-Value of type "enum_local_var_assign_with_wrong_enum_type.gd::MyOtherEnum" cannot be assigned to a variable of type "enum_local_var_assign_with_wrong_enum_type.gd::MyEnum".
+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 331113dd30..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
-Cannot assign a value of type enum_local_var_init_with_wrong_enum_type.gd::MyOtherEnum to variable "local_var" with specified type enum_local_var_init_with_wrong_enum_type.gd::MyEnum.
+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_preload_unnamed_assign_to_named.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.out
index 6298c026b4..e8c7f86c4f 100644
--- 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
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Value of type "enum_value_from_parent.gd::<anonymous enum>" cannot be assigned to a variable of type "enum_preload_unnamed_assign_to_named.gd::MyEnum".
+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_unnamed_assign_to_named.out b/modules/gdscript/tests/scripts/analyzer/errors/enum_unnamed_assign_to_named.out
index b70121ed81..fb18c94d0b 100644
--- 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
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Cannot assign a value of type enum_unnamed_assign_to_named.gd::<anonymous enum> to variable "local_var" with specified type enum_unnamed_assign_to_named.gd::MyEnum.
+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/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/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_wrong_return.out b/modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.out
index 53e2b012e6..69af0984f7 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/lambda_wrong_return.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Cannot return value of type "String" because the function return type is "int".
+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/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/preload_enum_error.out b/modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.out
index 5e3c446bf6..08a973503f 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.out
+++ b/modules/gdscript/tests/scripts/analyzer/errors/preload_enum_error.out
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
-Value of type "enum_from_outer.gd::Named" cannot be assigned to a variable of type "preload_enum_error.gd::LocalNamed".
+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/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/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/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
index 2d2c2bef19..595563541f 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.gd
@@ -1,9 +1,4 @@
func test():
- var one_0 = 0
- one_0 = 1
- var one_1 := one_0
- print(one_1)
-
var two: Variant = 0
two += 2
print(two)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.out b/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.out
index 7536c38490..0ddfa4b75f 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.out
+++ b/modules/gdscript/tests/scripts/analyzer/features/assignments_with_untyped.out
@@ -1,5 +1,4 @@
GDTEST_OK
-1
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/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/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/native_typed_assign_null.gd b/modules/gdscript/tests/scripts/analyzer/features/native_typed_assign_null.gd
new file mode 100644
index 0000000000..c197062d9f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/native_typed_assign_null.gd
@@ -0,0 +1,15 @@
+extends Node
+
+func test():
+ var typed: Variant = get_node_or_null("does_not_exist")
+ var untyped = null
+ var node_1: Node = typed
+ var node_2: Node = untyped
+ var node_3 = typed
+ var node_4 = untyped
+ print(typed)
+ print(untyped)
+ print(node_1)
+ print(node_2)
+ print(node_3)
+ print(node_4)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/native_typed_assign_null.out b/modules/gdscript/tests/scripts/analyzer/features/native_typed_assign_null.out
new file mode 100644
index 0000000000..d66b72f5c3
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/native_typed_assign_null.out
@@ -0,0 +1,7 @@
+GDTEST_OK
+<Object#null>
+<null>
+<Object#null>
+<null>
+<Object#null>
+<null>
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/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/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.out b/modules/gdscript/tests/scripts/analyzer/features/typed_array_as_default_parameter.out
index 082e3ade19..2729c5b6c7 100644
--- 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
@@ -2,7 +2,7 @@ GDTEST_OK
[0]
0
[1]
-2
+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..26542a9e2f
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd
@@ -0,0 +1,215 @@
+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)
+
+ const const_enums: Array[E] = []
+ assert(const_enums.get_typed_builtin() == TYPE_INT)
+ assert(const_enums.get_typed_class_name() == &'')
+
+
+ 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/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/typed_array_assignment.out b/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out
deleted file mode 100644
index ad2e6558d7..0000000000
--- a/modules/gdscript/tests/scripts/analyzer/typed_array_assignment.out
+++ /dev/null
@@ -1,2 +0,0 @@
-GDTEST_ANALYZER_ERROR
-Cannot assign a value of type Array[String] to constant "arr" with specified type Array[int].
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_enum.gd b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.gd
index 71616ea3af..71616ea3af 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_enum.gd
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_enum.gd
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/errors/cast_enum_bad_int.gd b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.gd
index 60a31fb318..60a31fb318 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/cast_enum_bad_int.gd
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/cast_enum_bad_int.gd
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_unused_arg.out b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.out
index b018091c18..32e230fc80 100644
--- a/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.out
+++ b/modules/gdscript/tests/scripts/analyzer/warnings/lambda_unused_arg.out
@@ -2,4 +2,4 @@ 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 0085b3f367..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,5 +1,5 @@
# Error here. Annotations should be used before `class_name`, not after.
-class_name HelloWorld
+class_name WrongAnnotationPlace
@icon("res://path/to/optional/icon.svg")
func test():
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 a598ff8424..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
-Annotation "@icon" is not allowed in this level.
+Annotation "@icon" must be at the top of the script, before "extends" and "class_name".
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/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/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/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_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/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/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/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/constant_array_push_back.gd b/modules/gdscript/tests/scripts/runtime/errors/constant_array_push_back.gd
deleted file mode 100644
index 3e71cd0518..0000000000
--- a/modules/gdscript/tests/scripts/runtime/errors/constant_array_push_back.gd
+++ /dev/null
@@ -1,4 +0,0 @@
-const array: Array = [0]
-
-func test():
- array.push_back(0)
diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_array_push_back.out b/modules/gdscript/tests/scripts/runtime/errors/constant_array_push_back.out
deleted file mode 100644
index ba3e1c46c6..0000000000
--- a/modules/gdscript/tests/scripts/runtime/errors/constant_array_push_back.out
+++ /dev/null
@@ -1,7 +0,0 @@
-GDTEST_RUNTIME_ERROR
->> ERROR
->> on function: push_back()
->> core/variant/array.cpp
->> 253
->> Condition "_p->read_only" is true.
->> Array is in read-only state.
diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.gd b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.gd
deleted file mode 100644
index 7b350e81ad..0000000000
--- a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.gd
+++ /dev/null
@@ -1,4 +0,0 @@
-const dictionary := {}
-
-func test():
- dictionary.erase(0)
diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.out b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.out
deleted file mode 100644
index 3e7ca11a4f..0000000000
--- a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.out
+++ /dev/null
@@ -1,7 +0,0 @@
-GDTEST_RUNTIME_ERROR
->> ERROR
->> on function: erase()
->> core/variant/dictionary.cpp
->> 177
->> Condition "_p->read_only" is true. Returning: false
->> Dictionary is in read-only state.
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/features/await_on_void.gd b/modules/gdscript/tests/scripts/runtime/features/await_on_void.gd
index 46b9fbc951..1490a164c9 100644
--- a/modules/gdscript/tests/scripts/runtime/features/await_on_void.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/await_on_void.gd
@@ -2,6 +2,6 @@ func wait() -> void:
pass
func test():
- @warning_ignore(redundant_await)
+ @warning_ignore("redundant_await")
await wait()
print("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/does_not_override_temp_values.gd b/modules/gdscript/tests/scripts/runtime/features/does_not_override_temp_values.gd
index 1d4b400d81..48af734317 100644
--- 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
@@ -7,11 +7,11 @@ func test():
func builtin_method():
var pba := PackedByteArray()
- @warning_ignore(return_value_discarded)
+ @warning_ignore("return_value_discarded")
pba.resize(1) # Built-in validated.
func builtin_method_static():
var _pba := PackedByteArray()
- @warning_ignore(return_value_discarded)
+ @warning_ignore("return_value_discarded")
Vector2.from_angle(PI) # Static built-in validated.
diff --git a/modules/gdscript/tests/scripts/runtime/features/gdscript.gd b/modules/gdscript/tests/scripts/runtime/features/gdscript.gd
index f2368643de..e686cffc48 100644
--- a/modules/gdscript/tests/scripts/runtime/features/gdscript.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/gdscript.gd
@@ -11,10 +11,10 @@ class InnerClass:
func _init() -> void:
prints("Inner")
'''
- @warning_ignore(return_value_discarded)
+ @warning_ignore("return_value_discarded")
gdscr.reload()
var inst = gdscr.new()
- @warning_ignore(unsafe_method_access)
+ @warning_ignore("unsafe_method_access")
inst.test()
diff --git a/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd b/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd
index cc34e71b01..2f55059334 100644
--- a/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd
@@ -20,26 +20,26 @@ func test_utility(v, f):
assert(not f) # Test unary operator reading from `nil`.
func test_builtin_call(v, f):
- @warning_ignore(unsafe_method_access)
+ @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)
+ @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)
+ @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)
+ @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)
+ @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/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/use_conversion_assign_with_variant_value.gd b/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.gd
index af3f3cb941..efa8270526 100644
--- 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
@@ -1,7 +1,7 @@
# https://github.com/godotengine/godot/issues/71172
func test():
- @warning_ignore(narrowing_conversion)
+ @warning_ignore("narrowing_conversion")
var foo: int = 0.0
print(typeof(foo) == TYPE_INT)
var dict : Dictionary = {"a":0.0}