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.
- package/build/cli.js +571 -363
- package/build/godot/addons/gdharness_editor/animation_reads.gd +7 -19
- package/build/godot/addons/gdharness_editor/bridge_client.gd +9 -9
- package/build/godot/addons/gdharness_editor/file_reads.gd +60 -25
- package/build/godot/addons/gdharness_editor/headless_check.gd +7 -7
- package/build/godot/addons/gdharness_editor/plugin.gd +6 -6
- package/build/godot/addons/gdharness_editor/property_values.gd +124 -62
- package/build/godot/addons/gdharness_editor/reading.gd +28 -0
- package/build/godot/addons/gdharness_editor/scene_file.gd +28 -23
- package/build/godot/addons/gdharness_editor/serialisation.gd +45 -94
- package/build/godot/addons/gdharness_editor/tool_executor.gd +24 -24
- package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +52 -41
- package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +4 -4
- package/build/godot/addons/gdharness_editor/tools/play_tools.gd +2 -2
- package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +14 -14
- package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +57 -50
- package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +17 -17
- package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +14 -12
- package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +7 -7
- package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +82 -78
- package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +4 -4
- package/build/godot/addons/gdharness_editor/value_shapes.gd +111 -0
- package/build/godot/addons/gdharness_editor/value_shapes.gd.uid +1 -0
- package/build/godot/addons/gdharness_runtime/reading.gd +28 -0
- package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +18 -18
- package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +32 -32
- package/build/godot/addons/gdharness_runtime/runtime_capture.gd +50 -18
- package/build/godot/addons/gdharness_runtime/runtime_changes.gd +86 -80
- package/build/godot/addons/gdharness_runtime/runtime_input.gd +65 -69
- package/build/godot/addons/gdharness_runtime/runtime_items.gd +6 -6
- package/build/godot/addons/gdharness_runtime/runtime_menus.gd +8 -8
- package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +13 -21
- package/build/godot/addons/gdharness_runtime/runtime_pad.gd +10 -10
- package/build/godot/addons/gdharness_runtime/runtime_paths.gd +7 -7
- package/build/godot/addons/gdharness_runtime/runtime_queries.gd +41 -41
- package/build/godot/addons/gdharness_runtime/runtime_says.gd +3 -3
- package/build/godot/addons/gdharness_runtime/runtime_targets.gd +33 -33
- package/build/godot/addons/gdharness_runtime/runtime_typing.gd +20 -20
- package/build/godot/addons/gdharness_runtime/runtime_values.gd +25 -24
- package/build/godot/addons/gdharness_runtime/runtime_waits.gd +56 -50
- package/build/godot/addons/gdharness_runtime/serialisation.gd +45 -94
- package/build/godot/addons/gdharness_runtime/value_shapes.gd +111 -0
- package/build/godot/addons/gdharness_runtime/value_shapes.gd.uid +1 -0
- package/build/godot/operations/animation_reads.gd +7 -19
- package/build/godot/operations/audio_buses.gd +10 -10
- package/build/godot/operations/class_cache.gd +16 -16
- package/build/godot/operations/classdb_queries.gd +12 -12
- package/build/godot/operations/dependencies.gd +33 -29
- package/build/godot/operations/editor_tools.gd +12 -12
- package/build/godot/operations/export_presets.gd +10 -8
- package/build/godot/operations/file_reads.gd +60 -25
- package/build/godot/operations/gdscript_analysis.gd +20 -20
- package/build/godot/operations/gdscript_authoring.gd +17 -15
- package/build/godot/operations/godot_operations.gd +64 -63
- package/build/godot/operations/import_pipeline.gd +20 -20
- package/build/godot/operations/input_actions.gd +17 -17
- package/build/godot/operations/logger.gd +1 -1
- package/build/godot/operations/plugins.gd +8 -8
- package/build/godot/operations/project_config.gd +24 -17
- package/build/godot/operations/project_diagnostics.gd +9 -9
- package/build/godot/operations/property_values.gd +124 -62
- package/build/godot/operations/reading.gd +28 -0
- package/build/godot/operations/rename_checks.gd +3 -3
- package/build/godot/operations/resource_files.gd +5 -5
- package/build/godot/operations/script_check.gd +7 -7
- package/build/godot/operations/serialisation.gd +45 -94
- package/build/godot/operations/value_shapes.gd +111 -0
- package/build/keeper.js +10 -4
- package/package.json +1 -2
- 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
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
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:
|
|
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:
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
62
|
-
return {"type": "error", "message":
|
|
63
|
-
var old_value: Variant =
|
|
64
|
-
var slot: Dictionary =
|
|
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 =
|
|
75
|
+
var copied: bool = GdhPaths.composite(holder)
|
|
76
76
|
if copied:
|
|
77
|
-
var unwritable: String =
|
|
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 =
|
|
82
|
+
var written: Variant = GdhPaths.write(holder, named, given)
|
|
83
83
|
if copied:
|
|
84
|
-
|
|
84
|
+
GdhPaths.write_back(chain, written)
|
|
85
85
|
var elapsed: int = Time.get_ticks_usec() - began
|
|
86
|
-
var now: Variant =
|
|
86
|
+
var now: Variant = GdhPaths.read_under(holder, named)
|
|
87
87
|
if copied:
|
|
88
|
-
var again: Dictionary =
|
|
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 =
|
|
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
|
|
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 =
|
|
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"]),
|
|
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
|
|
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
|
|
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
|
-
% [
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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),
|
|
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
|
|
273
|
+
if declared != TYPE_NIL or (not cut and GdhValues.acceptable(as_sent, wanted)):
|
|
267
274
|
given = _values.fitted(value, wanted)
|
|
268
|
-
if not
|
|
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
|
-
% [
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
347
|
+
elif GdhPaths.packed(reached["holder"]):
|
|
335
348
|
sort = "a packed list"
|
|
336
349
|
var spelled: String = str(reached["name"])
|
|
337
|
-
if
|
|
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
|
|
353
|
+
if GdhPaths.composite(reached["holder"]):
|
|
341
354
|
return {
|
|
342
355
|
"type": "error",
|
|
343
|
-
"message":
|
|
356
|
+
"message": GdhPaths.nothing_there(reached["holder"], spelled, str(reached["called"]))
|
|
344
357
|
}
|
|
345
|
-
if args.is_empty() and
|
|
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 =
|
|
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
|
|
363
|
-
else
|
|
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
|
|
382
|
-
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
|
|
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,
|
|
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:
|
|
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
|
|
478
|
-
var bracketed: Dictionary =
|
|
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 =
|
|
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
|
|
548
|
-
if not
|
|
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
|
|
554
|
-
return {"message":
|
|
555
|
-
holder =
|
|
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 = (
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
633
|
-
var wanted: String = "an instance of %s" %
|
|
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),
|
|
637
|
-
if script == null and not declared.is_empty() and not
|
|
638
|
-
return {"message": "%s is %s, not a %s" % [str(given),
|
|
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
|
|