Skip to content

Port WinMD generator#2393

Open
manodasanW wants to merge 50 commits intostaging/3.0from
manodasanw/winmdgenerator
Open

Port WinMD generator#2393
manodasanW wants to merge 50 commits intostaging/3.0from
manodasanw/winmdgenerator

Conversation

@manodasanW
Copy link
Copy Markdown
Member

  • Ported the WinMD generator for authoring support from a rosyln source generator in CsWinRT 2.x to a build task that analyzes the DLL and generates a WinMD file.
  • For consistency with our other build tools / generators, making use of AsmResolver to do the reading of the dll and writing of WinMD file.

manodasanW and others added 30 commits April 15, 2026 00:21
…inMD generator

- Fix static class type attributes: abstract-only classes no longer incorrectly
  get Sealed flag; static classes (abstract+sealed) now correctly get both
  Sealed and Abstract flags, matching the original source generator behavior
- Implement full custom attribute copying from input types/members to WinMD
  output, replacing the previous stub with CopyCustomAttributes that:
  - Filters out GuidAttribute, GeneratedBindableCustomProperty, VersionAttribute
    (handled separately), and System.Runtime.CompilerServices.* attributes
  - Skips non-public attribute types
  - Imports constructor references with type remapping
  - Clones attribute signatures including fixed args, named args, and arrays
  - Handles Type-valued elements via TypeSignature remapping
- Copy custom attributes at all member creation points: methods (class and
  interface), properties, and events
- Remove both TODO comments (custom attribute encoding and static class detection)

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

- Filter class interface implementations: skip interfaces that have a WinRT
  mapping (added separately by ProcessCustomMappedInterfaces) and interfaces
  in ImplementedInterfacesWithoutMapping (ICollection, IEnumerator, etc.)
  to avoid duplicate and spurious interfaces in the WinMD output
- Fix interface method filter: change '!IsPublic && IsPrivate' to '!IsPublic'
  so internal/protected methods are correctly excluded from WinMD interfaces
- Improve FindMatchingMethod to compare parameter types (via FullName) in
  addition to name and count, preventing incorrect MethodImpl records for
  overloaded methods with different parameter types

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The original source generator discovers nested types via recursive syntax
walking. The port only walked TopLevelTypes, missing nested public types.

- DiscoverPublicTypes now recursively walks TypeDefinition.NestedTypes
- Add GetEffectiveNamespace helper that traverses the declaring type chain
  to find the namespace for nested types (which have null namespace in
  ECMA-335 metadata)
- Update GetQualifiedName to use GetEffectiveNamespace so nested types
  get correct qualified names (e.g. 'MyNs.Inner' instead of just 'Inner')
- Update all Add*Type methods in WinmdWriter to use GetEffectiveNamespace
  instead of inputType.Namespace directly

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Exclude properties and events from the synthesized default interface when
  they are already provided by an implemented interface, matching the
  original source generator behavior. Uses accessor name matching (get_/add_)
  against the membersFromInterfaces set.
- Use GetEffectiveNamespace in ImportTypeReference fallback path so nested
  TypeDefinitions that aren't yet in the type mapping get correct namespace
  in their TypeReference.
- Update GetQualifiedName(ITypeDefOrRef) to use GetEffectiveNamespace for
  TypeDefinition arguments, ensuring nested types get correct qualified
  names for TypeMapper lookups.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Align WinRT.WinMD.Generator with the patterns used by WinRT.Interop.Generator,
WinRT.Impl.Generator, and WinRT.Projection.Generator:

csproj:
- Add IsBuildTool with conditional RuntimeIdentifier/SelfContained for publishing
- Add common metadata properties (Description, AssemblyTitle, Copyright, etc.)
- Split NativeAOT settings into separate PropertyGroup with missing settings:
  ControlFlowGuard, IlcDehydrate, IlcResilient, UseSystemResourceKeys (Release)
- Change LangVersion from 14.0 to preview (matches Impl/Projection)

