Compute visualizer graph layout in the language server (MSAGL)#19884
Merged
Conversation
Phase 5 of the visualizer MSAGL layout migration: compute graph layout in the Bicep language server instead of the webview. - Add Msagl to central package management and reference it from Bicep.LangServer. - Introduce IVisualGraphLayoutEngine / MsaglVisualGraphLayoutEngine running a layered (Sugiyama) top-to-bottom layout via LayoutHelpers.CalculateLayout, with straight-line routing and y-flipped, origin-normalized positions. - Lay out nested module scopes independently and compose them into parent module boxes (MSAGL clusters proved unreliable at runtime). - Keep shared defaults in VisualGraphLayoutOptions.Default so future callers (e.g. CLI image generation) do not duplicate React constants. - Register the engine in DI and add engine + differ unit tests, including a performance smoke test. - Update the migration plan (Phase 5).
Phase 6 of the visualizer MSAGL layout migration: split the protocol into a topology/metadata update and a measured layout request, then apply the server's MSAGL positions in the React webview behind the bicep.visualizer.serverLayout.enabled flag. - Add textDocument/visualGraphLayout (and the getGraphUpdate/getGraphLayout webview bridge); the graph update is now topology/metadata only, and the layout request carries client-measured node sizes. - Apply server positions in the webview and gate the legacy ELK auto-layout behind serverLayoutActiveAtom; route Reset Layout through the single in-flight slot so it cannot race a document-change update. - Derive layout invalidation by comparing updateNode field values (not presence) so range-only edits never reflow; centralize the rule in layout-invalidation.ts next to the rendered-graph equality check. - Spring nodes to their server positions via motion and fit the viewport to the same bounds as Fit View, so re-layout, additions, and removals animate and the two controls agree to the pixel; round measured node sizes to integers so module boxes stay stable and re-layout is idempotent. - Add Vitest to the visual-designer app with layout-invalidation unit tests; add visual-graph-protocol.md and update the migration plan (Phase 6 + known follow-ups).
Resolves import-ordering conflicts in fake-message-channel.ts, use-graph-update.ts, and view.ts (both sides added overlapping visual-graph imports); reconciled via prettier import sort.
Contributor
|
Test this change out locally with the following install scripts (Action run 27788009723) VSCode
Azure CLI
|
majastrz
approved these changes
Jun 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Computes the Bicep visualizer's graph layout in the language server with MSAGL instead of in the webview with ELK, behind the off-by-default
bicep.visualizer.serverLayout.enabledflag. This covers Phase 5 (server-side layout engine, shadow mode) and Phase 6 (applying server layout in the webview) of the visualizer MSAGL layout migration. Default behavior is unchanged while the flag is off.The two commits map to the two phases:
IVisualGraphLayoutEngine/MsaglVisualGraphLayoutEnginerun a layered (Sugiyama) top-to-bottom layout. Nested module scopes are laid out independently and composed into parent boxes (MSAGL clusters proved unreliable at runtime). Shared defaults live inVisualGraphLayoutOptions.Default. Engine + differ unit tests included, with a performance smoke test.textDocument/visualGraphUpdate) and a measured layout request (textDocument/visualGraphLayout) that carries client-measured node sizes; applies server positions in the webview and gates the legacy ELK auto-layout behindserverLayoutActiveAtom.Notable details for reviewers:
updateNodefield values (not presence), so range-only edits (e.g. deleting a blank line) never reflow. The rule is centralized inlayout-invalidation.ts.src/vscode-bicep-ui/apps/visual-designer/visual-graph-protocol.md.Example Usage
Enable the flag and open the visualizer:
Then run Open Bicep Visualizer on a
.bicepfile with resources/modules. Editing the file animates incremental layout changes; the Reset Layout button re-runs the server layout. With the flag off (default), the existing ELK path is used and behavior is unchanged.Checklist
Microsoft Reviewers: Open in CodeFlow