Skip to content

Build and ship a reference assembly for WinRT.Runtime#2453

Open
Sergio0694 wants to merge 11 commits into
staging/3.0from
staging/winrt-runtime-ref-assembly
Open

Build and ship a reference assembly for WinRT.Runtime#2453
Sergio0694 wants to merge 11 commits into
staging/3.0from
staging/winrt-runtime-ref-assembly

Conversation

@Sergio0694

Copy link
Copy Markdown
Member

Summary

Introduce a dedicated reference assembly for WinRT.Runtime, built alongside the implementation assembly with every implementation-only type and member stripped out, and ship it in the Microsoft.Windows.CsWinRT NuGet package under ref\net10.0\. A new [WindowsRuntimeImplementationOnlyMember] attribute and a banned-API analyzer make the implementation-only surface explicit and prevent it from ever leaking into the public API.

Motivation

WinRT.Runtime exposes a large set of public-but-private-implementation-detail APIs (marshallers, vtables, native object wrappers, collection adapters, ABI types, and so on) that exist solely to be consumed by generated code: the CsWinRT projections and the interop generator (WinRT.Interop.dll). Previously these were marked [Obsolete] + [EditorBrowsable(Never)] to hide them from IntelliSense, but they were still part of the public surface that consumers compiled against. That cluttered the API, risked accidental use, and meant the implementation-only surface was effectively versioned like public API.

Building a separate reference assembly that strips these APIs out entirely gives consumers a clean public surface to compile against, lets the implementation-only APIs evolve freely without semantic-versioning concerns, and makes the rules enforceable: deriving from WindowsRuntimeObject is now blocked at compile time (CSWINRT3001) because its constructor exists only in the reference assembly, and the banned-API analyzer fails the build if any implementation-only type ever leaks into the reference surface. This is the runtime-side foundation that complements the reference-projection model used by the rest of CsWinRT 3.0.

