gdharness 1.2.42 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/build/cli.js +571 -363
  2. package/build/godot/addons/gdharness_editor/animation_reads.gd +7 -19
  3. package/build/godot/addons/gdharness_editor/bridge_client.gd +9 -9
  4. package/build/godot/addons/gdharness_editor/file_reads.gd +60 -25
  5. package/build/godot/addons/gdharness_editor/headless_check.gd +7 -7
  6. package/build/godot/addons/gdharness_editor/plugin.gd +6 -6
  7. package/build/godot/addons/gdharness_editor/property_values.gd +124 -62
  8. package/build/godot/addons/gdharness_editor/reading.gd +28 -0
  9. package/build/godot/addons/gdharness_editor/scene_file.gd +28 -23
  10. package/build/godot/addons/gdharness_editor/serialisation.gd +45 -94
  11. package/build/godot/addons/gdharness_editor/tool_executor.gd +24 -24
  12. package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +52 -41
  13. package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +4 -4
  14. package/build/godot/addons/gdharness_editor/tools/play_tools.gd +2 -2
  15. package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +14 -14
  16. package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +57 -50
  17. package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +17 -17
  18. package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +14 -12
  19. package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +7 -7
  20. package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +82 -78
  21. package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +4 -4
  22. package/build/godot/addons/gdharness_editor/value_shapes.gd +111 -0
  23. package/build/godot/addons/gdharness_editor/value_shapes.gd.uid +1 -0
  24. package/build/godot/addons/gdharness_runtime/reading.gd +28 -0
  25. package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +18 -18
  26. package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +32 -32
  27. package/build/godot/addons/gdharness_runtime/runtime_capture.gd +50 -18
  28. package/build/godot/addons/gdharness_runtime/runtime_changes.gd +86 -80
  29. package/build/godot/addons/gdharness_runtime/runtime_input.gd +65 -69
  30. package/build/godot/addons/gdharness_runtime/runtime_items.gd +6 -6
  31. package/build/godot/addons/gdharness_runtime/runtime_menus.gd +8 -8
  32. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +13 -21
  33. package/build/godot/addons/gdharness_runtime/runtime_pad.gd +10 -10
  34. package/build/godot/addons/gdharness_runtime/runtime_paths.gd +7 -7
  35. package/build/godot/addons/gdharness_runtime/runtime_queries.gd +41 -41
  36. package/build/godot/addons/gdharness_runtime/runtime_says.gd +3 -3
  37. package/build/godot/addons/gdharness_runtime/runtime_targets.gd +33 -33
  38. package/build/godot/addons/gdharness_runtime/runtime_typing.gd +20 -20
  39. package/build/godot/addons/gdharness_runtime/runtime_values.gd +25 -24
  40. package/build/godot/addons/gdharness_runtime/runtime_waits.gd +56 -50
  41. package/build/godot/addons/gdharness_runtime/serialisation.gd +45 -94
  42. package/build/godot/addons/gdharness_runtime/value_shapes.gd +111 -0
  43. package/build/godot/addons/gdharness_runtime/value_shapes.gd.uid +1 -0
  44. package/build/godot/operations/animation_reads.gd +7 -19
  45. package/build/godot/operations/audio_buses.gd +10 -10
  46. package/build/godot/operations/class_cache.gd +16 -16
  47. package/build/godot/operations/classdb_queries.gd +12 -12
  48. package/build/godot/operations/dependencies.gd +33 -29
  49. package/build/godot/operations/editor_tools.gd +12 -12
  50. package/build/godot/operations/export_presets.gd +10 -8
  51. package/build/godot/operations/file_reads.gd +60 -25
  52. package/build/godot/operations/gdscript_analysis.gd +20 -20
  53. package/build/godot/operations/gdscript_authoring.gd +17 -15
  54. package/build/godot/operations/godot_operations.gd +64 -63
  55. package/build/godot/operations/import_pipeline.gd +20 -20
  56. package/build/godot/operations/input_actions.gd +17 -17
  57. package/build/godot/operations/logger.gd +1 -1
  58. package/build/godot/operations/plugins.gd +8 -8
  59. package/build/godot/operations/project_config.gd +24 -17
  60. package/build/godot/operations/project_diagnostics.gd +9 -9
  61. package/build/godot/operations/property_values.gd +124 -62
  62. package/build/godot/operations/reading.gd +28 -0
  63. package/build/godot/operations/rename_checks.gd +3 -3
  64. package/build/godot/operations/resource_files.gd +5 -5
  65. package/build/godot/operations/script_check.gd +7 -7
  66. package/build/godot/operations/serialisation.gd +45 -94
  67. package/build/godot/operations/value_shapes.gd +111 -0
  68. package/build/keeper.js +10 -4
  69. package/package.json +1 -2
  70. package/build/index.js +0 -45101
