gdharness 1.3.41 → 1.3.43

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 (107) hide show
  1. package/build/cli.js +131 -47
  2. package/build/godot/addons/auto_reload/auto_reload.gd +18 -19
  3. package/build/godot/addons/gdharness_editor/animation_reads.gd +84 -35
  4. package/build/godot/addons/gdharness_editor/bridge_client.gd +53 -58
  5. package/build/godot/addons/gdharness_editor/declared_values.gd +68 -32
  6. package/build/godot/addons/gdharness_editor/file_reads.gd +114 -39
  7. package/build/godot/addons/gdharness_editor/file_walk.gd +12 -5
  8. package/build/godot/addons/gdharness_editor/headless_check.gd +94 -41
  9. package/build/godot/addons/gdharness_editor/plugin.gd +2 -3
  10. package/build/godot/addons/gdharness_editor/property_paths.gd +22 -12
  11. package/build/godot/addons/gdharness_editor/property_values.gd +143 -78
  12. package/build/godot/addons/gdharness_editor/reading.gd +37 -12
  13. package/build/godot/addons/gdharness_editor/same_values.gd +4 -4
  14. package/build/godot/addons/gdharness_editor/scene_file.gd +136 -79
  15. package/build/godot/addons/gdharness_editor/scene_uids.gd +12 -6
  16. package/build/godot/addons/gdharness_editor/serialisation.gd +75 -51
  17. package/build/godot/addons/gdharness_editor/setting_reads.gd +7 -6
  18. package/build/godot/addons/gdharness_editor/tool_executor.gd +3 -6
  19. package/build/godot/addons/gdharness_editor/tools/animation_states.gd +41 -28
  20. package/build/godot/addons/gdharness_editor/tools/animation_tools.gd +84 -50
  21. package/build/godot/addons/gdharness_editor/tools/animation_tracks.gd +70 -40
  22. package/build/godot/addons/gdharness_editor/tools/class_tools.gd +34 -30
  23. package/build/godot/addons/gdharness_editor/tools/filesystem_tools.gd +24 -22
  24. package/build/godot/addons/gdharness_editor/tools/navigation_bake.gd +49 -29
  25. package/build/godot/addons/gdharness_editor/tools/play_tools.gd +26 -21
  26. package/build/godot/addons/gdharness_editor/tools/profile_tools.gd +40 -40
  27. package/build/godot/addons/gdharness_editor/tools/resource_tools.gd +181 -107
  28. package/build/godot/addons/gdharness_editor/tools/scene_groups.gd +16 -9
  29. package/build/godot/addons/gdharness_editor/tools/scene_kin.gd +75 -43
  30. package/build/godot/addons/gdharness_editor/tools/scene_paths.gd +35 -20
  31. package/build/godot/addons/gdharness_editor/tools/scene_placing.gd +28 -13
  32. package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd +66 -0
  33. package/build/godot/addons/gdharness_editor/tools/scene_sharing.gd.uid +1 -0
  34. package/build/godot/addons/gdharness_editor/tools/scene_tools.gd +171 -62
  35. package/build/godot/addons/gdharness_editor/tools/script_paths.gd +20 -8
  36. package/build/godot/addons/gdharness_editor/tools/settings_tools.gd +11 -8
  37. package/build/godot/addons/gdharness_editor/tools/signal_tools.gd +47 -34
  38. package/build/godot/addons/gdharness_editor/tools/tileset_tools.gd +77 -50
  39. package/build/godot/addons/gdharness_editor/value_shapes.gd +5 -6
  40. package/build/godot/addons/gdharness_runtime/call_errors.gd +1 -2
  41. package/build/godot/addons/gdharness_runtime/declared_values.gd +68 -32
  42. package/build/godot/addons/gdharness_runtime/error_report.gd +1 -2
  43. package/build/godot/addons/gdharness_runtime/reading.gd +37 -12
  44. package/build/godot/addons/gdharness_runtime/runtime_accessibility.gd +84 -63
  45. package/build/godot/addons/gdharness_runtime/runtime_autoload.gd +153 -148
  46. package/build/godot/addons/gdharness_runtime/runtime_capture.gd +64 -42
  47. package/build/godot/addons/gdharness_runtime/runtime_changes.gd +184 -122
  48. package/build/godot/addons/gdharness_runtime/runtime_frames.gd +2 -2
  49. package/build/godot/addons/gdharness_runtime/runtime_hover.gd +24 -20
  50. package/build/godot/addons/gdharness_runtime/runtime_input.gd +134 -92
  51. package/build/godot/addons/gdharness_runtime/runtime_items.gd +29 -13
  52. package/build/godot/addons/gdharness_runtime/runtime_menus.gd +0 -1
  53. package/build/godot/addons/gdharness_runtime/runtime_mouse.gd +38 -20
  54. package/build/godot/addons/gdharness_runtime/runtime_pad.gd +17 -13
  55. package/build/godot/addons/gdharness_runtime/runtime_paths.gd +84 -46
  56. package/build/godot/addons/gdharness_runtime/runtime_queries.gd +117 -79
  57. package/build/godot/addons/gdharness_runtime/runtime_says.gd +14 -17
  58. package/build/godot/addons/gdharness_runtime/runtime_screen.gd +23 -16
  59. package/build/godot/addons/gdharness_runtime/runtime_targets.gd +117 -66
  60. package/build/godot/addons/gdharness_runtime/runtime_touch.gd +211 -0
  61. package/build/godot/addons/gdharness_runtime/runtime_touch.gd.uid +1 -0
  62. package/build/godot/addons/gdharness_runtime/runtime_typing.gd +44 -27
  63. package/build/godot/addons/gdharness_runtime/runtime_values.gd +108 -73
  64. package/build/godot/addons/gdharness_runtime/runtime_waits.gd +111 -84
  65. package/build/godot/addons/gdharness_runtime/runtime_words.gd +10 -7
  66. package/build/godot/addons/gdharness_runtime/serialisation.gd +75 -51
  67. package/build/godot/addons/gdharness_runtime/value_shapes.gd +5 -6
  68. package/build/godot/addons/gdharness_tests/bench.gd +4 -5
  69. package/build/godot/addons/gdharness_tests/event.gd +10 -5
  70. package/build/godot/addons/gdharness_tests/share.gd +38 -18
  71. package/build/godot/addons/gdharness_tests/suites.gd +3 -3
  72. package/build/godot/addons/gdharness_tests/wait.gd +3 -2
  73. package/build/godot/loader/loader.gd +9 -9
  74. package/build/godot/operations/animation_reads.gd +84 -35
  75. package/build/godot/operations/audio_buses.gd +48 -19
  76. package/build/godot/operations/class_cache.gd +16 -11
  77. package/build/godot/operations/classdb_queries.gd +89 -44
  78. package/build/godot/operations/declared_values.gd +68 -32
  79. package/build/godot/operations/dependencies.gd +139 -93
  80. package/build/godot/operations/editor_tools.gd +9 -10
  81. package/build/godot/operations/export_presets.gd +100 -54
  82. package/build/godot/operations/file_reads.gd +114 -39
  83. package/build/godot/operations/file_walk.gd +12 -5
  84. package/build/godot/operations/gdscript_analysis.gd +105 -66
  85. package/build/godot/operations/gdscript_authoring.gd +138 -39
  86. package/build/godot/operations/godot_operations.gd +17 -11
  87. package/build/godot/operations/import_pipeline.gd +110 -59
  88. package/build/godot/operations/input_actions.gd +63 -39
  89. package/build/godot/operations/patterns.gd +3 -1
  90. package/build/godot/operations/plugins.gd +36 -16
  91. package/build/godot/operations/project_config.gd +144 -27
  92. package/build/godot/operations/project_diagnostics.gd +24 -11
  93. package/build/godot/operations/project_file.gd +16 -16
  94. package/build/godot/operations/project_validation.gd +71 -44
  95. package/build/godot/operations/property_paths.gd +22 -12
  96. package/build/godot/operations/property_values.gd +143 -78
  97. package/build/godot/operations/reading.gd +37 -12
  98. package/build/godot/operations/rename_checks.gd +2 -2
  99. package/build/godot/operations/resource_files.gd +11 -9
  100. package/build/godot/operations/same_values.gd +4 -4
  101. package/build/godot/operations/scene_connections.gd +27 -13
  102. package/build/godot/operations/script_check.gd +52 -49
  103. package/build/godot/operations/serialisation.gd +75 -51
  104. package/build/godot/operations/setting_reads.gd +7 -6
  105. package/build/godot/operations/value_shapes.gd +5 -6
  106. package/build/godot/tests/listed.gd +321 -268
  107. package/package.json +1 -1
