microsoft / microsoft/WinAppVSCE

XAML Language Server: WinMD-based type resolution for C++/WinRT projects

Open
#222 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Summary

After basic C++/WinRT syntactic support lands (#221), the next step is type-aware IntelliSense. Two architectural approaches are viable — the team should discuss trade-offs before committing.


Option A: WinMD-based type system (.winmd reader)

How it works

C++/WinRT projects produce .winmd metadata files during build. These use the ECMA-335 format (same as .NET assemblies), so .NET's built-in System.Reflection.Metadata can read them directly — no new dependencies needed.

WinMD sources
  1. Framework types: Windows App SDK .winmd files from NuGet package cache (Microsoft.WindowsAppSDK/*/lib/uap10.0/*.winmd)
  2. System types: %windir%/System32/WinMetadata/*.winmd (Windows Runtime APIs)
  3. App types: Project build output .winmd (generated from .idl files via MIDLRT)
Architecture
  • Abstract IXamlTypeSystem interface with two implementations:
    • RoslynTypeSystem (existing — for C# projects)
    • WinMdTypeSystem (new — for C++/WinRT projects)
  • WinMdTypeSystem uses System.Reflection.Metadata + MetadataReader to enumerate types, properties, events
  • Cache per-project, invalidate on rebuild (watch build output directory)
Pros
  • No new dependenciesSystem.Reflection.Metadata ships with .NET
  • Language-agnostic — same approach works for any WinRT language projection (Rust/WinRT, etc.)
  • Mirrors Visual Studio's architecture — VS uses WinMD + XamlCompiler for C++ XAML IntelliSense
  • Well-documented format — Microsoft's open-source microsoft/winmd and microsoft/winmd-rs parsers exist as reference
  • Covers framework AND app types — both NuGet .winmd and project-generated .winmd
Cons
  • Requires a build — app's own types only available after msbuild generates the .winmd from .idl
  • No source-level info — can't resolve into C++ source for go-to-definition on app types
  • Stale metadata risk — if user edits .idl but hasn't rebuilt, IntelliSense lags behind
  • New code path to maintain — separate type system impl with its own bugs/edge cases
What this enables
  • Element completion (all WinUI controls and their properties)
  • App's own custom control completion (from project-generated .winmd)
  • Property/event validation and completion
  • Enum value completion
  • Basic hover docs (type name, namespace, assembly)
What this does NOT enable
  • x:Bind path resolution (needs C++ source / IDL awareness)
  • Event handler go-to-definition (needs C++ symbol resolution)
  • Live editing — changes to .idl won't reflect until rebuild

Option B: Roslyn reads .winmd directly (extend existing type system)

How it works

Roslyn's MetadataReference.CreateFromFile() can load .winmd files as metadata references — the same way it loads .dll references for C# projects. We could extend the existing RoslynTypeSystem to create a "synthetic" compilation with .winmd references instead of .csproj-based ones.

Architecture
  • Keep XamlTypeSystem as-is (Roslyn-based)
  • For C++ projects: build a CSharpCompilation with no source files but with .winmd metadata references
  • Roslyn treats .winmd types like any other referenced assembly — existing completion/hover/diagnostics code works unchanged
Pros
  • Massive code reuse — all 14 Complete* methods, hover, diagnostics, etc. work without changes
  • Single code path — no interface abstraction or second implementation to maintain
  • Proven — Roslyn's .winmd reading is battle-tested (used by VS for mixed C#/C++ solutions)
Cons
  • Heavier runtime cost — full Roslyn compilation for what is essentially metadata reading
  • Semantic mismatch — using a C# compiler to serve a C++ project feels architecturally wrong
  • No app types from source — still needs built .winmd for app's own types (same as Option A)
  • Roslyn quirks — WinRT type projections (e.g., IVector<T>IList<T>) may surface C# names instead of WinRT names

Comparison

Criteria Option A (WinMD reader) Option B (Roslyn + WinMD refs)
New code ~New WinMdTypeSystem class ~New project detection + synthetic compilation
Dependencies None (built-in) None (Roslyn already in-tree)
Code reuse Low — reimplements type queries High — reuses all existing providers
Runtime cost Light (metadata-only) Heavy (full Roslyn compilation)
Architectural fit Clean separation Pragmatic but conceptually odd
Maintenance Two type system impls One code path, different project setup
VS alignment Matches VS architecture Does not match VS
Time to implement Medium (weeks) Small (days)

Recommendation

Discuss as a team. Option B is faster to ship (less new code) but creates a dependency on Roslyn for non-C# projects. Option A is cleaner long-term and aligns with how Visual Studio handles C++ XAML, but is more upfront work.

A hybrid approach is also possible: start with Option B for quick wins, then migrate to Option A if Roslyn's WinRT projections cause friction.

Context

  • Visual Studio uses WinMD + XamlCompiler for C++ XAML IntelliSense (aligns with Option A)
  • No third-party VS Code extensions exist for C++ WinUI XAML IntelliSense
  • .winmd format is ECMA-335; .NET has built-in System.Reflection.Metadata reader
  • Microsoft maintains open-source WinMD parsers: microsoft/winmd, microsoft/winmd-rs
  • Depends on #221 for basic C++/WinRT project detection

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.

Research direction

Start by reviewing dependency issue #221 and compare the WinMD reader and Roslyn synthetic-compilation approaches described here. No files or tests are named; done means the team has chosen an approach and defined an implementation plan for C++/WinRT type-aware IntelliSense.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, csharp
Domain
developer-experience, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.