@@ -4,22 +4,22 @@ extends RefCounted
4
4
  ## from the wire, so both fit them to what the game declares and refuse what cannot fit, and both read
5
5
  ## back what the engine did rather than trusting that it did it.
6
6
 
7
- const CallErrors = preload("call_errors.gd")
8
- const Paths = preload("runtime_paths.gd")
9
- const Read = preload("reading.gd")
10
- const Values = preload("runtime_values.gd")
7
+ const GdhCallErrors = preload("call_errors.gd")
8
+ const GdhPaths = preload("runtime_paths.gd")
9
+ const GdhRead = preload("reading.gd")
10
+ const GdhValues = preload("runtime_values.gd")
11
11
 
12
12
  ## The most errors a call's answer carries, which is enough to see what the method ran into and short
13
13
  ## of a method reporting one per element of a list of thousands.
14
14
  const ERRORS_KEPT: int = 20
15
15
 
16
16
  var _host: Node
17
- var _values: Values
17
+ var _values: GdhValues
18
18
 
19
19
 
20
20
  ## The host is the autoload, which is how the tree is reached: it is not in one when the
21
21
  ## modules are built, and a fixture may put it in one later.
22
- func _init(host: Node, values: Values) -> void:
22
+ func _init(host: Node, values: GdhValues) -> void:
23
23
  _host = host
24
24
  _values = values
25
25
 
@@ -32,16 +32,16 @@ func set_property(params: Dictionary) -> Dictionary:
32
32
  if node_path.is_empty() or property.is_empty():
33
33
  return {"type": "error", "message": "Node path and property required"}
34
34
 
35
- var standing: Dictionary = Values.target_at(_host.get_tree().root, node_path)
35
+ var standing: Dictionary = GdhValues.target_at(_host.get_tree().root, node_path)
36
36
  if standing.has("message"):
37
37
  return standing
38
38
  var node: Node = standing["node"]
39
39
  var target: Object = standing["object"]
40
40
 
41
- # Through a path as well, for the reason [method Paths.walk_to] gives, and read back off the same
41
+ # Through a path as well, for the reason [method GdhPaths.walk_to] gives, and read back off the same
42
42
  # holder afterwards: a set that does not take says so by answering with the old value, which is
43
43
  # how a typed container refusing a write is told from one accepting it.
44
- var reached: Dictionary = Paths.walk_to(target, node_path, property)
44
+ var reached: Dictionary = GdhPaths.walk_to(target, node_path, property)
45
45
  if reached.has("message"):
46
46
  return reached
47
47
 
@@ -49,7 +49,7 @@ func set_property(params: Dictionary) -> Dictionary:
49
49
  var named: String = reached["name"]
50
50
  # A call can be walked through and read, and is not a place: what it returns is the method's
51
51
  # to hand out, and writing "into" it would set nothing the game keeps.
52
- if not Paths.method_of(named).is_empty():
52
+ if not GdhPaths.method_of(named).is_empty():
53
53
  return {
54
54
  "type": "error",
55
55
  "message":
@@ -58,10 +58,10 @@ func set_property(params: Dictionary) -> Dictionary:
58
58
  % [reached["called"], named]
59
59
  )
60
60
  }
61
- if not Paths.can_read(holder, named):
62
- return {"type": "error", "message": Paths.nothing_there(holder, named, str(reached["called"]))}
63
- var old_value: Variant = Paths.read_under(holder, named)
64
- var slot: Dictionary = Values.slot_declared(holder, named)
61
+ if not GdhPaths.can_read(holder, named):
62
+ return {"type": "error", "message": GdhPaths.nothing_there(holder, named, str(reached["called"]))}
63
+ var old_value: Variant = GdhPaths.read_under(holder, named)
64
+ var slot: Dictionary = GdhValues.slot_declared(holder, named)
65
65
  var declared: int = slot["type"]
66
66
  var declared_script: Script = slot["script"]
