gdharness 1.1.30 → 1.1.32

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.
@@ -25,6 +25,10 @@ const MAX_RECONNECT_DELAY: float = 30.0
25
25
  ## What a server closes with when the editor that said hello belongs to another project. Kept in
26
26
  ## step with `OTHER_PROJECT_CLOSE_CODE` in src/godot-bridge.ts.
27
27
  const ELSEWHERE_CLOSE_CODE: int = 4001
28
+ ## What a server closes with when this process is one job that quits, such as a gate's `--import`,
29
+ ## rather than an editor: dialling in again changes nothing for the rest of the run. Kept in step
30
+ ## with `ONE_SHOT_CLOSE_CODE` in src/godot-bridge.ts.
31
+ const ONE_SHOT_CLOSE_CODE: int = 4002
28
32
 
29
33
  ## Where Godot keeps the three ports an editor serves. None of them is per editor: the settings
30
34
  ## file is one for every editor of this engine version on the machine, so two open at once want the
@@ -447,6 +451,8 @@ func _read_marker(path: String) -> String:
447
451
  func _handle_disconnect() -> void:
448
452
  _is_connected = false
449
453
  _said_elsewhere()
454
+ if socket.get_close_code() == ONE_SHOT_CLOSE_CODE:
455
+ _should_reconnect = false
450
456
  disconnected.emit()
451
457
 
452
458
  if _should_reconnect:
@@ -63,6 +63,15 @@ func rescan_filesystem(args: Dictionary) -> Dictionary:
63
63
  var uids: Dictionary = {"reread": [], "duplicated": []}
64
64
  if not Read.as_bool(args.get("statusOnly", false)) and not busy:
65
65
  uids = _reread_changed_uids(filesystem)
66
+ # Files the caller has just written, moved or deleted, read again one by one. The scan finds a
67
+ # script that appeared and leaves the global class of one that has gone in the editor's list,
68
+ # which it then writes back into the class cache at a path that is not there; reading the gone
69
+ # path again is what drops it.
70
+ var named: Variant = args.get("updateFiles", [])
71
+ if named is Array:
72
+ var paths: Array = named
73
+ for path: Variant in paths:
74
+ filesystem.update_file(str(path))
66
75
  filesystem.scan()
67
76
  # Whether the scan ran, read off the editor rather than assumed. `scan()` returns without
68
77
  # a word while the thread of the scan before is still to be joined, which is a frame or
@@ -26,6 +26,7 @@ const Log = preload("logger.gd")
26
26
  const Plugins = preload("plugins.gd")
27
27
  const ProjectConfig = preload("project_config.gd")
28
28
  const ProjectDiagnostics = preload("project_diagnostics.gd")
29
+ const RenameChecks = preload("rename_checks.gd")
29
30
  const ResourceFiles = preload("resource_files.gd")
30
31
 
31
32
  var _log: Log
@@ -171,6 +172,10 @@ func _run(operation: String, params: Dictionary) -> Dictionary:
171
172
  payload = GdscriptAuthoring.new(_log).modify_gdscript(params)
172
173
  "get_script_info":
173
174
  payload = GdscriptAnalysis.new(_log).get_gdscript_info(params)
175
+ "names_taken":
176
+ payload = RenameChecks.new(_log).names_taken(params)
177
+ "check_scripts":
178
+ payload = RenameChecks.new(_log).check_scripts(params)
174
179
 
175
180
  # Plugins and input
176
181
  "list_plugins":
@@ -0,0 +1,80 @@
1
+ extends RefCounted
2
+
3
+ const GdscriptAuthoring = preload("gdscript_authoring.gd")
4
+ const Log = preload("logger.gd")
5
+
6
+ var _log: Log
7
+
8
+
9
+ func _init(p_log: Log) -> void:
10
+ _log = p_log
11
+
12
+
13
+ # What each of the names asked about already is to the engine, and which class in the native
14
+ # chain from the base asked about declares it. A file cannot answer either: the native classes, the
15
+ # built-in types and the singletons are compiled into the engine, and a rename onto one of them is
16
+ # a script that no longer compiles, or one that quietly overrides an engine method.
17
+ func names_taken(params: Dictionary) -> Dictionary:
18
+ var names: Array = params.get("names", [])
19
+ var base: String = str(params.get("base", ""))
20
+ var built_in_types: Array[String] = []
21
+ for type: int in range(TYPE_MAX):
22
+ built_in_types.append(type_string(type))
23
+ var singletons: PackedStringArray = Engine.get_singleton_list()
24
+ var taken: Dictionary = {}
25
+ for value: Variant in names:
26
+ var name: String = str(value)
27
+ var as_what: Array[String] = []
28
+ if ClassDB.class_exists(name):
29
+ as_what.append("a native class")
30
+ if name in built_in_types:
31
+ as_what.append("a built-in type")
32
+ if singletons.has(name):
33
+ as_what.append("an engine singleton")
34
+ var entry: Dictionary = {"as": as_what, "declaredBy": null}
35
+ var declared_by: String = _declared_in_chain(base, name)
36
+ if not declared_by.is_empty():
37
+ entry["declaredBy"] = declared_by
38
+ taken[name] = entry
39
+ return {"taken": taken}
40
+
41
+
42
+ # The native class from [param base] upwards that declares [param name] as a method, property,
43
+ # signal, constant or enum, or empty when none does. Methods are read off the method list rather
44
+ # than asked with class_has_method, which answers false for a virtual such as Node._ready: those
45
+ # are the names a script most often overrides and the engine calls by name.
46
+ func _declared_in_chain(base: String, name: String) -> String:
47
+ var current: String = base
48
+ while not current.is_empty() and ClassDB.class_exists(current):
49
+ if (
50
+ _named(ClassDB.class_get_method_list(current, true), name)
51
+ or ClassDB.class_has_enum(current, name, true)
52
+ or _named(ClassDB.class_get_property_list(current, true), name)
53
+ or _named(ClassDB.class_get_signal_list(current, true), name)
54
+ or ClassDB.class_get_integer_constant_list(current, true).has(name)
55
+ ):
56
+ return current
57
+ current = str(ClassDB.get_parent_class(current))
58
+ return ""
59
+
60
+
61
+ static func _named(entries: Array[Dictionary], name: String) -> bool:
62
+ for entry: Dictionary in entries:
63
+ if str(entry.get("name", "")) == name:
64
+ return true
65
+ return false
66
+
67
+
68
+ # Whether each script compiles in a fresh engine, which reads the class cache as it starts and so
69
+ # resolves every class the cache lists. The engine's reasons go to stderr and come back with the
70
+ # answer.
71
+ func check_scripts(params: Dictionary) -> Dictionary:
72
+ var paths: Array = params.get("paths", [])
73
+ var failed: Array[String] = []
74
+ for value: Variant in paths:
75
+ var path: String = str(value)
76
+ var script: Script = ResourceLoader.load(path, "Script", ResourceLoader.CACHE_MODE_IGNORE)
77
+ if not GdscriptAuthoring._parses(script):
78
+ _log.error("Does not compile: " + path)
79
+ failed.append(path)
80
+ return {"checked": paths.size(), "failed": failed}