Skip to content

Commit 37122e1

Browse files
authored
Fix issues with circuit panel not refreshing properly (#1322)
Fixes issue where the Circuit panel will continue to display the previous circuit, even after it's been updated with a new circuit that fails to render. Repro: 1. Generate circuit for a valid program, e.g. Entanglement.qs 2. Now generate circuit for a program that doesn't allocate any qubits, e.g. Array.qs ![image](https://github.com/microsoft/qsharp/assets/16928427/299f68b1-d10d-4c4a-89cc-3486ed891eb1) Also a small fix where we force the circuit panel to come to the foreground when invoked through the code lens or at the beginning of a debugging session.
1 parent 038a613 commit 37122e1

File tree

3 files changed

+42
-21
lines changed

3 files changed

+42
-21
lines changed

npm/ux/circuit.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const MAX_QUBITS = 1000;
1313

1414
/* This component is shared by the Python widget and the VS Code panel */
1515
export function Circuit(props: { circuit: qviz.Circuit }) {
16+
const circuitDiv = useRef<HTMLDivElement>(null);
17+
1618
const errorDiv =
1719
props.circuit.qubits.length === 0 ? (
1820
<div>
@@ -42,13 +44,12 @@ export function Circuit(props: { circuit: qviz.Circuit }) {
4244
</div>
4345
) : undefined;
4446

45-
if (errorDiv) {
46-
return <div class=".qs-circuit-error">{errorDiv}</div>;
47-
}
48-
49-
const circuitDiv = useRef<HTMLDivElement>(null);
50-
5147
useEffect(() => {
48+
if (errorDiv !== undefined) {
49+
circuitDiv.current!.innerHTML = "";
50+
return;
51+
}
52+
5253
qviz.draw(props.circuit, circuitDiv.current!);
5354

5455
// quantum-viz hardcodes the styles in the SVG.
@@ -57,7 +58,12 @@ export function Circuit(props: { circuit: qviz.Circuit }) {
5758
styleElements?.forEach((tag) => tag.remove());
5859
}, [props.circuit]);
5960

60-
return <div class="qs-circuit" ref={circuitDiv}></div>;
61+
return (
62+
<div>
63+
<div class="qs-circuit-error">{errorDiv}</div>
64+
<div class="qs-circuit" ref={circuitDiv}></div>
65+
</div>
66+
);
6167
}
6268

6369
/* This component is exclusive to the VS Code panel */

vscode/src/circuit.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export async function showCircuitCommand(
6565
targetProfile,
6666
editor.document.uri.path,
6767
circuit,
68+
true, // reveal
6869
operation,
6970
);
7071

@@ -95,6 +96,7 @@ export async function showCircuitCommand(
9596
targetProfile,
9697
editor.document.uri.path,
9798
errorHtml,
99+
false, // reveal
98100
operation,
99101
);
100102
} finally {
@@ -107,6 +109,7 @@ export function updateCircuitPanel(
107109
targetProfile: string,
108110
docPath: string,
109111
circuitOrErrorHtml: CircuitData | string,
112+
reveal: boolean,
110113
operation?: IOperationInfo | undefined,
111114
) {
112115
let title;
@@ -128,7 +131,7 @@ export function updateCircuitPanel(
128131
errorHtml:
129132
typeof circuitOrErrorHtml === "string" ? circuitOrErrorHtml : undefined,
130133
};
131-
sendMessageToPanel("circuit", false, message);
134+
sendMessageToPanel("circuit", reveal, message);
132135
}
133136

134137
/**

vscode/src/debugger/session.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export class QscDebugSession extends LoggingDebugSession {
7272
private eventTarget: QscEventTarget;
7373
private supportsVariableType = false;
7474
private targetProfile = getTarget();
75+
private revealedCircuit = false;
7576

7677
public constructor(
7778
private debugService: IDebugServiceWorker,
@@ -315,12 +316,7 @@ export class QscDebugSession extends LoggingDebugSession {
315316
}
316317

317318
if (this.config.showCircuit) {
318-
const circuit = await this.debugService.getCircuit();
319-
updateCircuitPanel(
320-
this.targetProfile,
321-
vscode.Uri.parse(this.sources[0][0]).path,
322-
circuit,
323-
);
319+
await this.showCircuit();
324320
}
325321

326322
if (!result) {
@@ -816,19 +812,21 @@ export class QscDebugSession extends LoggingDebugSession {
816812
// This will get invoked when the "Quantum Circuit" scope is expanded
817813
// in the Variables view, but instead of showing any values in the variables
818814
// view, we can pop open the circuit diagram panel.
819-
const circuit = await this.debugService.getCircuit();
820-
updateCircuitPanel(
821-
this.targetProfile,
822-
vscode.Uri.parse(this.sources[0][0]).path,
823-
circuit,
824-
);
815+
this.showCircuit();
816+
825817
// Keep updating the circuit for the rest of this session, even if
826818
// the Variables scope gets collapsed by the user. If we don't do this,
827819
// the diagram won't get updated with each step even though the circuit
828820
// panel is still being shown, which is misleading.
829821
this.config.showCircuit = true;
830822
response.body = {
831-
variables: [],
823+
variables: [
824+
{
825+
name: "Circuit",
826+
value: "See Q# Circuit panel",
827+
variablesReference: 0,
828+
},
829+
],
832830
};
833831
}
834832
break;
@@ -928,4 +926,18 @@ export class QscDebugSession extends LoggingDebugSession {
928926
log.trace(`Could not resolve path ${pathOrUri}`);
929927
}
930928
}
929+
930+
private async showCircuit() {
931+
const circuit = await this.debugService.getCircuit();
932+
updateCircuitPanel(
933+
this.targetProfile,
934+
vscode.Uri.parse(this.sources[0][0]).path,
935+
circuit,
936+
!this.revealedCircuit,
937+
);
938+
939+
// Only reveal the panel once per session, to keep it from
940+
// moving around while stepping
941+
this.revealedCircuit = true;
942+
}
931943
}

0 commit comments

Comments
 (0)