diff --git a/lib/components/primitive-components/Group/Group.ts b/lib/components/primitive-components/Group/Group.ts index 134e7632c..be5762ed7 100644 --- a/lib/components/primitive-components/Group/Group.ts +++ b/lib/components/primitive-components/Group/Group.ts @@ -396,6 +396,16 @@ export class Group = typeof groupProps> return traces.length > 0 } + _markAsyncAutoroutingFailedAsSettled() { + // A routing failure should not block later PCB phases like placement DRC. + // Treat the subcircuit as settled with no routed traces and re-run PCB + // trace/render-dependent phases to surface any non-routing errors. + this._asyncAutoroutingResult = { + output_pcb_traces: [], + } + this._markDirty("PcbTraceRender") + } + async _runEffectMakeHttpAutoroutingRequest() { const { db } = this.root! const debug = Debug("tscircuit:core:_runEffectMakeHttpAutoroutingRequest") @@ -540,6 +550,7 @@ export class Group = typeof groupProps> error_type: "pcb_autorouting_error", message: err.message, }) + this._markAsyncAutoroutingFailedAsSettled() throw err } @@ -706,6 +717,8 @@ export class Group = typeof groupProps> message: error instanceof Error ? error.message : String(error), }) + this._markAsyncAutoroutingFailedAsSettled() + this.root?.emit("autorouting:error", { subcircuit_id: this.subcircuit_id, componentDisplayName: this.getString(), diff --git a/tests/drc/__snapshots__/pcb-hole-overlap-with-autorouting-error-pcb.snap.svg b/tests/drc/__snapshots__/pcb-hole-overlap-with-autorouting-error-pcb.snap.svg new file mode 100644 index 000000000..c4f977be3 --- /dev/null +++ b/tests/drc/__snapshots__/pcb-hole-overlap-with-autorouting-error-pcb.snap.svg @@ -0,0 +1 @@ +C13R1R2pcb_smtpad C13.pin1 overlaps with pcb_hole [pcb_hole_0] \ No newline at end of file diff --git a/tests/drc/pcb-hole-overlap-with-autorouting-error.test.tsx b/tests/drc/pcb-hole-overlap-with-autorouting-error.test.tsx new file mode 100644 index 000000000..b4d7ab056 --- /dev/null +++ b/tests/drc/pcb-hole-overlap-with-autorouting-error.test.tsx @@ -0,0 +1,64 @@ +import { test, expect } from "bun:test" +import { createBasicAutorouter } from "../fixtures/createBasicAutorouter" +import { getTestFixture } from "../fixtures/get-test-fixture" + +test("design rule check detects pad and hole overlap even after autorouting error", async () => { + const { circuit } = getTestFixture() + + circuit.add( + { + throw new Error("boom") + }), + }} + > + + + + + + + , + ) + + await circuit.renderUntilSettled() + + const circuitJson = circuit.getCircuitJson() + + const autoroutingErrors = circuitJson.filter( + (el) => el.type === "pcb_autorouting_error", + ) + expect(autoroutingErrors).toHaveLength(1) + + await expect(circuit).toMatchPcbSnapshot(import.meta.path, { + shouldDrawErrors: true, + }) + + const insertedOverlapErrors = circuitJson.filter( + (el) => el.type === "pcb_footprint_overlap_error", + ) + + expect(insertedOverlapErrors).toHaveLength(1) +})