summaryrefslogtreecommitdiff
path: root/addons/gdUnit4/src/core/parse/GdFunctionArgument.gd
diff options
context:
space:
mode:
authorradiohotline <radoihotline@disroot.rg>2026-08-25 16:33:56 +0300
committerradiohotline <radoihotline@disroot.rg>2026-08-25 16:33:56 +0300
commita89e744ed0e8c759caf041a580112365bbfe4303 (patch)
treedd61e320904176995727e86a857d00c90d4933ba /addons/gdUnit4/src/core/parse/GdFunctionArgument.gd
parent6d53d8cac78250dc888aa49d5f9d4175c6652feb (diff)
escoria updateHEADmain
Diffstat (limited to 'addons/gdUnit4/src/core/parse/GdFunctionArgument.gd')
-rw-r--r--addons/gdUnit4/src/core/parse/GdFunctionArgument.gd208
1 files changed, 208 insertions, 0 deletions
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 {}