Skip to content

[HotReload] Surface XAML Incremental Hot Reload diagnostics for IDE tooling - #36459

Merged
StephaneDelcroix merged 1 commit into
dotnet:feature/xaml-incremental-hotreloadfrom
noiseonwires:xaml-hotreload-diagnostics-tooling
Jul 9, 2026
Merged

[HotReload] Surface XAML Incremental Hot Reload diagnostics for IDE tooling#36459
StephaneDelcroix merged 1 commit into
dotnet:feature/xaml-incremental-hotreloadfrom
noiseonwires:xaml-hotreload-diagnostics-tooling

Conversation

@noiseonwires

@noiseonwires noiseonwires commented Jul 8, 2026

Copy link
Copy Markdown
Member

Description

Incremental contribution to feature/xaml-incremental-hotreload.

Extends HotReloadDiagnostics so IDE tooling (the Visual Studio / VS Code MAUI
Hot Reload diagnostics, a.k.a. "XamlTools") can classify a hot reload cycle as
XAML Incremental Hot Reload (XIHR), report its apply stats, and surface
per-instance failures. Today the tooling only sees a generic managed-code delta, so
it misclassifies XAML SourceGen edits as plain C# and can't report the incremental
apply result.

All changes are purely additive to the diagnostics surface — no change to the
hot reload apply itself, and no breaking API changes.

New / changed public API (Microsoft.Maui.Controls.Xaml.Diagnostics)

  • HotReloadDiagnostics.UpdateSkipped — new event. Terminal signal raised when an
    update is recognized (has generated UpdateComponent() types) but nothing is
    dispatched because there are no live instances to patch, so observers always get a
    definite outcome even when UpdateApplied never fires.
  • HotReloadRequestedEventArgs.HandledTypes — the recognized incremental-XAML
    subset of UpdatedTypes. Raised synchronously, before any UI-thread dispatch, so
    tooling can classify the update type inline (XIHR vs. non-XAML) without awaiting the
    async apply.
  • HotReloadErrorEventArgs.Version — the update-cycle version a per-instance
    failure belongs to (matches the corresponding HotReloadAppliedEventArgs.ToVersion),
    so failures can be correlated with their apply.
  • HotReloadSkippedEventArgs — new event args for UpdateSkipped (UpdatedTypes,
    HandledTypes, Timestamp).

Handler (XamlIncrementalHotReloadHandler)

  • Builds the handledTypes set and raises OnUpdateRequested synchronously before
    dispatch.
  • Raises OnUpdateSkipped for a recognized-but-empty batch (returns without dispatch).
  • Passes toVersion to OnUpdateFailed.
  • Allocates the diagnostic version only for non-empty batches, keeping the version
    stream gap-free (every increment is paired with an UpdateApplied).

Firing contract (documented in-code)

The three files carry brief "XamlTools contract" comments describing the reflection-by-
name binding surface tooling relies on: the type/event/property names, the
EventHandler<T> shapes, and the ordering guarantees — UpdateRequested is synchronous
and pre-dispatch; a dispatched batch ends with exactly one terminal UpdateApplied
(always raised, even if every instance failed) or UpdateSkipped; each UpdateFailed
precedes its batch's UpdateApplied.

Issues Fixed

Fixes #

Testing

  • Added XamlIncrementalHotReloadHandlerTests (7 tests, Controls/tests/Core.UnitTests)
    covering: UpdateRequested/HandledTypes classification, UpdateApplied
    instance/version/duration, UpdateFailed per-instance + Version correlation, and the
    UpdateSkipped no-live-instances path. Uses a MainThread custom-implementation
    harness for the UI-thread dispatch.
  • Verified end-to-end on a physical Android device with the consuming IDE tooling:
    a XAML SourceGen edit is classified as xaml-sourcegen and the IDE reports the
    incremental apply (instance count, version 0→1, duration).

API Changes

Additive only — see the updated PublicAPI.Unshipped.txt for all TFMs.

Extends HotReloadDiagnostics so IDE tooling (VS / VS Code MAUI Hot Reload) can classify and report XIHR cycles:

- HotReloadDiagnostics: add UpdateSkipped terminal event (recognized batch with no live instances to patch).

- HotReloadRequestedEventArgs.HandledTypes: the recognized incremental-XAML subset, raised synchronously before dispatch so tooling can classify the update type inline.

- HotReloadErrorEventArgs.Version: correlates a per-instance failure with its apply's ToVersion.

- XamlIncrementalHotReloadHandler: raise OnUpdateRequested (sync, pre-dispatch) with handled types; OnUpdateSkipped for an empty batch; pass toVersion to OnUpdateFailed; allocate the version only for non-empty batches (gap-free version stream).