Error handling:
- Add WellKnownWinMDException base class with error ID and formatted ToString()
- Add UnhandledWinMDException with phase tracking and bug-report message
- Update WellKnownWinMDExceptions to use error code prefix CSWINRTWINMDGEN
  with numbered IDs (0001-0006) instead of generic InvalidOperationException
- Add Extensions/WinMDExceptionExtensions.cs with IsWellKnown extension

Generator structure:
- Make WinMDGenerator a partial class split by phase:
  - WinMDGenerator.cs: Run() with try-catch-when per phase
  - WinMDGenerator.Discover.cs: assembly loading and type discovery
  - WinMDGenerator.Generate.cs: WinMD generation and writing
- Add WinMDGeneratorDiscoveryState to pass state between phases

WinmdWriter decomposition:
- Split 1819-line WinmdWriter.cs into partial files:
  - WinmdWriter.cs: core (fields, ProcessType, FinalizeGeneration, Write)
  - WinmdWriter.Types.cs: enum/delegate/interface/struct/class processing
  - WinmdWriter.SynthesizedInterfaces.cs: synthesized + custom mapped interfaces
  - WinmdWriter.Members.cs: method/property/event helpers
  - WinmdWriter.TypeMapping.cs: type signature mapping + type references
  - WinmdWriter.Attributes.cs: attribute creation, copying, and helpers
- Move TypeDeclaration class to Models/TypeDeclaration.cs
- Clean up unnecessary using directives per file

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

Remove duplicate CsWinRTGenTasksAssembly definition (already set by
CsWinRTGen.targets) and remove WinMD-specific output importance
properties in favor of the shared CsWinRTGeneratorStandardOutputImportance,
CsWinRTGeneratorStandardErrorImportance, and
CsWinRTGeneratorLogStandardErrorAsError properties.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove CsWinRTGenerateWinMD property  use CsWinRTComponent directly
  since WinMD generation is inherently a WinRT component authoring scenario
- Add CsWinRTWinMDGenEffectiveToolsDirectory to Directory.Build.props
  alongside the other generator tool directory overrides for solution builds
- Add _ResolveCsWinRTWinMDGenToolsDirectory target that depends on
  _ResolveCsWinRToolsDirectory and falls back to _CsWinRTToolsDirectory
  for NuGet package consumers
- Use  instead of hardcoded AnyCPU
- Remove hardcoded  path from targets file

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add import of Microsoft.Windows.CsWinMD.Generator.targets after
CsWinRTGen.targets, conditioned on CsWinRTComponent being true.
Placed after CsWinRTGen.targets since it depends on shared properties
like CsWinRTGenTasksAssembly and _CsWinRTToolsDirectory.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CsWinRTGeneratorTasksOverriden is set to true by CsWinRTGen.targets to
suppress .NET SDK built-in tasks. The other generator UsingTask entries
use CsWinRTGeneratorTasksOverriden2 to avoid being blocked by this.

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

AsmResolver requires TypeSignature values for System.Type-typed custom
attribute arguments, not raw strings. The ActivatableAttribute,
StaticAttribute, and ExclusiveToAttribute were passing qualified type
name strings which caused a cast failure during PE image construction.

Add ResolveTypeNameToSignature helper that looks up types in the output
type mapping first, then falls back to creating a TypeReference.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AsmResolver stores string custom attribute arguments as Utf8String,
not System.String. The 'is string' pattern match was always failing,
causing explicit [Guid] attributes to be ignored and SHA1-generated
GUIDs to be used instead. Use ToString() on the element value to
handle both Utf8String and string representations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Three differences found when comparing new WinMD output against old:

1. EncodeGuid: Add byte-swapping for little-endian systems to match the
   UUID v5 spec and the original source generator. The Guid(byte[])
   constructor interprets bytes 0-3 as little-endian int32, 4-5 as
   little-endian int16, 6-7 as little-endian int16, so the SHA1 hash
   bytes (big-endian) must be swapped before constructing the GUID.

2. Delegate .ctor: Change from Public to Private and add parameter
   definitions for (object, IntPtr) to match WinRT delegate convention
   and the original source generator output.