67
67
  var fitting: Dictionary = _value_for(value, slot, old_value, reached, node, node_path)
@@ -72,24 +72,24 @@ func set_property(params: Dictionary) -> Dictionary:
72
72
  # read from, setter and all; the read back is then taken off the game again, since the copy here
73
73
  # says only what was written into it.
74
74
  var chain: Array[Dictionary] = reached["chain"]
75
- var copied: bool = Paths.composite(holder)
75
+ var copied: bool = GdhPaths.composite(holder)
76
76
  if copied:
77
- var unwritable: String = Paths.unwritable_copy(chain)
77
+ var unwritable: String = GdhPaths.unwritable_copy(chain)
78
78
  if not unwritable.is_empty():
79
79
  return {"type": "error", "message": unwritable}
80
80
  # The write alone, setter included, which is where a property's cost is.
81
81
  var began: int = Time.get_ticks_usec()
82
- var written: Variant = Paths.write(holder, named, given)
82
+ var written: Variant = GdhPaths.write(holder, named, given)
83
83
  if copied:
84
- Paths.write_back(chain, written)
84
+ GdhPaths.write_back(chain, written)
85
85
  var elapsed: int = Time.get_ticks_usec() - began
86
- var now: Variant = Paths.read_under(holder, named)
86
+ var now: Variant = GdhPaths.read_under(holder, named)
87
87
  if copied:
88
- var again: Dictionary = Paths.walk_to(target, node_path, property)
88
+ var again: Dictionary = GdhPaths.walk_to(target, node_path, property)
89
89
  if again.has("message"):
90
90
  return again
91
91
  var reread: Variant = again["holder"]
92
- now = Paths.read_under(reread, named) if Paths.can_read(reread, named) else null
92
+ now = GdhPaths.read_under(reread, named) if GdhPaths.can_read(reread, named) else null
93
93
  # Read back rather than trusted. The engine drops a write it will not take without a word, and
94
94
  # the answer then showed the old value as the new one, shaped as a success: a typed container
95
95
  # refusing a plain list did exactly that. A value the property changed on the way in, a setter
@@ -100,12 +100,12 @@ func set_property(params: Dictionary) -> Dictionary:
100
100
  # Said as what was seen, because two causes look the same from here: the engine refusing the write,
101
101
  # and a setter that ran and left the value where it was, clamping it, say. The one this can name
102
102
  # is an object slot checked only by the engine class a script extends (see
103
- # [method Values.slot_declared]), where an object of that class with another script is refused.
103
+ # [method GdhValues.slot_declared]), where an object of that class with another script is refused.
104
104
  #
105
105
  # Judged by what reads back alone, so a value of another kind than the one held, which cannot be
106
106
  # compared with it, is still caught when the engine drops it.
107
107
  var already: bool = held_already(given, old_value)
108
- var unmoved: bool = Values.comparable(now, old_value) and now == old_value
108
+ var unmoved: bool = GdhValues.comparable(now, old_value) and now == old_value
109
109
  if unmoved and not already:
110
110
  var why: String = (
111
111
  "the write left it as it was, which is what the engine refusing it and a setter keeping the"
@@ -119,7 +119,7 @@ func set_property(params: Dictionary) -> Dictionary:
119
119
  + " class_name; if it is one, the object given has the right class and another script:"
120
120
  + " it is %s"
121
121
  )
122
- % [named, str(slot["class"]), Values.class_of(refused_object)]
122
+ % [named, str(slot["class"]), GdhValues.class_of(refused_object)]
123
123
  )
