Skip to content

Sequence diagram: activation bars and control flow blocks#174

Merged
jongalloway merged 3 commits into
mainfrom
copilot/add-mermaid-sequence-diagram-support
Apr 17, 2026
Merged

Sequence diagram: activation bars and control flow blocks#174
jongalloway merged 3 commits into
mainfrom
copilot/add-mermaid-sequence-diagram-support

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 17, 2026

Adds support for Mermaid sequence diagram activation bars (activate/deactivate, +/- shorthand) and control flow blocks (loop, alt, par, critical, break).

Parser

  • activate X / deactivate X standalone directives
  • +/- activation shorthand on message targets: A->>+B: call activates B; B-->>-A: reply deactivates the source (B)
  • loop/alt/par/critical/break [label] open a CF block; else/and/option are consumed as section separators without closing; end closes the innermost block
  • Unified openBlocks stack replaces openRects — handles both rect bands and CF blocks
  • Unclosed activations at end of input are auto-closed at the last message index
sequenceDiagram
    A->>+B: Request
    loop retry
        B->>C: Validate
        C-->>B: Result
    end
    alt success
        B-->>-A: OK
    else failure
        B-->>A: Error
    end

Layout

  • LayoutSequenceActivationBars: places 8px-wide bars centered on participant lifelines; nesting level offsets bars to the right so stacked activations remain distinct
  • CF block layout reuses the same start/end index → Y-range logic as rect bands

Rendering

  • AppendActivationBars (new, called after AppendLifelines): renders narrow theme-colored <rect> elements on lifelines
  • AppendSequenceCfBlock (new): renders UML combined-fragment style — dashed border, light fill, solid keyword tab at top-left (e.g. loop [Retry up to 3 times])
  • Both group types are skipped in the main AppendGroup pass

Tests

  • 27 new unit tests: standalone activate/deactivate, nested activations, all 5 CF keywords, separator handling
  • 2 new E2E snapshot fixtures: mermaid-sequence-activation, mermaid-sequence-cf-blocks

- Parser: activate/deactivate (standalone and +/- shorthand on messages)
- Parser: loop/alt/par/critical/break CF blocks; else/and/option separators
- Parser: unified openBlocks stack for rect and CF blocks; auto-close unclosed activations
- Layout: position activation bars on lifelines with nesting level offsets
- Layout: position CF blocks as full-width bands (same logic as rect bands)
- Renderer: AppendActivationBars after lifelines; AppendSequenceCfBlock with dashed border + label tab
- Tests: 27 new unit tests covering all new parser features
- E2E: two new snapshot fixtures (activation, cf-blocks)

Agent-Logs-Url: https://github.com/jongalloway/DiagramForge/sessions/a7c2c7e5-637e-4b72-8a9c-2d2df2ed3f02

Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for Mermaid sequence diagram activation bars and control flow blocks Sequence diagram: activation bars and control flow blocks Apr 17, 2026
Copilot AI requested a review from jongalloway April 17, 2026 19:04
@jongalloway jongalloway marked this pull request as ready for review April 17, 2026 19:20
@jongalloway jongalloway requested a review from Copilot April 17, 2026 19:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Mermaid sequence-diagram support for activation bars and UML-style control-flow (combined-fragment) blocks, spanning parser → layout → SVG rendering, with new unit + snapshot tests.

Changes:

  • Parser: adds activate/deactivate, +/- shorthand handling, and CF blocks (loop/alt/par/critical/break + separators).
  • Layout: computes activation bar geometry and reuses index-range → Y-range logic for CF blocks.
  • Rendering: draws activation bars after lifelines and renders CF blocks as dashed bordered regions with a keyword tab.
Show a summary per file
File Description
src/DiagramForge/Parsers/Mermaid/MermaidSequenceParser.cs Parses activation directives/shorthand and CF blocks; unifies open block tracking.
src/DiagramForge/Layout/DefaultLayoutEngine.Sequence.cs Lays out activation bars and positions CF-block groups using message index ranges.
src/DiagramForge/Rendering/SvgStructureWriter.cs Renders CF blocks (combined fragments) and activation bars (dedicated pass).
src/DiagramForge/Rendering/SvgRenderer.cs Integrates activation bar rendering into the sequence render pipeline.
tests/DiagramForge.Tests/Parsers/Mermaid/MermaidSequenceParserTests.cs Adds unit coverage for activation and CF parsing behaviors.
tests/DiagramForge.E2ETests/Fixtures/mermaid-sequence-activation.* Adds snapshot fixture for activation bar rendering.
tests/DiagramForge.E2ETests/Fixtures/mermaid-sequence-cf-blocks.* Adds snapshot fixture for CF block rendering.

