Skip to content

Commit 04246ac

Browse files
Label a named state set's diagram with its name
The verifier's messages now show a state of a named set as a value of its set, doorState(d) == closed. liquidjava-fsm 0.2.3 reads these specs and reports each diagram's stateSetName, which the server passes on and the State Machine view uses as the diagram's title, also when the class has a single state set, so the diagram can be matched with the message. A state set without a name keeps its states as the title. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 7292a64 commit 04246ac

5 files changed

Lines changed: 24 additions & 7 deletions

File tree

‎client/src/types/fsm.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export type LJStateMachine = {
55
className: string;
66
// index of the state set among the class's @StateSet annotations, in declaration order
77
stateSet?: number;
8+
// the name given to the state set, as the verifier's messages use it, e.g. phase(this) == open; null if it has none
9+
stateSetName?: string | null;
810
initialTransitions: { to: string; toCondition?: string | null; constructorSignature?: string | null }[];
911
// methods that put an object in an unknown state (a field, a parameter or a getter's result) into a state
1012
entryTransitions?: { to: string; label: string; toCondition?: string | null }[];

‎client/src/webview/views/fsm/fsm.spec.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,15 @@ describe('state machine view', () => {
325325
expect(document.querySelectorAll('#diagram-wrapper')).toHaveLength(1);
326326
});
327327

328+
it('labels a named state set with its name, even when it is the only one', () => {
329+
renderStateMachineView(document.body, [{ ...tiling, stateSetName: 'tiling' }, compression], ['tiling diagram', 'compression diagram'], 'TB', false);
330+
expect(Array.from(document.querySelectorAll('.diagram-state-set-title'), node => node.textContent))
331+
.toEqual(['tiling', 'startCompression \u00B7 compressionExplicit']);
332+
333+
renderStateMachineView(document.body, [{ ...tiling, stateSetName: 'tiling' }], [diagram], 'TB', false);
334+
expect(document.querySelector('.diagram-state-set-title')?.textContent).toBe('tiling');
335+
});
336+
328337
it('keeps a single state set without a state set label', () => {
329338
renderStateMachineView(document.body, [tiling], [diagram], 'TB', false);
330339

‎client/src/webview/views/fsm/fsm.ts‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function renderStateMachineViewHtml(sms: LJStateMachine[], diagrams: string[], o
6767
` : ''}
6868
<div class="diagram-viewport${focusOnError && errorFocuses.length > 0 ? ' diagram-focused' : ''}">
6969
<div id="diagram-wrapper" class="diagram-wrapper">
70-
${sms.length === 1
70+
${sms.length === 1 && !sms[0].stateSetName
7171
? `<pre class="mermaid">${diagrams[0]}</pre>`
7272
: sms.map((sm, i) => renderStateSetDiagram(sm, diagrams[i], focusOnError && errorFocuses.length > 0)).join('')}
7373
</div>
@@ -79,12 +79,14 @@ function renderStateMachineViewHtml(sms: LJStateMachine[], diagrams: string[], o
7979
`;
8080
}
8181

82-
// the diagram of one state set, labelled with its states, and dimmed when focusing on an error of another state set
82+
// the diagram of one state set, labelled with its name, or its states if it has none,
83+
// and dimmed when focusing on an error of another state set
8384
function renderStateSetDiagram(sm: LJStateMachine, diagram: string, dimUnrelated: boolean): string {
8485
const dimmed = dimUnrelated && !sm.errorContext;
86+
const title = sm.stateSetName ?? sm.states.join(' \u00B7 ');
8587
return /*html*/`
8688
<div class="diagram-state-set${dimmed ? ' diagram-state-set-dimmed' : ''}">
87-
<h3 class="diagram-state-set-title">${sm.states.map(state => escapeHtml(state)).join(' \u00B7 ')}</h3>
89+
<h3 class="diagram-state-set-title">${escapeHtml(title)}</h3>
8890
<pre class="mermaid">${diagram}</pre>
8991
</div>
9092
`;

‎server/src/main/java/dtos/fsm/StateMachineDTO.java‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
* DTO for serializing the state machine diagram of one state set, with the state error shown on it
1313
*
1414
* @param stateSet the index of the state set among the class's StateSet annotations
15+
* @param stateSetName the name given to the state set, or null if it has none
1516
* @param entryTransitions the methods that put an object in an unknown state into a state of this state set
1617
* @param errorContext the state error on this diagram, or null if the call does not involve this state set
1718
*/
1819
public record StateMachineDTO(
1920
String className,
2021
int stateSet,
22+
String stateSetName,
2123
List<String> states,
2224
List<StateMachineTransition> transitions,
2325
List<StateMachineInitialTransition> initialTransitions,
@@ -26,7 +28,7 @@ public record StateMachineDTO(
2628

2729
public static StateMachineDTO from(StateMachine sm, StateErrorContext context) {
2830
if (sm == null) return null;
29-
return new StateMachineDTO(sm.className(), sm.stateSet(), sm.states(), sm.transitions(),
31+
return new StateMachineDTO(sm.className(), sm.stateSet(), sm.stateSetName(), sm.states(), sm.transitions(),
3032
sm.initialTransitions(), sm.entryTransitions(), StateErrorContextDTO.from(context, sm.states(), sm.stateSet()));
3133
}
3234

‎server/src/test/java/dtos/fsm/StateMachineDTOTest.java‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ void showsTheErrorOnEveryStateSetWhenNoneHasTheCalledMethod() {
5353
}
5454

5555
@Test
56-
void keepsTheEntryTransitions() {
57-
StateMachine sm = new StateMachine("example.Edit", 0, List.of("start", "endDone"),
56+
void keepsTheStateSetNameAndEntryTransitions() {
57+
StateMachine sm = new StateMachine("example.Edit", 0, "phase", List.of("start", "endDone"),
5858
List.of(new StateMachineTransition("start", "endDone", "end")),
5959
List.of(new StateMachineInitialTransition("start")),
6060
List.of(new StateMachineEntryTransition("endDone", "canUndo", "return")));
61-
assertEquals(sm.entryTransitions(), StateMachineDTO.from(sm, null).entryTransitions());
61+
StateMachineDTO dto = StateMachineDTO.from(sm, null);
62+
assertEquals("phase", dto.stateSetName());
63+
assertEquals(sm.entryTransitions(), dto.entryTransitions());
6264
}
6365

6466
@Test

0 commit comments

Comments
 (0)