Skip to content

Draw a StateRefinement without from only from the states it leaves uncovered - #19

Merged
CatarinaGamboa merged 2 commits into
mainfrom
fix/to-without-from
Nov 10, 2026
Merged

CatarinaGamboa merged 2 commits into
mainfrom
fix/to-without-from

Conversation

@CatarinaGamboa

@CatarinaGamboa CatarinaGamboa commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Closes #18

What changes

A @StateRefinement with a to but no from is no longer drawn from the start node. Only constructors and factory methods come from there now.

In the verifier (AuxStateHandler.getStates), a to without from gets from = true: the method can be called in any state and moves to to. changeState uses the first alternative whose from matches, so the from-less one applies in every state that the earlier from= alternatives do not cover. The parser already drew exactly those edges (since #15). So the fix only drops the extra arrow from the start node. The arrow stood for "an object whose state is unknown (a field, a parameter)". That case is not a state in the diagram, and next to new UndoManager() it reads as a second way to create the object.

A from-less @StateRefinement that is the only one on its method still goes from every state. Nothing changes for ToOnlyTransition.

API

I kept StateMachine.entryTransitions and StateMachineEntryTransition, both @Deprecated and always empty. That way 0.2.4 is a drop-in patch: the VS Code server's StateMachineDTO still compiles, and its client draws nothing for an empty list. No vscode-liquidjava change is needed. Removing the record, the DTO field and the client's entry-transition drawing (diagram.ts, fsm.ts) can be a follow-up once vscode-liquidjava#180 has landed, since that work is in the same files.

A1_56 (UndoManager), redo state set

canRedo() is a query whose return value tells the state:

@StateRefinement(from = "redo(this) == redoable", to = "redo(this) == redoable && return")
@StateRefinement(to = "return ? redo(this) == redoable : redo(this) == notRedoable")
boolean canRedo();

Parsed state machine (canUndo/canRedo lines only; undo is the same with canUndo):

before (0.2.3) after
start node [*] -> notRedoable : new UndoManager()
[*] -> redoable : canRedo [return]
[*] -> notRedoable : canRedo [!return]
[*] -> notRedoable : new UndoManager()
edges redoable -> redoable : canRedo [return]
notRedoable -> redoable : canRedo [return]
notRedoable -> notRedoable : canRedo [!return]
unchanged

Rendered in VS Code (vscode-liquidjava main with fsm 0.2.3, then the same build with this branch's classes), focused on the state error:

before after
before after

All methods:

before after
before after

canRedo [return] from notRedoable to redoable is the guard that the verifier's hint suggests (if (um.canRedo()) um.redo();). In the focused view it is in the collapsed "2 methods" on that edge.

Tests

  • testEntryTransition is now testNoFromBesideFromIsNotEntryTransition. It keeps the same edges, renames the fixture from EntryTransition to NoFromBesideFrom, and asserts no entry transitions. It fails on main, which returns [canUndo -> endDone, reset -> start].
  • I removed testToOnlyTransitionHasNoEntryTransition. entryTransitions is always empty now, so that test no longer checks anything.
  • mvn -B test: 32 tests, 0 failures.

🤖 Generated with Claude Code

…covered

A StateRefinement with a to but no from was also drawn from the initial pseudo state, like a constructor, when the
method had other StateRefinements with from. The verifier reads it as from = true, so it already goes from the states
the others do not cover; only constructors and factory methods enter the state machine. entryTransitions is kept,
always empty, so that clients still compile.

Closes #18

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CatarinaGamboa CatarinaGamboa added the bug Something isn't working label Nov 10, 2026
@CatarinaGamboa

Copy link
Copy Markdown
Contributor Author

Codex review, round 1 (codex exec review --base origin/main)

The changes consistently remove entry-transition generation while preserving the API field for compatibility. The test suite passes.

No findings, so there is nothing to fix.

…beside others

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@CatarinaGamboa

Copy link
Copy Markdown
Contributor Author

Clean-code audit (clean-code-principles skill, on the diff against main)

  • src/test/resources/fsm/EntryTransition.java:7 - [name-meaningful] The fixture was still named EntryTransition, but the test now asserts that it has none. Fixed in the latest commit: it is now NoFromBesideFrom, after the case it covers.
  • src/main/java/liquidjava/fsm/StateMachine.java:19 - [core-yagni] entryTransitions is always empty and kept only for compatibility. Kept on purpose: the VS Code server's StateMachineDTO reads it, so 0.2.4 stays a drop-in patch. Removing it, together with the client's drawing code, is a follow-up after vscode-liquidjava#180.
  • src/main/java/liquidjava/fsm/StateMachine.java:21 - [core-encapsulation] The 6-argument constructor still accepts a non-empty entryTransitions. Kept: it is public API, and the parser always passes List.of().
  • StateMachineParser.java: removing the out-parameter entryTransitions makes getTransitions a pure query again ([func-no-side-effects]). No other findings.

mvn -B test: 32 tests, 0 failures.

@CatarinaGamboa

Copy link
Copy Markdown
Contributor Author

Codex review, round 2 (after the fixture rename)

The removal of generated entry transitions is consistent across the parser, API documentation, and tests. The test suite passes, and I found no actionable regression.

No findings. The review loop is done.

@CatarinaGamboa
CatarinaGamboa merged commit 68a31fe into main Nov 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Methods with a to but no from are drawn from the start node, like constructors

1 participant