Copilot's findings

  • Files reviewed: 7/9 changed files
  • Comments generated: 3

Comment on lines 349 to 352
|| line.Equals("end", StringComparison.OrdinalIgnoreCase)
|| IsCfSeparator(line)
|| TryParseCfKeyword(line, out _, out _)
|| TryParseMessage(line, out _, out _, out _, out _, out _);
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsSequenceKeyword now treats control-flow separators/keywords (else/and/option, loop/alt/etc.) as hard sequence keywords. This can break multi-line note continuation: an indented note line beginning with e.g. and/else will stop being appended to the pending note, and then gets swallowed by the IsCfSeparator(line) branch—dropping user text. Consider excluding CF separators/keywords from the note-continuation keyword check (or only treating them as keywords when actually inside an open CF block).

Copilot uses AI. Check for mistakes.
Comment on lines +379 to +383
kind = label = null;

ReadOnlySpan<string> keywords = ["loop", "alt", "par", "critical", "break"];

foreach (var kw in keywords)
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TryParseCfKeyword builds the keywords span from a collection expression on each call. Since this runs once per input line (and is also invoked from IsSequenceKeyword), it can introduce avoidable allocations/overhead. Consider hoisting the keyword set to a static readonly field (or similar) and matching against it.

Copilot uses AI. Check for mistakes.
Comment on lines 172 to 176
@@ -168,14 +174,20 @@ private static void LayoutSequenceDiagram(

diagram.Metadata["sequence:canvasWidth"] = canvasWidth;

Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sequence canvasWidth is finalized and stored before CF groups are laid out, but CF rendering adds a keyword/label tab whose width is based on estimated text width. For long CF labels the tab can exceed canvasWidth, and because SvgRenderer uses sequence:canvasWidth as the final SVG width, the tab/text can be clipped at the right edge. Consider expanding canvasWidth during layout based on the maximum CF tab width (and updating group widths accordingly).

Copilot uses AI. Check for mistakes.
@jongalloway
Copy link
Copy Markdown
Owner

@copilot apply changes based on the comments in this thread

- Remove IsCfSeparator/TryParseCfKeyword from IsSequenceKeyword so CF words
  in multi-line note continuations are preserved (e.g. 'else', 'and', 'loop')
- Hoist CfKeywords array to a static readonly field to avoid per-call allocations
- Expand canvasWidth in layout when a CF block's keyword tab exceeds the
  current canvas width, preventing long labels from being clipped
- Add regression test for CF words in note continuation lines

Agent-Logs-Url: https://github.com/jongalloway/DiagramForge/sessions/0f3c8c0d-de52-4b1e-a99d-360569395469

Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 17, 2026

@copilot apply changes based on the comments in this thread

All three review points addressed in b3c22f7:

  1. Note continuation + CF keywords: Removed IsCfSeparator and TryParseCfKeyword from IsSequenceKeyword. Words like else, and, loop are common enough to appear in note text; only hard sequence keywords (participant, Note, rect, activate, end, etc.) interrupt continuation. Added a regression test (Parse_MultilineNote_CfWordsInContinuationArePreserved).

  2. TryParseCfKeyword allocations: Hoisted the keyword list to a static readonly string[] CfKeywords field.

  3. CF tab label clipping: canvasWidth is now finalized after the CF block layout pass. If any CF block's keyword tab would overflow the canvas right edge, canvasWidth is expanded and a back-fill pass updates all group widths to the final value before storing sequence:canvasWidth.

@jongalloway jongalloway merged commit c12f0cc into main Apr 17, 2026
5 checks passed
@jongalloway jongalloway deleted the copilot/add-mermaid-sequence-diagram-support branch April 17, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sequence diagram: activation bars and control flow blocks

3 participants