@@ -3,7 +3,6 @@ extends RefCounted
3
3
  const GdhFileWalk = preload("file_walk.gd")
4
4
  const GdhLog = preload("logger.gd")
5
5
  const GdhPatterns = preload("patterns.gd")
6
-
7
6
  ## Where the engine keeps a file's UID, by what kind of file it is. Measured on 4.7.2: a script or
8
7
  ## shader has a `.uid` file beside it, an imported file has it in its `.import`, and a text scene or
9
8
  ## resource has it in its own header. `ResourceLoader.get_resource_uid` answers the first two in a
@@ -34,7 +33,7 @@ func get_uid(params: Dictionary) -> Dictionary:
34
33
  GdhFileWalk.new().with_nearest_files("File does not exist: " + file_path, file_path)
35
34
  )
36
35
 
37
- var answer: Dictionary = {"file": file_path, "absolute_path": absolute_path}
36
+ var answer: Dictionary = { "file": file_path, "absolute_path": absolute_path }
38
37
  var found: Dictionary = uid_of(file_path)
39
38
  if found.is_empty():
40
39
  answer["exists"] = false
@@ -51,12 +50,12 @@ static func uid_of(file_path: String) -> Dictionary:
51
50
  if FileAccess.file_exists(sidecar):
52
51
  var text: String = FileAccess.get_file_as_string(sidecar).strip_edges()
53
52
  if not text.is_empty():
54
- return {"uid": text, "from": sidecar}
53
+ return { "uid": text, "from": sidecar }
55
54
  var import_file: String = file_path + ".import"
56
55
  if FileAccess.file_exists(import_file):
57
56
  var config: ConfigFile = ConfigFile.new()
58
57
  if config.load(import_file) == OK and config.has_section_key("remap", "uid"):
59
- return {"uid": str(config.get_value("remap", "uid")), "from": import_file}
58
+ return { "uid": str(config.get_value("remap", "uid")), "from": import_file }
60
59
  if file_path.get_extension().to_lower() in TEXT_RESOURCE_KINDS:
61
60
  var file: FileAccess = FileAccess.open(file_path, FileAccess.READ)
62
61
  if file != null:
@@ -64,10 +63,10 @@ static func uid_of(file_path: String) -> Dictionary:
64
63
  file.close()
65
64
  var matched: RegExMatch = GdhPatterns.compiled('\\buid="(uid://[^"]+)"').search(header)
66
65
  if matched != null:
67
- return {"uid": matched.get_string(1), "from": "the file's header"}
66
+ return { "uid": matched.get_string(1), "from": "the file's header" }
68
67
  var id: int = ResourceLoader.get_resource_uid(file_path)
69
68
  if id != ResourceUID.INVALID_ID:
70
- return {"uid": ResourceUID.id_to_text(id), "from": "the engine"}
69
+ return { "uid": ResourceUID.id_to_text(id), "from": "the engine" }
71
70
  return {}
72
71
 
73
72
 
@@ -79,9 +78,12 @@ func _why_none(file_path: String) -> String:
79
78
  return "No .uid file beside it. refresh_uids writes one for every script and shader."