3. Delegate Invoke parameters: Mark all parameters with ParameterAttributes.In
   to match the original source generator output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The output module was using the default metadata version 'v4.0.30319'
instead of 'WindowsRuntime 1.4'. This version string is how tools like
ILSpy, MIDL, and the CLR itself identify a PE file as a WinMD rather
than a regular .NET assembly. Without it, the file is treated as a
normal assembly and WinRT-specific decompilation and activation
behavior does not apply.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The old source generator defaults to SHA1 via System.Reflection.Metadata.
Match this for consistency in the generated WinMD.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AsmResolver's MethodImplementation constructor takes (declaration, body)
where declaration is the interface method and body is the class method.
Our code had them reversed, causing the .override directives to point
the wrong way. Confirmed by comparing with Interop.Generator usage.

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

Synthesized interfaces (IFooClass, IFooStatic, IFooFactory) are defined
in the same WinMD module. Using GetOrCreateTypeReference created external
TypeReference entries pointing back to the same assembly, causing ILSpy
to display them with full namespace qualification. Use the TypeDefinition
directly for both the interface implementation and MethodImpl records.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Several fixes for correct same-module type references in WinMD output:

- Register class TypeDefinition in _typeDefinitionMapping early (before
  processing methods/properties/events) so self-referencing return types
  like TypeOnlyActivatableViaItsOwnFactory.Create() resolve to the
  output TypeDefinition instead of creating a TypeRef to self
- Add _typeDefinitionMapping lookup in ImportTypeReference's TypeReference
  branch to catch same-module type references from input assembly
- Use output TypeDefinition directly in AddFactoryMethod for the return
  type instead of going through ImportTypeReference
- Use TypeDefinition.ToTypeSignature() in ResolveTypeNameToSignature
  without a fallback to GetOrCreateTypeReference, preventing self-ref
  AssemblyRef creation from attribute arguments
- Skip default synthesized interface in the first MethodImpl loop since
  it is already handled by the dedicated second loop, fixing duplicate
  MethodImpl records
- Remove unused _assemblyName field

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two differences found in thorough WinMD comparison:

1. Enum literal fields: Use the enum type itself (e.g. AuthoringTest.BasicEnum)
   as the field type instead of the underlying primitive (System.Int32). The
   value__ field still uses the underlying type. Also moved type registration
   before field creation so the TypeDefinition is available for the signature.

2. DefaultAttribute: When a class implements user interfaces but has no
   synthesized default interface (all instance members come from interfaces),
   mark the first user interface implementation as [Default]. This matches
   the old source generator behavior where ICustomInterfaceGuid gets [Default]
   on CustomInterfaceGuidClass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove explicit <Module> type addition since AsmResolver's
  ModuleDefinition constructor already creates one automatically
- Mutate the default CorLib AssemblyReference in-place to use
  mscorlib v255.255.255.255 with PKT, matching WinMD convention,
  instead of creating a separate AssemblyReference
- Cache the mutated CorLib reference in _assemblyReferenceCache so
  GetOrCreateAssemblyReference reuses it

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two fixes from comparison with new types:

1. Mark all method parameters as ParameterAttributes.In in interface
   methods, class methods, and factory methods. The old source generator
   uses [In] for all non-out parameters. Our code was copying the input
   assembly's parameter attributes which are 0 (None) in compiled .NET.

2. Register all type kinds (interfaces, structs, delegates) in
   _typeDefinitionMapping early (before processing members), not just
   classes. This prevents self-referencing TypeRef/AssemblyRef entries
   when a type is referenced by another type's method signature before
   being processed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When a method signature references a public type from the input assembly
that hasn't been processed yet (e.g. PartialClass.GetPartialStruct()
referencing PartialStruct which appears later), process it on demand
via ProcessType instead of creating a self-referencing TypeRef. This
eliminates the self-referencing AssemblyReference entry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Port the WriteCustomMappedTypeMembers functionality from the original
source generator. When a class implements .NET interfaces that map to
WinRT equivalents (IDictionary->IMap, IList->IVector, IDisposable->
IClosable, etc.), the WinMD must contain explicit implementation methods
with WinRT-style signatures and MethodImpl records.

New file WinmdWriter.CustomMappedMembers.cs handles:
- All 15 mapped interface types (IClosable, IIterable, IMap, IMapView,
  IVector, IVectorView, IBindableIterable, IBindableVector,
  INotifyPropertyChanged, ICommand, INotifyCollectionChanged,
  INotifyDataErrorInfo, IXamlServiceProvider, IIterator)
- Public vs explicit (private) implementation based on whether the
  class publicly exposes the mapped members
- Generic type argument mapping (KeyValuePair->IKeyValuePair)
- Filtering duplicate IBindableIterable when IIterable<T> present
- Events with EventRegistrationToken pattern
- Properties with get/put accessors
- MethodImpl records for all mapped methods

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

Walk the base type chain and interface inheritance to collect all
interfaces, not just directly declared ones. This fixes types like
TestCollection which inherits IList from a base class  the
IBindableVector/IBindableIterable mapped members were missing because
only direct interfaces were checked.

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

Two fixes for custom mapped interface methods:

1. Public detection: Walk the class hierarchy when checking if interface
   members are publicly implemented, fixing inherited interfaces like
   IList on TestCollection. Also checks .NET interface member names
   (not WinRT names) against the class methods.

2. Generic type name formatting: Use short type names in explicit
   method name prefixes (e.g., 'IMap\2<String, Int32>' instead of
   'IMap\2<System.String, System.Int32>') to match the old source
   generator output. These are actual metadata strings that affect
   tooling.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Static properties were using PropertySignature.CreateInstance which sets
HasThis, but the getter/setter methods use MethodAttributes.Static
without HasThis. AsmResolver validates this consistency and throws
'An instance method requires a signature with the HasThis flag set'
when a static method has an instance-style property signature.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When a static property or event from a class is added to a synthesized
interface (IFooStatic), the method signature must use CreateInstance
(HasThis) because interface methods are always instance methods, even
when they model static class members. The isStatic flag is now forced
to false when isInterfaceParent is true.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Major fixes for WinMD correctness:

1. Type mapping in signatures: MapTypeSignatureToOutput now checks the
   TypeMapper for WinRT mappings on TypeDefOrRefSignature and
   GenericInstanceTypeSignature types. This transforms .NET types like
   System.IDisposable, IList<T>, Nullable<T>, System.Type to their
   WinRT equivalents (IClosable, IVector<T>, IReference<T>, TypeName)
   in all method signatures, property types, and struct fields.

2. Collection member filtering: Class members from custom mapped and
   unmapped .NET interfaces (Add, Contains, Count, IsReadOnly,
   GetEnumerator, etc.) are now excluded from the WinMD output via
   CollectCustomMappedMemberNames. These .NET-specific members are
   replaced by the WinRT mapped interface members.

3. Interface method deduplication: Skip IsSpecialName methods (property
   accessors, event accessors) in AddInterfaceType's method loop since
   they are already created by the property/event processing. This
   prevents duplicate methods and wrong parameter names.

4. Version attribute from source: FinalizeGeneration now reads the
   version from the input type's VersionAttribute if present, instead
   of always using the default version.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add System.Reflection.DefaultMemberAttribute to the skip list in
  ShouldCopyAttribute since it's a .NET-specific attribute that
  shouldn't appear in WinMD output
- Fix FormatShortTypeName to only use short names for CorLib primitive
  types (String, Int32, etc.) and full qualified names for user types
  (AuthoringTest.DisposableClass), matching the old generator

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
manodasanW and others added 20 commits April 15, 2026 00:21
…bleVector

Three fixes:

1. DefaultAttribute: Improved membersFromInterfaces collection to use
   GatherAllInterfaces, include property/event names, union with custom
   mapped member names, and detect explicit implementations from
   compiled IL. This prevents creating empty synthesized default
   interfaces when all instance members come from user interfaces.

