Add end-to-end smoke tests for the CsWinRT NuGet package#2456
Open
Sergio0694 wants to merge 42 commits into
Open
Add end-to-end smoke tests for the CsWinRT NuGet package#2456Sergio0694 wants to merge 42 commits into
Sergio0694 wants to merge 42 commits into
Conversation
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>
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>
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>
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>
…ed 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>
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.
83a4142 to
42e58d7
Compare
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>
42e58d7 to
de07e31
Compare
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>
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>
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>
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>
…n 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>
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>
…ssembly (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>
85022f7 to
9b524b3
Compare
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.
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.
a69dd92 to
9af3bda
Compare
…nents
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>
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>
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>
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>
…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>
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 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>
3bc4fb3 to
956937e
Compare
…NRT3004) 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>
2e540ad to
f2b9278
Compare
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>
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>
7da8415 to
d7f00d4
Compare
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>
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>
1be69e0 to
e29c0d3
Compare
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>
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>
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.
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>
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>
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>
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>
… 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>
…ctions 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>
0580ff7 to
5362e08
Compare
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>
5362e08 to
c140feb
Compare
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>
456201f to
3d84e8a
Compare
…Factory
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>
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>
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds minimal, isolated end-to-end smoke tests that consume the real
Microsoft.Windows.CsWinRTNuGet package — a consumption app and an authoring component — to verify the package works correctly in a real production environment, independent of the repository's own build infrastructure.Motivation
The CsWinRT 3.0 build pipeline is complex (reference projections, forwarder assemblies, several post-build generators, and the dual reference/implementation
WinRT.Runtimeassembly added in this branch). The existing unit and functional tests all build against the local build infrastructure (SimulateCsWinRTNugetReference, project references to the in-repo projections, etc.), so they never exercise the actual packagedref/libassemblies, the packaged generators, or the NuGet build targets the way a real customer consumes them. These smoke tests close that gap: they reference the packed NuGet package exactly like an external app or component author would, validating that the correct assemblies are referenced and that all generators run correctly end-to-end.Changes
The smoke tests live under
src/Tests/SmokeTests/and are intentionally kept out ofcswinrt.slnx(the package they consume only exists after the build packs it).src/Tests/SmokeTests/Directory.Build.props/Directory.Build.targets: blank files that isolate the smoke tests from the repository build infrastructure, so they inherit nothing fromsrc/Directory.Build.*.src/Tests/SmokeTests/Directory.Packages.props: disables central package management for the smoke tests (and shadows the repositoryDirectory.Packages.props), so each project pins the CsWinRT package version directly.src/Tests/SmokeTests/.gitignore: ignores the defaultbin/objoutput (these projects use the default output folders rather than the repo_buildredirect).src/Tests/SmokeTests/Consumption/: anExethat callsJsonObject.Parse(...)thenStringify()fromWindows.Data.Json, exercising the Windows SDK projection, the interop generator, and theWinRT.Runtimeref/impl assemblies.src/Tests/SmokeTests/Authoring/: aCsWinRTComponentlibrary exposing a minimalGreeterclass, exercising WinMD generation, the reference projection, and the forwarder assembly.src/Tests/SmokeTests/run-smoke-tests.ps1: builds and runs the consumption test (asserting a clean exit code), then builds the authoring test and verifies that the generatedAuthoring.winmdis a valid Windows Runtime metadata file definingAuthoring.Greeter.src/build.cmd: runs the smoke tests after the localnuget packstep (x64 only; skippable viacswinrt_run_smoke_tests=false).build/AzurePipelineTemplates/CsWinRT-PublishToNuGet-Steps.yml: runs the smoke tests after the CINuGet packstep, against the freshly packed package.Both projects override
RestoreSourcesto restore the package being tested from the local build output (or the CI pack output) and everything else — notably the preview Windows SDK ref pack — from public NuGet. They use the real .NET SDK targeting pack via a pinnedWindowsSdkPackageVersionand the.1Windows TFM revision, mirroringsrc/WinRT.Internal. The package version and source default to the localbuild.cmd x64 Releaseoutput and are overridden by the build or CI that produced the package.Validation
Verified end-to-end against a real CsWinRT 3.0 package using the committed configuration: the consumption test builds and runs (round-tripping the JSON to
{"a":42}with a clean exit), and the authoring component's generatedAuthoring.winmdis confirmed to defineAuthoring.Greeter. In CI the same runner executes against the freshly packed package.