80
79
  if kind in TEXT_RESOURCE_KINDS:
81
80
  return (
82
- "Its header carries no uid. The editor writes one when it saves the file; refresh_uids does not,"
83
- + " and a headless save does not either."
81
+ "Its header carries no uid. The editor writes one when it saves the file; refresh_uids "
82
+ + "does not, and a headless save does not either."
84
83
  )
85
84
  if ResourceLoader.exists(file_path):
86
85
  return "The engine keeps no UID for it."
87
- return "It has not been imported, and the import is what gives it a UID: project_import reimport imports it."
86
+ return (
87
+ "It has not been imported, and the import is what gives it a UID: project_import reimport "
88
+ + "imports it."
89
+ )
@@ -1,12 +1,10 @@
1
1
  @tool
2
2
  extends RefCounted
3
-
4
3
  ## Whether a value read back is the value that was given, as the tools that write properties judge
5
4
  ## what a write kept and what it changed besides.
6
5
 
7
6
  const GdhRead = preload("reading.gd")
8
7
  const GdhSerialisation = preload("serialisation.gd")
9
-
10
8
  # The types made of floats, which a read back compares within float precision: a Vector2 property
11
9
  # stores 32-bit components, so 0.1 comes back as 0.100000001.
12
10
  const FLOAT_SHAPES: Array[int] = [
@@ -23,7 +21,6 @@ const FLOAT_SHAPES: Array[int] = [
23
21
  TYPE_AABB,
24
22
  TYPE_PROJECTION,
25
23
  ]
26
-
27
24
  const PACKED: Array[int] = [
28
25
  TYPE_PACKED_BYTE_ARRAY,
29
26
  TYPE_PACKED_INT32_ARRAY,
@@ -63,7 +60,10 @@ static func same(held: Variant, given: Variant) -> bool:
63
60
  return held_type == given_type and held == given
64
61
  var held_number: float = GdhRead.as_float(held)
65
62
  var given_number: float = GdhRead.as_float(given)
66
- return (is_nan(held_number) and is_nan(given_number)) or is_equal_approx(held_number, given_number)
63
+ return (
64
+ (is_nan(held_number) and is_nan(given_number))
65
+ or is_equal_approx(held_number, given_number)
66
+ )
67
67
  if GdhSerialisation.TEXTS.has(held_type) and GdhSerialisation.TEXTS.has(given_type):
68
68
  return str(held) == str(given)
69
69
  if _listed(held_type) and _listed(given_type):
@@ -1,5 +1,4 @@
1
1
  extends RefCounted
2
-
3
2
  ## The signal connections the project's scenes hold that cannot work: a method the node it calls
4
3
  ## does not have, which fails on every emission, or a signal the node it leaves does not have, which
5
4
  ## the engine drops as the scene loads. Read from the text of each scene and script, so nothing is
@@ -13,7 +12,6 @@ extends RefCounted
13
12
  const GdhDependencies = preload("dependencies.gd")
14
13
  const GdhFileWalk = preload("file_walk.gd")
15
14
  const GdhLog = preload("logger.gd")
16
-
17
15
  const EXT_RESOURCE: String = '^\\[ext_resource [^\\]]*?path="([^"]+)"[^\\]]*? id="([^"]+)"'
18
16
  const NODE: String = "^\\[node ([^\\]]*)\\]"
19
17
  const CONNECTION: String = "^\\[connection ([^\\]]*)\\]"
@@ -38,8 +36,8 @@ func _init(p_log: GdhLog) -> void:
38
36
  _globals = GdhDependencies.new(p_log).classes_declared()
39
37
 
40
38
 
41
- ## Every connection that cannot work, as {scene, from, signal, to, method, missing}, where missing is
42
- ## "method" or "signal".
39
+ ## Every connection that cannot work, as {scene, from, signal, to, method, missing}, where missing
40
+ ## is "method" or "signal".
43
41
  func broken() -> Array[Dictionary]:
44
42
  var found: Array[Dictionary] = []
45
43
  for scene: String in _files.find_files_with_extensions("res://", ["tscn"]):
@@ -76,7 +74,10 @@ static func broken_line(entry: Dictionary) -> String:
76
74
  % [entry["scene"], entry["from"], entry["signal"], entry["to"], entry["method"]]
77
75
  )
78
76
  if entry["missing"] == "signal":
79
- return connected + ", a signal that node does not have, so the engine drops it as the scene loads."
77
+ return (
78
+ connected
79
+ + ", a signal that node does not have, so the engine drops it as the scene loads."
80
+ )
80
81
  return connected + ", a method that node does not have, so every emission fails to call it."
81
82
 
82
83
 
@@ -100,11 +101,17 @@ func _nodes_of(content: String, scene: String) -> Dictionary:
100
101
  var attributes: Dictionary = _attributes(heading.get_string(1))
101
102
  var name: String = str(attributes.get("name", ""))
102
103
  var parent: Variant = attributes.get("parent")
103
- current = "." if parent == null else (name if parent == "." else "%s/%s" % [parent, name])
104
- var node: Dictionary = {"class": str(attributes.get("type", "")), "script": "", "name": name}
104
+ current = (
105
+ "." if parent == null else (name if parent == "." else "%s/%s" % [parent, name])
106
+ )
107
+ var node: Dictionary = {
108
+ "class": str(attributes.get("type", "")), "script": "", "name": name,
109
+ }
105
110
  var instanced: RegExMatch = instance.search(heading.get_string(1))
106
111
  if instanced != null:
107
- var root: Dictionary = _root_of(str(resources.get(instanced.get_string(1), "")), scene)
112
+ var root: Dictionary = _root_of(
113
+ str(resources.get(instanced.get_string(1), "")), scene
114
+ )
108
115
  node = root.duplicate()
109
116
  node["name"] = name
110
117
  nodes[current] = node
@@ -118,7 +125,9 @@ func _nodes_of(content: String, scene: String) -> Dictionary:
118
125
  # A built-in script lives in the scene, where this does not read it, so its node is one
119
126
  # nothing here can judge, which a path that is no script file says.
120
127
  var external: bool = scripted.get_string(1) == "Ext"
121
- node["script"] = str(resources.get(scripted.get_string(2), "?")) if external else "built-in"
128
+ node["script"] = (
129
+ str(resources.get(scripted.get_string(2), "?")) if external else "built-in"
130
+ )
122
131
  return nodes
123
132
 
124
133
 
@@ -127,11 +136,16 @@ func _nodes_of(content: String, scene: String) -> Dictionary:
127
136
  func _root_of(path: String, from: String) -> Dictionary:
128
137
  if _roots.has(path):
129
138
  return _roots[path]
130
- _roots[path] = {"class": "", "script": ""}
131
- if path.is_empty() or path == from or not path.ends_with(".tscn") or not FileAccess.file_exists(path):
139
+ _roots[path] = { "class": "", "script": "" }
140
+ if (
141
+ path.is_empty()
142
+ or path == from
143
+ or not path.ends_with(".tscn")
144
+ or not FileAccess.file_exists(path)
145
+ ):
132
146
  return _roots[path]
133
147
  var nodes: Dictionary = _nodes_of(FileAccess.get_file_as_string(path), path)
134
- _roots[path] = nodes.get(".", {"class": "", "script": ""})
148
+ _roots[path] = nodes.get(".", { "class": "", "script": "" })
135
149
  return _roots[path]
136
150
 
137
151
 
@@ -200,7 +214,7 @@ func _script(path: String, seen: Dictionary) -> Dictionary:
200
214
  methods.merge(inherited_methods)
201
215
  signals.merge(inherited_signals)
202
216
  engine_class = str(inherited["class"])
203
- _scripts[path] = {"class": engine_class, "methods": methods, "signals": signals}
217
+ _scripts[path] = { "class": engine_class, "methods": methods, "signals": signals }
204
218
  return _scripts[path]
205
219
 
206
220
 
@@ -1,28 +1,25 @@
1
1
  extends RefCounted
2
-
3
2
  ## Compiles scripts the way the engine does when it loads them, and answers what it raised.
4
3
  ##
5
4
  ## The engine reports a script that does not compile as errors raised from GDScript::reload, each
6
5
  ## naming the file and line, and they reach a Logger as well as stderr. Measured on 4.7.2: a script
7
- ## whose dependency does not compile reports the dependency's errors at the dependency's path and one
8
- ## of its own at line 0, "Compile Error: Failed to compile depended scripts", and is still handed
9
- ## back as a script that can_instantiate() calls instantiable. Warnings are not among them: the engine
10
- ## sends those only to an editor or a debugger.
6
+ ## whose dependency does not compile reports the dependency's errors at the dependency's path and
7
+ ## one of its own at line 0, "Compile Error: Failed to compile depended scripts", and is still
8
+ ## handed back as a script that can_instantiate() calls instantiable. Warnings are not among them:
9
+ ## the engine sends those only to an editor or a debugger.
11
10
  ##
12
- ## A script that failed stays failed in the engine's script cache, which no ResourceLoader cache mode
13
- ## reaches, and every script loaded after it that depends on it compiles in silence, reload() and all.
14
- ## So a run ends at the first script that raised anything, and the rest go to a fresh engine.
11
+ ## A script that failed stays failed in the engine's script cache, which no ResourceLoader cache
12
+ ## mode reaches, and every script loaded after it that depends on it compiles in silence, reload()
13
+ ## and all. So a run ends at the first script that raised anything, and the rest go to a fresh
14
+ ## engine.
15
15
 
16
16
  const GdhRead = preload("reading.gd")
17
17
  const GdhLog = preload("logger.gd")
18
-
19
18
  ## Where the engine raises a script's compile errors from.
20
19
  const RELOAD: String = "GDScript::reload"
21
-
22
20
  ## What the engine puts on the end of a warning it raised as an error. Kept in step with
23
21
  ## `RAISED_WARNING` in src/server.ts.
24
22
  const RAISED: String = " (Warning treated as error.)"
25
-
26
23
  ## Where the project's warning levels are, each 0 to ignore, 1 to warn and 2 to raise as an error.
27
24
  const WARNING_LEVELS: String = "debug/gdscript/warnings/"
28
25
  const WARN: int = 1
@@ -31,34 +28,6 @@ const ERROR_LEVEL: int = 2
31
28
  var _log: GdhLog
32
29
 
33
30
 
34
- ## Every compile error the engine raises while it is attached, in order.
35
- class GdhCaught:
36
- extends Logger
37
-
38
- var raised: Array[Dictionary] = []
39
-
40
- func _log_message(_message: String, _error: bool) -> void:
41
- pass
42
-
43
- # The engine's own signature for a Logger, eight parameters and not this project's to shape.
44
- # gdlint:ignore = function-arguments-number
45
- func _log_error(
46
- function: String,
47
- file: String,
48
- line: int,
49
- code: String,
50
- rationale: String,
51
- _editor_notify: bool,
52
- _error_type: int,
53
- _script_backtraces: Array[ScriptBacktrace],
54
- ) -> void:
55
- if function != RELOAD:
56
- return
57
- raised.append(
58
- {"path": file, "line": line, "message": rationale if not rationale.is_empty() else code}
59
- )
60
-
61
-
62
31
  func _init(p_log: GdhLog) -> void:
63
32
  _log = p_log
64
33
 
@@ -105,22 +74,24 @@ func check_scripts(params: Dictionary) -> Dictionary:
105
74
  if not at in others:
106
75
  others.append(at)
107
76
  continue
108
- var found: Dictionary = {"line": GdhRead.as_int(error["line"]), "message": str(error["message"])}
77
+ var found: Dictionary = {
78
+ "line": GdhRead.as_int(error["line"]), "message": str(error["message"]),
79
+ }
109
80
  if not found in errors:
110
81
  errors.append(found)
111
82
  if loaded == null and errors.is_empty():
112
- errors.append({"line": 0, "message": "The engine could not load it as a script."})
83
+ errors.append({ "line": 0, "message": "The engine could not load it as a script." })
113
84
  if errors.is_empty() and others.is_empty():
114
85
  continue
115
86
  if not errors.is_empty():
116
87
  failed.append(path)
117
- var one: Dictionary = {"path": path, "errors": errors}
88
+ var one: Dictionary = { "path": path, "errors": errors }
118
89
  if not others.is_empty():
119
90
  one["dependencies_with_errors"] = others
120
91
  scripts.append(one)
121
92
  break
122
93
  OS.remove_logger(caught)
123
- return {"checked": checked, "failed": failed, "scripts": scripts}
94
+ return { "checked": checked, "failed": failed, "scripts": scripts }
124
95
 
125
96
 
126
97
  ## Raises every warning the project sets to warn so that the engine reports it as an error, which is
@@ -144,9 +115,9 @@ static func raise_warnings() -> void:
144
115
 
145
116
  ## The warnings of each script in [code]paths[/code], under the levels [method raise_warnings] left:
146
117
  ## [code]scripts[/code] holds each that has any, with its warnings' lines and the engine's messages
147
- ## as raised. The analyser runs before anything is compiled, so a script whose dependency failed on a
148
- ## warning still reports its own, and loading on past a failure loses nothing; only what is raised at
149
- ## the script's own path is its, since a dependency is read on its own entry as well.
118
+ ## as raised. The analyser runs before anything is compiled, so a script whose dependency failed on
119
+ ## a warning still reports its own, and loading on past a failure loses nothing; only what is raised
120
+ ## at the script's own path is its, since a dependency is read on its own entry as well.
150
121
  func check_warnings(params: Dictionary) -> Dictionary:
151
122
  var asked: Array = params.get("paths", [])
152
123
  var caught: GdhCaught = GdhCaught.new()
@@ -163,10 +134,42 @@ func check_warnings(params: Dictionary) -> Dictionary:
163
134
  var message: String = str(error["message"])
164
135
  if str(error["path"]) != path or not message.ends_with(RAISED):
165
136
  continue
166
- var found: Dictionary = {"line": GdhRead.as_int(error["line"]), "message": message}
137
+ var found: Dictionary = { "line": GdhRead.as_int(error["line"]), "message": message }
167
138
  if not found in warnings:
168
139
  warnings.append(found)
169
140
  if not warnings.is_empty():
170
- scripts.append({"path": path, "warnings": warnings})
141
+ scripts.append({ "path": path, "warnings": warnings })
171
142
  OS.remove_logger(caught)
172
- return {"checked": checked, "scripts": scripts}
143
+ return { "checked": checked, "scripts": scripts }
144
+
145
+
146
+ ## Every compile error the engine raises while it is attached, in order.
147
+ class GdhCaught:
148
+ extends Logger
149
+
150
+ var raised: Array[Dictionary] = []
151
+
152
+ func _log_message(_message: String, _error: bool) -> void:
153
+ pass
154
+
155
+ # The engine's own signature for a Logger, eight parameters and not this project's to shape.
156
+ # gdstyle:ignore=quality/max-parameters
157
+ func _log_error(
158
+ function: String,
159
+ file: String,
160
+ line: int,
161
+ code: String,
162
+ rationale: String,
163
+ _editor_notify: bool,
164
+ _error_type: int,
165
+ _script_backtraces: Array[ScriptBacktrace],
166
+ ) -> void:
167
+ if function != RELOAD:
168
+ return
169
+ raised.append(
170
+ {
171
+ "path": file,
172
+ "line": line,
173
+ "message": rationale if not rationale.is_empty() else code,
174
+ }
175
+ )