2. Explicit interface implementations: Add private qualified-name
   methods (e.g., AuthoringTest.IDouble.GetDouble) for types with
   explicit .NET interface implementations, including properties,
   events, and MethodImpl records.

3. ObservableVector: Skip adding mapped interface implementations
   when the output type already implements the WinRT interface through
   another interface (e.g., IObservableVector<T> already brings
   IVector<T>).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Issue 2: Explicit interface implementation methods now apply WinRT
conventions:
- set_ renamed to put_ in method names and MethodImpl targets
- Event add_ returns EventRegistrationToken (not void) with param
  named 'handler'
- Event remove_ takes EventRegistrationToken param named 'token'

Issue 3: GatherAllInterfaces now resolves generic type parameters
when walking the base class chain. When a class inherits from a
generic base (e.g., ObservableCollection<IDouble>), the base type's
interfaces (like IList<!0>) have their generic parameters substituted
with the concrete type arguments (IList<IDouble>), producing correct
mapped interface signatures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Check all gathered interfaces (not just mapped ones) for generic
  IEnumerable<T> presence when deciding to suppress IBindableIterable.
  The generic IEnumerable<T> might not be in the mapped interfaces
  list but still indicates IIterable<T> should be used.
- For unresolvable interfaces in ImplementedInterfacesWithoutMapping
  (like ICollection<T> from System.Runtime), use MethodImpl records
  from the input type to find which class methods implement the
  interface and add their names to the exclusion set.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… synthesized interfaces, assembly resolver

- Fix recursive generic parameter resolution in GatherAllInterfaces for nested
  generic types like KeyValuePair<!0, !1>
- Fix double-arity bug in GetQualifiedName(TypeDefinition) where generic type
  names already include backtick suffix
- Fix MethodImpl generic parameter encoding: use !0/!1 in declaration signatures
  instead of resolved concrete types for mapped interface members
- Fix synthesized default interface creation: detect interface members from input
  MethodImplementations and avoid creating unnecessary synthesized interfaces
- Fix MSBuild targets to use ReferencePathWithRefAssemblies instead of
  ReferencePath to get actual ref assemblies instead of forwarders
- Add sibling directory fallback in PathAssemblyResolver for type forwarding
- Fix FinalizeGeneration to resolve TypeSpecification interfaces and fall back
  to input type's interface references for unresolvable WinRT contract types
- Support explicit interface implementation matching in MethodImpl generation

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

- Use IsProjectionEquivalent for type comparison instead of MapTypeSignatureToOutput
  to avoid unwanted side effects (type imports into output module)
- Use class method signature for MethodImpl declarations when interface resolved
  from input ref assemblies (maps .NET projection types to WinRT types)
- Snapshot _typeDefinitionMapping for all FinalizeGeneration phases to prevent
  InvalidOperationException from dictionary modification during enumeration
- Support explicit interface implementation matching with parameter type verification

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Prefer explicit interface implementations over public methods when both exist
  for the same interface method (prevents duplicate MethodImpls)
- Resolve generic parameters (!0, !1) in interface method signatures when matching
  against class methods for generic interface instances
- Extract and pass generic type arguments from TypeSpecification interfaces

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update from incorrect 'WinRT.EventRegistrationToken' to correct
'WindowsRuntime.InteropServices.EventRegistrationToken' matching
the CsWinRT projection namespace in helpers.h.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add name-only fallback matching for event accessor methods from ref assemblies
  where CsWinRT projections change event signatures (.NET delegate vs WinRT
  EventRegistrationToken convention)
- Add System.EventHandler\2 -> TypedEventHandler\2 type mapping
- Remove debug logging

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Place [Default] on the WinRT equivalent of the first user-declared .NET
interface, matching the intended behavior. Remove interface sorting since
WinRT spec does not prescribe interface ordering - only requires exactly
one DefaultAttribute on InterfaceImpl rows.

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

Convert GenericInstanceTypeSignature to open generic form in MethodImpl
declaration signatures. E.g., EventHandler\1<Object> becomes
EventHandler\1<!0> to match WinRT metadata conventions.

Applies to both AddMappedMethod (via ToOpenGenericForm) and
AddMappedEvent (via ToOpenGenericFormStatic).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Map Span<T> and ReadOnlySpan<T> to T[] in WinMD output with correct
WinRT array passing conventions:
- ReadOnlySpan<T> -> [in] T[] (PassArray: caller provides, callee reads)
- Span<T> -> [out] T[] without BYREF (FillArray: caller allocates, callee fills)
- out T[] -> [out] T[] with BYREF (ReceiveArray: callee allocates)

This replaces the old ReadOnlyArrayAttribute/WriteOnlyArrayAttribute
pattern with idiomatic .NET span types for CsWinRT 3.0.

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

- Fix !0 generic params on non-generic interfaces: only convert to open
  generic form when parent interface is generic (ToGenericParam, AddMappedEvent)
- Fix duplicate type args overwrite in reverse map: replace string-keyed
  dictionary with index-based FindParentGenericParam that returns first match
- Fix explicit interface impl params always [In]: use GetWinRTParameterAttributes
  to correctly set Out for ByRef/Span parameters
- Fix factory method params always [In]: use AddParameterDefinitions helper
- Fix resolver comment: accurately describe same-directory search behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Strip type arguments from FullName before TypeMapper lookup so
instantiated generic types like IEnumerable\1<String> correctly
match the open generic mapper key IEnumerable\1. Without this,
MethodImpl matching for interfaces with mapped generic parameters
would silently fail.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use WindowsRuntimeTypeAttribute to get WinRT contract assembly names
  for external types instead of projection assembly names (e.g.,
  StackPanel references Microsoft.UI.Xaml not Microsoft.WinUI)
- Add EnsureTypeReference to convert TypeDef to TypeRef for interface
  implementations, matching WinMD TypeDef redirection convention
- Apply to class interfaces, interface inheritance, and synthesized interfaces

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add test types covering: out params on interfaces, nullable/IReference
parameters, mapped type parameters (DateTimeOffset, TimeSpan, Uri),
mixed Span/array params, IDisposable + custom interface, multiple
constructors, static complex props, overloaded methods with DefaultOverload,
nested structs, multi-param delegates, Flags enums, signed enums,
IAsyncAction, versioned interface members, deprecated members,
INotifyPropertyChanged + custom interface, factory + static combined,
and full-featured interface (props + methods + events).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- HasVersionAttribute now also checks for ContractVersionAttribute
- Skip adding VersionAttribute when input type has ContractVersionAttribute
  (ContractVersionAttribute is copied via CopyCustomAttributes in Phase 3)
- Type arguments in ContractVersionAttribute are mapped via existing
  CloneAttributeArgument/MapTypeSignatureToOutput
- ApiContract empty structs emitted as-is (allowed per WinMD spec)
- Add contract versioning test types (AnotherNamespaceContract, ContractVersionedClass)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the custom PathAssemblyResolver and use the built-in one from
AsmResolver with FromSearchDirectories for sibling-directory fallback.
Add RuntimeContextExtensions for loading modules via RuntimeContext.
Update all API calls for the new AsmResolver signatures:
- Resolve() now requires RuntimeContext parameter
- ToTypeSignature() now requires isValueType boolean
- MethodSignature.CreateInstance params wrapped in collection expressions
- MakeGenericReferenceType args wrapped in collection expressions

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: bunch of extra whitespace in this file, in case you want to clean it up


TypeAttributes typeAttributes =
TypeAttributes.NotPublic |
(TypeAttributes)0x4000 | // WindowsRuntime
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a proper flag you can use now in 6.0.0-rc1


TypeAttributes typeAttributes =
TypeAttributes.Public |
(TypeAttributes)0x4000 | // WindowsRuntime
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above for the flag, and for the other cases in this file.

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed, we can use 14.0 (or remove this if it's already inherited from .props)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants