diff options
Diffstat (limited to 'modules/gdscript/tests/scripts/analyzer')
20 files changed, 323 insertions, 8 deletions
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_dictionary.gd b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_dictionary.gd new file mode 100644 index 0000000000..c180cca03c --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_dictionary.gd @@ -0,0 +1,3 @@ +func test(): + for key: int in { "a": 1 }: + print(key) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_dictionary.out b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_dictionary.out new file mode 100644 index 0000000000..8530783673 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/for_loop_wrong_specified_type_with_literal_dictionary.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_dictionary_assign_differently_typed.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed.gd new file mode 100644 index 0000000000..75d1b7fe62 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed.gd @@ -0,0 +1,4 @@ +func test(): + var differently: Dictionary[float, float] = { 1.0: 0.0 } + var typed: Dictionary[int, int] = differently + print('not ok') diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed.out new file mode 100644 index 0000000000..e05d4be8c9 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assign_differently_typed.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot assign a value of type Dictionary[float, float] to variable "typed" with specified type Dictionary[int, int]. diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assignment.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assignment.gd new file mode 100644 index 0000000000..e0af71823a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assignment.gd @@ -0,0 +1,2 @@ +func test(): + const dict: Dictionary[int, int] = { "Hello": "World" } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assignment.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_assignment.out new file mode 100644 index 0000000000..8530783673 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_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_dictionary_init_with_unconvertible_in_literal.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_init_with_unconvertible_in_literal.gd new file mode 100644 index 0000000000..814ba12aef --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_init_with_unconvertible_in_literal.gd @@ -0,0 +1,4 @@ +func test(): + var unconvertible := 1 + var typed: Dictionary[Object, Object] = { unconvertible: unconvertible } + print('not ok') diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_init_with_unconvertible_in_literal.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_init_with_unconvertible_in_literal.out new file mode 100644 index 0000000000..9d6c9d9144 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_init_with_unconvertible_in_literal.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Cannot have a key of type "int" in a dictionary of type "Dictionary[Object, Object]". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_pass_differently_to_typed.gd b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_pass_differently_to_typed.gd new file mode 100644 index 0000000000..73d8ce2b96 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_pass_differently_to_typed.gd @@ -0,0 +1,7 @@ +func expect_typed(typed: Dictionary[int, int]): + print(typed.size()) + +func test(): + var differently: Dictionary[float, float] = { 1.0: 0.0 } + expect_typed(differently) + print('not ok') diff --git a/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_pass_differently_to_typed.out b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_pass_differently_to_typed.out new file mode 100644 index 0000000000..302109cf8a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/typed_dictionary_pass_differently_to_typed.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Invalid argument for "expect_typed()" function: argument 1 should be "Dictionary[int, int]" but is "Dictionary[float, float]". diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_as_default_parameter.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_as_default_parameter.gd new file mode 100644 index 0000000000..65f5e7da07 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_as_default_parameter.gd @@ -0,0 +1,20 @@ +func print_untyped(dictionary = { 0: 1 }) -> void: + print(dictionary) + print(dictionary.get_typed_key_builtin()) + print(dictionary.get_typed_value_builtin()) + +func print_inferred(dictionary := { 2: 3 }) -> void: + print(dictionary) + print(dictionary.get_typed_key_builtin()) + print(dictionary.get_typed_value_builtin()) + +func print_typed(dictionary: Dictionary[int, int] = { 4: 5 }) -> void: + print(dictionary) + print(dictionary.get_typed_key_builtin()) + print(dictionary.get_typed_value_builtin()) + +func test(): + print_untyped() + print_inferred() + print_typed() + print('ok') diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_as_default_parameter.out b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_as_default_parameter.out new file mode 100644 index 0000000000..c31561bee3 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_as_default_parameter.out @@ -0,0 +1,11 @@ +GDTEST_OK +{ 0: 1 } +0 +0 +{ 2: 3 } +0 +0 +{ 4: 5 } +2 +2 +ok diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_inferred_access_isnt_constant.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_inferred_access_isnt_constant.gd new file mode 100644 index 0000000000..0aa3de2c4a --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_inferred_access_isnt_constant.gd @@ -0,0 +1,4 @@ +func test(): + var dict := { 0: 0 } + dict[0] = 1 + print(dict[0]) diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_inferred_access_isnt_constant.out b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_inferred_access_isnt_constant.out new file mode 100644 index 0000000000..a7f1357bb2 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_inferred_access_isnt_constant.out @@ -0,0 +1,2 @@ +GDTEST_OK +1 diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.gd new file mode 100644 index 0000000000..9d3fffd1de --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.gd @@ -0,0 +1,214 @@ +class A: pass +class B extends A: pass + +enum E { E0 = 391, E1 = 193 } + +func floats_identity(floats: Dictionary[float, float]): return floats + +class Members: + var one: Dictionary[int, int] = { 104: 401 } + var two: Dictionary[int, int] = one + + func check_passing() -> bool: + Utils.check(str(one) == '{ 104: 401 }') + Utils.check(str(two) == '{ 104: 401 }') + two[582] = 285 + Utils.check(str(one) == '{ 104: 401, 582: 285 }') + Utils.check(str(two) == '{ 104: 401, 582: 285 }') + two = { 486: 684 } + Utils.check(str(one) == '{ 104: 401, 582: 285 }') + Utils.check(str(two) == '{ 486: 684 }') + return true + + +@warning_ignore("unsafe_method_access") +@warning_ignore("assert_always_true") +@warning_ignore("return_value_discarded") +func test(): + var untyped_basic = { 459: 954 } + Utils.check(str(untyped_basic) == '{ 459: 954 }') + Utils.check(untyped_basic.get_typed_key_builtin() == TYPE_NIL) + Utils.check(untyped_basic.get_typed_value_builtin() == TYPE_NIL) + + var inferred_basic := { 366: 663 } + Utils.check(str(inferred_basic) == '{ 366: 663 }') + Utils.check(inferred_basic.get_typed_key_builtin() == TYPE_NIL) + Utils.check(inferred_basic.get_typed_value_builtin() == TYPE_NIL) + + var typed_basic: Dictionary = { 521: 125 } + Utils.check(str(typed_basic) == '{ 521: 125 }') + Utils.check(typed_basic.get_typed_key_builtin() == TYPE_NIL) + Utils.check(typed_basic.get_typed_value_builtin() == TYPE_NIL) + + + var empty_floats: Dictionary[float, float] = {} + Utils.check(str(empty_floats) == '{ }') + Utils.check(empty_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(empty_floats.get_typed_value_builtin() == TYPE_FLOAT) + + untyped_basic = empty_floats + Utils.check(untyped_basic.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(untyped_basic.get_typed_value_builtin() == TYPE_FLOAT) + + inferred_basic = empty_floats + Utils.check(inferred_basic.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(inferred_basic.get_typed_value_builtin() == TYPE_FLOAT) + + typed_basic = empty_floats + Utils.check(typed_basic.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(typed_basic.get_typed_value_builtin() == TYPE_FLOAT) + + empty_floats[705.0] = 507.0 + untyped_basic[430.0] = 34.0 + inferred_basic[263.0] = 362.0 + typed_basic[518.0] = 815.0 + Utils.check(str(empty_floats) == '{ 705: 507, 430: 34, 263: 362, 518: 815 }') + Utils.check(str(untyped_basic) == '{ 705: 507, 430: 34, 263: 362, 518: 815 }') + Utils.check(str(inferred_basic) == '{ 705: 507, 430: 34, 263: 362, 518: 815 }') + Utils.check(str(typed_basic) == '{ 705: 507, 430: 34, 263: 362, 518: 815 }') + + + const constant_float := 950.0 + const constant_int := 170 + var typed_float := 954.0 + var filled_floats: Dictionary[float, float] = { constant_float: constant_int, typed_float: empty_floats[430.0] + empty_floats[263.0] } + Utils.check(str(filled_floats) == '{ 950: 170, 954: 396 }') + Utils.check(filled_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(filled_floats.get_typed_value_builtin() == TYPE_FLOAT) + + var casted_floats := { empty_floats[263.0] * 2: empty_floats[263.0] / 2 } as Dictionary[float, float] + Utils.check(str(casted_floats) == '{ 724: 181 }') + Utils.check(casted_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(casted_floats.get_typed_value_builtin() == TYPE_FLOAT) + + var returned_floats = (func () -> Dictionary[float, float]: return { 554: 455 }).call() + Utils.check(str(returned_floats) == '{ 554: 455 }') + Utils.check(returned_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(returned_floats.get_typed_value_builtin() == TYPE_FLOAT) + + var passed_floats = floats_identity({ 663.0 if randf() > 0.5 else 663.0: 366.0 if randf() <= 0.5 else 366.0 }) + Utils.check(str(passed_floats) == '{ 663: 366 }') + Utils.check(passed_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(passed_floats.get_typed_value_builtin() == TYPE_FLOAT) + + var default_floats = (func (floats: Dictionary[float, float] = { 364.0: 463.0 }): return floats).call() + Utils.check(str(default_floats) == '{ 364: 463 }') + Utils.check(default_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(default_floats.get_typed_value_builtin() == TYPE_FLOAT) + + var typed_int := 556 + var converted_floats: Dictionary[float, float] = { typed_int: typed_int } + converted_floats[498.0] = 894 + Utils.check(str(converted_floats) == '{ 556: 556, 498: 894 }') + Utils.check(converted_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(converted_floats.get_typed_value_builtin() == TYPE_FLOAT) + + + const constant_basic = { 228: 822 } + Utils.check(str(constant_basic) == '{ 228: 822 }') + Utils.check(constant_basic.get_typed_key_builtin() == TYPE_NIL) + Utils.check(constant_basic.get_typed_value_builtin() == TYPE_NIL) + + const constant_floats: Dictionary[float, float] = { constant_float - constant_basic[228] - constant_int: constant_float + constant_basic[228] + constant_int } + Utils.check(str(constant_floats) == '{ -42: 1942 }') + Utils.check(constant_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(constant_floats.get_typed_value_builtin() == TYPE_FLOAT) + + + var source_floats: Dictionary[float, float] = { 999.74: 47.999 } + untyped_basic = source_floats + var destination_floats: Dictionary[float, float] = untyped_basic + destination_floats[999.74] -= 0.999 + Utils.check(str(source_floats) == '{ 999.74: 47 }') + Utils.check(str(untyped_basic) == '{ 999.74: 47 }') + Utils.check(str(destination_floats) == '{ 999.74: 47 }') + Utils.check(destination_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(destination_floats.get_typed_value_builtin() == TYPE_FLOAT) + + + var duplicated_floats := empty_floats.duplicate() + duplicated_floats.erase(705.0) + duplicated_floats.erase(430.0) + duplicated_floats.erase(518.0) + duplicated_floats[263.0] *= 3 + Utils.check(str(duplicated_floats) == '{ 263: 1086 }') + Utils.check(duplicated_floats.get_typed_key_builtin() == TYPE_FLOAT) + Utils.check(duplicated_floats.get_typed_value_builtin() == TYPE_FLOAT) + + + var b_objects: Dictionary[int, B] = { 0: B.new(), 1: B.new() as A, 2: null } + Utils.check(b_objects.size() == 3) + Utils.check(b_objects.get_typed_value_builtin() == TYPE_OBJECT) + Utils.check(b_objects.get_typed_value_script() == B) + + var a_objects: Dictionary[int, A] = { 0: A.new(), 1: B.new(), 2: null, 3: b_objects[0] } + Utils.check(a_objects.size() == 4) + Utils.check(a_objects.get_typed_value_builtin() == TYPE_OBJECT) + Utils.check(a_objects.get_typed_value_script() == A) + + var a_passed = (func check_a_passing(p_objects: Dictionary[int, A]): return p_objects.size()).call(a_objects) + Utils.check(a_passed == 4) + + var b_passed = (func check_b_passing(basic: Dictionary): return basic[0] != null).call(b_objects) + Utils.check(b_passed == true) + + + var empty_strings: Dictionary[String, String] = {} + var empty_bools: Dictionary[bool, bool] = {} + var empty_basic_one := {} + var empty_basic_two := {} + Utils.check(empty_strings == empty_bools) + Utils.check(empty_basic_one == empty_basic_two) + Utils.check(empty_strings.hash() == empty_bools.hash()) + Utils.check(empty_basic_one.hash() == empty_basic_two.hash()) + + + var assign_source: Dictionary[int, int] = { 527: 725 } + var assign_target: Dictionary[int, int] = {} + assign_target.assign(assign_source) + Utils.check(str(assign_source) == '{ 527: 725 }') + Utils.check(str(assign_target) == '{ 527: 725 }') + assign_source[657] = 756 + Utils.check(str(assign_source) == '{ 527: 725, 657: 756 }') + Utils.check(str(assign_target) == '{ 527: 725 }') + + + var defaults_passed = (func check_defaults_passing(one: Dictionary[int, int] = {}, two := one): + one[887] = 788 + two[198] = 891 + Utils.check(str(one) == '{ 887: 788, 198: 891 }') + Utils.check(str(two) == '{ 887: 788, 198: 891 }') + two = {130: 31} + Utils.check(str(one) == '{ 887: 788, 198: 891 }') + Utils.check(str(two) == '{ 130: 31 }') + return true + ).call() + Utils.check(defaults_passed == true) + + + var members := Members.new() + var members_passed := members.check_passing() + Utils.check(members_passed == true) + + + var typed_enums: Dictionary[E, E] = {} + typed_enums[E.E0] = E.E1 + Utils.check(str(typed_enums) == '{ 391: 193 }') + Utils.check(typed_enums.get_typed_key_builtin() == TYPE_INT) + Utils.check(typed_enums.get_typed_value_builtin() == TYPE_INT) + + const const_enums: Dictionary[E, E] = {} + Utils.check(const_enums.get_typed_key_builtin() == TYPE_INT) + Utils.check(const_enums.get_typed_key_class_name() == &'') + Utils.check(const_enums.get_typed_value_builtin() == TYPE_INT) + Utils.check(const_enums.get_typed_value_class_name() == &'') + + + var a := A.new() + var b := B.new() + var typed_natives: Dictionary[RefCounted, RefCounted] = { a: b } + var typed_scripts = Dictionary(typed_natives, TYPE_OBJECT, "RefCounted", A, TYPE_OBJECT, "RefCounted", B) + Utils.check(typed_scripts[a] == b) + + + print('ok') diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.out b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.out new file mode 100644 index 0000000000..1b47ed10dc --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_usage.out @@ -0,0 +1,2 @@ +GDTEST_OK +ok diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_with_custom_class.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_with_custom_class.gd new file mode 100644 index 0000000000..f4a23ade14 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_with_custom_class.gd @@ -0,0 +1,9 @@ +class Inner: + var prop = "Inner" + +var dict: Dictionary[int, Inner] = { 0: Inner.new() } + + +func test(): + var element: Inner = dict[0] + print(element.prop) diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_with_custom_class.out b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_with_custom_class.out new file mode 100644 index 0000000000..8f250d2632 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_dictionary_with_custom_class.out @@ -0,0 +1,2 @@ +GDTEST_OK +Inner diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/unused_signal.gd b/modules/gdscript/tests/scripts/analyzer/warnings/unused_signal.gd index d937dfdcfe..37f118dc5d 100644 --- a/modules/gdscript/tests/scripts/analyzer/warnings/unused_signal.gd +++ b/modules/gdscript/tests/scripts/analyzer/warnings/unused_signal.gd @@ -1,12 +1,29 @@ -signal s1() -signal s2() -signal s3() +# Doesn't produce the warning: +signal used_as_first_class_signal() +signal used_with_signal_constructor() +signal used_with_signal_emit() +signal used_with_object_emit_signal() +signal used_with_object_connect() +signal used_with_object_disconnect() +signal used_with_self_prefix() + +# Produce the warning: +signal used_with_dynamic_name() +signal just_unused() @warning_ignore("unused_signal") -signal s4() +signal unused_but_ignored() func no_exec(): - s1.emit() - print(s2) + print(used_as_first_class_signal) + print(Signal(self, "used_with_signal_constructor")) + used_with_signal_emit.emit() + print(emit_signal("used_with_object_emit_signal")) + print(connect("used_with_object_connect", Callable())) + disconnect("used_with_object_disconnect", Callable()) + print(self.emit_signal("used_with_self_prefix")) + + var dynamic_name := "used_with_dynamic_name" + print(emit_signal(dynamic_name)) func test(): pass diff --git a/modules/gdscript/tests/scripts/analyzer/warnings/unused_signal.out b/modules/gdscript/tests/scripts/analyzer/warnings/unused_signal.out index ff57017830..39ddf91c76 100644 --- a/modules/gdscript/tests/scripts/analyzer/warnings/unused_signal.out +++ b/modules/gdscript/tests/scripts/analyzer/warnings/unused_signal.out @@ -1,5 +1,9 @@ GDTEST_OK >> WARNING ->> Line: 3 +>> Line: 11 >> UNUSED_SIGNAL ->> The signal "s3" is declared but never explicitly used in the class. +>> The signal "used_with_dynamic_name" is declared but never explicitly used in the class. +>> WARNING +>> Line: 12 +>> UNUSED_SIGNAL +>> The signal "just_unused" is declared but never explicitly used in the class. |