microsoft / microsoft/WinAppVSCE

[Feature]: XAML Language Server

Open
#52 0 comments 0 reactions 1 assignee View on GitHub

@chiaramooney is already working on this.

Since Jul 20, 2026.

enhancement
Dominant language
TypeScript
Stars
13
Forks
3
Avg merge
6d 1h
Merged PRs (30d)
11

Description

1. Summary

Ship a XAML language server that gives WinUI XAML files first-class editor intelligence inside VS Code and its AI-native forks (Cursor, Windsurf):

  • element and attribute completion
  • value completion (enums, brushes, StaticResource/ThemeResource keys, event handlers)
  • hover docs, go-to-definition
  • find-all-references across XAML↔C#, diagnostics with quick fixes, and formatting

It is delivered as a Language Server Protocol (LSP) server bundled with the WinApp extension so it works identically across all LSP-capable editors.

Image

2. Problem / motivation

Today, editing WinUI XAML in VS Code is colorization only — there is no first-party XAML IntelliSense outside Visual Studio (Windows-only). A Windows engineer who lives in VS Code (or Cursor / Windsurf) hand-types control names, guesses attribute names, and only discovers typos at build time. This is a big editor-parity gap between VS Code and Visual Studio for Windows app developers.

3. Similar Products

Tool Approach Gap we address
Visual Studio (WPF/WinUI/UWP) Rich native XAML IntelliSense via the in-proc XAML Language Service; Windows + VS only. We bring comparable intelligence to VS Code / Cursor / Windsurf, cross-editor.
Avalonia for VS Code Ships a dedicated Avalonia XAML LSP (project-aware completion, diagnostics, go-to-def). Proves the LSP model works well in VS Code; we target WinUI/WinRT metadata rather than Avalonia's.
Uno Platform for VS Code Roslyn-based XAML language server for Uno's XAML dialect.

We should make sure to look into these solutions to see what we can reuse here. My understanding is the XAML language server in Visual Studio code isn't shipped independently as an LSP and its implementation is tightly coupled with VS.

4. Goals / non-goals

Goals

  • Element, attribute (property/event), and attribute-value completion for WinUI 3 controls.
  • Namespace-aware completion (xmlns prefixes, using: / clr-namespace:; custom controls).
  • Resource key completion ({StaticResource}, {ThemeResource}, {x:Bind} path hints).
  • Hover docs (type/member summary + namespace + inheritance) and signature-style info for markup extensions.
  • Diagnostics: unknown type/property, wrong value type, duplicate x:Name, unresolved resource key,
    unresolved event handler — each with a quick fix where obvious (spelling suggestions, add handler stub).
  • Go-to-definition / find-references bridging XAML x:Name, event handlers, and {x:Bind} paths to C#.
  • Document + selection formatting.
  • Works in VS Code, Cursor, Windsurf (pure LSP, no VS Code-only APIs in the server).

5. Proposed implementation

Architecture: a standalone language server process + a thin VS Code client.

VS Code / Cursor / Windsurf  ──LSP──▶  WinApp XAML Language Server
   (vscode-languageclient)                 │
                                           ├─ XAML parser (tolerant, incremental)
                                           ├─ Type/metadata provider  ◀── B4 design-time engine
                                           │     (WinMD + project references + custom controls)
                                           ├─ Project model  ◀── winapp CLI (B): csproj/RID/refs
                                           └─ Providers: completion, hover, diagnostics,
                                                 definition, references, formatting

6. API / contribution surface

package.json contributions

"contributes": {
  "languages": [{ "id": "xaml", "extensions": [".xaml"], "aliases": ["XAML"],
                  "configuration": "./xaml-language-configuration.json" }],
  "grammars": [{ "language": "xaml", "scopeName": "text.xml.xaml",
                 "path": "./syntaxes/xaml.tmLanguage.json" }],
  "configuration": {
    "winapp.xaml.languageServer.enable": { "type": "boolean", "default": true },
    "winapp.xaml.diagnostics.level": { "enum": ["off","warning","error"], "default": "warning" },
    "winapp.xaml.completion.includeCustomControls": { "type": "boolean", "default": true },
    "winapp.xaml.trace.server": { "enum": ["off","messages","verbose"], "default": "off" }
  }
}

Commands: winapp.xaml.restartLanguageServer, winapp.xaml.reloadMetadata.

LSP capabilities advertised: completionProvider (trigger chars <, space, ., ", {),
hoverProvider, definitionProvider, referencesProvider, documentFormattingProvider,
documentRangeFormattingProvider, codeActionProvider (quick fixes), diagnostics (push).

7. Design tradeoffs & alternatives

  • .NET server vs Node server. .NET wins on metadata/Roslyn reuse and B4 sharing; costs a bundled .NET
    runtime (mitigated: the extension already ships/downloads the winapp CLI, a .NET app).
  • Precision vs latency for {x:Bind}/binding type-checking. Full compiler-grade checking needs a
    Roslyn compilation of the code-behind and generated x:Bind code — expensive. Start with
    name/path resolution (does the property exist on the DataContext type?) and defer full type-flow checks.
  • Bundled metadata snapshot vs project-restored metadata. Snapshot gives instant value with zero
    setup but can drift from the project's SDK version; project-restored is accurate but needs a restore.
    Ship both: snapshot as fallback, project metadata when available.

10. Open questions

  1. Do we reuse the Visual Studio XAML Language Service internals, or build fresh on Roslyn + WinMD?
    (Licensing / componentization question for the VS team.)
  2. Is B4 committed to exposing a public type-resolution API the LSP can consume, and on what timeline?
  3. How much {x:Bind} checking is "enough" for v1 to feel credible vs. VS?
Additional context

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.