gdharness 0.13.31 → 0.13.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.
package/build/cli.js
CHANGED
|
@@ -15593,7 +15593,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
15593
15593
|
direction: {
|
|
15594
15594
|
type: "string",
|
|
15595
15595
|
enum: ["forward", "reverse"],
|
|
15596
|
-
description: "forward: what this resource loads, with cycles reported. reverse: every file that refers to it and how, a scene instancing it, a script extending, preloading or loading it, and for a script with a class_name every use of that name. Default forward."
|
|
15596
|
+
description: "forward: what this resource loads, with cycles reported. reverse: every file that refers to it and how, a scene instancing it, a script extending, preloading or loading it, and for a script with a class_name every use of that name. Each reference carries a kind, and two of them are mentions rather than uses: doc is a name inside a ## documentation comment, which renaming would break in the generated docs, and comment is one in ordinary prose, which it would only make stale. summary.in_code is the count with both of those left out, which is the number to read when the question is whether anything still uses this. Default forward."
|
|
15597
15597
|
},
|
|
15598
15598
|
depth: { type: "number", description: "forward: how many levels to follow. Default unlimited." },
|
|
15599
15599
|
includeBuiltin: {
|
|
@@ -128,6 +128,7 @@ func find_resource_usages(params: Dictionary) -> Dictionary:
|
|
|
128
128
|
var usages: Array[Dictionary] = []
|
|
129
129
|
var by_kind: Dictionary = {}
|
|
130
130
|
var total: int = 0
|
|
131
|
+
var in_code: int = 0
|
|
131
132
|
|
|
132
133
|
for file_path: String in all_files:
|
|
133
134
|
if file_path == resource_path:
|
|
@@ -141,16 +142,32 @@ func find_resource_usages(params: Dictionary) -> Dictionary:
|
|
|
141
142
|
var references: Array[Dictionary] = []
|
|
142
143
|
for i: int in range(lines.size()):
|
|
143
144
|
var line: String = lines[i]
|
|
145
|
+
var by_its_path: bool = by_path.search(line) != null
|
|
146
|
+
var by_its_name: bool = not by_its_path and by_class != null and by_class.search(line) != null
|
|
147
|
+
if not by_its_path and not by_its_name:
|
|
148
|
+
continue
|
|
149
|
+
var trimmed: String = line.strip_edges()
|
|
144
150
|
var kind: String = ""
|
|
145
|
-
|
|
151
|
+
# A mention in a comment is not a use, and both were answered as one. The question a
|
|
152
|
+
# reverse walk is asked is whether anything still uses a class, and a project that
|
|
153
|
+
# documents itself names its collaborators in `##` links: four references to one class,
|
|
154
|
+
# three of them prose, all counted as code. The more carefully a project is documented
|
|
155
|
+
# the worse that ratio gets. `##` and `#` are kept apart because renaming the class
|
|
156
|
+
# breaks Godot's generated documentation and leaves the prose merely stale.
|
|
157
|
+
if trimmed.begins_with("##"):
|
|
158
|
+
kind = "doc"
|
|
159
|
+
elif trimmed.begins_with("#"):
|
|
160
|
+
kind = "comment"
|
|
161
|
+
elif by_its_path:
|
|
146
162
|
kind = _path_reference_kind(line)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
references.append({"line": i + 1, "kind": kind, "text": line.strip_edges()})
|
|
163
|
+
else:
|
|
164
|
+
kind = (
|
|
165
|
+
"extends" if Patterns.without_annotations(line).begins_with("extends ") else "class_name"
|
|
166
|
+
)
|
|
167
|
+
references.append({"line": i + 1, "kind": kind, "text": trimmed})
|
|
153
168
|
by_kind[kind] = Read.as_int(by_kind.get(kind, 0)) + 1
|
|
169
|
+
if kind != "doc" and kind != "comment":
|
|
170
|
+
in_code += 1
|
|
154
171
|
|
|
155
172
|
if not references.is_empty():
|
|
156
173
|
usages.append({"file": file_path, "references": references})
|
|
@@ -168,6 +185,9 @@ func find_resource_usages(params: Dictionary) -> Dictionary:
|
|
|
168
185
|
"files_searched": all_files.size(),
|
|
169
186
|
"files_with_usages": usages.size(),
|
|
170
187
|
"total": total,
|
|
188
|
+
# The arithmetic done here rather than left to the caller, because the caller who most
|
|
189
|
+
# needs it is the one asking whether a class is dead, and that caller reads one number.
|
|
190
|
+
"in_code": in_code,
|
|
171
191
|
"by_kind": by_kind,
|
|
172
192
|
},
|
|
173
193
|
}
|
|
@@ -80,6 +80,10 @@ func get_gdscript_info(params: Dictionary) -> Dictionary:
|
|
|
80
80
|
# Only a declaration, because an unbalanced line anywhere else is a file mid-edit and
|
|
81
81
|
# joining from one swallows the rest of it: a body holding `print(` with nothing closing it
|
|
82
82
|
# took every declaration below it, which is the state an agent is most likely to ask about.
|
|
83
|
+
# `header` rather than `stripped`: an annotation in front pushes the keyword off the start
|
|
84
|
+
# of the line, so asking the raw line whether it can wrap says no to every annotated
|
|
85
|
+
# declaration that does. Held by the combined case, which nothing else in the fixture
|
|
86
|
+
# reaches: the single-feature cases each carry one of these and never a second.
|
|
83
87
|
if _can_wrap(header):
|
|
84
88
|
while _bracket_depth(stripped) > 0 and i + 1 < lines.size():
|
|
85
89
|
i += 1
|
|
@@ -479,6 +483,12 @@ func _up_to(text: String, needle: String) -> String:
|
|
|
479
483
|
|
|
480
484
|
|
|
481
485
|
# The line with any trailing comment taken off, quote-aware so a `#` inside a string stays.
|
|
486
|
+
#
|
|
487
|
+
# The only one of these scanners that does not count brackets, on purpose: a `#` starts a comment
|
|
488
|
+
# wherever it is, and there is no depth at which it does not. Giving this one the depth its
|
|
489
|
+
# neighbours have puts the comment into the value of `var table := { # keyed by name`, because the
|
|
490
|
+
# brace opens before the `#` and closes on a later line. Held by a case, since the argument for the
|
|
491
|
+
# difference is not visible from the code and reads like an oversight beside its neighbours.
|
|
482
492
|
func _without_comment(line: String) -> String:
|
|
483
493
|
var quote: String = ""
|
|
484
494
|
for i: int in range(line.length()):
|
|
@@ -510,9 +520,9 @@ func _closing_paren(text: String, from: int) -> int:
|
|
|
510
520
|
if ch == '"' or ch == "'":
|
|
511
521
|
quote = ch
|
|
512
522
|
continue
|
|
513
|
-
if ch == "(":
|
|
523
|
+
if ch == "(" or ch == "[" or ch == "{":
|
|
514
524
|
depth += 1
|
|
515
|
-
elif ch == ")":
|
|
525
|
+
elif ch == ")" or ch == "]" or ch == "}":
|
|
516
526
|
depth -= 1
|
|
517
527
|
if depth == 0:
|
|
518
528
|
return i
|
|
@@ -16,6 +16,11 @@ extends RefCounted
|
|
|
16
16
|
# Kept, because the readers below call these per line of every script in a project and a fresh
|
|
17
17
|
# compile each time is the whole cost of the scan. The patterns are literals in this repository, so
|
|
18
18
|
# the set is bounded by the source rather than by anything a caller passes.
|
|
19
|
+
#
|
|
20
|
+
# Held by `test/support/gd/patterns_cache.gd`, with `is_same` rather than `==`: two RegEx built from
|
|
21
|
+
# one pattern match the same text and compare equal on everything else, so identity is the only
|
|
22
|
+
# question that separates a cache from a recompile. Without that case, taking the cache away would
|
|
23
|
+
# have broken no answer anywhere and failed nothing, which is the argued-and-unheld shape.
|
|
19
24
|
static var _compiled: Dictionary = {}
|
|
20
25
|
|
|
21
26
|
|
package/build/index.js
CHANGED
|
@@ -28675,7 +28675,7 @@ var TOOL_SPECS = [
|
|
|
28675
28675
|
direction: {
|
|
28676
28676
|
type: "string",
|
|
28677
28677
|
enum: ["forward", "reverse"],
|
|
28678
|
-
description: "forward: what this resource loads, with cycles reported. reverse: every file that refers to it and how, a scene instancing it, a script extending, preloading or loading it, and for a script with a class_name every use of that name. Default forward."
|
|
28678
|
+
description: "forward: what this resource loads, with cycles reported. reverse: every file that refers to it and how, a scene instancing it, a script extending, preloading or loading it, and for a script with a class_name every use of that name. Each reference carries a kind, and two of them are mentions rather than uses: doc is a name inside a ## documentation comment, which renaming would break in the generated docs, and comment is one in ordinary prose, which it would only make stale. summary.in_code is the count with both of those left out, which is the number to read when the question is whether anything still uses this. Default forward."
|
|
28679
28679
|
},
|
|
28680
28680
|
depth: { type: "number", description: "forward: how many levels to follow. Default unlimited." },
|
|
28681
28681
|
includeBuiltin: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.32",
|
|
4
4
|
"mcpName": "io.github.Aureliolo/gdharness",
|
|
5
5
|
"description": "A harness for driving a Godot 4 project from an agent: editor addons, a runtime bridge into the running game, an MCP server in front of them, and a CLI that installs and diagnoses the Godot side.",
|
|
6
6
|
"type": "module",
|