Changes

  • [WindowsRuntimeImplementationOnlyMember] attribute (Use a dedicated attribute to mark implementation-only members #2434) — new internal sealed, [Conditional("WINDOWS_RUNTIME_REFERENCE_ASSEMBLY")] marker in src/WinRT.Runtime2/Attributes/ that replaces the previous [Obsolete] + [EditorBrowsable(Never)] combination used to mark private implementation-detail types and members. Applied throughout ABI/, InteropServices/, NativeObjects/, Windows.Foundation/, and the marker attributes under Attributes/. Removes the old WindowsRuntimeConstants private-implementation-detail messaging and the corresponding warning suppression.
  • WindowsRuntimeObject partial split (Split WindowsRuntimeObject into a partial implementation file #2446) — splits the base type into WindowsRuntimeObject.cs (shared/reference surface, including the explicit interface implementations as throw null stubs) and WindowsRuntimeObject.Impl.cs (implementation-only half), so the implementation can be excluded from the reference assembly.
  • Dual implementation/reference assembly build (Set up dual reference assembly build for WinRT.Runtime #2444) — src/WinRT.Runtime2/WinRT.Runtime.csproj now builds twice: the implementation assembly by default and a stripped reference assembly when CsWinRTBuildReferenceAssembly=true. Adds the WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY / WINDOWS_RUNTIME_REFERENCE_ASSEMBLY compilation symbols, sets ProduceReferenceAssembly=false on the implementation build, and adds a RemoveWindowsRuntimeImplementationOnlyFiles target that excludes implementation-only sources (files defining WINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE, plus whole folders such as ABI/, NativeObjects/, and most of InteropServices/) from the reference build.
  • Banned-API analyzer guard (Add banned API analyzer to guard the reference assembly surface #2447) — the reference build references Microsoft.CodeAnalysis.BannedApiAnalyzers (src/Directory.Packages.props) and lists WindowsRuntimeImplementationOnlyMemberAttribute in src/WinRT.Runtime2/BannedSymbols.txt with RS0030 promoted to an error, so the build fails if any implementation-only type ever leaks into the reference surface.
  • Reference-assembly-only constructor and CSWINRT3001 (Add a reference-assembly-only constructor for WindowsRuntimeObject #2448) — a parameterless protected WindowsRuntimeObject() constructor exists only in the reference assembly, marked [Obsolete(..., DiagnosticId = "CSWINRT3001")]. User code that derives from WindowsRuntimeObject now gets the CSWINRT3001 warning and, because the constructor is absent from the implementation assembly, a MissingMethodException at runtime. Only CsWinRT-generated projections may derive from it. Adds docs/diagnostics/cswinrt3001.md.
  • Packaging (Package the WinRT.Runtime reference assembly #2451) — the Microsoft.Windows.CsWinRT NuGet package now ships the implementation assembly under lib\net10.0\ and the reference assembly (with its XML documentation trimmed to the reference surface) under ref\net10.0\. The dual build and staging are wired through nuget/Microsoft.Windows.CsWinRT.nuspec, src/build.cmd, and the Azure Pipelines build/publish steps.
  • Documentation (Document the WinRT.Runtime reference assembly and impl-only APIs #2452) — updates the Copilot instructions (.github/copilot-instructions.md) and the interop generator skill docs (.github/skills/...) to describe the reference assembly, the [WindowsRuntimeImplementationOnlyMember] attribute, the CSWINRT3001 diagnostic, and the implementation-only API surface consumed by the interop generator.

Sergio0694 and others added 9 commits June 14, 2026 11:35
* Add WindowsRuntimeImplementationOnlyMemberAttribute

Introduce an internal sealed attribute to mark implementation-only members for WinRT runtime. The attribute targets all members, is non-inherited, and is conditional on WINDOWS_RUNTIME_REFERENCE_ASSEMBLY so it is emitted only in reference assemblies; this makes it explicit which members are implementation-only and allows them to be stripped from the runtime DLL. Added at src/WinRT.Runtime2/Attributes/WindowsRuntimeImplementationOnlyMemberAttribute.cs.

* Use [WindowsRuntimeImplementationOnlyMember] for implementation-only members

Replace the combination of [EditorBrowsable(Never)] and [Obsolete(...)] with the single [WindowsRuntimeImplementationOnlyMember] attribute on implementation-only members across WinRT.Runtime.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove WindowsRuntimeConstants.cs

Delete WindowsRuntimeConstants.cs which contained constants for WinRT private implementation detail messaging, the PrivateImplementationDetailObsoleteDiagnosticId (CSWINRT3001), and the CsWinRT diagnostics URL format. These constants have been removed from the project.

* Remove CSWINRT3001 NoWarn suppression

Delete the NoWarn entry and its comment for CSWINRT3001 from src/WinRT.Runtime2/WinRT.Runtime.csproj so warnings about '[Obsolete]' private implementation details are no longer suppressed. This change surfaces those warnings for visibility during builds.

* Delete CSWINRT3001 diagnostic documentation

This diagnostic is no longer applicable now that the private
implementation detail [Obsolete] attributes have been removed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Use [WindowsRuntimeImplementationOnlyMember] in IActivationFactoryImpl

This file was missed in the bulk conversion to the new attribute; it still referenced the now-deleted WindowsRuntimeConstants type, which would break the build.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove CSWINRT3001 warning suppressions

Remove pragma suppressions and documentation references for the CSWINRT3001 diagnostic. Deleted several "#pragma warning disable CSWINRT3001" (and matching restores) from source files and code-generation templates, and removed CSWINRT3001 from the suppressed warnings list and obsolete-marker table in docs. Affected files include .github/copilot-instructions.md, docs/interop.md, various tests and shim sources, and cswinrt code/template headers.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract the bulk of WindowsRuntimeObject's implementation into a new partial file (WindowsRuntimeObject.Impl.cs) and update WindowsRuntimeObject.cs to be a partial declaration. The change relocates constructors, caching fields, dynamic cast/QueryInterface logic, virtual method table helpers, and exception stubs into the new file while removing now-unneeded usings from the original file. This refactor preserves existing behavior but improves code organization and maintainability by separating surface declaration from detailed implementation.
* Adjust reference assembly build for WinRT.Runtime

Prevent the SDK-produced reference assembly from leaking implementation-only types by customizing the ref-assembly build. When not building the explicit CsWinRT reference assembly, ProduceReferenceAssembly is disabled and WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY is defined to simplify #if usage. When CsWinRTBuildReferenceAssembly is true, WINDOWS_RUNTIME_REFERENCE_ASSEMBLY is defined and expected warnings (CS8597, IDE0005, IDE0380) are suppressed. A BeforeTargets CoreCompile target removes files that opt out of reference assemblies (via WINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE), ABI sources, and several implementation-only folders so the packaged reference assembly omits private implementation details.

* Guard Windows metadata by assembly type

Wrap Windows runtime metadata and platform/contract attributes with build-time symbols to differentiate reference vs implementation assemblies. Many files now conditionally include Windows.Foundation.Metadata usings and apply [ContractVersion]/[SupportedOSPlatform] for WINDOWS_RUNTIME_REFERENCE_ASSEMBLY and [WindowsRuntimeMetadata]/[WindowsRuntimeClassName]/marshalling attributes for WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY. Removed unconditional SupportedOSPlatform/usings where appropriate and added #if guards across foundation, collections, streams, async adapters and task/asyncinfo helpers to allow building both reference and implementation variants.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Disable CS1574 in WindowsRuntimeFeatureSwitches

Suppress CS1574 (XML doc 'cref' not found) warnings in WindowsRuntimeFeatureSwitches.cs by adding `#pragma warning disable CS1574` before the namespace declaration. This prevents spurious documentation warnings during the build, likely caused by cref references to internal or conditional types.

* Move WindowsRuntimeInspectable to NativeObjects

Rename/move WindowsRuntimeInspectable.cs from src/WinRT.Runtime2/ to src/WinRT.Runtime2/NativeObjects/ to reorganize project structure. File content unchanged (100% similarity).

* Split WindowsRuntimeObject into partial file

Move the core implementation into a new partial file (src/WinRT.Runtime2/WindowsRuntimeObject.Impl.cs) and make WindowsRuntimeObject partial. The impl file contains caching, dynamic cast lookup, generated COM vtable handling, QueryInterface logic, activation constructors and an exceptions helper; redundant usings/implementation were removed from WindowsRuntimeObject.cs to keep the public surface unchanged.

* Add build guards for reference vs implementation

Introduce compile-time guards to separate reference and implementation builds. Many files were marked as implementation-only by adding a WINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE define; APIs and method bodies were wrapped with WINDOWS_RUNTIME_REFERENCE_ASSEMBLY / WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY conditionals (throw null in reference builds, real code in implementation builds). Adjustments touch attributes, interop/activation, marshalling, async helpers, buffer/stream utilities, and WindowsRuntimeMarshal/RestrictedErrorInfo/RestrictedErrorInfoExceptionMarshaller. Also updated the project file to exclude the Marshalling folder from the reference build. This enables producing lightweight reference assemblies while keeping full implementations in the implementation assembly.

* Use explicit #elif WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY in WinRT.Runtime

Replace the plain #else branch following #if WINDOWS_RUNTIME_REFERENCE_ASSEMBLY
with an explicit #elif WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY for clarity. The
two constants are mutually exclusive and exhaustive, so the behavior is
unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add banned API analyzer and ref-assembly config

Add Microsoft.CodeAnalysis.BannedApiAnalyzers to central package versions and include it as a private analyzer when building the reference assembly. Add a BannedSymbols.txt listing the WindowsRuntimeImplementationOnlyMemberAttribute to prevent implementation-only types from being exposed in the published ref assembly. Rearrange and annotate the WinRT.Runtime.csproj property groups for implementation vs reference assembly builds, set RS0030 as an error to fail on leaked private APIs, and wire BannedSymbols.txt as an AdditionalFiles input for the analyzer.

* Mark implementation-only sources; adjust csproj

Add #define WINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE to several implementation-only sources (Activation/WindowsRuntimeActivationArgsReference.cs, WindowsRuntimeActivationFactoryCallback.cs, WindowsRuntimeActivationTypes.cs, Windows.Foundation/TrustLevel.cs) so they can be excluded from reference-assembly builds. Tidy WinRT.Runtime.csproj Compile Remove entries (self-closing tags / spacing) and add exclusion for Windows.UI.Xaml.Interop to ensure implementation-only folders are removed from reference builds.
…2448)

* Bring back WindowsRuntimeConstants for the WindowsRuntimeObject constructor

Re-add the type removed in #2434, now holding the dedicated obsolete message, diagnostic id (CSWINRT3001) and URL format used to flag the reference-assembly-only WindowsRuntimeObject constructor.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Add a reference-assembly-only constructor for WindowsRuntimeObject

After #2446 all WindowsRuntimeObject constructors live in the implementation-only WindowsRuntimeObject.Impl.cs and are stripped from the reference assembly, so the compiler would synthesize a protected parameterless constructor. That constructor is absent from the implementation assembly and would throw MissingMethodException at runtime if a user type derived from WindowsRuntimeObject.

Explicitly define it for the reference assembly only, marked obsolete (CSWINRT3001) and hidden, so deriving from WindowsRuntimeObject produces a build diagnostic instead. Only generated projections may derive from it.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Add back the CSWINRT3001 diagnostics doc

Re-add the diagnostics doc removed in #2434, updated for the new scenario (deriving from WindowsRuntimeObject is not supported), and rename it to match the diagnostic id (updating the solution reference, which was previously dangling).

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make the dual reference-assembly build for WinRT.Runtime (set up via the
'CsWinRTBuildReferenceAssembly' switch) functional end to end, so the NuGet
package ships a proper reference assembly under 'ref\net10.0'.

The reference build recompiles WinRT.Runtime with all implementation-only
types stripped out, producing a lightweight metadata-only assembly along with
an XML doc that is likewise stripped to the public reference surface. NuGet
binds the compiler to the 'ref' assembly (and the runtime to the 'lib'
assembly), and the compiler resolves XML docs next to the compile-time
assembly, so the stripped XML is shipped next to the reference assembly in
'ref\net10.0' (IntelliSense then shows only the public surface). The 'lib'
folder ships only the implementation assembly; its XML doc is not packaged,
since it would never be surfaced and only documents implementation details.

The reference build is run as AnyCPU, matching how the solution builds the
implementation assembly, so its outputs land in the platform-less
'bin\<config>\net10.0' and 'obj\<config>\net10.0\ref' folders. Because the
reference build overwrites the 'bin' outputs, the implementation assembly is
staged out before it runs, and both are packaged from the staging folder.

- nuget: ship 'ref\net10.0\WinRT.Runtime.dll' and its XML (lib has dll only)
- build.cmd: stage the impl dll, build the reference assembly, stage ref dll + xml
- CsWinRT-Build-Steps.yml: build and stage the reference assembly and its XML
- CsWinRT-PublishToNuGet-Steps.yml: add the 'net10_runtime_ref(_xml)' props

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add docs for reference assembly and impl-only API

Document the WinRT.Runtime dual-build (implementation + stripped reference assembly) and the implementation-only API workflow. Updates include: explaining CsWinRTBuildReferenceAssembly and compilation symbols (WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY / WINDOWS_RUNTIME_REFERENCE_ASSEMBLY / WINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE), ProduceReferenceAssembly=false behavior, the WindowsRuntimeImplementationOnlyMember attribute, BannedSymbols.txt + Microsoft.CodeAnalysis.BannedApiAnalyzers guard, reference-only WindowsRuntimeObject() constructor and CSWINRT3001 diagnostic, and packaging into ref\net10.0 alongside lib\net10.0. Also update interop-generator SKILL and reference docs to note that generator-consumed runtime APIs are marked as implementation-only and stripped from the reference assembly to ensure version compatibility.

* Add docs for implementation-only WinRT.Runtime types

Add a new "Implementation-only types consumed from WinRT.Runtime" section to .github/skills/interop-generator/SKILL.md describing the categories of implementation-only APIs the generator calls (ABI marshallers, scalar/object/delegate marshallers, array marshallers, native object wrappers, interface method implementations, collection adapters, ComWrappers/object-reference types, event sources, type-map groups/attributes, IID table/error helpers). Explain that these APIs live only in the WinRT.Runtime implementation assembly, that generated code emits [IgnoresAccessChecksTo] to reach them, and note the need to version-match cswinrtinteropgen to the targeted WinRT.Runtime. Also update .github/skills/update-interop-generator-instructions/SKILL.md to add a verification step to ensure the implementation-only types inventory is current and reconciled with References/InteropReferences.cs and the WinRT.Runtime implementation.
Sergio0694 and others added 2 commits July 1, 2026 15:40
* Add isolated infrastructure for end-to-end smoke tests

Adds blank Directory.Build.props/.targets and a Directory.Packages.props that disables central package management, so the smoke tests can consume the real CsWinRT NuGet package in full isolation from the repository build infrastructure. A .gitignore keeps their default bin/obj output out of source control.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add consumption end-to-end smoke test

A .NET app that parses a JSON object from Windows.Data.Json and round-trips it via Stringify, exercising the Windows SDK projection, the interop generator, and the WinRT.Runtime ref/impl assemblies against the real NuGet package.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add authoring end-to-end smoke test

A Windows Runtime component library exposing a minimal class, exercising WinMD generation, the reference projection, and the forwarder assembly against the real NuGet package.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Build and run smoke tests in local and CI builds

Adds a runner that builds and runs the consumption test and builds the authoring test against a given package source and version, and wires it into build.cmd (after the pack step, on x64) and the PublishToNuGet CI steps (after packing).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Verify the authoring smoke test produces a .winmd defining the expected type

After building the component, the runner now locates the generated Authoring.winmd and asserts it is a Windows Runtime metadata file that defines the Authoring.Greeter type, using a dependency-free inspection that works in any PowerShell host.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Trim comments and whitespace in smoke tests

Remove explanatory comments and extra blank lines from SmokeTests projects and source files to reduce noise. Changes touch Authoring.csproj, Greeter.cs, Consumption.csproj, Program.cs, Directory.Build.props, Directory.Build.targets, and Directory.Packages.props. No functional code changes — only formatting and comment cleanup to keep the smoke test files minimal.

* Centralize shared smoke test configuration in Directory.Build.props

Moves the target framework, Windows SDK ref pack pin, NuGet restore sources, CsWinRT package version/source, and the CsWinRT package reference (all previously duplicated in both smoke test projects) into the shared SmokeTests Directory.Build.props. Each project now only declares what makes it different: the consumption app's output type and the authoring library's component flag.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Document the smoke tests and refresh test documentation

Updates the testing skill and docs/structure.md to account for the new SmokeTests projects, and fixes other outdated test documentation: expands the SourceGenerator2Test analyzer test list (now CSWINRT2009-2017), corrects the AuthoringTest status and TFM, fixes the TestComponentCSharp IDL filename and the cswinrt.slnx reference, and lists the missing test projects in the repository structure doc. Also adds a smoke-tests verification step to the update-testing-instructions skill.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Use the CsWinRTDependencies feed for smoke test restore

CI agents cannot reach public NuGet (api.nuget.org), which broke the smoke test restore. Restore the preview Windows SDK ref pack from the repository's standard CsWinRTDependencies feed instead (the same feed the rest of the repo uses, e.g. src/WinRT.Internal), keeping the local CsWinRT build output as the source for the package under test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Keep type map group types in the WinRT.Runtime reference assembly

The type map group types (WindowsRuntimeComWrappersTypeMapGroup, WindowsRuntimeMetadataTypeMapGroup, and DynamicInterfaceCastableImplementationTypeMapGroup) were stripped from the reference assembly as implementation-only types. However, they are referenced by code the CsWinRT source generator emits into consumer assemblies (the '[assembly: TypeMapAssemblyTarget<T>]' attributes that register assemblies for the interop type map infrastructure), which is compiled against the reference assembly. Stripping them broke consumers with CS0234.

Keep these three types in the reference assembly, and instead mark them '[Obsolete]' (with the new CSWINRT3002 diagnostic) and '[EditorBrowsable(Never)]', only in the reference assembly, to discourage direct use in user code. This mirrors the reference-assembly-only obsolete pattern already used for the parameterless 'WindowsRuntimeObject' constructor (CSWINRT3001). The marker is reference-assembly-only because the implementation assembly has internal '[assembly: TypeMap<T>]' usages that would otherwise trip the obsolete warning. The projection writer's generated-file header now also suppresses CSWINRT3002, since the generated projection code references these types. Adds the docs/diagnostics/cswinrt3002.md page.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Run each smoke test as its own CI step with a final failure gate

Previously all smoke tests ran in a single CI step, so a failure didn't make it obvious which one failed. Following the unit test pattern in CsWinRT-Test-Steps.yml, each smoke test now runs as its own step with 'continueOnError' (an individual failure only marks the job as 'SucceededWithIssues'), and a final gate step turns any such issue into an actual failure. This makes it clear exactly which smoke test failed while still letting every test run and report.

The runner script gains a '-Test' parameter (Consumption, Authoring, or All) so CI can invoke a single test per step; local builds keep using the default 'All'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Compile generated projections against the WinRT.Runtime implementation assembly

The NuGet package ships WinRT.Runtime as both a reference assembly (ref/net10.0, with implementation-only types stripped) and an implementation assembly (lib/net10.0). The projection and interop generators compile and inspect generated implementation projection code that references those implementation-only types (e.g. WindowsRuntimeObjectReferenceValue, RestrictedErrorInfo, the marshallers), so they must use the implementation assembly rather than the reference assembly that MSBuild resolves for compilation.

Introduce a CsWinRTRuntimeImplementationAssemblyPath property (defaulting to the package lib layout) and swap WinRT.Runtime for it in each affected generator target. Repo-internal builds override the property to point at the locally built implementation assembly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Make the WinRT.Runtime reference assembly swap an explicit opt-out

The prior commit made the projection and interop generators unconditionally swap the WinRT.Runtime reference assembly for an implementation assembly, and overrode CsWinRTRuntimeImplementationAssemblyPath in src/Directory.Build.props to point at src/WinRT.Runtime2/bin/<config>/net10.0/WinRT.Runtime.dll. The official build rebuilds that bin output as the stripped reference assembly (CsWinRTBuildReferenceAssembly=true), so the override pointed the generators at the stripped assembly and broke repo builds.

The package always lays out both the reference assembly (ref/net10.0) and the implementation assembly (lib/net10.0), so the generators can simply assume the implementation assembly is present and swap to it; if it were ever missing, the smoke tests (and any real consumer) would fail loudly. The swap is now controlled by CsWinRTSwapRuntimeReferenceAssembly (default true). This repo references WinRT.Runtime directly as its implementation assembly, so it opts out via src/Directory.Build.props. The fragile bin-pointing override is removed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Expose the authoring component assembly attributes in the reference assembly (CSWINRT3003)

The authoring smoke test failed to build because the CsWinRT source generator emits '[assembly: WindowsRuntimeComponentAssembly]' and '[assembly: WindowsRuntimeComponentAssemblyExportsType(...)]' into the component (in 'ManagedExports.g.cs'), but both attributes were stripped from the 'WinRT.Runtime' reference assembly (they were marked as implementation-only files), so the component compilation could not resolve them.

Keep both attributes in the reference assembly and mark them, only there, with a reference-assembly-only '[Obsolete]' (new diagnostic CSWINRT3003) plus '[EditorBrowsable(Never)]', exactly like the type map group types (CSWINRT3002). The generated code that applies them already suppresses warnings, so normal builds are unaffected, while direct use in user code is discouraged. Add a 'docs/diagnostics/cswinrt3003.md' page describing the diagnostic.

Also fix a related leak: the 'ReferenceVftbl' struct in the projection writer's 'InspectableVftbl' baseline declared its 'GetTrustLevel' slot as 'TrustLevel*', referencing the implementation-only 'Windows.Foundation.TrustLevel' enum. The slot is layout-only (the vtable is populated by copying 'IInspectableImpl.Vtable' and only 'get_Value' is set), so type it as 'int*' to match 'IInspectableVftbl.GetTrustLevel' and keep 'TrustLevel' out of the generated component projection.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Move vtable types to runtime and add assembly attributes

Relocate and consolidate vtable and assembly metadata: removed the duplicate InspectableVftbl resource and added a shared AssemblyAttributes.cs. Updated ReferenceImplFactory to reference IReferenceVftbl. Adjusted IInspectableVftbl, IReferenceVftbl and IUnknownVftbl visibility and API surface (made structs public, marked with WindowsRuntimeImplementationOnlyMember, tightened helper methods to internal, and added pragma disables). These changes centralize vtable definitions in the runtime project and unify assembly-level attributes (DisableRuntimeMarshalling / trimmable/AOT metadata) for projection builds.

* Remove unsupported-marshalling remarks from enums

Drop redundant XML <remarks> comments that stated marshalling was not supported for TrustLevel and TypeKind. Clean up TrustLevel.cs and TypeKind.cs by removing the two-line remarks blocks so the enum docs are concise. No behavior changes.

* Skip the reference projection generator for input-less authored components

When a project is an authored Windows Runtime component ('CsWinRTComponent=true') that does not reference any input .winmd files, there are no Windows Runtime types for 'cswinrtprojectionrefgen' to project: the component only authors its own types, which are described by the .winmd that 'cswinrtwinmdgen' emits and projected into 'WinRT.Component.dll' by 'cswinrtprojectiongen'.

Skip invoking the reference projection generator in that case. This keeps authoring-only builds faster and avoids emitting projection support code (and its assembly-level attributes) into the component's own assembly. The skip is decided in the target body, where '@(CsWinRTInputs)' is reliably populated by the 'CsWinRTRemoveWinMDReferences' dependency (a target condition would evaluate before that item is populated).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Set DisableRuntimeMarshalling for the smoke test projects

CsWinRT relies on runtime marshalling being disabled for its interop. Authored components normally get '[assembly: DisableRuntimeMarshalling]' emitted in generated projection source, but an input-less component now skips the reference projection generator entirely, so the project must opt in itself. Set it in the shared smoke test 'Directory.Build.props', exactly as a real component author would in their own project.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Run the smoke tests on both CoreCLR and Native AOT

Add a '-Runtime' parameter to the smoke test runner: 'CoreCLR' (default) keeps the existing build-and-run behavior, while 'NativeAot' publishes the project with 'PublishAot=true' for win-x64, exercising the full publish pipeline (projection and interop generators, then ILC). Consumption publishes a self-contained app and runs it directly from the '.exe'; authoring just verifies the component publishes cleanly (the output is never loaded).

In CI, suffix the existing smoke test steps with '(CoreCLR)' and add a '(NAOT)' step after each, so a failure points at the exact runtime. All four keep 'continueOnError' and feed the existing final gate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Document the public-but-hidden implementation-only type strategy

CsWinRT now keeps a few implementation-only types public in the reference assembly but hidden (reference-assembly-only [Obsolete] + [EditorBrowsable(Never)]), instead of stripping them entirely. Explain both strategies and why stripping is not always possible: when CsWinRT-generated user code names the type and is compiled against the reference assembly, stripping would cause CS0234/CS0246, so the type must remain present but discouraged. Cover the current cases (CSWINRT3002 type map groups, CSWINRT3003 component authoring attributes, CSWINRT3004 TrustLevel) and update the runtime error-id table accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Cover the public-but-hidden implementation-only type strategy in the maintenance skills

The two 'update-*-instructions' skills drive the self-maintenance of copilot-instructions.md and the interop-generator SKILL.md, but their checklists did not mention the public-but-hidden implementation-only type strategy that those docs now describe. Extend the WinRT.Runtime and source-generator verification items in the copilot-instructions maintenance skill to cover the two strategies (strip-entirely vs public-but-hidden) and the current CSWINRT3001-3004 cases, and extend the interop-generator maintenance skill (resolvers/references and related-docs steps) to verify the public-but-hidden note and the marking scheme.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Include RestrictedErrorInfoExceptionMarshaller

Add an explicit <Compile Include> for InteropServices/Marshalling/RestrictedErrorInfoExceptionMarshaller.cs so the public RestrictedErrorInfoExceptionMarshaller type is present in reference assemblies. The file was previously excluded by the blanket removals; we add it back manually for simplicity while keeping other implementation-only folders excluded.

* Add a projection smoke test for the real NuGet package

Add a third smoke test that generates a reference projection for a third-party Windows Runtime component, exactly as a NuGet projection author would. It sets 'CsWinRTGenerateReferenceProjection=true' and points 'CsWinRTInputs' at a '.winmd', exercising 'cswinrtprojectionrefgen' and 'cswinrtimplgen' end-to-end against the packed package.

The projected metadata is reused from the sibling 'Authoring' smoke test: a build-ordering 'ProjectReference' (ReferenceOutputAssembly/Private both false, mirroring 'src/WinRT.Internal') ensures 'Authoring.winmd' exists before this project runs the generator, avoiding a separate hand-authored '.winmd'. The test is build-only (CoreCLR), verifying both a forwarder and a 'ref' reference assembly are produced.

Wire it into 'run-smoke-tests.ps1' (-Test Projection, skipped for Native AOT), 'src/build.cmd', and a CoreCLR CI step, and document it in docs/structure.md and the testing skills.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Make WindowsRuntimeReferenceAssemblyAttribute public-but-hidden (CSWINRT3004)

The reference projection generator emits '[assembly: WindowsRuntimeReferenceAssembly]' into the projection assemblies it produces (via the projection writer's 'AssemblyAttributes.cs' base resource), and that attribute genuinely ships in the reference projection assemblies of Windows Runtime projection NuGet packages. It must therefore remain resolvable in the 'WinRT.Runtime.dll' reference assembly, so it cannot be stripped like other implementation-only types.

Apply the same public-but-hidden strategy already used for the type map group types (CSWINRT3002) and the component authoring attributes (CSWINRT3003): keep the type in the reference assembly but mark it reference-assembly-only '[Obsolete(DiagnosticId = CSWINRT3004)]' + '[EditorBrowsable(Never)]' to discourage direct use. Add the obsolete message/diagnostic-id constants, a 'docs/diagnostics/cswinrt3004.md' page, and suppress the diagnostic in the generated 'AssemblyAttributes.cs'. Update the copilot instructions (the two-strategies note and the error-id table) and the maintenance skill, repurposing the previously-stale CSWINRT3004 id (it had been documented for a since-reverted 'TrustLevel' case that no longer exists).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Stop reference projections from referencing implementation-only types

A reference projection ships in a Windows Runtime projection NuGet package and is compiled (with 'ProduceOnlyReferenceAssembly') against the stripped 'WinRT.Runtime.dll' reference assembly, which contains only the public API surface. The projection writer was emitting code that referenced implementation-only types in signature positions (field types, method parameters, base types, attributes) that do not exist in that reference assembly, so building a reference projection from the package failed to compile (CS0246/CS0234).

In reference-projection mode, stop emitting the implementation-only signatures: the '[WindowsRuntimeMetadata]' attribute, the private '_objRef_*' fields (typed 'WindowsRuntimeObjectReference'), the static activation-factory object references, the activation-factory plumbing (factory callback classes and args structs), and the '[UnsafeAccessor]' static extern declarations (whose parameters are typed 'WindowsRuntimeObjectReference'). Constructors keep their public signatures but emit a 'throw null' body instead of a base call referencing implementation-only activation types. Member bodies are unaffected: a reference assembly compile does not bind method bodies, so the public member signatures are all that needs to resolve. Implementation-mode output is unchanged.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Broaden the authoring smoke test to cover more projection shapes

The authoring smoke test produces 'Authoring.winmd', which the projection smoke test then generates a reference projection for. Add a richer set of authored Windows Runtime types alongside the existing 'Greeter' so the projection path exercises more codegen: two enums (including a [Flags] enum), a struct, a delegate, an interface, and a runtime class with two constructors (default and parameterized), instance methods, a settable property, an interface-implemented property, an event, and static members.

Validated end-to-end locally: the types compile, 'cswinrtwinmdgen' emits a valid '.winmd' for them, and the resulting reference projection compiles cleanly against the stripped 'WinRT.Runtime' reference assembly (no implementation-only types referenced).

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Recognize reference projection types in interop generator discovery

The interop generator identified projected Windows Runtime types via the
per-type [WindowsRuntimeMetadata] attribute (IsProjectedWindowsRuntimeType).
That attribute is now stripped from reference projections (it is an
implementation-only type, absent from the WinRT.Runtime reference assembly
that reference projections compile against), so the type-hierarchy discovery
crawl over reference projection assemblies stopped recognizing any projected
classes and failed with CSWINRTINTEROPGEN0036 (no type hierarchy key-value
pairs discovered).

Add IsReferenceProjectionWindowsRuntimeType, which recognizes a projected
type by its declaring assembly's [WindowsRuntimeReferenceAssembly] marker,
mirroring the existing IsComponentWindowsRuntimeType handling for authored
components (which likewise expose projected types without the per-type
attribute). Fold it into the five "is this a projected Windows Runtime type"
gates that can observe reference projection definitions directly (type
hierarchy base-type tracking, IsProjectedWindowsRuntimeClassType,
IsWindowsRuntimeType, IsNotExclusiveToWindowsRuntimeType, and the projected
interface branch in InteropInterfaceEntriesResolver).

The type-hierarchy base-type check now inspects the resolved base type
definition (instead of the unresolved reference) so the assembly-level
marker can be read off it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Recover Windows Runtime metadata name from the implementation projection

The interop type-name marker for a third-party (non-well-known) projected type
must be the source .winmd stem, because the projection writer encodes that same
stem into the [UnsafeAccessorType] references it bakes into the implementation
projection (WinRT.Projection.dll). The generator read that stem from the per-type
[WindowsRuntimeMetadata] attribute.

That attribute is now stripped from reference projections (it is an
implementation-only attribute, absent from the WinRT.Runtime reference assembly
they compile against). The discovery input set keeps the reference projection and
excludes the forwarder/impl .dll, so a third-party type resolves to the reference
projection where the attribute is gone. The marker would then fall back to the
reference projection's own assembly name, which is not guaranteed to equal the
.winmd stem (e.g. WinUI / Windows App SDK merge several .winmd files into one
projection assembly), producing [UnsafeAccessor] references that don't match the
generated interop type names.

Add a TypeDefinition.GetWindowsRuntimeMetadataName(RuntimeContext) overload that
reads the attribute directly when present, and otherwise — for a type from a
reference projection — recovers the stem from the matching type in the third-party
implementation projection (WinRT.Projection.dll), which retains it. The
implementation projection is located through RuntimeContext.GetLoadedAssemblies(),
which returns assemblies loaded via LoadModule even when they are outside the
resolver's path set, so this needs no changes to the many InteropUtf8NameFactory
call sites (they already flow the RuntimeContext through). When the stem cannot be
found, the caller's fallback to the assembly name is preserved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Emit XAML struct metadata attributes only for implementation projections

The hand-authored full-replacement XAML struct additions (CornerRadius,
Duration, GridLength, KeyTime, RepeatBehavior, Matrix3D, for both the
Windows.UI.Xaml and Microsoft.UI.Xaml namespaces) carried their
[WindowsRuntimeMetadata("...")] attribute outside the
'#if !CSWINRT_REFERENCE_PROJECTION' block, so it was also emitted into
reference projections. That attribute is implementation-only and is stripped
from the WinRT.Runtime reference assembly, so a reference projection compiled
against that reference assembly would fail to resolve it.

Move the attribute inside the existing '#if !CSWINRT_REFERENCE_PROJECTION'
block, alongside the other implementation-only attributes
([WindowsRuntimeClassName] and the ComWrappers marshaller), so it is only
emitted for implementation projections.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Emit GetDefaultInterface helper only for implementation projections

The 'internal new GetDefaultInterface()' helper emitted on unsealed projected
runtime classes returns 'WindowsRuntimeObjectReferenceValue', which is an
implementation-only type stripped from the WinRT.Runtime reference assembly.
It was emitted in both implementation and reference-projection modes, but its
only consumer is the ABI marshaller (also implementation-only and not emitted
in reference-projection mode). As a result, the helper was dead code in a
reference projection, yet it still failed to compile against the WinRT.Runtime
reference assembly that reference projections bind against.

This only surfaced for unsealed classes: the helper exists so that overrides on
derived classes can hide it with 'new', so sealed classes never emit it. That is
why simple sealed components (e.g. the authoring smoke test) never hit it, while
the Windows SDK XAML projections (full of unsealed base classes) did.

Gate the helper on '!context.Settings.ReferenceProjection', matching the sibling
'IWindowsRuntimeInterface<T>.GetInterface()' helper, so neither is emitted into
reference projections.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarify runtime class shapes in Thermometer test

Update Thermometer smoke test comments to mention both a sealed (non-derivable) runtime class and an unsealed (derivable) runtime class. Add a commented-out Weather class (TODO) to represent an unsealed runtime class for future authoring support. The change documents intended coverage and leaves a placeholder for when unsealed class authoring is supported.

* Guard implementation-only TokenizerHelper usage in reference projections

The hand-authored XAML struct/Color additions (CornerRadius, Thickness, Matrix,
Matrix3D for both Windows.UI.Xaml and Microsoft.UI.Xaml, plus Windows.UI.Color)
format their ToString output using 'WindowsRuntime.InteropServices.TokenizerHelper'
to get the culture's numeric list separator. That helper is an implementation-only
API ([WindowsRuntimeImplementationOnlyMember]) that is stripped from the
WinRT.Runtime reference assembly, so a reference projection that includes any of
these types fails to compile against that reference assembly (CS0234).

Following the same pattern the runtime uses for its reference-assembly stubs,
guard each affected method body with '#if CSWINRT_REFERENCE_PROJECTION' / 'throw
null;' / '#else' / the existing implementation / '#endif'. The implementation
projection keeps the real body; the reference projection gets a stub, so it no
longer references the stripped helper. The bodies are never executed in a
reference projection (the real implementation is generated at app build time).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Guard implementation-only DispatcherQueueSynchronizationContext wrappers

The DispatcherQueueSynchronizationContext additions (Windows.System and
Microsoft.UI.Dispatching) wrap the implementation-only
'WindowsRuntime.InteropServices.DispatcherQueueSynchronizationContext'
([WindowsRuntimeImplementationOnlyMember], stripped from the WinRT.Runtime
reference assembly). The impl-only type appeared in a private field, both
constructors, and every method body, so a reference projection that included
these types failed to compile against the reference assembly.

Guard the implementation-only members (the private '_innerContext' field and the
private copy constructor) with '#if !CSWINRT_REFERENCE_PROJECTION', and stub the
public API bodies (the public constructor, Post, Send, CreateCopy) with
'#if CSWINRT_REFERENCE_PROJECTION' / 'throw null;' / '#else'. The reference
projection keeps the public API surface but no longer references the stripped
type; the real implementation is generated for the implementation projection at
app build time.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Stub mapped-interface members in reference projections

MappedInterfaceStubFactory emits the C# collection-interface members (IList<T>,
IDictionary<K,V>, IEnumerable<T>, IDisposable, the bindable collections, and
INotifyDataErrorInfo) on classes that implement the corresponding WinRT
interfaces. It already skipped its implementation-only '[UnsafeAccessor]' externs
in reference-projection mode, but it still emitted the member *bodies*, which
reference those skipped externs (the '*Methods_*' helpers), the skipped '_objRef_*'
fields, and the implementation-only 'ABI.*Methods' helpers. None of those exist in
a reference projection, so a reference projection that included any mapped-collection
class failed to compile against the stripped WinRT.Runtime reference assembly.

Give each per-interface 'Emit*' method a reference-projection-first branch that
emits the full member set as a single stub (every body is 'throw null'), keeping
the public member signatures identical to the implementation projection. The
implementation path is unchanged. The previously inline switch cases
(IBindableIterable, IBindableIterator, INotifyDataErrorInfo) are extracted into
their own 'Emit*' methods so they follow the same shape.

Validated that the implementation-projection output is byte-for-byte identical to
before across the full Windows SDK projection (no runtime impact), and that the
reference projection no longer references any of the stripped plumbing. This
removes ~4,900 of the reference-projection compile errors against the stripped
reference assembly (the remaining errors are tracked separately in #2468).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Make the synthetic ref-mode ctor accessible to derived projected classes

In a reference projection, a projected class with no activatable/composable
constructors gets a synthetic 'private TypeName() { throw null; }' ctor to
suppress the C# compiler's implicit public default constructor. When such a class
is the base of another projected class (e.g. 'UriActionEntity : ActionEntity'),
the derived class's own synthetic ctor implicitly chains to the base's
parameterless ctor -- which was 'private', so the derived class failed to compile
against the stripped WinRT.Runtime reference assembly (CS0122). The real
'WindowsRuntimeObjectReference'-based ctor that derived classes chain to in the
implementation projection is not emitted in a reference projection, so the
synthetic ctor is the only one available.

Emit the synthetic ctor as 'private protected' for unsealed classes (which can be
base classes), so derived projected classes in the same projection can chain to
it. Sealed classes keep 'private'. The ctor stays non-public, so it still
suppresses the implicit public default constructor and does not widen the public
API surface. The implementation projection is unaffected (its output is unchanged).

This removes the CS0122 reference-projection errors (tracked in #2468).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Emit accessible parameterless ctor for unsealed composable classes in ref projections

In reference-projection mode the real WindowsRuntimeObjectReference-based base
constructor is not emitted, so a derived projected class's ref-mode constructor
(whose implicit base() call has no target) fails to compile against an unsealed
base that only exposes parameterized composable constructors.

Emit a 'private protected TypeName() { throw null; }' for unsealed classes that
don't already emit a public parameterless constructor (a default [Activatable], or
a factory/composable method with no user parameters), giving derived projected
classes a base-chain target. Sealed classes keep the existing behavior (a synthetic
ctor only to suppress the implicit public default ctor when none are emitted).

Validated byte-identical implementation-mode output for the full Windows SDK
projection; reduces the reference-projection compile from 192 to 12 errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Guard implementation-only storage-extension bodies in reference projections

WindowsRuntimeStorageExtensions calls implementation-only APIs (WindowsRuntimeIOHelpers
and the IStorage*HandleAccessMethods classes) that are absent from the WinRT.Runtime
reference assembly, so the hand-authored Windows.Storage addition failed to compile in
reference-projection mode.

Following the same pattern the runtime uses for its reference-assembly stubs (and the
earlier TokenizerHelper guard), wrap each affected method body with
'#if CSWINRT_REFERENCE_PROJECTION' / 'throw null;' / '#else' / the existing
implementation / '#endif'. The implementation projection keeps the real body; the
reference projection gets a stub. The added directives are inert when
CSWINRT_REFERENCE_PROJECTION is undefined, so implementation-mode output is unchanged.

With this fix the full Windows SDK reference projection compiles with 0 errors against
the stripped WinRT.Runtime reference assembly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add Windows SDK and XAML reference-projection smoke tests

Generating the Windows SDK reference projections (the 'Microsoft.Windows.SDK.NET.Ref'
projection packages) is exactly what a downstream repository does with the CsWinRT
package, and it is where reference-projection codegen regressions surface: the generated
projection must compile against the stripped 'WinRT.Runtime' reference assembly, with no
references to implementation-only runtime types. Add two end-to-end smoke tests that
exercise this so such regressions fail here, early, instead of breaking that package.

  * WindowsSdkProjection generates the base Windows SDK reference projection from the
    'Microsoft.Windows.SDK.Contracts' '.winmd' files.
  * WindowsSdkXamlProjection generates the 'Windows.UI.Xaml' reference projection, which
    references the base projection above (mirroring how the UWP XAML projection package
    depends on the base Windows SDK projection package).

Both mirror the existing 'Projection' smoke test (CsWinRTGenerateReferenceProjection) and
the Windows SDK metadata staging in 'WinRT.Sdk.Projection.csproj', and use the same
namespace include/exclude split the projection generator applies for 'WinRT.Sdk.Projection'
and 'WinRT.Sdk.Xaml.Projection' (see 'WriteWindowsSdkFilters'). The shared
'WindowsSdkContracts.targets' downloads 'Microsoft.Windows.SDK.Contracts' and feeds its
'.winmd' files into '@(CsWinRTInputs)'. That package, like the preview Windows SDK ref pack,
is restored from the CsWinRTDependencies feed, alongside the local package under test.

The reference-projection verification in 'run-smoke-tests.ps1' (forwarder + reference
assembly produced) is shared across all three reference-projection tests, and both new
tests are build-only (CoreCLR), wired into the CI as their own 'continueOnError' steps.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Build the Windows SDK projection smoke tests as plain net10.0

The two Windows SDK reference-projection smoke tests inherited the '-windows10.0.26100.1'
target framework from the shared 'Directory.Build.props'. That target framework makes the
.NET SDK add an implicit reference to the prebuilt Windows SDK projection
('Microsoft.Windows.SDK.NET.dll') -- the very projection these tests regenerate -- so every
generated type collided with its prebuilt counterpart (tens of thousands of CS0436), and
'ApiContractAttribute' collided between 'Microsoft.Windows.SDK.NET' and 'WinRT.Runtime'
(CS0433), failing the build.

Override the target framework to plain 'net10.0' for both projects, exactly as the real
Windows SDK projection is built ('src/WinRT.Sdk.Projection/WinRT.Sdk.Projection.csproj'):
generating the Windows SDK projection means it cannot reference the Windows SDK projection.
The base 'Windows.*' types the XAML projection needs come from the sibling 'WindowsSdkProjection'
reference assembly instead. The '-windows'-specific properties the shared props also set
('TargetPlatformMinVersion', 'WindowsSdkPackageVersion') are inert without a target platform.
The package's reference-projection flow fully supports this (CsWinRTExeTFM resolves to
'net10.0' for any net10.0+ target framework), and the generated projection still compiles
against the packaged 'WinRT.Runtime' reference assembly (NuGet uses 'ref/net10.0' at compile
time), which is what these tests validate.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

* Simplify over-escaped interpolated raw strings in MappedInterfaceStubFactory

Several reference- and implementation-mode stub strings used the '$$""" + ... + """'
form (with '{{x}}' interpolation holes) even though their content has no literal braces,
so the doubled '$$' was unnecessary. Reduce those six to a single '$' (with '{x}' holes).
The strings that do contain literal braces (indexers, event accessors, 'Dispose() { }')
still need '$$' and are left unchanged. This is a purely cosmetic change: the generated
text is identical.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update testing skill for the Windows SDK projection smoke tests

The smoke tests section listed three projects; it now documents all five, adding
'WindowsSdkProjection' and 'WindowsSdkXamlProjection' (the Windows SDK reference
projections built from 'Microsoft.Windows.SDK.Contracts', staged by the shared
'WindowsSdkContracts.targets'). Also correct the smoke tests' shared configuration:
'RestoreSources' uses the local package output plus the 'CsWinRTDependencies' feed (not
public NuGet), the two SDK projection tests override the target framework to plain
'net10.0', and the reference-projection verification is shared across all three
reference-projection tests (build-only, CoreCLR). Refresh the 'Authoring' smoke test
description to reflect its broader authored type catalog ('Thermometer.cs'), and update
the routing table accordingly.

Update the 'update-testing-instructions' skill's smoke-test verification step to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Use <see> tag for TypeDefinition in docs

Replace XML <c> tag with a <see cref="TypeDefinition"/> reference in the GetWindowsRuntimeMetadataName documentation to produce a proper XML doc reference and improve IntelliSense/linking. No functional changes.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant