gdharness 1.1.16 → 1.1.17
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
|
@@ -8706,6 +8706,18 @@ function classRemedy(entries) {
|
|
|
8706
8706
|
const reload = declaring.length === 1 ? `editor_rescan with reloadScript set to ${declaring[0]}` : `editor_rescan with reloadScript, a call each for ${declaring.join(" and ")} since it takes one script,`;
|
|
8707
8707
|
return `For ${entries.map(written).join(", ")}, run ${reload} first. In the one project that has ` + "reproduced a stale enum member, twice, the reload cleared it at once both times, and the one " + "plain editor_rescan tried left the diagnostic standing.";
|
|
8708
8708
|
}
|
|
8709
|
+
function failedReloadNote(failed) {
|
|
8710
|
+
const missing = (before, after) => before.filter((name) => !after.includes(name));
|
|
8711
|
+
const lost = [
|
|
8712
|
+
...missing(failed.heldBefore, failed.heldAfter),
|
|
8713
|
+
...missing(failed.constantsBefore, failed.constantsAfter)
|
|
8714
|
+
];
|
|
8715
|
+
const unchanged = lost.length === 0 && missing(failed.heldAfter, failed.heldBefore).length === 0 && missing(failed.constantsAfter, failed.constantsBefore).length === 0;
|
|
8716
|
+
const answered = failed.codeName === "" ? `error ${failed.code}` : `error ${failed.code}, ${failed.codeName}`;
|
|
8717
|
+
const copy = unchanged ? "The copy the editor holds is as it was, with the members under heldBeforeReload and heldConstantsBeforeReload." : `The copy the editor holds changed even so${lost.length === 0 ? "" : `, and has lost ${lost.join(", ")}`}: anything diagnosed against it now is answered from what is left, and reloading it once it compiles rebuilds it.`;
|
|
8718
|
+
const order = failed.names.length === 0 ? "" : ` If they deny a member of ${failed.names.join(" or ")} that its file declares, the editor's copy of that class is behind: reload that class first with reloadScript and then this script, the order that cleared it in the one project that has met this.`;
|
|
8719
|
+
return `${failed.script} did not compile, so nothing was reloaded: Godot answered ${answered}. ${copy} ` + `script_diagnostics on it gives the errors.${order}`;
|
|
8720
|
+
}
|
|
8709
8721
|
function uncachedClassNote(types) {
|
|
8710
8722
|
if (types.length === 0) {
|
|
8711
8723
|
return "";
|
|
@@ -17341,7 +17353,7 @@ var init_tool_definitions = __esm(() => {
|
|
|
17341
17353
|
},
|
|
17342
17354
|
reloadScript: {
|
|
17343
17355
|
type: "string",
|
|
17344
|
-
description: "A script to recompile in the editor after the scan, for the half a scan does not reach: a script the editor has loaded keeps the copy it built, that copy is refreshed when one of its dependencies changes rather than when it changes itself, and a scan leaves it alone. Measured here, a built copy comes back without a method added to it while script_diagnostics on the same script reads clean in the same window, so the copy the editor built and whatever the analyser resolves types against are not known to be one thing: reload for the copy, and read the diagnostics as a separate answer rather than as this one confirmed. This recompiles into the same object, so the holders that kept the stale copy alive see the new one. The methods it has afterwards come back under reloadedMethods, because a reload that compiled nothing and answered OK is the failure worth catching, and what it held before under heldBeforeReload. Its constants come back the same way, under heldConstantsBeforeReload and reloadedConstants, with each enum value as Kind.SHORT: an enum member is held as a constant and never shows among the methods."
|
|
17356
|
+
description: "A script to recompile in the editor after the scan, for the half a scan does not reach: a script the editor has loaded keeps the copy it built, that copy is refreshed when one of its dependencies changes rather than when it changes itself, and a scan leaves it alone. Measured here, a built copy comes back without a method added to it while script_diagnostics on the same script reads clean in the same window, so the copy the editor built and whatever the analyser resolves types against are not known to be one thing: reload for the copy, and read the diagnostics as a separate answer rather than as this one confirmed. This recompiles into the same object, so the holders that kept the stale copy alive see the new one. The methods it has afterwards come back under reloadedMethods, because a reload that compiled nothing and answered OK is the failure worth catching, and what it held before under heldBeforeReload. Its constants come back the same way, under heldConstantsBeforeReload and reloadedConstants, with each enum value as Kind.SHORT: an enum member is held as a constant and never shows among the methods. A script that does not compile is not reloaded: reloadProblem gives Godot's error, says whether the copy the editor holds survived, and names the classes the file uses, whose held copies being behind is what failed one before."
|
|
17345
17357
|
}
|
|
17346
17358
|
},
|
|
17347
17359
|
requires: ["projectPath"]
|
|
@@ -41297,6 +41309,11 @@ class GodotServer {
|
|
|
41297
41309
|
shortListEditorPid: this.godotBridge.getStatus().editorPid ?? null
|
|
41298
41310
|
});
|
|
41299
41311
|
}
|
|
41312
|
+
classesAScriptNames(projectPath, scriptPath) {
|
|
41313
|
+
const source = this.sourceOfClass(projectPath, scriptPath);
|
|
41314
|
+
const known = cachedClasses(projectPath) ?? declaredClasses(projectPath);
|
|
41315
|
+
return source === null ? [] : classesNamedIn(source, known).filter((name) => known.get(name) !== scriptPath);
|
|
41316
|
+
}
|
|
41300
41317
|
sourceOfClass(projectPath, resourcePath) {
|
|
41301
41318
|
const contained = resolveWithinProject(projectPath, resourcePath);
|
|
41302
41319
|
if (!contained.ok || !existsSync15(contained.absolutePath)) {
|
|
@@ -43027,12 +43044,30 @@ class GodotServer {
|
|
|
43027
43044
|
const found = readArray(answer, field);
|
|
43028
43045
|
return found ? { [field]: found.map(String) } : {};
|
|
43029
43046
|
};
|
|
43030
|
-
|
|
43031
|
-
|
|
43032
|
-
|
|
43033
|
-
|
|
43034
|
-
|
|
43035
|
-
|
|
43047
|
+
const failed = answer["failed"];
|
|
43048
|
+
if (typeof failed === "number" && failed !== 0) {
|
|
43049
|
+
reloaded = {
|
|
43050
|
+
...listed("heldBefore"),
|
|
43051
|
+
...listed("heldConstantsBefore"),
|
|
43052
|
+
problem: failedReloadNote({
|
|
43053
|
+
script: reloading,
|
|
43054
|
+
code: failed,
|
|
43055
|
+
codeName: readString(answer, "failedAs") ?? "",
|
|
43056
|
+
heldBefore: listed("heldBefore")["heldBefore"] ?? [],
|
|
43057
|
+
heldAfter: methods?.map(String) ?? [],
|
|
43058
|
+
constantsBefore: listed("heldConstantsBefore")["heldConstantsBefore"] ?? [],
|
|
43059
|
+
constantsAfter: listed("constants")["constants"] ?? [],
|
|
43060
|
+
names: projectPath === "" ? [] : this.classesAScriptNames(projectPath, reloading)
|
|
43061
|
+
})
|
|
43062
|
+
};
|
|
43063
|
+
} else {
|
|
43064
|
+
reloaded = methods ? {
|
|
43065
|
+
methods: methods.map(String),
|
|
43066
|
+
...listed("heldBefore"),
|
|
43067
|
+
...listed("constants"),
|
|
43068
|
+
...listed("heldConstantsBefore")
|
|
43069
|
+
} : { problem: `the editor would not say what ${reloading} has after reloading it` };
|
|
43070
|
+
}
|
|
43036
43071
|
} catch (error) {
|
|
43037
43072
|
reloaded = { problem: `${reloading} could not be reloaded: ${errorMessage(error)}` };
|
|
43038
43073
|
}
|
|
@@ -43095,7 +43130,13 @@ class GodotServer {
|
|
|
43095
43130
|
}
|
|
43096
43131
|
try {
|
|
43097
43132
|
const answer = asParams(await this.godotBridge.invokeTool("reload_script", { scriptPath }));
|
|
43098
|
-
|
|
43133
|
+
const failed = answer["failed"];
|
|
43134
|
+
if (typeof failed === "number" && failed !== 0) {
|
|
43135
|
+
notReloaded.push({
|
|
43136
|
+
scriptPath,
|
|
43137
|
+
problem: `it did not compile: Godot answered error ${failed}${readString(answer, "failedAs") ? `, ${readString(answer, "failedAs")}` : ""}`
|
|
43138
|
+
});
|
|
43139
|
+
} else if (readArray(answer, "methods") === undefined) {
|
|
43099
43140
|
notReloaded.push({
|
|
43100
43141
|
scriptPath,
|
|
43101
43142
|
problem: "the editor would not say what it has after reloading it"
|
|
@@ -74,16 +74,22 @@ func reload_script(args: Dictionary) -> Dictionary:
|
|
|
74
74
|
var reader: FileAccess = FileAccess.open(path, FileAccess.READ)
|
|
75
75
|
if reader == null:
|
|
76
76
|
return {"ok": false, "error": "Could not read " + path + ": " + str(FileAccess.get_open_error())}
|
|
77
|
+
var previous: String = script.source_code
|
|
77
78
|
script.source_code = reader.get_as_text()
|
|
78
79
|
reader.close()
|
|
79
80
|
|
|
81
|
+
# A reload that fails is still answered as a call that ran, because the readings are what a
|
|
82
|
+
# caller needs then: a failure travels back as its message alone, and a project met one and
|
|
83
|
+
# could not tell whether the copy had been damaged by it or before it. The old text goes back
|
|
84
|
+
# into the object, so what it holds and the source it says it was built from still agree.
|
|
80
85
|
var failed: Error = script.reload(true)
|
|
81
86
|
if failed != OK:
|
|
82
|
-
|
|
83
|
-
|
|
87
|
+
script.source_code = previous
|
|
84
88
|
return {
|
|
85
89
|
"ok": true,
|
|
86
90
|
"script": path,
|
|
91
|
+
"failed": failed,
|
|
92
|
+
"failedAs": error_string(failed) if failed != OK else "",
|
|
87
93
|
"heldBefore": held,
|
|
88
94
|
"methods": _method_names(script),
|
|
89
95
|
"heldConstantsBefore": held_constants,
|
package/build/index.js
CHANGED
|
@@ -26276,6 +26276,18 @@ function classRemedy(entries) {
|
|
|
26276
26276
|
const reload = declaring.length === 1 ? `editor_rescan with reloadScript set to ${declaring[0]}` : `editor_rescan with reloadScript, a call each for ${declaring.join(" and ")} since it takes one script,`;
|
|
26277
26277
|
return `For ${entries.map(written).join(", ")}, run ${reload} first. In the one project that has ` + "reproduced a stale enum member, twice, the reload cleared it at once both times, and the one " + "plain editor_rescan tried left the diagnostic standing.";
|
|
26278
26278
|
}
|
|
26279
|
+
function failedReloadNote(failed) {
|
|
26280
|
+
const missing = (before, after) => before.filter((name) => !after.includes(name));
|
|
26281
|
+
const lost = [
|
|
26282
|
+
...missing(failed.heldBefore, failed.heldAfter),
|
|
26283
|
+
...missing(failed.constantsBefore, failed.constantsAfter)
|
|
26284
|
+
];
|
|
26285
|
+
const unchanged = lost.length === 0 && missing(failed.heldAfter, failed.heldBefore).length === 0 && missing(failed.constantsAfter, failed.constantsBefore).length === 0;
|
|
26286
|
+
const answered = failed.codeName === "" ? `error ${failed.code}` : `error ${failed.code}, ${failed.codeName}`;
|
|
26287
|
+
const copy = unchanged ? "The copy the editor holds is as it was, with the members under heldBeforeReload and heldConstantsBeforeReload." : `The copy the editor holds changed even so${lost.length === 0 ? "" : `, and has lost ${lost.join(", ")}`}: anything diagnosed against it now is answered from what is left, and reloading it once it compiles rebuilds it.`;
|
|
26288
|
+
const order = failed.names.length === 0 ? "" : ` If they deny a member of ${failed.names.join(" or ")} that its file declares, the editor's copy of that class is behind: reload that class first with reloadScript and then this script, the order that cleared it in the one project that has met this.`;
|
|
26289
|
+
return `${failed.script} did not compile, so nothing was reloaded: Godot answered ${answered}. ${copy} ` + `script_diagnostics on it gives the errors.${order}`;
|
|
26290
|
+
}
|
|
26279
26291
|
function uncachedClassNote(types) {
|
|
26280
26292
|
if (types.length === 0) {
|
|
26281
26293
|
return "";
|
|
@@ -30998,7 +31010,7 @@ var TOOL_SPECS = [
|
|
|
30998
31010
|
},
|
|
30999
31011
|
reloadScript: {
|
|
31000
31012
|
type: "string",
|
|
31001
|
-
description: "A script to recompile in the editor after the scan, for the half a scan does not reach: a script the editor has loaded keeps the copy it built, that copy is refreshed when one of its dependencies changes rather than when it changes itself, and a scan leaves it alone. Measured here, a built copy comes back without a method added to it while script_diagnostics on the same script reads clean in the same window, so the copy the editor built and whatever the analyser resolves types against are not known to be one thing: reload for the copy, and read the diagnostics as a separate answer rather than as this one confirmed. This recompiles into the same object, so the holders that kept the stale copy alive see the new one. The methods it has afterwards come back under reloadedMethods, because a reload that compiled nothing and answered OK is the failure worth catching, and what it held before under heldBeforeReload. Its constants come back the same way, under heldConstantsBeforeReload and reloadedConstants, with each enum value as Kind.SHORT: an enum member is held as a constant and never shows among the methods."
|
|
31013
|
+
description: "A script to recompile in the editor after the scan, for the half a scan does not reach: a script the editor has loaded keeps the copy it built, that copy is refreshed when one of its dependencies changes rather than when it changes itself, and a scan leaves it alone. Measured here, a built copy comes back without a method added to it while script_diagnostics on the same script reads clean in the same window, so the copy the editor built and whatever the analyser resolves types against are not known to be one thing: reload for the copy, and read the diagnostics as a separate answer rather than as this one confirmed. This recompiles into the same object, so the holders that kept the stale copy alive see the new one. The methods it has afterwards come back under reloadedMethods, because a reload that compiled nothing and answered OK is the failure worth catching, and what it held before under heldBeforeReload. Its constants come back the same way, under heldConstantsBeforeReload and reloadedConstants, with each enum value as Kind.SHORT: an enum member is held as a constant and never shows among the methods. A script that does not compile is not reloaded: reloadProblem gives Godot's error, says whether the copy the editor holds survived, and names the classes the file uses, whose held copies being behind is what failed one before."
|
|
31002
31014
|
}
|
|
31003
31015
|
},
|
|
31004
31016
|
requires: ["projectPath"]
|
|
@@ -33757,6 +33769,11 @@ class GodotServer {
|
|
|
33757
33769
|
shortListEditorPid: this.godotBridge.getStatus().editorPid ?? null
|
|
33758
33770
|
});
|
|
33759
33771
|
}
|
|
33772
|
+
classesAScriptNames(projectPath, scriptPath) {
|
|
33773
|
+
const source = this.sourceOfClass(projectPath, scriptPath);
|
|
33774
|
+
const known = cachedClasses(projectPath) ?? declaredClasses(projectPath);
|
|
33775
|
+
return source === null ? [] : classesNamedIn(source, known).filter((name) => known.get(name) !== scriptPath);
|
|
33776
|
+
}
|
|
33760
33777
|
sourceOfClass(projectPath, resourcePath) {
|
|
33761
33778
|
const contained = resolveWithinProject(projectPath, resourcePath);
|
|
33762
33779
|
if (!contained.ok || !existsSync12(contained.absolutePath)) {
|
|
@@ -35487,12 +35504,30 @@ class GodotServer {
|
|
|
35487
35504
|
const found = readArray(answer, field);
|
|
35488
35505
|
return found ? { [field]: found.map(String) } : {};
|
|
35489
35506
|
};
|
|
35490
|
-
|
|
35491
|
-
|
|
35492
|
-
|
|
35493
|
-
|
|
35494
|
-
|
|
35495
|
-
|
|
35507
|
+
const failed = answer["failed"];
|
|
35508
|
+
if (typeof failed === "number" && failed !== 0) {
|
|
35509
|
+
reloaded = {
|
|
35510
|
+
...listed("heldBefore"),
|
|
35511
|
+
...listed("heldConstantsBefore"),
|
|
35512
|
+
problem: failedReloadNote({
|
|
35513
|
+
script: reloading,
|
|
35514
|
+
code: failed,
|
|
35515
|
+
codeName: readString(answer, "failedAs") ?? "",
|
|
35516
|
+
heldBefore: listed("heldBefore")["heldBefore"] ?? [],
|
|
35517
|
+
heldAfter: methods?.map(String) ?? [],
|
|
35518
|
+
constantsBefore: listed("heldConstantsBefore")["heldConstantsBefore"] ?? [],
|
|
35519
|
+
constantsAfter: listed("constants")["constants"] ?? [],
|
|
35520
|
+
names: projectPath === "" ? [] : this.classesAScriptNames(projectPath, reloading)
|
|
35521
|
+
})
|
|
35522
|
+
};
|
|
35523
|
+
} else {
|
|
35524
|
+
reloaded = methods ? {
|
|
35525
|
+
methods: methods.map(String),
|
|
35526
|
+
...listed("heldBefore"),
|
|
35527
|
+
...listed("constants"),
|
|
35528
|
+
...listed("heldConstantsBefore")
|
|
35529
|
+
} : { problem: `the editor would not say what ${reloading} has after reloading it` };
|
|
35530
|
+
}
|
|
35496
35531
|
} catch (error) {
|
|
35497
35532
|
reloaded = { problem: `${reloading} could not be reloaded: ${errorMessage(error)}` };
|
|
35498
35533
|
}
|
|
@@ -35555,7 +35590,13 @@ class GodotServer {
|
|
|
35555
35590
|
}
|
|
35556
35591
|
try {
|
|
35557
35592
|
const answer = asParams(await this.godotBridge.invokeTool("reload_script", { scriptPath }));
|
|
35558
|
-
|
|
35593
|
+
const failed = answer["failed"];
|
|
35594
|
+
if (typeof failed === "number" && failed !== 0) {
|
|
35595
|
+
notReloaded.push({
|
|
35596
|
+
scriptPath,
|
|
35597
|
+
problem: `it did not compile: Godot answered error ${failed}${readString(answer, "failedAs") ? `, ${readString(answer, "failedAs")}` : ""}`
|
|
35598
|
+
});
|
|
35599
|
+
} else if (readArray(answer, "methods") === undefined) {
|
|
35559
35600
|
notReloaded.push({
|
|
35560
35601
|
scriptPath,
|
|
35561
35602
|
problem: "the editor would not say what it has after reloading it"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gdharness",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.17",
|
|
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",
|