- Document the reflection-by-name contract XamlTools relies on.

- Add XamlIncrementalHotReloadHandlerTests (7 tests).
@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label Jul 8, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey there @@noiseonwires! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey there @noiseonwires! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@noiseonwires

Copy link
Copy Markdown
Member Author

@StephaneDelcroix that's the implementation of #36078 (comment) proposal

@noiseonwires noiseonwires changed the title [HotReload] Add XAML Incremental Hot Reload diagnostics for tooling [HotReload] Surface XAML Incremental Hot Reload diagnostics for IDE tooling Jul 8, 2026
@StephaneDelcroix
StephaneDelcroix merged commit 7680d96 into dotnet:feature/xaml-incremental-hotreload Jul 9, 2026
8 of 10 checks passed
StephaneDelcroix pushed a commit that referenced this pull request Jul 20, 2026
…ooling (#36459)

### Description

Incremental contribution to `feature/xaml-incremental-hotreload`.

Extends `HotReloadDiagnostics` so IDE tooling (the Visual Studio / VS
Code MAUI
Hot Reload diagnostics, a.k.a. "XamlTools") can **classify** a hot
reload cycle as
XAML Incremental Hot Reload (XIHR), **report** its apply stats, and
**surface**
per-instance failures. Today the tooling only sees a generic
managed-code delta, so
it misclassifies XAML SourceGen edits as plain C# and can't report the
incremental
apply result.

All changes are **purely additive** to the diagnostics surface — no
change to the
hot reload apply itself, and no breaking API changes.

#### New / changed public API
(`Microsoft.Maui.Controls.Xaml.Diagnostics`)

- **`HotReloadDiagnostics.UpdateSkipped`** — new event. Terminal signal
raised when an
update is *recognized* (has generated `UpdateComponent()` types) but
nothing is
dispatched because there are no live instances to patch, so observers
always get a
  definite outcome even when `UpdateApplied` never fires.
- **`HotReloadRequestedEventArgs.HandledTypes`** — the recognized
incremental-XAML
subset of `UpdatedTypes`. Raised **synchronously, before any UI-thread
dispatch**, so
tooling can classify the update type inline (XIHR vs. non-XAML) without
awaiting the
  async apply.
- **`HotReloadErrorEventArgs.Version`** — the update-cycle version a
per-instance
failure belongs to (matches the corresponding
`HotReloadAppliedEventArgs.ToVersion`),
  so failures can be correlated with their apply.
- **`HotReloadSkippedEventArgs`** — new event args for `UpdateSkipped`
(`UpdatedTypes`,
  `HandledTypes`, `Timestamp`).

#### Handler (`XamlIncrementalHotReloadHandler`)

- Builds the `handledTypes` set and raises `OnUpdateRequested`
synchronously before
  dispatch.
- Raises `OnUpdateSkipped` for a recognized-but-empty batch (returns
without dispatch).
- Passes `toVersion` to `OnUpdateFailed`.
- Allocates the diagnostic version only for **non-empty** batches,
keeping the version
  stream gap-free (every increment is paired with an `UpdateApplied`).

#### Firing contract (documented in-code)

The three files carry brief "XamlTools contract" comments describing the
reflection-by-
name binding surface tooling relies on: the type/event/property names,
the
`EventHandler<T>` shapes, and the ordering guarantees —
`UpdateRequested` is synchronous
and pre-dispatch; a dispatched batch ends with exactly one terminal
`UpdateApplied`
(always raised, even if every instance failed) or `UpdateSkipped`; each
`UpdateFailed`
precedes its batch's `UpdateApplied`.

### Issues Fixed

Fixes # <!-- link the XIHR-diagnostics tracking issue, if any -->

### Testing

- Added `XamlIncrementalHotReloadHandlerTests` (7 tests,
`Controls/tests/Core.UnitTests`)
covering: `UpdateRequested`/`HandledTypes` classification,
`UpdateApplied`
instance/version/duration, `UpdateFailed` per-instance + `Version`
correlation, and the
`UpdateSkipped` no-live-instances path. Uses a `MainThread`
custom-implementation
  harness for the UI-thread dispatch.
- Verified end-to-end on a physical Android device with the consuming
IDE tooling:
a XAML SourceGen edit is classified as `xaml-sourcegen` and the IDE
reports the
  incremental apply (instance count, `version 0→1`, duration).

### API Changes

Additive only — see the updated `PublicAPI.Unshipped.txt` for all TFMs.
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 9, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

community ✨ Community Contribution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants