Skip to content

XAML: two activation events load the extension in workspaces that never use it #211

Description

Follow-up from the PR #50 review. Two activation events load the extension host in workspaces that never use it. This supersedes two earlier, wrong versions of this issue — see the correction note at the bottom.

workspaceContains:**/*.xaml — its purpose was deleted, the event was not

4ad4295 ("Accelerate staged XAML IntelliSense loading") added this event for a real performance reason. Early activation let the extension findFiles a XAML file, call startClient, and send winui-xaml/warmUp so the expensive .NET + Roslyn + MSBuild project load completed before the user opened a XAML file.

fdeb42d ("Start XAML server on document open") removed that whole mechanism — src/xaml/workspacePreload.ts, the warmUp notification in doStart, and the speculative startClient branch in activateXaml — so IntelliSense always resolves the project for the document the user actually opened. It did not touch activationEvents.

What the event does today: hoists extension-host activation to VS Code startup. activateXaml creates an output channel and a status bar item, registers ~8 commands and some event handlers, and returns. hasOpenXamlDocument is false, so no server starts.

That hoist is close to worthless:

  • onLanguage:xaml is also an activation event, so opening a XAML file activates the extension anyway, and VS Code awaits activation before delivering the open event. Time-to-IntelliSense is unchanged.
  • Nothing user-visible appears beforehand. renderProjectContextStatus (src/xaml/xamlLanguageService.ts:814-849) hides the status bar item unless a project context status exists, and those only come from a running server.
  • workspaceContains:**/[Aa]ppx[Mm]anifest.xml, **/*.appxmanifest, and onLanguage:xml are already activation events, so a packaged WinUI workspace activates at startup regardless. The marginal cost of the .xaml glob lands mostly on WPF and UWP projects that have XAML but no app manifest — precisely the workspaces that never use this extension.

Why it was not simply removed in PR #50: src/test/xaml-workspace-activation.test.ts:11 asserts the event is present in package.json. That test was added by the same commit that removed the event's purpose, and it only asserts the string exists — a change detector, not a behavioral guarantee. Removing the event is a deliberate decision that must also update that test, so it did not belong in this PR.

onLanguage:csharp — one gated notification

Added by c33a99c ("Recommend C# Dev Kit for XAML code-behind") solely to trigger that recommendation. CsharpDevKitNotificationGate.shouldShow (src/xaml/csharpDevKitNotification.ts:16-28) returns false unless the path ends in .xaml.cs.

Opening any .cs file in any C# project activates the whole extension — debug configuration provider, debug adapter factory, manifest custom editor, manifest IntelliSense, XAML client registration, output channel, status bar item — to test a filename suffix and usually do nothing. It buys the ability to suggest Dev Kit when a user opens code-behind with no XAML file open.

Timing

Only workspaceContains is evaluated during VS Code startup. onLanguage:csharp activates later, on first C# document open — a real cost, but not a startup-time one.

Suggested work

  • Remove workspaceContains:**/*.xaml and update src/test/xaml-workspace-activation.test.ts to assert the intended behavior (no activation without an open XAML document) rather than the presence of a string. Confirm with code --prof-startup on a WPF workspace first.
  • Decide whether onLanguage:csharp earns its cost, or whether the Dev Kit recommendation should fire from the XAML path instead (e.g. opening a .xaml with a sibling .xaml.cs), accepting that it would no longer fire for code-behind opened alone.

Correction history

An earlier version of this issue called the .xaml glob "vestigial" with no evidence. A second version overcorrected and called it an intentional warm-up, on the strength of the test alone. Neither was right: the commit history shows a deleted purpose plus a retained line, and the test locks in the line rather than any behavior.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions