fix(ghidra): keep the NativeAOT target refusal's own recovery advice
An unsupported-target error always projected the generic "select a target" remediation, which hid the adapter's available workflows (omit REA_GHIDRA_NATIVEAOT_JAR for ordinary analysis, or use inspect_managed_artifact). AnalysisUnsupportedTargetError accepts a refusal-specific remediation, as AnalysisResourceConstraintError does, and the NativeAOT refusal supplies its reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
42c276af1e
commit
f198993f41
@@ -7,13 +7,16 @@ import {
|
||||
/** A readable supplied artifact lies outside this operation's supported target formats. */
|
||||
export class AnalysisUnsupportedTargetError extends AnalysisError {
|
||||
readonly _tag = "AnalysisUnsupportedTargetError";
|
||||
/** Refusal-specific recovery, when the producer knows an available workflow. */
|
||||
readonly remediationAction: string | undefined;
|
||||
constructor(
|
||||
readonly operation: string,
|
||||
readonly path: string,
|
||||
readonly reason: string,
|
||||
options?: AnalysisErrorOptions,
|
||||
options?: AnalysisErrorOptions & { readonly remediationAction?: string },
|
||||
) {
|
||||
super(`Unsupported target for ${operation} at ${path}: ${reason}`, options);
|
||||
this.remediationAction = options?.remediationAction;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,10 @@ export const analysisErrorRemediationAction = (
|
||||
if (error instanceof AnalysisSnapshotMismatchError)
|
||||
return "Run analysis without this snapshot, then save a fresh snapshot using the intended artifact, provider, and analysis profile.";
|
||||
if (error instanceof AnalysisUnsupportedTargetError)
|
||||
return "Select a target supported by this operation or choose an operation supporting the reported target format.";
|
||||
return (
|
||||
error.remediationAction ??
|
||||
"Select a target supported by this operation or choose an operation supporting the reported target format."
|
||||
);
|
||||
if (error instanceof AnalysisResourceConstraintError)
|
||||
return (
|
||||
error.remediationAction ??
|
||||
|
||||
@@ -106,6 +106,9 @@ describe("optional Ghidra extension refusals", () => {
|
||||
if (!architecture.ok)
|
||||
expect(projectAnalysisError(architecture.error)).toMatchObject({
|
||||
code: "unsupported_target",
|
||||
remediation: {
|
||||
action: expect.stringContaining("omit REA_GHIDRA_NATIVEAOT_JAR"),
|
||||
},
|
||||
details: {
|
||||
operation: "resolve_analysis_profile",
|
||||
path: target.path,
|
||||
@@ -312,9 +315,11 @@ describe("Ghidra extension profile and producer validation", () => {
|
||||
);
|
||||
expect(resolved.ok).toBe(false);
|
||||
if (!resolved.ok)
|
||||
expect(resolved.error).toMatchObject({
|
||||
_tag: "AnalysisUnsupportedTargetError",
|
||||
reason: expect.stringContaining("inspect_managed_artifact"),
|
||||
expect(projectAnalysisError(resolved.error)).toMatchObject({
|
||||
code: "unsupported_target",
|
||||
remediation: {
|
||||
action: expect.stringContaining("inspect_managed_artifact"),
|
||||
},
|
||||
});
|
||||
});
|
||||
it("does not substitute another artifact under an unchanged configured path", async () => {
|
||||
|
||||
@@ -198,6 +198,8 @@ const extensionRefusalError = (
|
||||
"resolve_analysis_profile",
|
||||
target.path,
|
||||
refusal.reason,
|
||||
// The reason names the workflows that remain available.
|
||||
{ remediationAction: refusal.reason },
|
||||
);
|
||||
|
||||
/** Snapshot committed extension bytes into the private runtime before Java loads them. */
|
||||
|
||||
Reference in New Issue
Block a user