124
124
  return {
125
125
  "type": "error",
@@ -150,7 +150,7 @@ func set_property(params: Dictionary) -> Dictionary:
150
150
 
151
151
 
152
152
  ## What [param sent] becomes as argument [param index] of the method [param named] on the holder
153
- ## [param reached] ends at, as [method Paths.walk_to] answered it, as `{"value": ...}`, or the refusal
153
+ ## [param reached] ends at, as [method GdhPaths.walk_to] answered it, as `{"value": ...}`, or the refusal
154
154
  ## saying why it cannot become one: a number the parameter would have to cut, a value that cannot be
155
155
  ## converted, or a list or map that cannot be built as the typed one the parameter takes.
156
156
  func _argument_for(
@@ -159,23 +159,30 @@ func _argument_for(
159
159
  var holder: Object = reached["holder"]
160
160
  var called: String = reached["called"]
161
161
  var wants: int = _values.parameter_type(holder, named, index)
162
- if Values.cuts(sent, wants):
162
+ if GdhValues.cuts(sent, wants):
163
163
  return {
164
164
  "type": "error",
165
165
  "message":
166
166
  (
167
167
  "%s.%s takes %s as argument %d and was given %s, which %s cannot hold without changing it"
168
- % [called, named, type_string(wants), index + 1, JSON.stringify(sent), Values.cut_by(wants)]
168
+ % [
169
+ called,
170
+ named,
171
+ type_string(wants),
172
+ index + 1,
173
+ JSON.stringify(sent),
174
+ GdhValues.cut_by(wants)
175
+ ]
169
176
  )
170
177
  }
171
- var rounded: String = Values.inexact(sent, wants)
178
+ var rounded: String = GdhValues.inexact(sent, wants)
172
179
  if not rounded.is_empty():
173
180
  return {
174
181
  "type": "error",
175
182
  "message": "%s.%s takes int as argument %d: %s." % [called, named, index + 1, rounded]
176
183
  }
177
184
  var given: Variant = _values.fitted(sent, wants)
178
- if not Values.acceptable(given, wants):
185
+ if not GdhValues.acceptable(given, wants):
179
186
  return {
180
187
  "type": "error",
181
188
  "message":
@@ -187,7 +194,7 @@ func _argument_for(
187
194
  type_string(wants),
188
195
  index + 1,
189
196
  type_string(typeof(given)),
190
- _written_as(wants)
197
+ GdhValues.remedy(sent, wants)
191
198
  ]
192
199
  )
193
200
  }
@@ -202,7 +209,7 @@ func _argument_for(
202
209
  "type": "error",
203
210
  "message":
204
211
  (
205
- "%s.%s takes a typed %s as argument %d: %s."
212
+ "%s.%s takes a typed %s as argument %d: %s"
206
213
  % [called, named, _sort_of(container), index + 1, typed["message"]]
207
214
  )
208
215
  }
@@ -210,7 +217,7 @@ func _argument_for(
210
217
 
211
218
 
212
219
  ## What [param value] becomes written into the slot [param reached] ends on, as
213
- ## [method Paths.walk_to] answered it, as `{"value": ...}`, or the refusal saying why it cannot become
220
+ ## [method GdhPaths.walk_to] answered it, as `{"value": ...}`, or the refusal saying why it cannot become
214
221
  ## one.
215
222
  ##
216
223
  ## The same rule the call path holds: a value that cannot become what the property holds is
@@ -248,11 +255,11 @@ func _value_for(
248
255
  "message": "%s.%s holds an object: %s" % [called, named, named_object["message"]]
249
256
  }
250
257
  return {"value": named_object["object"]}
251
- var rounded: String = Values.inexact(value, wanted)
258
+ var rounded: String = GdhValues.inexact(value, wanted)
252
259
  if not rounded.is_empty():
253
260
  return {"type": "error", "message": "%s.%s holds int: %s." % [called, named, rounded]}
254
261
  var as_sent: Variant = _values.fitted(value, TYPE_NIL)
255
- var cut: bool = Values.cuts(value, wanted)
262
+ var cut: bool = GdhValues.cuts(value, wanted)
256
263
  var given: Variant = as_sent
257
264
  if declared != TYPE_NIL and cut:
258
265
  return {
@@ -260,25 +267,31 @@ func _value_for(
260
267
  "message":
261
268
  (
262
269
  "%s.%s holds %s and the value given is %s, which %s cannot hold without changing it"
263
- % [called, named, type_string(wanted), JSON.stringify(value), Values.cut_by(wanted)]
270
+ % [called, named, type_string(wanted), JSON.stringify(value), GdhValues.cut_by(wanted)]
264
271
  )
265
272
  }
266
- if declared != TYPE_NIL or (not cut and Values.acceptable(as_sent, wanted)):
273
+ if declared != TYPE_NIL or (not cut and GdhValues.acceptable(as_sent, wanted)):
267
274
  given = _values.fitted(value, wanted)
268
- if not Values.acceptable(given, wanted):
275
+ if not GdhValues.acceptable(given, wanted):
269
276
  return {
270
277
  "type": "error",
271
278
  "message":
272
279
  (
273
280
  "%s.%s holds %s and the value given is %s, which cannot become one.%s"
274
- % [called, named, type_string(wanted), type_string(typeof(given)), _written_as(wanted)]
281
+ % [
282
+ called,
283
+ named,
284
+ type_string(wanted),
285
+ type_string(typeof(given)),
286
+ GdhValues.remedy(value, wanted)
287
+ ]
275
288
  )
276
289
  }
277
290
  var typed: Dictionary = _values.typed_like(given, old_value, _element_object.bind(node, node_path))
278
291
  if typed.has("message"):
279
292
  return {
280
293
  "type": "error",
281
- "message": "%s.%s is a typed %s: %s." % [called, named, _sort_of(old_value), typed["message"]]
294
+ "message": "%s.%s is a typed %s: %s" % [called, named, _sort_of(old_value), typed["message"]]
282
295
  }
283
296
  return {"value": typed["value"]}
284
297
 
@@ -294,7 +307,7 @@ func _value_for(
294
307
  ## unchanged rather than refused. Vectors and colours hold 32-bit parts in the value itself, so they
295
308
  ## already compare at the property's precision.
296
309
  static func held_already(given: Variant, held: Variant) -> bool:
297
- if not Values.comparable(given, held):
310
+ if not GdhValues.comparable(given, held):
298
311
  return false
299
312
  if given == held:
300
313
  return true
@@ -311,16 +324,16 @@ func call_method(params: Dictionary) -> Dictionary:
311
324
  if node_path.is_empty() or method.is_empty():
312
325
  return {"type": "error", "message": "Node path and method required"}
313
326
 
314
- var standing: Dictionary = Values.target_at(_host.get_tree().root, node_path)
327
+ var standing: Dictionary = GdhValues.target_at(_host.get_tree().root, node_path)
315
328
  if standing.has("message"):
316
329
  return standing
317
330
  var node: Node = standing["node"]
318
331
  var target: Object = standing["object"]
319
332
 
320
- # Through a path as well, for the reason [method Paths.walk_to] gives. What a game does hangs off its
333
+ # Through a path as well, for the reason [method GdhPaths.walk_to] gives. What a game does hangs off its
321
334
  # nodes as much as its state does, so reading `_game:run:day` while being unable to call
322
335
  # `_game:run:advance` answers half of what a node holds and refuses the other half.
323
- var reached: Dictionary = Paths.walk_to(target, node_path, method)
336
+ var reached: Dictionary = GdhPaths.walk_to(target, node_path, method)
324
337
  if reached.has("message"):
325
338
  return reached
326
339
 
@@ -331,20 +344,20 @@ func call_method(params: Dictionary) -> Dictionary:
331
344
  var sort: String = "a list"
332
345
  if reached["holder"] is Dictionary:
333
346
  sort = "a map"
334
- elif Paths.packed(reached["holder"]):
347
+ elif GdhPaths.packed(reached["holder"]):
335
348
  sort = "a packed list"
336
349
  var spelled: String = str(reached["name"])
337
- if Paths.method_of(spelled).is_empty():
350
+ if GdhPaths.method_of(spelled).is_empty():
338
351
  spelled += "()"
339
352
  # A vector or a transform has no element to call a method on: it is read by its components.
340
- if Paths.composite(reached["holder"]):
353
+ if GdhPaths.composite(reached["holder"]):
341
354
  return {
342
355
  "type": "error",
343
- "message": Paths.nothing_there(reached["holder"], spelled, str(reached["called"]))
356
+ "message": GdhPaths.nothing_there(reached["holder"], spelled, str(reached["called"]))
344
357
  }
345
- if args.is_empty() and Paths.can_read(reached["holder"], spelled):
358
+ if args.is_empty() and GdhPaths.can_read(reached["holder"], spelled):
346
359
  var read_from: int = Time.get_ticks_usec()
347
- var answered: Variant = Paths.read_under(reached["holder"], spelled)
360
+ var answered: Variant = GdhPaths.read_under(reached["holder"], spelled)
348
361
  var read_for: int = Time.get_ticks_usec() - read_from
349
362
  var listed: Dictionary = {
350
363
  "type": "method_result",
@@ -359,8 +372,8 @@ func call_method(params: Dictionary) -> Dictionary:
359
372
  return listed
360
373
  var why: String = (
361
374
  "%s:%s takes no arguments" % [reached["called"], spelled]
362
- if Paths.can_read(reached["holder"], spelled)
363
- else Paths.nothing_there(reached["holder"], spelled, str(reached["called"]))
375
+ if GdhPaths.can_read(reached["holder"], spelled)
376
+ else GdhPaths.nothing_there(reached["holder"], spelled, str(reached["called"]))
364
377
  )
365
378
  return {
366
379
  "type": "error",
@@ -378,8 +391,8 @@ func call_method(params: Dictionary) -> Dictionary:
378
391
  var not_called: String = _not_a_method_to_call(holder, named, str(reached["called"]))
379
392
  if not not_called.is_empty():
380
393
  return {"type": "error", "message": not_called}
381
- if not Paths.method_of(named).is_empty():
382
- named = Paths.method_of(named)
394
+ if not GdhPaths.method_of(named).is_empty():
395
+ named = GdhPaths.method_of(named)
383
396
 
384
397
  # Checked before the call rather than left to it. `callv` raises inside the game when an
385
398
  # argument cannot be converted, and an error raised in a game somebody is playing holds it at a
@@ -390,7 +403,7 @@ func call_method(params: Dictionary) -> Dictionary:
390
403
  return {"type": "error", "message": "%s.%s %s" % [reached["called"], named, count]}
391
404
  var deserialized_args: Array = []
392
405
  # The object arguments checked only against the engine class, by position from 1, for the refusal
393
- # the engine may still make: see [method Values.slot_declared].
406
+ # the engine may still make: see [method GdhValues.slot_declared].
394
407
  var by_engine_class: Dictionary = {}
395
408
  for index: int in args.size():
396
409
  var wants: int = _values.parameter_type(holder, named, index)
@@ -405,7 +418,7 @@ func call_method(params: Dictionary) -> Dictionary:
405
418
  }
406
419
  var resolved: Object = named_object["object"]
407
420
  if resolved != null and ClassDB.class_exists(declared):
408
- by_engine_class[index + 1] = [declared, Values.class_of(resolved)]
421
+ by_engine_class[index + 1] = [declared, GdhValues.class_of(resolved)]
409
422
  deserialized_args.append(named_object["object"])
410
423
  continue
411
424
  var argument: Dictionary = _argument_for(args[index], index, reached, named, node, node_path)
@@ -416,7 +429,7 @@ func call_method(params: Dictionary) -> Dictionary:
416
429
  # Timed around the call alone, since the bridge's round trip is a second or more and swamps what
417
430
  # one click's work costs; the frame metrics read whichever frame is last, which is not this one.
418
431
  # Listened to as well, because a call the engine refused returns null like one that ran.
419
- var caught: CallErrors = CallErrors.new()
432
+ var caught: GdhCallErrors = GdhCallErrors.new()
420
433
  OS.add_logger(caught)
421
434
  var began: int = Time.get_ticks_usec()
422
435
  var result: Variant = holder.callv(named, deserialized_args)
@@ -474,15 +487,15 @@ static func _keep_reported(answer: Dictionary, field: String, reported: Array[St
474
487
  ## other, or with the bracketed ones quietly dropped.
475
488
  static func _not_a_method_to_call(holder: Object, named: String, called: String) -> String:
476
489
  var method: String = named
477
- if not Paths.method_of(named).is_empty():
478
- var bracketed: Dictionary = Paths.arguments_of(named)
490
+ if not GdhPaths.method_of(named).is_empty():
491
+ var bracketed: Dictionary = GdhPaths.arguments_of(named)
479
492
  var in_brackets: Array = bracketed.get("args", [])
480
493
  if bracketed.has("message") or not in_brackets.is_empty():
481
494
  return (
482
495
  "%s:%s: the method a call ends on takes its arguments under args, not in its brackets"
483
496
  % [called, named]
484
497
  )
485
- method = Paths.method_of(named)
498
+ method = GdhPaths.method_of(named)
486
499
  return "" if holder.has_method(method) else "%s has no method %s" % [called, method]
487
500
 
488
501
 
@@ -544,15 +557,15 @@ static func _script_variables(object: Object) -> Array[String]:
544
557
  static func _walk_from(object: Object, path: String) -> Dictionary:
545
558
  var holder: Variant = object
546
559
  var called: String = "the result"
547
- for named: String in Paths.steps_of(path):
548
- if not Paths.can_hold(holder):
560
+ for named: String in GdhPaths.steps_of(path):
561
+ if not GdhPaths.can_hold(holder):
549
562
  return {
550
563
  "message":
551
564
  "%s holds %s, which has nothing to read %s off" % [called, type_string(typeof(holder)), named]
552
565
  }
553
- if not Paths.can_read(holder, named):
554
- return {"message": Paths.nothing_there(holder, named, called)}
555
- holder = Paths.read_under(holder, named)
566
+ if not GdhPaths.can_read(holder, named):
567
+ return {"message": GdhPaths.nothing_there(holder, named, called)}
568
+ holder = GdhPaths.read_under(holder, named)
556
569
  called = "%s:%s" % [called, named]
557
570
  return {"value": holder}
558
571
 
@@ -574,7 +587,7 @@ static func _argument_count_refused(holder: Object, method: String, given: int)
574
587
  var defaults: Array = entry.get("default_args", [])
575
588
  var most: int = parameters.size()
576
589
  var least: int = most - defaults.size()
577
- var any_more: bool = (Read.as_int(entry.get("flags", 0), 0) & METHOD_FLAG_VARARG) != 0
590
+ var any_more: bool = (GdhRead.as_int(entry.get("flags", 0), 0) & METHOD_FLAG_VARARG) != 0
578
591
  if given >= least and (given <= most or any_more):
579
592
  return ""
580
593
  var takes: String = "%d" % least
@@ -587,7 +600,7 @@ static func _argument_count_refused(holder: Object, method: String, given: int)
587
600
  return ""
588
601
 
589
602
 
590
- ## [method _object_named] with the path first, which is the order [method Values.typed_like] calls
603
+ ## [method _object_named] with the path first, which is the order [method GdhValues.typed_like] calls
591
604
  ## an element resolver in.
592
605
  func _element_object(
593
606
  given: Variant, declared: String, script: Script, node: Node, node_path: String
@@ -596,13 +609,6 @@ func _element_object(
596
609
 
597
610
 
598
611
  ## "list" or "map", for a refusal about a typed container.
599
- ## The sentence a refusal ends with for a type built from fields, naming the shape that is read as
600
- ## one, or nothing for a type that is not.
601
- static func _written_as(type: int) -> String:
602
- var shape: String = Values.written_as(type)
603
- return "" if shape.is_empty() else " A %s is sent as %s." % [type_string(type), shape]
604
-
605
-
606
612
  static func _sort_of(container: Variant) -> String:
607
613
  return "list" if container is Array else "map"
608
614
 
@@ -619,23 +625,23 @@ static func _sort_of(container: Variant) -> String:
619
625
  ## caller's null arrived as that text in #772 and #783, and was looked up as a node called "null".
620
626
  ##
621
627
  ## Checked against [param script] where the declaration hands one over, which only a typed container
622
- ## does: see [method Values.is_a].
628
+ ## does: see [method GdhValues.is_a].
623
629
  func _object_named(
624
630
  node: Node, node_path: String, given: Variant, declared: String, script: Script = null
625
631
  ) -> Dictionary:
626
632
  if names_no_object(given):
627
633
  return {"object": null}
628
- var found: Dictionary = Paths.object_at(_host.get_tree().root, node, node_path, given)
634
+ var found: Dictionary = GdhPaths.object_at(_host.get_tree().root, node, node_path, given)
629
635
  if found.has("message"):
630
636
  return found
631
637
  var instance: Object = found["object"]
632
- if script != null and not Values.is_a(instance, declared, script):
633
- var wanted: String = "an instance of %s" % Values.script_named(script)
638
+ if script != null and not GdhValues.is_a(instance, declared, script):
639
+ var wanted: String = "an instance of %s" % GdhValues.script_named(script)
634
640
  if not script.get_global_name().is_empty():
635
641
  wanted = "a %s" % script.get_global_name()
636
- return {"message": "%s is %s, not %s" % [str(given), Values.class_of(instance), wanted]}
637
- if script == null and not declared.is_empty() and not Values.is_a(instance, declared):
638
- return {"message": "%s is %s, not a %s" % [str(given), Values.class_of(instance), declared]}
642
+ return {"message": "%s is %s, not %s" % [str(given), GdhValues.class_of(instance), wanted]}
643
+ if script == null and not declared.is_empty() and not GdhValues.is_a(instance, declared):
644
+ return {"message": "%s is %s, not a %s" % [str(given), GdhValues.class_of(instance), declared]}
639
645
  return found
640
646
 
641
647