From a89e744ed0e8c759caf041a580112365bbfe4303 Mon Sep 17 00:00:00 2001 From: radiohotline Date: Tue, 25 Aug 2026 16:33:56 +0300 Subject: escoria update --- .../gdUnit4/src/core/parse/GdFunctionArgument.gd | 208 +++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 addons/gdUnit4/src/core/parse/GdFunctionArgument.gd (limited to 'addons/gdUnit4/src/core/parse/GdFunctionArgument.gd') diff --git a/addons/gdUnit4/src/core/parse/GdFunctionArgument.gd b/addons/gdUnit4/src/core/parse/GdFunctionArgument.gd new file mode 100644 index 0000000..bd38eb2 --- /dev/null +++ b/addons/gdUnit4/src/core/parse/GdFunctionArgument.gd @@ -0,0 +1,208 @@ +class_name GdFunctionArgument +extends RefCounted + + +const GdUnitTools := preload("res://addons/gdUnit4/src/core/GdUnitTools.gd") +const UNDEFINED: String = "<-NO_ARG->" +const ARG_PARAMETERIZED_TEST := ["test_parameters", "_test_parameters"] + +static var _fuzzer_regex: RegEx +static var _cleanup_leading_spaces: RegEx +static var _fix_comma_space: RegEx + +var _name: String +var _type: int +var _type_hint: int +var _default_value: Variant +var _parameter_sets: PackedStringArray = [] + + +func _init(p_name: String, p_type: int, value: Variant = UNDEFINED, p_type_hint: int = TYPE_NIL) -> void: + _init_static_variables() + _name = p_name + _type = p_type + _type_hint = p_type_hint + if value != null and p_name in ARG_PARAMETERIZED_TEST: + _parameter_sets = _parse_parameter_set(str(value)) + _default_value = value + # is argument a fuzzer? + if _type == TYPE_OBJECT and _fuzzer_regex.search(_name): + _type = GdObjects.TYPE_FUZZER + + +func _init_static_variables() -> void: + if _fuzzer_regex == null: + _fuzzer_regex = GdUnitTools.to_regex("((?!(fuzzer_(seed|iterations)))fuzzer?\\w+)( ?+= ?+| ?+:= ?+| ?+:Fuzzer ?+= ?+|)") + _cleanup_leading_spaces = RegEx.create_from_string("(?m)^[ \t]+") + _fix_comma_space = RegEx.create_from_string(""", {0,}\t{0,}(?=(?:[^"]*"[^"]*")*[^"]*$)(?!\\s)""") + + +func name() -> String: + return _name + + +func default() -> Variant: + return type_convert(_default_value, _type) + + +func set_value(value: String) -> void: + # we onle need to apply default values for Objects, all others are provided by the method descriptor + if _type == GdObjects.TYPE_FUZZER: + _default_value = value + return + if _name in ARG_PARAMETERIZED_TEST: + _parameter_sets = _parse_parameter_set(value) + _default_value = value + return + + if _type == TYPE_NIL or _type == GdObjects.TYPE_VARIANT: + _type = _extract_value_type(value) + if _type == GdObjects.TYPE_VARIANT and _default_value == null: + _default_value = value + if _default_value == null: + match _type: + TYPE_DICTIONARY: + _default_value = as_dictionary(value) + TYPE_ARRAY: + _default_value = as_array(value) + GdObjects.TYPE_FUZZER: + _default_value = value + _: + _default_value = str_to_var(value) + # if converting fails assign the original value without converting + if _default_value == null and value != null: + _default_value = value + #prints("set default_value: ", _default_value, "with type %d" % _type, " from original: '%s'" % value) + + +func _extract_value_type(value: String) -> int: + if value != UNDEFINED: + if _fuzzer_regex.search(_name): + return GdObjects.TYPE_FUZZER + if value.rfind(")") == value.length()-1: + return GdObjects.TYPE_FUNC + return _type + + +func value_as_string() -> String: + if has_default(): + return GdDefaultValueDecoder.decode_typed(_type, _default_value) + return "" + + +func plain_value() -> Variant: + return _default_value + + +func type() -> int: + return _type + + +func type_hint() -> int: + return _type_hint + + +func has_default() -> bool: + return not is_same(_default_value, UNDEFINED) + + +func is_typed_array() -> bool: + return _type == TYPE_ARRAY and _type_hint != TYPE_NIL + + +func is_parameter_set() -> bool: + return _name in ARG_PARAMETERIZED_TEST + + +func parameter_sets() -> PackedStringArray: + return _parameter_sets + + +static func get_parameter_set(parameters :Array[GdFunctionArgument]) -> GdFunctionArgument: + for current in parameters: + if current != null and current.is_parameter_set(): + return current + return null + + +func _to_string() -> String: + var s := _name + if _type != TYPE_NIL: + s += ": " + GdObjects.type_as_string(_type) + if _type_hint != TYPE_NIL: + s += "[%s]" % GdObjects.type_as_string(_type_hint) + if has_default(): + s += "=" + value_as_string() + return s + + +func _parse_parameter_set(input :String) -> PackedStringArray: + if not input.contains("["): + return [] + + input = _cleanup_leading_spaces.sub(input, "", true) + input = input.replace("\n", "").strip_edges().trim_prefix("[").trim_suffix("]").trim_prefix("]") + var single_quote := false + var double_quote := false + var array_end := 0 + var current_index := 0 + var output :PackedStringArray = [] + var buf := input.to_utf8_buffer() + var collected_characters: = PackedByteArray() + var matched :bool = false + + for c in buf: + current_index += 1 + matched = current_index == buf.size() + @warning_ignore("return_value_discarded") + collected_characters.push_back(c) + + match c: + # ' ': ignore spaces between array elements + 32: if array_end == 0 and (not double_quote and not single_quote): + collected_characters.remove_at(collected_characters.size()-1) + # ',': step over array element seperator ',' + 44: if array_end == 0: + matched = true + collected_characters.remove_at(collected_characters.size()-1) + # '`': + 39: single_quote = !single_quote + # '"': + 34: if not single_quote: double_quote = !double_quote + # '[' + 91: if not double_quote and not single_quote: array_end +=1 # counts array open + # ']' + 93: if not double_quote and not single_quote: array_end -=1 # counts array closed + + # if array closed than collect the element + if matched: + var parameters := _fix_comma_space.sub(collected_characters.get_string_from_utf8(), ", ", true) + if not parameters.is_empty(): + @warning_ignore("return_value_discarded") + output.append(parameters) + collected_characters.clear() + matched = false + return output + + +## value converters + +func as_array(value: String) -> Array: + if value == "Array()" or value == "[]": + return [] + + if value.begins_with("Array("): + value = value.lstrip("Array(").rstrip(")") + if value.begins_with("["): + return str_to_var(value) + return [] + + +func as_dictionary(value: String) -> Dictionary: + if value == "Dictionary()": + return {} + if value.begins_with("Dictionary("): + value = value.lstrip("Dictionary(").rstrip(")") + if value.begins_with("{"): + return str_to_var(value) + return {} -- cgit v1.3