Skip to content

fix(core): apply a project descriptor edit in the build it starts - #238

Merged
martin-fleck-at merged 1 commit into
mainfrom
fix/descriptor-edit-lag
Sep 30, 2026
Merged

martin-fleck-at merged 1 commit into
mainfrom
fix/descriptor-edit-lag

Conversation

@martin-fleck-at

@martin-fleck-at martin-fleck-at commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Editing a project descriptor changed the project registry only on the descriptor's next edit. AbstractProjectManager reads descriptors from a DocumentBuilder.onUpdate listener, and Langium calls those listeners after it resets the changed documents but before the build parses them, so parseProjectDescriptor saw the previous edit's AST. This change has loadDescriptor re-parse a descriptor that has not been parsed since the edit, from the same text the build reads, and then restore the document's state. The build still runs its own parse phase and fires its phase notification, and the factory skips the second parse because the text is unchanged. The change event is still emitted from the listener, and Langium awaits the listeners before it collects the documents to rebuild, so the dependent documents join that same build rather than a second one. The same guard fixes a descriptor created by an update: Langium holds it as an unparsed INVALID placeholder until the build's parse phase, so its project was not registered until the file's next edit.

The three doc comments that said the cascade reset is picked up by "the next build cycle" now say it joins the build of the update that changed the descriptor. Discovery emits with no affected documents, so that update's build is the only one a reset can land in.

What it leaves alone

The re-parse runs with CancellationToken.None, because Langium passes its update listeners no token, so a newer edit cannot cancel a descriptor parse already under way. An onUpdate listener registered after the project manager now sees the descriptor's new AST rather than the old one.

How I know it works

  • The new order-flow test removes requires commerce-core from orders.domain, runs one update, and expects orders to have no dependencies and Order.total to be unresolved; then it restores the line and expects both back after one more update. With the core change stashed and core rebuilt it fails with expected [ 'commerce-core' ] to be undefined, the stale registry from the issue.
  • A second test writes a new refunds/refunds.domain carrying project refunds requires commerce-core, runs one update, and expects the project registered and its Money field resolved. With the core change stashed it fails with expected undefined to deeply equal [ 'commerce-core' ]: the project is not registered until the file's next edit.
  • A throwaway onUpdate listener, deleted afterwards, logged the descriptor at state Changed with its AST still containing requires commerce-core at the moment the project manager reads it.

Fixes #221.

- Re-parse a descriptor still at Changed before reading it, since
  the onUpdate listeners run before the build's parse phase and
  otherwise see the previous edit's AST
- Restore the document state afterwards so the build still runs and
  notifies its own parse phase, without parsing the text twice
- Say the cascade reset joins the build of the descriptor's update,
  not a later one
- Cover removing and re-adding a requires clause, and creating a new
  descriptor, in order-flow

Fixes #221
@martin-fleck-at
martin-fleck-at merged commit 6cd2368 into main Sep 30, 2026
7 checks passed
@martin-fleck-at
martin-fleck-at deleted the fix/descriptor-edit-lag branch September 30, 2026 09:46
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.

A project descriptor edit takes effect one edit late

1 participant