diff --git a/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml b/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml
index 6017ac7c0..1c040cf2c 100644
--- a/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml
+++ b/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml
@@ -111,6 +111,18 @@ stages:
script: |
dir _build\$(BuildPlatform)\$(BuildConfiguration)\AuthoringConsumptionTest\bin
_build\$(BuildPlatform)\$(BuildConfiguration)\AuthoringConsumptionTest\bin\AuthoringConsumptionTest.exe --gtest_output=xml:AUTHORINGTEST-$(Build.BuildNumber).xml
+ exit /b 0
+
+# Run WUX Tests
+ - task: CmdLine@2
+ displayName: Run WUX Tests
+ condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64')))
+ continueOnError: True
+ inputs:
+ workingDirectory: $(Build.SourcesDirectory)\src
+ script: |
+ dir _build\$(BuildPlatform)\$(BuildConfiguration)\AuthoringWuxConsumptionTest\bin
+ _build\$(BuildPlatform)\$(BuildConfiguration)\AuthoringWuxConsumptionTest\bin\AuthoringWuxConsumptionTest.exe --gtest_output=xml:AUTHORINGWUXTEST-$(Build.BuildNumber).xml
exit /b 0
# Run Functional Tests
diff --git a/nuget/Microsoft.Windows.CsWinRT.Authoring.targets b/nuget/Microsoft.Windows.CsWinRT.Authoring.targets
index 608746067..bb3ae3f19 100644
--- a/nuget/Microsoft.Windows.CsWinRT.Authoring.targets
+++ b/nuget/Microsoft.Windows.CsWinRT.Authoring.targets
@@ -31,6 +31,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
+
diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets
index f9b18979d..03c1d284a 100644
--- a/nuget/Microsoft.Windows.CsWinRT.targets
+++ b/nuget/Microsoft.Windows.CsWinRT.targets
@@ -230,6 +230,13 @@ $(CsWinRTInternalProjection)
+
+
+ $(CsWinRTUiXamlMode)
+ true
+
+
+
diff --git a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs
index 13501d1e1..f6996659d 100644
--- a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs
+++ b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs
@@ -20,17 +20,28 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
{
var properties = context.AnalyzerConfigOptionsProvider.Select(static (provider, _) => (provider.IsCsWinRTAotOptimizerEnabled(), provider.IsCsWinRTComponent()));
- var vtableAttributesToAdd = context.SyntaxProvider.CreateSyntaxProvider(
+ var typeMapper = context.AnalyzerConfigOptionsProvider.Select((options, ct) => options.GlobalOptions.GetUiXamlMode()).Select((mode, ct) => new TypeMapper(mode));
+
+ var possibleVtableAttributesToAdd = context.SyntaxProvider.CreateSyntaxProvider(
static (n, _) => NeedVtableAttribute(n),
- static (n, _) => GetVtableAttributeToAdd(n)
- ).Where(vtableAttribute => vtableAttribute != null);
+ static (n, _) => n
+ );
+
+ var vtableAttributesToAdd = possibleVtableAttributesToAdd
+ .Combine(typeMapper)
+ .Select((data, ct) => GetVtableAttributeToAdd(data.Left, data.Right))
+ .Where(n => n is not null);
context.RegisterImplementationSourceOutput(vtableAttributesToAdd.Collect().Combine(properties), GenerateVtableAttributes);
- var vtablesToAddOnLookupTable = context.SyntaxProvider.CreateSyntaxProvider(
+ var possibleVtablesToAddOnLookupTable = context.SyntaxProvider.CreateSyntaxProvider(
static (n, _) => NeedVtableOnLookupTable(n),
- static (n, _) => GetVtableAttributesToAddOnLookupTable(n)
- ).Where(vtableAttribute => vtableAttribute != null);
+ static (n, _) => n);
+
+ var vtablesToAddOnLookupTable = possibleVtablesToAddOnLookupTable
+ .Combine(typeMapper)
+ .Select((data, ct) => GetVtableAttributesToAddOnLookupTable(data.Left, data.Right))
+ .Where(vtableAttribute => vtableAttribute != null);
var genericInterfacesFromVtableAttribute = vtableAttributesToAdd.SelectMany(static (vtableAttribute, _) => vtableAttribute.GenericInterfaces).Collect();
var genericInterfacesFromVtableLookupTable = vtablesToAddOnLookupTable.SelectMany(static (vtable, _) => vtable.SelectMany(v => v.GenericInterfaces)).Collect();
@@ -52,10 +63,10 @@ private static bool NeedVtableAttribute(SyntaxNode node)
!GeneratorHelper.IsWinRTType(declaration); // Making sure it isn't an RCW we are projecting.
}
- private static VtableAttribute GetVtableAttributeToAdd(GeneratorSyntaxContext context)
+ private static VtableAttribute GetVtableAttributeToAdd(GeneratorSyntaxContext context, TypeMapper typeMapper)
{
var symbol = context.SemanticModel.GetDeclaredSymbol(context.Node as ClassDeclarationSyntax);
- return GetVtableAttributeToAdd(symbol, GeneratorHelper.IsWinRTType, context.SemanticModel.Compilation.Assembly, false);
+ return GetVtableAttributeToAdd(symbol, GeneratorHelper.IsWinRTType, typeMapper, context.SemanticModel.Compilation.Assembly, false);
}
private static string ToFullyQualifiedString(ISymbol symbol)
@@ -88,7 +99,7 @@ private static string ToVtableLookupString(ISymbol symbol)
}
}
- internal static VtableAttribute GetVtableAttributeToAdd(ITypeSymbol symbol, Func isWinRTType, IAssemblySymbol assemblySymbol, bool isAuthoring, string authoringDefaultInterface = "")
+ internal static VtableAttribute GetVtableAttributeToAdd(ITypeSymbol symbol, Func isWinRTType, TypeMapper mapper, IAssemblySymbol assemblySymbol, bool isAuthoring, string authoringDefaultInterface = "")
{
if (GeneratorHelper.HasNonInstantiatedWinRTGeneric(symbol) || GeneratorHelper.HasPrivateclass(symbol))
{
@@ -105,13 +116,13 @@ internal static VtableAttribute GetVtableAttributeToAdd(ITypeSymbol symbol, Func
foreach (var iface in symbol.AllInterfaces)
{
- if (isWinRTType(iface))
+ if (isWinRTType(iface, mapper))
{
interfacesToAddToVtable.Add(ToFullyQualifiedString(iface));
AddGenericInterfaceInstantiation(iface);
}
- if (iface.IsGenericType && TryGetCompatibleWindowsRuntimeTypesForVariantType(iface, null, isWinRTType, out var compatibleIfaces))
+ if (iface.IsGenericType && TryGetCompatibleWindowsRuntimeTypesForVariantType(iface, mapper, null, isWinRTType, out var compatibleIfaces))
{
foreach (var compatibleIface in compatibleIfaces)
{
@@ -189,7 +200,7 @@ void AddGenericInterfaceInstantiation(INamedTypeSymbol iface)
genericParameters.Add(new GenericParameter(
ToFullyQualifiedString(genericParameter),
- GeneratorHelper.GetAbiType(genericParameter),
+ GeneratorHelper.GetAbiType(genericParameter, mapper),
genericParameter.TypeKind));
}
@@ -207,7 +218,7 @@ bool IsExternalInternalInterface(INamedTypeSymbol iface)
}
}
- private static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(INamedTypeSymbol type, Stack typeStack, Func isWinRTType, out IList compatibleTypes)
+ private static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(INamedTypeSymbol type, TypeMapper mapper, Stack typeStack, Func isWinRTType, out IList compatibleTypes)
{
compatibleTypes = null;
@@ -220,7 +231,7 @@ private static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(INamedType
}
var definition = type.OriginalDefinition;
- if (!isWinRTType(definition))
+ if (!isWinRTType(definition, mapper))
{
return false;
}
@@ -240,20 +251,20 @@ private static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(INamedType
HashSet compatibleTypesForGeneric = new(SymbolEqualityComparer.Default);
- if (isWinRTType(type.TypeArguments[0]))
+ if (isWinRTType(type.TypeArguments[0], mapper))
{
compatibleTypesForGeneric.Add(type.TypeArguments[0]);
}
foreach (var iface in type.TypeArguments[0].AllInterfaces)
{
- if (isWinRTType(iface))
+ if (isWinRTType(iface, mapper))
{
compatibleTypesForGeneric.Add(iface);
}
if (iface.IsGenericType
- && TryGetCompatibleWindowsRuntimeTypesForVariantType(iface, typeStack, isWinRTType, out var compatibleIfaces))
+ && TryGetCompatibleWindowsRuntimeTypesForVariantType(iface, mapper, typeStack, isWinRTType, out var compatibleIfaces))
{
compatibleTypesForGeneric.UnionWith(compatibleIfaces);
}
@@ -262,7 +273,7 @@ private static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(INamedType
var baseType = type.TypeArguments[0].BaseType;
while (baseType != null)
{
- if (isWinRTType(baseType))
+ if (isWinRTType(baseType, mapper))
{
compatibleTypesForGeneric.Add(baseType);
}
@@ -503,7 +514,7 @@ private static bool NeedVtableOnLookupTable(SyntaxNode node)
node is AssignmentExpressionSyntax;
}
- private static List GetVtableAttributesToAddOnLookupTable(GeneratorSyntaxContext context)
+ private static List GetVtableAttributesToAddOnLookupTable(GeneratorSyntaxContext context, TypeMapper mapper)
{
HashSet vtableAttributes = new();
@@ -511,7 +522,7 @@ private static List GetVtableAttributesToAddOnLookupTable(Gener
{
var invocationSymbol = context.SemanticModel.GetSymbolInfo(invocation.Expression).Symbol;
// Check if function is within a CsWinRT projected class or interface.
- if (invocationSymbol is IMethodSymbol methodSymbol && GeneratorHelper.IsWinRTType(methodSymbol.ContainingSymbol))
+ if (invocationSymbol is IMethodSymbol methodSymbol && GeneratorHelper.IsWinRTType(methodSymbol.ContainingSymbol, mapper))
{
// Get the concrete types directly from the argument rather than
// using what the method accepts, which might just be an interface, so
@@ -530,14 +541,14 @@ private static List GetVtableAttributesToAddOnLookupTable(Gener
{
if (methodSymbol.Parameters[paramsIdx].Type is not IArrayTypeSymbol)
{
- var vtableAtribute = GetVtableAttributeToAdd(arrayType, GeneratorHelper.IsWinRTType, context.SemanticModel.Compilation.Assembly, false);
+ var vtableAtribute = GetVtableAttributeToAdd(arrayType, GeneratorHelper.IsWinRTType, mapper, context.SemanticModel.Compilation.Assembly, false);
if (vtableAtribute != default)
{
vtableAttributes.Add(vtableAtribute);
}
// Also add the enumerator type to the lookup table as the native caller may call it.
- AddEnumeratorAdapterForType(arrayType.ElementType, context.SemanticModel.Compilation, GeneratorHelper.IsWinRTType, vtableAttributes);
+ AddEnumeratorAdapterForType(arrayType.ElementType, mapper, context.SemanticModel.Compilation, GeneratorHelper.IsWinRTType, vtableAttributes);
}
}
else if (argumentType.Type is not null)
@@ -552,11 +563,11 @@ private static List GetVtableAttributesToAddOnLookupTable(Gener
// information is available.
if (argumentClassTypeSymbol.TypeKind == TypeKind.Delegate &&
argumentClassTypeSymbol.MetadataName.Contains("`") &&
- GeneratorHelper.IsWinRTType(argumentClassTypeSymbol) &&
+ GeneratorHelper.IsWinRTType(argumentClassTypeSymbol, mapper) &&
methodSymbol.Parameters[paramsIdx].Type.SpecialType == SpecialType.System_Object)
{
var argumentClassNamedTypeSymbol = argumentClassTypeSymbol as INamedTypeSymbol;
- vtableAttributes.Add(GetVtableAttributeToAdd(argumentClassTypeSymbol, GeneratorHelper.IsWinRTType, context.SemanticModel.Compilation.Assembly, false));
+ vtableAttributes.Add(GetVtableAttributeToAdd(argumentClassTypeSymbol, GeneratorHelper.IsWinRTType, mapper, context.SemanticModel.Compilation.Assembly, false));
}
// This handles the case where the source generator wasn't able to run
@@ -569,19 +580,19 @@ private static List GetVtableAttributesToAddOnLookupTable(Gener
// we handle it here.
if (argumentClassTypeSymbol.TypeKind == TypeKind.Class &&
(argumentClassTypeSymbol.MetadataName.Contains("`") ||
- (!GeneratorHelper.IsWinRTType(argumentClassTypeSymbol) &&
+ (!GeneratorHelper.IsWinRTType(argumentClassTypeSymbol, mapper) &&
!GeneratorHelper.HasWinRTExposedTypeAttribute(argumentClassTypeSymbol) &&
// If the type is defined in the same assembly as what the source generator is running on,
// we let the WinRTExposedType attribute generator handle it.
!SymbolEqualityComparer.Default.Equals(argumentClassTypeSymbol.ContainingAssembly, context.SemanticModel.Compilation.Assembly))))
{
- var vtableAtribute = GetVtableAttributeToAdd(argumentClassTypeSymbol, GeneratorHelper.IsWinRTType, context.SemanticModel.Compilation.Assembly, false);
+ var vtableAtribute = GetVtableAttributeToAdd(argumentClassTypeSymbol, GeneratorHelper.IsWinRTType, mapper, context.SemanticModel.Compilation.Assembly, false);
if (vtableAtribute != default)
{
vtableAttributes.Add(vtableAtribute);
}
- AddEnumeratorAdapterForEnumerableInterface(argumentClassTypeSymbol, context.SemanticModel.Compilation, GeneratorHelper.IsWinRTType, vtableAttributes);
+ AddEnumeratorAdapterForEnumerableInterface(argumentClassTypeSymbol, mapper, context.SemanticModel.Compilation, GeneratorHelper.IsWinRTType, vtableAttributes);
}
}
}
@@ -602,7 +613,7 @@ private static List GetVtableAttributesToAddOnLookupTable(Gener
// Check if property being assigned to is within a CsWinRT projected class or interface.
if (leftSymbol is IPropertySymbol propertySymbol &&
- GeneratorHelper.IsWinRTType(propertySymbol.ContainingSymbol))
+ GeneratorHelper.IsWinRTType(propertySymbol.ContainingSymbol, mapper))
{
var argumentType = context.SemanticModel.GetTypeInfo(assignment.Right);
@@ -613,14 +624,14 @@ private static List GetVtableAttributesToAddOnLookupTable(Gener
{
if (propertySymbol.Type is not IArrayTypeSymbol)
{
- var vtableAtribute = GetVtableAttributeToAdd(arrayType, GeneratorHelper.IsWinRTType, context.SemanticModel.Compilation.Assembly, false);
+ var vtableAtribute = GetVtableAttributeToAdd(arrayType, GeneratorHelper.IsWinRTType, mapper, context.SemanticModel.Compilation.Assembly, false);
if (vtableAtribute != default)
{
vtableAttributes.Add(vtableAtribute);
}
// Also add the enumerator type to the lookup table as the native caller can call it.
- AddEnumeratorAdapterForType(arrayType.ElementType, context.SemanticModel.Compilation, GeneratorHelper.IsWinRTType, vtableAttributes);
+ AddEnumeratorAdapterForType(arrayType.ElementType, mapper, context.SemanticModel.Compilation, GeneratorHelper.IsWinRTType, vtableAttributes);
}
}
else if (argumentType.Type is not null || argumentType.ConvertedType is not null)
@@ -635,28 +646,28 @@ private static List GetVtableAttributesToAddOnLookupTable(Gener
// assignment to object, it is not known, and that is handled here.
if (argumentClassTypeSymbol.TypeKind == TypeKind.Delegate &&
argumentClassTypeSymbol.MetadataName.Contains("`") &&
- GeneratorHelper.IsWinRTType(argumentClassTypeSymbol) &&
+ GeneratorHelper.IsWinRTType(argumentClassTypeSymbol, mapper) &&
propertySymbol.Type.SpecialType == SpecialType.System_Object)
{
var argumentClassNamedTypeSymbol = argumentClassTypeSymbol as INamedTypeSymbol;
- vtableAttributes.Add(GetVtableAttributeToAdd(argumentClassTypeSymbol, GeneratorHelper.IsWinRTType, context.SemanticModel.Compilation.Assembly, false));
+ vtableAttributes.Add(GetVtableAttributeToAdd(argumentClassTypeSymbol, GeneratorHelper.IsWinRTType, mapper, context.SemanticModel.Compilation.Assembly, false));
}
if (argumentClassTypeSymbol.TypeKind == TypeKind.Class &&
(argumentClassTypeSymbol.MetadataName.Contains("`") ||
- (!GeneratorHelper.IsWinRTType(argumentClassTypeSymbol) &&
+ (!GeneratorHelper.IsWinRTType(argumentClassTypeSymbol, mapper) &&
!GeneratorHelper.HasWinRTExposedTypeAttribute(argumentClassTypeSymbol) &&
// If the type is defined in the same assembly as what the source generator is running on,
// we let the WinRTExposedType attribute generator handle it.
!SymbolEqualityComparer.Default.Equals(argumentClassTypeSymbol.ContainingAssembly, context.SemanticModel.Compilation.Assembly))))
{
- var vtableAtribute = GetVtableAttributeToAdd(argumentClassTypeSymbol, GeneratorHelper.IsWinRTType, context.SemanticModel.Compilation.Assembly, false);
+ var vtableAtribute = GetVtableAttributeToAdd(argumentClassTypeSymbol, GeneratorHelper.IsWinRTType, mapper, context.SemanticModel.Compilation.Assembly, false);
if (vtableAtribute != default)
{
vtableAttributes.Add(vtableAtribute);
}
- AddEnumeratorAdapterForEnumerableInterface(argumentClassTypeSymbol, context.SemanticModel.Compilation, GeneratorHelper.IsWinRTType, vtableAttributes);
+ AddEnumeratorAdapterForEnumerableInterface(argumentClassTypeSymbol, mapper, context.SemanticModel.Compilation, GeneratorHelper.IsWinRTType, vtableAttributes);
}
}
}
@@ -668,11 +679,11 @@ private static List GetVtableAttributesToAddOnLookupTable(Gener
// Any of the IEnumerable interfaces on the vtable can be used to get the enumerator. Given IEnumerable is
// a covariant interface, it means that we can end up getting an instance of the enumerable adapter for any one
// of those covariant interfaces and thereby need vtable lookup entries for all of them.
- private static void AddEnumeratorAdapterForType(ITypeSymbol type, Compilation compilation, Func isWinRTType, HashSet vtableAttributes)
+ private static void AddEnumeratorAdapterForType(ITypeSymbol type, TypeMapper mapper, Compilation compilation, Func isWinRTType, HashSet vtableAttributes)
{
var enumerableType = compilation.GetTypeByMetadataName("System.Collections.Generic.IEnumerable`1").
Construct(type);
- if (TryGetCompatibleWindowsRuntimeTypesForVariantType(enumerableType, null, isWinRTType, out var compatibleIfaces))
+ if (TryGetCompatibleWindowsRuntimeTypesForVariantType(enumerableType, mapper, null, isWinRTType, out var compatibleIfaces))
{
foreach (var compatibleIface in compatibleIfaces)
{
@@ -681,51 +692,51 @@ private static void AddEnumeratorAdapterForType(ITypeSymbol type, Compilation co
{
var enumeratorAdapterType = compilation.GetTypeByMetadataName("ABI.System.Collections.Generic.ToAbiEnumeratorAdapter`1").
Construct(compatibleIface.TypeArguments[0]);
- vtableAttributes.Add(GetVtableAttributeToAdd(enumeratorAdapterType, isWinRTType, compilation.Assembly, false));
+ vtableAttributes.Add(GetVtableAttributeToAdd(enumeratorAdapterType, isWinRTType, mapper, compilation.Assembly, false));
}
}
}
}
- internal static void AddEnumeratorAdapterForEnumerableInterface(ITypeSymbol classType, Compilation compilation, Func isWinRTType, HashSet vtableAttributes)
+ internal static void AddEnumeratorAdapterForEnumerableInterface(ITypeSymbol classType, TypeMapper mapper, Compilation compilation, Func isWinRTType, HashSet vtableAttributes)
{
// Type may implement multiple unique IEnumerable interfaces.
foreach (var iface in classType.AllInterfaces)
{
if (iface.MetadataName == "IEnumerable`1")
{
- AddEnumeratorAdapterForType(iface.TypeArguments[0], compilation, isWinRTType, vtableAttributes);
+ AddEnumeratorAdapterForType(iface.TypeArguments[0], mapper, compilation, isWinRTType, vtableAttributes);
}
}
}
- internal static void AddVtableAdapterTypeForKnownInterface(ITypeSymbol classType, Compilation compilation, Func isWinRTType, HashSet vtableAttributes)
+ internal static void AddVtableAdapterTypeForKnownInterface(ITypeSymbol classType, Compilation compilation, Func isWinRTType, TypeMapper mapper, HashSet vtableAttributes)
{
foreach (var iface in classType.AllInterfaces)
{
if (iface.MetadataName == "IEnumerable`1")
{
- AddEnumeratorAdapterForType(iface.TypeArguments[0], compilation, isWinRTType, vtableAttributes);
+ AddEnumeratorAdapterForType(iface.TypeArguments[0], mapper, compilation, isWinRTType, vtableAttributes);
}
else if (iface.MetadataName == "IDictionary`2")
{
var readOnlyDictionaryType = compilation.GetTypeByMetadataName("System.Collections.ObjectModel.ReadOnlyDictionary`2").
Construct([.. iface.TypeArguments]);
- vtableAttributes.Add(GetVtableAttributeToAdd(readOnlyDictionaryType, isWinRTType, compilation.Assembly, false));
+ vtableAttributes.Add(GetVtableAttributeToAdd(readOnlyDictionaryType, isWinRTType, mapper, compilation.Assembly, false));
var keyValuePairType = compilation.GetTypeByMetadataName("System.Collections.Generic.KeyValuePair`2").
Construct([.. iface.TypeArguments]);
- vtableAttributes.Add(GetVtableAttributeToAdd(keyValuePairType, isWinRTType, compilation.Assembly, false));
+ vtableAttributes.Add(GetVtableAttributeToAdd(keyValuePairType, isWinRTType, mapper, compilation.Assembly, false));
var constantSplittableMapType = compilation.GetTypeByMetadataName("ABI.System.Collections.Generic.ConstantSplittableMap`2").
Construct([.. iface.TypeArguments]);
- vtableAttributes.Add(GetVtableAttributeToAdd(constantSplittableMapType, isWinRTType, compilation.Assembly, false));
+ vtableAttributes.Add(GetVtableAttributeToAdd(constantSplittableMapType, isWinRTType, mapper, compilation.Assembly, false));
}
else if (iface.MetadataName == "IList`1")
{
var readOnlyCollectionType = compilation.GetTypeByMetadataName("System.Collections.ObjectModel.ReadOnlyCollection`1").
Construct([.. iface.TypeArguments]);
- vtableAttributes.Add(GetVtableAttributeToAdd(readOnlyCollectionType, isWinRTType, compilation.Assembly, false));
+ vtableAttributes.Add(GetVtableAttributeToAdd(readOnlyCollectionType, isWinRTType, mapper, compilation.Assembly, false));
}
}
}
diff --git a/src/Authoring/WinRT.SourceGenerator/DiagnosticUtils.cs b/src/Authoring/WinRT.SourceGenerator/DiagnosticUtils.cs
index 9c2215de1..528bd1598 100644
--- a/src/Authoring/WinRT.SourceGenerator/DiagnosticUtils.cs
+++ b/src/Authoring/WinRT.SourceGenerator/DiagnosticUtils.cs
@@ -16,11 +16,13 @@ public WinRTComponentScanner(GeneratorExecutionContext context, string assemblyN
_assemblyName = assemblyName;
_context = context;
_flag = false;
+ _typeMapper = new TypeMapper(context.AnalyzerConfigOptions.GlobalOptions.GetUiXamlMode());
}
private readonly string _assemblyName;
private readonly GeneratorExecutionContext _context;
private bool _flag;
+ private readonly TypeMapper _typeMapper;
public bool Found() { return _flag; }
@@ -105,7 +107,7 @@ private void CheckDeclarations()
var props = @class.DescendantNodes().OfType().Where(IsPublic);
// filter out methods and properties that will be replaced with our custom type mappings
- IgnoreCustomTypeMappings(classSymbol, ref publicMethods, ref props);
+ IgnoreCustomTypeMappings(classSymbol, _typeMapper, ref publicMethods, ref props);
if (!classSymbol.IsSealed && !classSymbol.IsStatic)
{
@@ -137,7 +139,7 @@ private void CheckDeclarations()
var props = @interface.DescendantNodes().OfType().Where(IsPublic);
// filter out methods and properties that will be replaced with our custom type mappings
- IgnoreCustomTypeMappings(interfaceSym, ref methods, ref props);
+ IgnoreCustomTypeMappings(interfaceSym, _typeMapper, ref methods, ref props);
if (interfaceSym.IsGenericType)
{
@@ -206,6 +208,7 @@ private bool IsMethodImpl(IMethodSymbol m, IMethodSymbol interfaceMethod)
}
private void IgnoreCustomTypeMappings(INamedTypeSymbol typeSymbol,
+ TypeMapper typeMapper,
ref IEnumerable methods,
ref IEnumerable properties)
{
@@ -217,7 +220,7 @@ string QualifiedName(INamedTypeSymbol sym)
HashSet classMethods = new();
foreach (var @interface in typeSymbol.AllInterfaces.
- Where(symbol => GeneratorHelper.MappedCSharpTypes.ContainsKey(QualifiedName(symbol)) ||
+ Where(symbol => typeMapper.HasMappingForType(QualifiedName(symbol)) ||
WinRTTypeWriter.ImplementedInterfacesWithoutMapping.Contains(QualifiedName(symbol))))
{
foreach (var interfaceMember in @interface.GetMembers())
diff --git a/src/Authoring/WinRT.SourceGenerator/Generator.cs b/src/Authoring/WinRT.SourceGenerator/Generator.cs
index baf75519b..303051597 100644
--- a/src/Authoring/WinRT.SourceGenerator/Generator.cs
+++ b/src/Authoring/WinRT.SourceGenerator/Generator.cs
@@ -1,4 +1,4 @@
-using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
@@ -20,11 +20,14 @@ public class ComponentGenerator
private Logger Logger { get; }
private readonly GeneratorExecutionContext context;
private string tempFolder;
+ private readonly TypeMapper mapper;
public ComponentGenerator(GeneratorExecutionContext context)
{
this.context = context;
Logger = new Logger(context);
+ mapper = new(context.AnalyzerConfigOptions.GlobalOptions.GetUiXamlMode());
+ // TODO-WuxMux: output a module initializer that validates the MUX/WUX projection mode to ensure that things don't get out of sync.
}
private string GetTempFolder(bool clearSourceFilesFromFolder = false)
@@ -152,7 +155,8 @@ public void Generate()
assembly,
version,
metadataBuilder,
- Logger);
+ Logger,
+ mapper);
WinRTSyntaxReceiver syntaxReceiver = (WinRTSyntaxReceiver)context.SyntaxReceiver;
Logger.Log("Found " + syntaxReceiver.Declarations.Count + " types");
diff --git a/src/Authoring/WinRT.SourceGenerator/Helper.cs b/src/Authoring/WinRT.SourceGenerator/Helper.cs
index 1cd7f89ab..55c699c19 100644
--- a/src/Authoring/WinRT.SourceGenerator/Helper.cs
+++ b/src/Authoring/WinRT.SourceGenerator/Helper.cs
@@ -1,117 +1,117 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-
-using Microsoft.CodeAnalysis;
+
+using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using System.Text.RegularExpressions;
-namespace Generator
-{
- public static class Helper
- {
- public static Guid EncodeGuid(byte[] data)
- {
- if (BitConverter.IsLittleEndian)
- {
- // swap bytes of int a
- byte t = data[0];
- data[0] = data[3];
- data[3] = t;
- t = data[1];
- data[1] = data[2];
- data[2] = t;
- // swap bytes of short b
- t = data[4];
- data[4] = data[5];
- data[5] = t;
- // swap bytes of short c and encode rfc time/version field
- t = data[6];
- data[6] = data[7];
- data[7] = (byte)((t & 0x0f) | (5 << 4));
- // encode rfc clock/reserved field
- data[8] = (byte)((data[8] & 0x3f) | 0x80);
- }
- return new Guid(data.Take(16).ToArray());
- }
- }
-
- class AttributeDataComparer : IEqualityComparer
- {
- public bool Equals(AttributeData x, AttributeData y)
- {
- return string.CompareOrdinal(x.ToString(), y.ToString()) == 0;
- }
-
- public int GetHashCode(AttributeData obj)
- {
- return obj.ToString().GetHashCode();
- }
- }
-
- static class GeneratorExecutionContextHelper
- {
- public static string GetAssemblyName(this GeneratorExecutionContext context)
- {
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.AssemblyName", out var assemblyName);
- return assemblyName;
- }
-
- public static string GetAssemblyVersion(this GeneratorExecutionContext context)
- {
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.AssemblyVersion", out var assemblyVersion);
- return assemblyVersion;
- }
-
- public static string GetGeneratedFilesDir(this GeneratorExecutionContext context)
- {
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTGeneratedFilesDir", out var generatedFilesDir);
- Directory.CreateDirectory(generatedFilesDir);
- return generatedFilesDir;
- }
-
- public static bool IsCsWinRTComponent(this GeneratorExecutionContext context)
- {
- if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTComponent", out var isCsWinRTComponentStr))
- {
- return bool.TryParse(isCsWinRTComponentStr, out var isCsWinRTComponent) && isCsWinRTComponent;
- }
-
- return false;
- }
-
- public static bool IsCsWinRTComponent(this AnalyzerConfigOptionsProvider provider)
- {
- if (provider.GlobalOptions.TryGetValue("build_property.CsWinRTComponent", out var isCsWinRTComponentStr))
- {
- return bool.TryParse(isCsWinRTComponentStr, out var isCsWinRTComponent) && isCsWinRTComponent;
- }
-
- return false;
- }
-
- public static bool IsCsWinRTAotOptimizerEnabled(this AnalyzerConfigOptionsProvider provider)
- {
- if (provider.GlobalOptions.TryGetValue("build_property.CsWinRTAotOptimizerEnabled", out var isCsWinRTAotOptimizerEnabledStr))
- {
- return bool.TryParse(isCsWinRTAotOptimizerEnabledStr, out var isCsWinRTAotOptimizerEnabled) && isCsWinRTAotOptimizerEnabled;
- }
-
- return false;
- }
-
- public static bool ShouldGenerateWinMDOnly(this GeneratorExecutionContext context)
- {
- if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTGenerateWinMDOnly", out var CsWinRTGenerateWinMDOnlyStr))
- {
- return bool.TryParse(CsWinRTGenerateWinMDOnlyStr, out var CsWinRTGenerateWinMDOnly) && CsWinRTGenerateWinMDOnly;
- }
-
- return false;
+namespace Generator
+{
+ public static class Helper
+ {
+ public static Guid EncodeGuid(byte[] data)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ // swap bytes of int a
+ byte t = data[0];
+ data[0] = data[3];
+ data[3] = t;
+ t = data[1];
+ data[1] = data[2];
+ data[2] = t;
+ // swap bytes of short b
+ t = data[4];
+ data[4] = data[5];
+ data[5] = t;
+ // swap bytes of short c and encode rfc time/version field
+ t = data[6];
+ data[6] = data[7];
+ data[7] = (byte)((t & 0x0f) | (5 << 4));
+ // encode rfc clock/reserved field
+ data[8] = (byte)((data[8] & 0x3f) | 0x80);
+ }
+ return new Guid(data.Take(16).ToArray());
+ }
+ }
+
+ class AttributeDataComparer : IEqualityComparer
+ {
+ public bool Equals(AttributeData x, AttributeData y)
+ {
+ return string.CompareOrdinal(x.ToString(), y.ToString()) == 0;
+ }
+
+ public int GetHashCode(AttributeData obj)
+ {
+ return obj.ToString().GetHashCode();
+ }
+ }
+
+ static class GeneratorExecutionContextHelper
+ {
+ public static string GetAssemblyName(this GeneratorExecutionContext context)
+ {
+ context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.AssemblyName", out var assemblyName);
+ return assemblyName;
+ }
+
+ public static string GetAssemblyVersion(this GeneratorExecutionContext context)
+ {
+ context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.AssemblyVersion", out var assemblyVersion);
+ return assemblyVersion;
+ }
+
+ public static string GetGeneratedFilesDir(this GeneratorExecutionContext context)
+ {
+ context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTGeneratedFilesDir", out var generatedFilesDir);
+ Directory.CreateDirectory(generatedFilesDir);
+ return generatedFilesDir;
+ }
+
+ public static bool IsCsWinRTComponent(this GeneratorExecutionContext context)
+ {
+ if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTComponent", out var isCsWinRTComponentStr))
+ {
+ return bool.TryParse(isCsWinRTComponentStr, out var isCsWinRTComponent) && isCsWinRTComponent;
+ }
+
+ return false;
+ }
+
+ public static bool IsCsWinRTComponent(this AnalyzerConfigOptionsProvider provider)
+ {
+ if (provider.GlobalOptions.TryGetValue("build_property.CsWinRTComponent", out var isCsWinRTComponentStr))
+ {
+ return bool.TryParse(isCsWinRTComponentStr, out var isCsWinRTComponent) && isCsWinRTComponent;
+ }
+
+ return false;
+ }
+
+ public static bool IsCsWinRTAotOptimizerEnabled(this AnalyzerConfigOptionsProvider provider)
+ {
+ if (provider.GlobalOptions.TryGetValue("build_property.CsWinRTAotOptimizerEnabled", out var isCsWinRTAotOptimizerEnabledStr))
+ {
+ return bool.TryParse(isCsWinRTAotOptimizerEnabledStr, out var isCsWinRTAotOptimizerEnabled) && isCsWinRTAotOptimizerEnabled;
+ }
+
+ return false;
+ }
+
+ public static bool ShouldGenerateWinMDOnly(this GeneratorExecutionContext context)
+ {
+ if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTGenerateWinMDOnly", out var CsWinRTGenerateWinMDOnlyStr))
+ {
+ return bool.TryParse(CsWinRTGenerateWinMDOnlyStr, out var CsWinRTGenerateWinMDOnly) && CsWinRTGenerateWinMDOnly;
+ }
+
+ return false;
}
///
@@ -119,51 +119,51 @@ public static bool ShouldGenerateWinMDOnly(this GeneratorExecutionContext contex
///
/// The input value to use.
/// Whether the "CsWinRTAotExportsEnabled" MSBuild property is defined.
- public static bool ShouldGenerateWinRTNativeExports(this GeneratorExecutionContext context)
- {
- if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTAotExportsEnabled", out var isCsWinRTAotExportsEnabledStr))
- {
- return bool.TryParse(isCsWinRTAotExportsEnabledStr, out var isCsWinRTAotExportsEnabled) && isCsWinRTAotExportsEnabled;
- }
-
- return false;
- }
-
- public static string GetCsWinRTExe(this GeneratorExecutionContext context)
- {
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTExe", out var cswinrtExe);
- return cswinrtExe;
- }
-
- public static bool GetKeepGeneratedSources(this GeneratorExecutionContext context)
- {
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTKeepGeneratedSources", out var keepGeneratedSourcesStr);
- return keepGeneratedSourcesStr != null && bool.TryParse(keepGeneratedSourcesStr, out var keepGeneratedSources) && keepGeneratedSources;
- }
-
- public static string GetCsWinRTWindowsMetadata(this GeneratorExecutionContext context)
- {
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTWindowsMetadata", out var cswinrtWindowsMetadata);
- return cswinrtWindowsMetadata;
- }
-
- public static string GetCsWinRTDependentMetadata(this GeneratorExecutionContext context)
- {
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTAuthoringInputs", out var winmds);
- return winmds;
- }
-
- public static string GetWinmdOutputFile(this GeneratorExecutionContext context)
- {
+ public static bool ShouldGenerateWinRTNativeExports(this GeneratorExecutionContext context)
+ {
+ if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTAotExportsEnabled", out var isCsWinRTAotExportsEnabledStr))
+ {
+ return bool.TryParse(isCsWinRTAotExportsEnabledStr, out var isCsWinRTAotExportsEnabled) && isCsWinRTAotExportsEnabled;
+ }
+
+ return false;
+ }
+
+ public static string GetCsWinRTExe(this GeneratorExecutionContext context)
+ {
+ context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTExe", out var cswinrtExe);
+ return cswinrtExe;
+ }
+
+ public static bool GetKeepGeneratedSources(this GeneratorExecutionContext context)
+ {
+ context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTKeepGeneratedSources", out var keepGeneratedSourcesStr);
+ return keepGeneratedSourcesStr != null && bool.TryParse(keepGeneratedSourcesStr, out var keepGeneratedSources) && keepGeneratedSources;
+ }
+
+ public static string GetCsWinRTWindowsMetadata(this GeneratorExecutionContext context)
+ {
+ context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTWindowsMetadata", out var cswinrtWindowsMetadata);
+ return cswinrtWindowsMetadata;
+ }
+
+ public static string GetCsWinRTDependentMetadata(this GeneratorExecutionContext context)
+ {
+ context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTAuthoringInputs", out var winmds);
+ return winmds;
+ }
+
+ public static string GetWinmdOutputFile(this GeneratorExecutionContext context)
+ {
var fileName = context.GetAssemblyName();
if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTWinMDOutputFile", out var ret))
{
fileName = ret!;
- }
- return Path.Combine(context.GetGeneratedFilesDir(), fileName + ".winmd");
- }
- }
-
+ }
+ return Path.Combine(context.GetGeneratedFilesDir(), fileName + ".winmd");
+ }
+ }
+
static class GeneratorHelper
{
private static bool IsFundamentalType(ISymbol type)
@@ -192,12 +192,12 @@ private static bool IsFundamentalType(ISymbol type)
return type.ToDisplayString() == "System.Guid";
}
- public static bool IsWinRTType(ISymbol type)
+ public static bool IsWinRTType(ISymbol type, TypeMapper mapper)
{
- return IsWinRTType(type, null);
+ return IsWinRTType(type, mapper, null);
}
- public static bool IsWinRTType(ISymbol type, Func isAuthoringWinRTType)
+ public static bool IsWinRTType(ISymbol type, TypeMapper mapper, Func isAuthoringWinRTType)
{
bool isProjectedType = type.GetAttributes().
Any(attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeTypeAttribute") == 0) ||
@@ -205,14 +205,14 @@ public static bool IsWinRTType(ISymbol type, Func isAuthoringWinR
if (!isProjectedType & type.ContainingNamespace != null)
{
- isProjectedType = MappedCSharpTypes.ContainsKey(string.Join(".", type.ContainingNamespace.ToDisplayString(), type.MetadataName));
+ isProjectedType = mapper.HasMappingForType(string.Join(".", type.ContainingNamespace.ToDisplayString(), type.MetadataName));
}
// Ensure all generic parameters are WinRT types.
if (isProjectedType && type is INamedTypeSymbol namedType && namedType.IsGenericType && !namedType.IsDefinition)
{
isProjectedType = namedType.TypeArguments.All(t =>
- IsWinRTType(t, isAuthoringWinRTType) ||
+ IsWinRTType(t, mapper, isAuthoringWinRTType) ||
(isAuthoringWinRTType != null && isAuthoringWinRTType(t)));
}
@@ -295,7 +295,7 @@ private static string GetAbiTypeForFundamentalType(ISymbol type)
return type.ToDisplayString();
}
- public static bool IsBlittableValueType(ITypeSymbol type)
+ public static bool IsBlittableValueType(ITypeSymbol type, TypeMapper typeMapper)
{
if (!type.IsValueType)
{
@@ -325,9 +325,9 @@ public static bool IsBlittableValueType(ITypeSymbol type)
}
string customTypeMapKey = string.Join(".", type.ContainingNamespace.ToDisplayString(), type.MetadataName);
- if (MappedCSharpTypes.ContainsKey(customTypeMapKey))
+ if (typeMapper.HasMappingForType(customTypeMapKey))
{
- return MappedCSharpTypes[customTypeMapKey].IsBlittable();
+ return typeMapper.GetMappedType(customTypeMapKey).IsBlittable();
}
if (type.TypeKind == TypeKind.Enum)
@@ -339,7 +339,7 @@ public static bool IsBlittableValueType(ITypeSymbol type)
{
foreach (var typeMember in type.GetMembers())
{
- if (typeMember is IFieldSymbol field && !IsBlittableValueType(field.Type))
+ if (typeMember is IFieldSymbol field && !IsBlittableValueType(field.Type, typeMapper))
{
return false;
}
@@ -348,7 +348,7 @@ public static bool IsBlittableValueType(ITypeSymbol type)
return true;
}
- public static string GetAbiType(ITypeSymbol type)
+ public static string GetAbiType(ITypeSymbol type, TypeMapper mapper)
{
if (IsFundamentalType(type))
{
@@ -368,9 +368,9 @@ public static string GetAbiType(ITypeSymbol type)
if (type.IsValueType)
{
string customTypeMapKey = string.Join(".", type.ContainingNamespace.ToDisplayString(), type.MetadataName);
- if (MappedCSharpTypes.ContainsKey(customTypeMapKey))
+ if (mapper.HasMappingForType(customTypeMapKey))
{
- string prefix = MappedCSharpTypes[customTypeMapKey].IsBlittable() ? "" : "ABI.";
+ string prefix = mapper.GetMappedType(customTypeMapKey).IsBlittable() ? "" : "ABI.";
return prefix + typeStr;
}
@@ -385,7 +385,7 @@ public static string GetAbiType(ITypeSymbol type)
// Handling authoring scenario where Impl type has the attributes and
// if the current component is the one being authored, it may not be
// generated yet to check given it is the same compilation.
- else if (!IsBlittableValueType(type))
+ else if (!IsBlittableValueType(type, mapper))
{
return "ABI." + typeStr;
}
@@ -731,63 +731,5 @@ public bool IsBlittable()
return isValueType && isBlittable;
}
}
-
- // Based on whether System.Type is used in an attribute declaration or elsewhere, we need to choose the correct custom mapping
- // as attributes don't use the TypeName mapping.
- internal static (string, string, string, bool, bool) GetSystemTypeCustomMapping(ISymbol containingSymbol)
- {
- bool isDefinedInAttribute =
- containingSymbol != null &&
- string.CompareOrdinal((containingSymbol as INamedTypeSymbol).BaseType?.ToString(), "System.Attribute") == 0;
- return isDefinedInAttribute ?
- ("System", "Type", "mscorlib", true, false) :
- ("Windows.UI.Xaml.Interop", "TypeName", "Windows.Foundation.UniversalApiContract", false, true);
- }
-
- // This should be in sync with the reverse mapping from WinRT.Runtime/Projections.cs and cswinrt/helpers.h.
- public static readonly Dictionary MappedCSharpTypes = new(StringComparer.Ordinal)
- {
- { "System.DateTimeOffset", new MappedType("Windows.Foundation", "DateTime", "Windows.Foundation.FoundationContract", true, false) },
- { "System.Exception", new MappedType("Windows.Foundation", "HResult", "Windows.Foundation.FoundationContract", true, false) },
- { "System.EventHandler`1", new MappedType("Windows.Foundation", "EventHandler`1", "Windows.Foundation.FoundationContract") },
- { "System.FlagsAttribute", new MappedType("System", "FlagsAttribute", "mscorlib" ) },
- { "System.IDisposable", new MappedType("Windows.Foundation", "IClosable", "Windows.Foundation.FoundationContract") },
- { "System.IServiceProvider", new MappedType("Microsoft.UI.Xaml", "IXamlServiceProvider", "Microsoft.UI") },
- { "System.Nullable`1", new MappedType("Windows.Foundation", "IReference`1", "Windows.Foundation.FoundationContract" ) },
- { "System.Object", new MappedType("System", "Object", "mscorlib" ) },
- { "System.TimeSpan", new MappedType("Windows.Foundation", "TimeSpan", "Windows.Foundation.FoundationContract", true, false) },
- { "System.Uri", new MappedType("Windows.Foundation", "Uri", "Windows.Foundation.FoundationContract") },
- { "System.ComponentModel.DataErrorsChangedEventArgs", new MappedType("Microsoft.UI.Xaml.Data", "DataErrorsChangedEventArgs", "Microsoft.UI") },
- { "System.ComponentModel.INotifyDataErrorInfo", new MappedType("Microsoft.UI.Xaml.Data", "INotifyDataErrorInfo", "Microsoft.UI") },
- { "System.ComponentModel.INotifyPropertyChanged", new MappedType("Microsoft.UI.Xaml.Data", "INotifyPropertyChanged", "Microsoft.UI") },
- { "System.ComponentModel.PropertyChangedEventArgs", new MappedType("Microsoft.UI.Xaml.Data", "PropertyChangedEventArgs", "Microsoft.UI") },
- { "System.ComponentModel.PropertyChangedEventHandler", new MappedType("Microsoft.UI.Xaml.Data", "PropertyChangedEventHandler", "Microsoft.UI") },
- { "System.Windows.Input.ICommand", new MappedType("Microsoft.UI.Xaml.Input", "ICommand", "Microsoft.UI") },
- { "System.Collections.IEnumerable", new MappedType("Microsoft.UI.Xaml.Interop", "IBindableIterable", "Microsoft.UI") },
- { "System.Collections.IList", new MappedType("Microsoft.UI.Xaml.Interop", "IBindableVector", "Microsoft.UI") },
- { "System.Collections.Specialized.INotifyCollectionChanged", new MappedType("Microsoft.UI.Xaml.Interop", "INotifyCollectionChanged", "Microsoft.UI") },
- { "System.Collections.Specialized.NotifyCollectionChangedAction", new MappedType("Microsoft.UI.Xaml.Interop", "NotifyCollectionChangedAction", "Microsoft.UI") },
- { "System.Collections.Specialized.NotifyCollectionChangedEventArgs", new MappedType("Microsoft.UI.Xaml.Interop", "NotifyCollectionChangedEventArgs", "Microsoft.UI") },
- { "System.Collections.Specialized.NotifyCollectionChangedEventHandler", new MappedType("Microsoft.UI.Xaml.Interop", "NotifyCollectionChangedEventHandler", "Microsoft.UI") },
- { "WinRT.EventRegistrationToken", new MappedType("Windows.Foundation", "EventRegistrationToken", "Windows.Foundation.FoundationContract", true, true) },
- { "System.AttributeTargets", new MappedType("Windows.Foundation.Metadata", "AttributeTargets", "Windows.Foundation.FoundationContract", true, true) },
- { "System.AttributeUsageAttribute", new MappedType("Windows.Foundation.Metadata", "AttributeUsageAttribute", "Windows.Foundation.FoundationContract") },
- { "System.Numerics.Matrix3x2", new MappedType("Windows.Foundation.Numerics", "Matrix3x2", "Windows.Foundation.FoundationContract", true, true) },
- { "System.Numerics.Matrix4x4", new MappedType("Windows.Foundation.Numerics", "Matrix4x4", "Windows.Foundation.FoundationContract", true, true) },
- { "System.Numerics.Plane", new MappedType("Windows.Foundation.Numerics", "Plane", "Windows.Foundation.FoundationContract", true, true) },
- { "System.Numerics.Quaternion", new MappedType("Windows.Foundation.Numerics", "Quaternion", "Windows.Foundation.FoundationContract", true, true) },
- { "System.Numerics.Vector2", new MappedType("Windows.Foundation.Numerics", "Vector2", "Windows.Foundation.FoundationContract", true, true) },
- { "System.Numerics.Vector3", new MappedType("Windows.Foundation.Numerics", "Vector3", "Windows.Foundation.FoundationContract", true, true) },
- { "System.Numerics.Vector4", new MappedType("Windows.Foundation.Numerics", "Vector4", "Windows.Foundation.FoundationContract", true, true) },
- { "System.Type", new MappedType(GetSystemTypeCustomMapping) },
- { "System.Collections.Generic.IEnumerable`1", new MappedType("Windows.Foundation.Collections", "IIterable`1", "Windows.Foundation.FoundationContract") },
- { "System.Collections.Generic.IEnumerator`1", new MappedType("Windows.Foundation.Collections", "IIterator`1", "Windows.Foundation.FoundationContract") },
- { "System.Collections.Generic.KeyValuePair`2", new MappedType("Windows.Foundation.Collections", "IKeyValuePair`2", "Windows.Foundation.FoundationContract") },
- { "System.Collections.Generic.IReadOnlyDictionary`2", new MappedType("Windows.Foundation.Collections", "IMapView`2", "Windows.Foundation.FoundationContract") },
- { "System.Collections.Generic.IDictionary`2", new MappedType("Windows.Foundation.Collections", "IMap`2", "Windows.Foundation.FoundationContract") },
- { "System.Collections.Generic.IReadOnlyList`1", new MappedType("Windows.Foundation.Collections", "IVectorView`1", "Windows.Foundation.FoundationContract") },
- { "System.Collections.Generic.IList`1", new MappedType("Windows.Foundation.Collections", "IVector`1", "Windows.Foundation.FoundationContract") },
- { "Windows.UI.Color", new MappedType("Windows.UI", "Color", "Windows.Foundation.UniversalApiContract", true, true) },
- };
- }
-}
+ }
+}
diff --git a/src/Authoring/WinRT.SourceGenerator/TypeMapper.cs b/src/Authoring/WinRT.SourceGenerator/TypeMapper.cs
new file mode 100644
index 000000000..e35ccc63e
--- /dev/null
+++ b/src/Authoring/WinRT.SourceGenerator/TypeMapper.cs
@@ -0,0 +1,125 @@
+using Microsoft.CodeAnalysis;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using static Generator.GeneratorHelper;
+
+namespace Generator
+{
+ internal sealed class TypeMapper
+ {
+ private readonly Dictionary typeMapping;
+
+ // Based on whether System.Type is used in an attribute declaration or elsewhere, we need to choose the correct custom mapping
+ // as attributes don't use the TypeName mapping.
+ private static (string, string, string, bool, bool) GetSystemTypeCustomMapping(ISymbol containingSymbol)
+ {
+ bool isDefinedInAttribute =
+ containingSymbol != null &&
+ string.CompareOrdinal((containingSymbol as INamedTypeSymbol).BaseType?.ToString(), "System.Attribute") == 0;
+ return isDefinedInAttribute ?
+ ("System", "Type", "mscorlib", true, false) :
+ ("Windows.UI.Xaml.Interop", "TypeName", "Windows.Foundation.UniversalApiContract", false, true);
+ }
+
+ public TypeMapper(UiXamlMode xamlMode)
+ {
+ // This should be in sync with the reverse mapping from WinRT.Runtime/Projections.cs and cswinrt/helpers.h.
+ if (xamlMode == UiXamlMode.WindowsUiXaml)
+ {
+ typeMapping = new(StringComparer.Ordinal)
+ {
+ { "System.DateTimeOffset", new MappedType("Windows.Foundation", "DateTime", "Windows.Foundation.FoundationContract", true, false) },
+ { "System.Exception", new MappedType("Windows.Foundation", "HResult", "Windows.Foundation.FoundationContract", true, false) },
+ { "System.EventHandler`1", new MappedType("Windows.Foundation", "EventHandler`1", "Windows.Foundation.FoundationContract") },
+ { "System.FlagsAttribute", new MappedType("System", "FlagsAttribute", "mscorlib" ) },
+ { "System.IDisposable", new MappedType("Windows.Foundation", "IClosable", "Windows.Foundation.FoundationContract") },
+ { "System.Nullable`1", new MappedType("Windows.Foundation", "IReference`1", "Windows.Foundation.FoundationContract" ) },
+ { "System.Object", new MappedType("System", "Object", "mscorlib" ) },
+ { "System.TimeSpan", new MappedType("Windows.Foundation", "TimeSpan", "Windows.Foundation.FoundationContract", true, false) },
+ { "System.Uri", new MappedType("Windows.Foundation", "Uri", "Windows.Foundation.FoundationContract") },
+ { "System.ComponentModel.INotifyPropertyChanged", new MappedType("Windows.UI.Xaml.Data", "INotifyPropertyChanged", "Windows.UI.Xaml") },
+ { "System.ComponentModel.PropertyChangedEventArgs", new MappedType("Windows.UI.Xaml.Data", "PropertyChangedEventArgs", "Windows.UI.Xaml") },
+ { "System.ComponentModel.PropertyChangedEventHandler", new MappedType("Windows.UI.Xaml.Data", "PropertyChangedEventHandler", "Windows.UI.Xaml") },
+ { "System.Windows.Input.ICommand", new MappedType("Windows.UI.Xaml.Input", "ICommand", "Windows.UI.Xaml") },
+ { "System.Collections.IEnumerable", new MappedType("Windows.UI.Xaml.Interop", "IBindableIterable", "Windows.UI.Xaml") },
+ { "System.Collections.IList", new MappedType("Windows.UI.Xaml.Interop", "IBindableVector", "Windows.UI.Xaml") },
+ { "System.Collections.Specialized.INotifyCollectionChanged", new MappedType("Windows.UI.Xaml.Interop", "INotifyCollectionChanged", "Windows.UI.Xaml") },
+ { "System.Collections.Specialized.NotifyCollectionChangedAction", new MappedType("Windows.UI.Xaml.Interop", "NotifyCollectionChangedAction", "Windows.UI.Xaml") },
+ { "System.Collections.Specialized.NotifyCollectionChangedEventArgs", new MappedType("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventArgs", "Windows.UI.Xaml") },
+ { "System.Collections.Specialized.NotifyCollectionChangedEventHandler", new MappedType("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventHandler", "Windows.UI.Xaml") },
+ { "WinRT.EventRegistrationToken", new MappedType("Windows.Foundation", "EventRegistrationToken", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.AttributeTargets", new MappedType("Windows.Foundation.Metadata", "AttributeTargets", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.AttributeUsageAttribute", new MappedType("Windows.Foundation.Metadata", "AttributeUsageAttribute", "Windows.Foundation.FoundationContract") },
+ { "System.Numerics.Matrix3x2", new MappedType("Windows.Foundation.Numerics", "Matrix3x2", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Matrix4x4", new MappedType("Windows.Foundation.Numerics", "Matrix4x4", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Plane", new MappedType("Windows.Foundation.Numerics", "Plane", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Quaternion", new MappedType("Windows.Foundation.Numerics", "Quaternion", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Vector2", new MappedType("Windows.Foundation.Numerics", "Vector2", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Vector3", new MappedType("Windows.Foundation.Numerics", "Vector3", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Vector4", new MappedType("Windows.Foundation.Numerics", "Vector4", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Type", new MappedType(GetSystemTypeCustomMapping) },
+ { "System.Collections.Generic.IEnumerable`1", new MappedType("Windows.Foundation.Collections", "IIterable`1", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IEnumerator`1", new MappedType("Windows.Foundation.Collections", "IIterator`1", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.KeyValuePair`2", new MappedType("Windows.Foundation.Collections", "IKeyValuePair`2", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IReadOnlyDictionary`2", new MappedType("Windows.Foundation.Collections", "IMapView`2", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IDictionary`2", new MappedType("Windows.Foundation.Collections", "IMap`2", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IReadOnlyList`1", new MappedType("Windows.Foundation.Collections", "IVectorView`1", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IList`1", new MappedType("Windows.Foundation.Collections", "IVector`1", "Windows.Foundation.FoundationContract") },
+ { "Windows.UI.Color", new MappedType("Windows.UI", "Color", "Windows.Foundation.UniversalApiContract", true, true) },
+ };
+ }
+ else
+ {
+ typeMapping = new(StringComparer.Ordinal)
+ {
+ { "System.DateTimeOffset", new MappedType("Windows.Foundation", "DateTime", "Windows.Foundation.FoundationContract", true, false) },
+ { "System.Exception", new MappedType("Windows.Foundation", "HResult", "Windows.Foundation.FoundationContract", true, false) },
+ { "System.EventHandler`1", new MappedType("Windows.Foundation", "EventHandler`1", "Windows.Foundation.FoundationContract") },
+ { "System.FlagsAttribute", new MappedType("System", "FlagsAttribute", "mscorlib" ) },
+ { "System.IDisposable", new MappedType("Windows.Foundation", "IClosable", "Windows.Foundation.FoundationContract") },
+ { "System.IServiceProvider", new MappedType("Microsoft.UI.Xaml", "IXamlServiceProvider", "Microsoft.UI") },
+ { "System.Nullable`1", new MappedType("Windows.Foundation", "IReference`1", "Windows.Foundation.FoundationContract" ) },
+ { "System.Object", new MappedType("System", "Object", "mscorlib" ) },
+ { "System.TimeSpan", new MappedType("Windows.Foundation", "TimeSpan", "Windows.Foundation.FoundationContract", true, false) },
+ { "System.Uri", new MappedType("Windows.Foundation", "Uri", "Windows.Foundation.FoundationContract") },
+ { "System.ComponentModel.DataErrorsChangedEventArgs", new MappedType("Microsoft.UI.Xaml.Data", "DataErrorsChangedEventArgs", "Microsoft.UI") },
+ { "System.ComponentModel.INotifyDataErrorInfo", new MappedType("Microsoft.UI.Xaml.Data", "INotifyDataErrorInfo", "Microsoft.UI") },
+ { "System.ComponentModel.INotifyPropertyChanged", new MappedType("Microsoft.UI.Xaml.Data", "INotifyPropertyChanged", "Microsoft.UI") },
+ { "System.ComponentModel.PropertyChangedEventArgs", new MappedType("Microsoft.UI.Xaml.Data", "PropertyChangedEventArgs", "Microsoft.UI") },
+ { "System.ComponentModel.PropertyChangedEventHandler", new MappedType("Microsoft.UI.Xaml.Data", "PropertyChangedEventHandler", "Microsoft.UI") },
+ { "System.Windows.Input.ICommand", new MappedType("Microsoft.UI.Xaml.Input", "ICommand", "Microsoft.UI") },
+ { "System.Collections.IEnumerable", new MappedType("Microsoft.UI.Xaml.Interop", "IBindableIterable", "Microsoft.UI") },
+ { "System.Collections.IList", new MappedType("Microsoft.UI.Xaml.Interop", "IBindableVector", "Microsoft.UI") },
+ { "System.Collections.Specialized.INotifyCollectionChanged", new MappedType("Microsoft.UI.Xaml.Interop", "INotifyCollectionChanged", "Microsoft.UI") },
+ { "System.Collections.Specialized.NotifyCollectionChangedAction", new MappedType("Microsoft.UI.Xaml.Interop", "NotifyCollectionChangedAction", "Microsoft.UI") },
+ { "System.Collections.Specialized.NotifyCollectionChangedEventArgs", new MappedType("Microsoft.UI.Xaml.Interop", "NotifyCollectionChangedEventArgs", "Microsoft.UI") },
+ { "System.Collections.Specialized.NotifyCollectionChangedEventHandler", new MappedType("Microsoft.UI.Xaml.Interop", "NotifyCollectionChangedEventHandler", "Microsoft.UI") },
+ { "WinRT.EventRegistrationToken", new MappedType("Windows.Foundation", "EventRegistrationToken", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.AttributeTargets", new MappedType("Windows.Foundation.Metadata", "AttributeTargets", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.AttributeUsageAttribute", new MappedType("Windows.Foundation.Metadata", "AttributeUsageAttribute", "Windows.Foundation.FoundationContract") },
+ { "System.Numerics.Matrix3x2", new MappedType("Windows.Foundation.Numerics", "Matrix3x2", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Matrix4x4", new MappedType("Windows.Foundation.Numerics", "Matrix4x4", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Plane", new MappedType("Windows.Foundation.Numerics", "Plane", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Quaternion", new MappedType("Windows.Foundation.Numerics", "Quaternion", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Vector2", new MappedType("Windows.Foundation.Numerics", "Vector2", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Vector3", new MappedType("Windows.Foundation.Numerics", "Vector3", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Numerics.Vector4", new MappedType("Windows.Foundation.Numerics", "Vector4", "Windows.Foundation.FoundationContract", true, true) },
+ { "System.Type", new MappedType(GetSystemTypeCustomMapping) },
+ { "System.Collections.Generic.IEnumerable`1", new MappedType("Windows.Foundation.Collections", "IIterable`1", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IEnumerator`1", new MappedType("Windows.Foundation.Collections", "IIterator`1", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.KeyValuePair`2", new MappedType("Windows.Foundation.Collections", "IKeyValuePair`2", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IReadOnlyDictionary`2", new MappedType("Windows.Foundation.Collections", "IMapView`2", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IDictionary`2", new MappedType("Windows.Foundation.Collections", "IMap`2", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IReadOnlyList`1", new MappedType("Windows.Foundation.Collections", "IVectorView`1", "Windows.Foundation.FoundationContract") },
+ { "System.Collections.Generic.IList`1", new MappedType("Windows.Foundation.Collections", "IVector`1", "Windows.Foundation.FoundationContract") },
+ { "Windows.UI.Color", new MappedType("Windows.UI", "Color", "Windows.Foundation.UniversalApiContract", true, true) },
+ };
+ }
+ }
+
+ public bool HasMappingForType(string typeName) => typeMapping.ContainsKey(typeName);
+
+ public MappedType GetMappedType(string typeName) => typeMapping[typeName];
+ }
+}
diff --git a/src/Authoring/WinRT.SourceGenerator/UiXamlMode.cs b/src/Authoring/WinRT.SourceGenerator/UiXamlMode.cs
new file mode 100644
index 000000000..7432a1075
--- /dev/null
+++ b/src/Authoring/WinRT.SourceGenerator/UiXamlMode.cs
@@ -0,0 +1,26 @@
+using Microsoft.CodeAnalysis.Diagnostics;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Generator
+{
+ internal enum UiXamlMode
+ {
+ MicrosoftUiXaml,
+ WindowsUiXaml,
+ }
+
+ internal static class OptionsHelper
+ {
+ public static UiXamlMode GetUiXamlMode(this AnalyzerConfigOptions options)
+ {
+ if (options.TryGetValue("build_property.CsWinRTUiXamlMode", out var value) && Enum.TryParse(value, out UiXamlMode mode))
+ {
+ return mode;
+ }
+
+ return UiXamlMode.MicrosoftUiXaml;
+ }
+ }
+}
diff --git a/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs b/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs
index 9e33c92c6..d2ef2cc11 100644
--- a/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs
+++ b/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs
@@ -265,7 +265,7 @@ class WinRTTypeWriter : CSharpSyntaxWalker
private readonly Dictionary typeReferenceMapping;
private readonly Dictionary assemblyReferenceMapping;
private readonly MetadataBuilder metadataBuilder;
-
+ private readonly TypeMapper mapper;
private readonly Dictionary typeDefinitionMapping;
private TypeDeclaration currentTypeDeclaration;
@@ -275,12 +275,14 @@ public WinRTTypeWriter(
string assembly,
string version,
MetadataBuilder metadataBuilder,
- Logger logger)
+ Logger logger,
+ TypeMapper mapper)
{
this.assembly = assembly;
this.version = version;
this.metadataBuilder = metadataBuilder;
Logger = logger;
+ this.mapper = mapper;
typeReferenceMapping = new Dictionary(StringComparer.Ordinal);
assemblyReferenceMapping = new Dictionary(StringComparer.Ordinal);
typeDefinitionMapping = new Dictionary(StringComparer.Ordinal);
@@ -435,9 +437,9 @@ private EntityHandle GetTypeReference(ISymbol symbol)
var assembly = GetAssemblyForWinRTType(symbol);
if (assembly == null)
{
- if (GeneratorHelper.MappedCSharpTypes.ContainsKey(fullType))
+ if (mapper.HasMappingForType(fullType))
{
- (@namespace, name, assembly, _, _) = GeneratorHelper.MappedCSharpTypes[fullType].GetMapping(currentTypeDeclaration.Node);
+ (@namespace, name, assembly, _, _) = mapper.GetMappedType(fullType).GetMapping(currentTypeDeclaration.Node);
Logger.Log("custom mapping " + fullType + " to " + QualifiedName(@namespace, name) + " from " + assembly);
}
else
@@ -520,9 +522,9 @@ private void EncodeSymbol(Symbol symbol, SignatureTypeEncoder typeEncoder)
else
{
bool isValueType = symbol.Type.TypeKind == TypeKind.Enum || symbol.Type.TypeKind == TypeKind.Struct;
- if (GeneratorHelper.MappedCSharpTypes.ContainsKey(QualifiedName(symbol.Type)))
+ if (mapper.HasMappingForType(QualifiedName(symbol.Type)))
{
- (_, _, _, _, isValueType) = GeneratorHelper.MappedCSharpTypes[QualifiedName(symbol.Type)].GetMapping(currentTypeDeclaration.Node);
+ (_, _, _, _, isValueType) = mapper.GetMappedType(QualifiedName(symbol.Type)).GetMapping(currentTypeDeclaration.Node);
}
typeEncoder.Type(GetTypeReference(symbol.Type), isValueType);
}
@@ -804,7 +806,7 @@ private void ProcessCustomMappedInterfaces(INamedTypeSymbol classSymbol)
// Mark custom mapped interface members for removal later.
// Note we want to also mark members from interfaces without mappings.
foreach (var implementedInterface in GetInterfaces(classSymbol, true).
- Where(symbol => GeneratorHelper.MappedCSharpTypes.ContainsKey(QualifiedName(symbol)) ||
+ Where(symbol => mapper.HasMappingForType(QualifiedName(symbol)) ||
ImplementedInterfacesWithoutMapping.Contains(QualifiedName(symbol))))
{
bool isPubliclyImplemented = false;
@@ -825,7 +827,7 @@ private void ProcessCustomMappedInterfaces(INamedTypeSymbol classSymbol)
}
foreach (var implementedInterface in GetInterfaces(classSymbol)
- .Where(symbol => GeneratorHelper.MappedCSharpTypes.ContainsKey(QualifiedName(symbol))))
+ .Where(symbol => mapper.HasMappingForType(QualifiedName(symbol))))
{
WriteCustomMappedTypeMembers(implementedInterface, true, isPublicImplementation[implementedInterface]);
}
@@ -853,9 +855,9 @@ INamedTypeSymbol GetTypeByMetadataName(string metadataName)
private string GetMappedQualifiedTypeName(ITypeSymbol symbol)
{
string qualifiedName = QualifiedName(symbol);
- if (GeneratorHelper.MappedCSharpTypes.ContainsKey(qualifiedName))
+ if (mapper.HasMappingForType(qualifiedName))
{
- var (@namespace, mappedTypeName, _, _, _) = GeneratorHelper.MappedCSharpTypes[qualifiedName].GetMapping(currentTypeDeclaration.Node);
+ var (@namespace, mappedTypeName, _, _, _) = mapper.GetMappedType(qualifiedName).GetMapping(currentTypeDeclaration.Node);
qualifiedName = QualifiedName(@namespace, mappedTypeName);
if (symbol is INamedTypeSymbol namedType && namedType.TypeArguments.Length > 0)
{
@@ -874,7 +876,7 @@ private string GetMappedQualifiedTypeName(ITypeSymbol symbol)
private void WriteCustomMappedTypeMembers(INamedTypeSymbol symbol, bool isDefinition, bool isPublic = true)
{
- var (_, mappedTypeName, _, _, _) = GeneratorHelper.MappedCSharpTypes[QualifiedName(symbol)].GetMapping(currentTypeDeclaration.Node);
+ var (_, mappedTypeName, _, _, _) = mapper.GetMappedType(QualifiedName(symbol)).GetMapping(currentTypeDeclaration.Node);
string qualifiedName = GetMappedQualifiedTypeName(symbol);
Logger.Log("writing custom mapped type members for " + mappedTypeName + " public: " + isPublic + " qualified name: " + qualifiedName);
@@ -1233,7 +1235,7 @@ void GatherPubliclyAccessibleInterfaces(ITypeSymbol symbol)
GatherPubliclyAccessibleInterfaces(symbol);
var baseType = symbol.BaseType;
- while (baseType != null && !GeneratorHelper.IsWinRTType(baseType))
+ while (baseType != null && !GeneratorHelper.IsWinRTType(baseType, mapper))
{
GatherPubliclyAccessibleInterfaces(baseType);
@@ -2438,9 +2440,9 @@ void AddType(INamedTypeSymbol type, bool treatAsProjectedType = false)
{
AddProjectedType(type);
}
- else if (GeneratorHelper.MappedCSharpTypes.ContainsKey(qualifiedName))
+ else if (mapper.HasMappingForType(qualifiedName))
{
- var (@namespace, name, assembly, isSystemType, _) = GeneratorHelper.MappedCSharpTypes[qualifiedName].GetMapping();
+ var (@namespace, name, assembly, isSystemType, _) = mapper.GetMappedType(qualifiedName).GetMapping();
if (isSystemType)
{
var projectedType = Model.Compilation.GetTypeByMetadataName(QualifiedName(@namespace, name));
@@ -2532,7 +2534,7 @@ public void FinalizeGeneration()
Logger.Log("finalizing interface " + implementedInterfaceQualifiedNameWithGenerics);
var interfaceTypeDeclaration = typeDefinitionMapping[implementedInterfaceQualifiedNameWithGenerics];
- if (GeneratorHelper.MappedCSharpTypes.ContainsKey(QualifiedName(implementedInterface)))
+ if (mapper.HasMappingForType(QualifiedName(implementedInterface)))
{
Logger.Log("adding MethodImpls for custom mapped interface");
foreach (var interfaceMember in interfaceTypeDeclaration.MethodReferences)
@@ -2663,11 +2665,11 @@ public void FinalizeGeneration()
public void GenerateWinRTExposedClassAttributes(GeneratorExecutionContext context)
{
- bool IsWinRTType(ISymbol symbol)
+ bool IsWinRTType(ISymbol symbol, TypeMapper mapper)
{
if (!SymbolEqualityComparer.Default.Equals(symbol.ContainingAssembly, context.Compilation.Assembly))
{
- return GeneratorHelper.IsWinRTType(symbol, IsWinRTType);
+ return GeneratorHelper.IsWinRTType(symbol, mapper, symbol => IsWinRTType(symbol, mapper));
}
if (symbol is INamedTypeSymbol namedType)
@@ -2701,8 +2703,8 @@ typeDeclaration.Node is INamedTypeSymbol symbol &&
symbol.TypeKind == TypeKind.Class &&
!symbol.IsStatic)
{
- vtableAttributesToAdd.Add(WinRTAotSourceGenerator.GetVtableAttributeToAdd(symbol, IsWinRTType, context.Compilation.Assembly, true, typeDeclaration.DefaultInterface));
- WinRTAotSourceGenerator.AddVtableAdapterTypeForKnownInterface(symbol, context.Compilation, IsWinRTType, vtableAttributesToAddOnLookupTable);
+ vtableAttributesToAdd.Add(WinRTAotSourceGenerator.GetVtableAttributeToAdd(symbol, IsWinRTType, mapper, context.Compilation.Assembly, true, typeDeclaration.DefaultInterface));
+ WinRTAotSourceGenerator.AddVtableAdapterTypeForKnownInterface(symbol, context.Compilation, IsWinRTType, mapper, vtableAttributesToAddOnLookupTable);
}
}
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 5a1370dc5..caef79a59 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -30,6 +30,8 @@
netcoreapp3.1;net6.0;net8.0
netstandard2.0;net6.0;net8.0
netstandard2.0;net6.0;net8.0
+ net6.0;net8.0
+ net6.0;net8.0
net6.0-windows10.0.19041.0;net7.0-windows10.0.19041.0
net6.0-windows10.0.19041.0
net6.0;net8.0
diff --git a/src/Perf/IIDOptimizer/GuidPatcher.cs b/src/Perf/IIDOptimizer/GuidPatcher.cs
index bd200dfd6..411b855fa 100644
--- a/src/Perf/IIDOptimizer/GuidPatcher.cs
+++ b/src/Perf/IIDOptimizer/GuidPatcher.cs
@@ -72,12 +72,14 @@ public GuidPatcher(AssemblyDefinition winRTRuntime, AssemblyDefinition targetAss
guidGeneratorType = null;
TypeDefinition? typeExtensionsType = null;
+ TypeDefinition? wuxMuxProjectedInterfaceAttributeType = null;
// Use the type definition if we are patching WinRT.Runtime, otherwise lookup the types as references
if (string.CompareOrdinal(assembly.Name.Name, "WinRT.Runtime") == 0)
{
- guidGeneratorType = winRTRuntimeAssembly.MainModule.Types.Where(typeDef => string.CompareOrdinal(typeDef.Name, "GuidGenerator") == 0).First();
- typeExtensionsType = winRTRuntimeAssembly.MainModule.Types.Where(typeDef => string.CompareOrdinal(typeDef.Name, "TypeExtensions") == 0).First();
+ guidGeneratorType = winRTRuntimeAssembly.MainModule.Types.Where(typeDef => string.Equals(typeDef.Name, "GuidGenerator", StringComparison.Ordinal)).First();
+ typeExtensionsType = winRTRuntimeAssembly.MainModule.Types.Where(typeDef => string.Equals(typeDef.Name, "TypeExtensions", StringComparison.Ordinal)).First();
+ wuxMuxProjectedInterfaceAttributeType = winRTRuntimeAssembly.MainModule.Types.Where(typedef => string.Equals(typedef.Name, "WuxMuxProjectedInterfaceAttribute", StringComparison.Ordinal)).First();
}
foreach (var asm in assembly.MainModule.AssemblyReferences)
@@ -87,6 +89,7 @@ public GuidPatcher(AssemblyDefinition winRTRuntime, AssemblyDefinition targetAss
guidGeneratorType =
new TypeReference("WinRT", "GuidGenerator", assembly.MainModule, asm).Resolve();
typeExtensionsType = new TypeReference("WinRT", "TypeExtensions", assembly.MainModule, asm).Resolve();
+ wuxMuxProjectedInterfaceAttributeType = new TypeReference("WinRT", "WuxMuxProjectedInterfaceAttribute", assembly.MainModule, asm).Resolve();
}
else if (string.CompareOrdinal(asm.Name, "System.Runtime.InteropServices") == 0)
{
@@ -101,7 +104,7 @@ public GuidPatcher(AssemblyDefinition winRTRuntime, AssemblyDefinition targetAss
getHelperTypeMethod = typeExtensionsType.Methods.First(m => String.CompareOrdinal(m.Name, "GetHelperType") == 0);
}
- signatureGenerator = new SignatureGenerator(assembly, guidAttributeType!, winRTRuntimeAssembly);
+ signatureGenerator = new SignatureGenerator(assembly, guidAttributeType!, wuxMuxProjectedInterfaceAttributeType!, winRTRuntimeAssembly);
methodCache = new Dictionary();
}
@@ -262,6 +265,11 @@ private void VisitSignature(SignaturePart rootSignaturePart, SignatureEmitter em
emitter.PushCustomSignature(custom.Method);
}
break;
+ case GenericFallback fallback:
+ {
+ emitter.PushFallback(fallback.Type);
+ }
+ break;
default:
break;
}
diff --git a/src/Perf/IIDOptimizer/SignatureEmitter.cs b/src/Perf/IIDOptimizer/SignatureEmitter.cs
index aa3d6a393..3483105d8 100644
--- a/src/Perf/IIDOptimizer/SignatureEmitter.cs
+++ b/src/Perf/IIDOptimizer/SignatureEmitter.cs
@@ -35,6 +35,8 @@ sealed record RuntimeGenericSignatureStep(GenericParameter OriginalTypeParameter
sealed record RuntimeCustomSignatureStep(MethodReference method) : SignatureStep;
+ sealed record FallbackSignatureStep(TypeReference type) : SignatureStep;
+
public SignatureEmitter(TypeReference describedType, MethodDefinition guidDataGetterMethod)
{
this.describedType = describedType;
@@ -76,6 +78,16 @@ public void PushCustomSignature(MethodReference customSignatureMethod)
signatureSteps.Add(new RuntimeCustomSignatureStep(customSignatureMethod));
}
+ public void PushFallback(TypeReference type)
+ {
+ if (currentStringBuilder is not null)
+ {
+ signatureSteps.Add(new StringStep(currentStringBuilder.ToString()));
+ currentStringBuilder = null;
+ }
+ signatureSteps.Add(new FallbackSignatureStep(type));
+ }
+
public void EmitGuidGetter(
TypeDefinition guidDataBlockType,
TypeDefinition implementationDetailsType,
@@ -289,6 +301,25 @@ private void GenerateGuidFactoryFromComplexSignature(TypeDefinition implementati
il.Emit(OpCodes.Stloc, fullSignatureLength);
}
break;
+ case FallbackSignatureStep(TypeReference type):
+ {
+ // byte[] bytes = Encoding.UTF8.GetBytes(GetSignature(typeof(type)))
+ il.Emit(OpCodes.Call, utf8EncodingGetter);
+ il.Emit(OpCodes.Ldtoken, type);
+ il.Emit(OpCodes.Call, getTypeFromHandleMethod);
+ il.Emit(OpCodes.Call, getSignatureMethod);
+ il.Emit(OpCodes.Callvirt, encodingGetBytes);
+ il.Emit(OpCodes.Dup);
+ // = new ReadOnlySpan(bytes);
+ il.Emit(OpCodes.Newobj, readOnlySpanOfByteArrayCtor);
+ il.Emit(OpCodes.Stloc, signatureParts[i]);
+ // signatureLength += bytes.Length
+ il.Emit(OpCodes.Ldlen);
+ il.Emit(OpCodes.Ldloc, fullSignatureLength);
+ il.Emit(OpCodes.Add_Ovf);
+ il.Emit(OpCodes.Stloc, fullSignatureLength);
+ }
+ break;
default:
il.Clear();
throw new InvalidOperationException();
diff --git a/src/Perf/IIDOptimizer/SignatureGenerator.cs b/src/Perf/IIDOptimizer/SignatureGenerator.cs
index 7c6fd6282..67b2c2be3 100644
--- a/src/Perf/IIDOptimizer/SignatureGenerator.cs
+++ b/src/Perf/IIDOptimizer/SignatureGenerator.cs
@@ -37,6 +37,8 @@ sealed record NonGenericDelegateSignature(Guid DelegateIID) : SignaturePart;
sealed record UninstantiatedGeneric(GenericParameter OriginalGenericParameter) : SignaturePart;
+ sealed record GenericFallback(TypeReference Type) : SignaturePart;
+
abstract record SignatureWithChildren(string GroupingName, string ThisEntitySignature, IEnumerable ChildrenSignatures) : SignaturePart;
sealed record GenericSignature(Guid BaseGuid, IEnumerable GenericMemberSignatures) :
@@ -55,12 +57,14 @@ sealed class SignatureGenerator
{
private readonly AssemblyDefinition assembly;
private readonly TypeDefinition guidAttributeType;
+ private readonly TypeDefinition wuxMuxProjectedInterfaceAttributeType;
private readonly AssemblyDefinition winRTRuntimeAssembly;
- public SignatureGenerator(AssemblyDefinition assembly, TypeDefinition guidAttributeType, AssemblyDefinition runtimeAssembly)
+ public SignatureGenerator(AssemblyDefinition assembly, TypeDefinition guidAttributeType, TypeDefinition wuxMuxProjectedInterfaceAttributeType, AssemblyDefinition runtimeAssembly)
{
this.assembly = assembly;
this.guidAttributeType = guidAttributeType;
+ this.wuxMuxProjectedInterfaceAttributeType = wuxMuxProjectedInterfaceAttributeType;
this.winRTRuntimeAssembly = runtimeAssembly;
}
@@ -170,6 +174,13 @@ public SignaturePart GetSignatureParts(TypeReference type)
return new RuntimeClassSignature(type, GetSignatureParts(iface));
}
+ // For types projected from WUX or MUX into .NET, we'll need to do a runtime lookup for the IID.
+ // TODO-WuxMux: We can instead take an option in the IID optimizer to hard-code the lookup for WUX or MUX when specified, which would be more efficient for scenarios where this is possible.
+ if (helperType?.Resolve().CustomAttributes.Any(attr => attr.AttributeType.Resolve() == wuxMuxProjectedInterfaceAttributeType) == true)
+ {
+ return new GenericFallback(type);
+ }
+
Guid? guidAttributeValue = type.ReadGuidFromAttribute(guidAttributeType, winRTRuntimeAssembly);
if (guidAttributeValue == null)
{
diff --git a/src/Projections/Windows.UI.Xaml/Module.cs b/src/Projections/Windows.UI.Xaml/Module.cs
new file mode 100644
index 000000000..636144eed
--- /dev/null
+++ b/src/Projections/Windows.UI.Xaml/Module.cs
@@ -0,0 +1,3 @@
+#if NET
+[assembly: global::System.Runtime.Versioning.SupportedOSPlatform("Windows")]
+#endif
diff --git a/src/Projections/Windows.UI.Xaml/Windows.UI.Xaml.csproj b/src/Projections/Windows.UI.Xaml/Windows.UI.Xaml.csproj
new file mode 100644
index 000000000..d28f78380
--- /dev/null
+++ b/src/Projections/Windows.UI.Xaml/Windows.UI.Xaml.csproj
@@ -0,0 +1,28 @@
+
+
+
+ $(LibBuildTFMsNoNetStandard)
+ x64;x86
+ Microsoft.Windows.UI.Xaml
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+-exclude Windows
+-include Windows.UI.Xaml
+-exclude Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute
+-exclude Windows.UI.Xaml.Media.Animation.KeyTime
+-exclude Windows.UI.Xaml.Media.Animation.RepeatBehavior
+
+
+
+
\ No newline at end of file
diff --git a/src/Tests/AuthoringWuxConsumptionTest/AuthoringWuxConsumptionTest.exe.manifest b/src/Tests/AuthoringWuxConsumptionTest/AuthoringWuxConsumptionTest.exe.manifest
new file mode 100644
index 000000000..3d69fa84a
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/AuthoringWuxConsumptionTest.exe.manifest
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Tests/AuthoringWuxConsumptionTest/AuthoringWuxConsumptionTest.vcxproj b/src/Tests/AuthoringWuxConsumptionTest/AuthoringWuxConsumptionTest.vcxproj
new file mode 100644
index 000000000..64c641b2f
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/AuthoringWuxConsumptionTest.vcxproj
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {A04A0416-5E35-4DD0-8226-63D941B28467}
+ Win32Proj
+ AuthoringConsumptionTest
+ Application
+ v143
+ v142
+ Unicode
+ <_WinMDPlatform>$(Platform)
+ <_WinMDPlatform Condition="'$(Platform)' == 'Win32'">x86
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+ true
+ true
+ true
+ true
+
+
+
+
+ {ffa9a78b-f53f-43ee-af87-24a80f4c330a}
+ TargetFramework=net6.0
+
+
+ {0bb8f82d-874e-45aa-bca3-20ce0562164a}
+ TargetFramework=net6.0
+
+
+ {7e33bcb7-19c5-4061-981d-ba695322708a}
+
+
+ {25244ced-966e-45f2-9711-1f51e951ff89}
+ TargetFramework=net6.0
+
+
+ {d60cfcad-4a13-4047-91c8-9d7df4753493}
+ TargetFramework=net6.0
+
+
+
+
+ ..\AuthoringWuxTest\bin\$(_WinMDPlatform)\$(Configuration)\net6.0\AuthoringWuxTest.winmd
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use
+ pch.h
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebugDLL
+ Level3
+
+
+ true
+ Console
+
+
+
+
+ Use
+ pch.h
+ Disabled
+ X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebugDLL
+ Level3
+
+
+ DebugFull
+ Console
+
+
+
+
+ Use
+ pch.h
+ Disabled
+ X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ EnableFastChecks
+ MultiThreadedDebugDLL
+ Level3
+
+
+ DebugFull
+ Console
+
+
+
+
+ Use
+ pch.h
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Level3
+ ProgramDatabase
+
+
+ true
+ Console
+ true
+ true
+
+
+
+
+ Use
+ pch.h
+ X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Level3
+ ProgramDatabase
+
+
+ true
+ Console
+ true
+ true
+
+
+
+
+ Use
+ pch.h
+ X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Level3
+ ProgramDatabase
+
+
+ true
+ Console
+ true
+ true
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Tests/AuthoringWuxConsumptionTest/AuthoringWuxConsumptionTest.vcxproj.filters b/src/Tests/AuthoringWuxConsumptionTest/AuthoringWuxConsumptionTest.vcxproj.filters
new file mode 100644
index 000000000..1332cff35
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/AuthoringWuxConsumptionTest.vcxproj.filters
@@ -0,0 +1,39 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Tests/AuthoringWuxConsumptionTest/Directory.Build.targets b/src/Tests/AuthoringWuxConsumptionTest/Directory.Build.targets
new file mode 100644
index 000000000..623267b30
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/Directory.Build.targets
@@ -0,0 +1,16 @@
+
+
+
+ $(MSBuildProjectDirectory)/DoNotImport_MsAppxPackageTargets.targets
+ CopyTestAssets;$(PrepareForRunDependsOn)
+
+
+
+
+
+
+
+
+
diff --git a/src/Tests/AuthoringWuxConsumptionTest/DoNotImport_MsAppxPackageTargets.targets b/src/Tests/AuthoringWuxConsumptionTest/DoNotImport_MsAppxPackageTargets.targets
new file mode 100644
index 000000000..bcb335b80
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/DoNotImport_MsAppxPackageTargets.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/Tests/AuthoringWuxConsumptionTest/WinRT.Host.runtimeconfig.json b/src/Tests/AuthoringWuxConsumptionTest/WinRT.Host.runtimeconfig.json
new file mode 100644
index 000000000..89437eff9
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/WinRT.Host.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "rollForward": "LatestMinor",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "CsWinRT.UiXamlMode": "WindowsUiXaml"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Tests/AuthoringWuxConsumptionTest/packages.config b/src/Tests/AuthoringWuxConsumptionTest/packages.config
new file mode 100644
index 000000000..98b40a750
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Tests/AuthoringWuxConsumptionTest/pch.cpp b/src/Tests/AuthoringWuxConsumptionTest/pch.cpp
new file mode 100644
index 000000000..bcb5590be
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/src/Tests/AuthoringWuxConsumptionTest/pch.h b/src/Tests/AuthoringWuxConsumptionTest/pch.h
new file mode 100644
index 000000000..db3c5d270
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/pch.h
@@ -0,0 +1,26 @@
+#pragma once
+
+// Undefine GetCurrentTime macro to prevent
+// conflict with Storyboard::GetCurrentTime
+#undef GetCurrentTime
+
+#include
+#include
+#include
+
+#pragma push_macro("X86")
+#pragma push_macro("X64")
+#undef X86
+#undef X64
+#include "winrt/Windows.System.h"
+#pragma pop_macro("X64")
+#pragma pop_macro("X86")
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include "gtest/gtest.h"
diff --git a/src/Tests/AuthoringWuxConsumptionTest/test.cpp b/src/Tests/AuthoringWuxConsumptionTest/test.cpp
new file mode 100644
index 000000000..b182b935c
--- /dev/null
+++ b/src/Tests/AuthoringWuxConsumptionTest/test.cpp
@@ -0,0 +1,75 @@
+#include "pch.h"
+
+using namespace winrt;
+using namespace Windows::Foundation;
+using namespace AuthoringWuxTest;
+
+TEST(AuthoringWuxTest, Collections)
+{
+ DisposableClass disposed;
+ disposed.Close();
+ MultipleInterfaceMappingClass multipleInterfaces;
+ Windows::UI::Xaml::Interop::IBindableIterable bindable = multipleInterfaces;
+ Windows::Foundation::Collections::IVector vector = multipleInterfaces;
+ Windows::UI::Xaml::Interop::IBindableVector bindableVector = multipleInterfaces;
+ EXPECT_EQ(vector.Size(), 0);
+ EXPECT_EQ(bindableVector.Size(), 0);
+ vector.Append(DisposableClass());
+ vector.Append(DisposableClass());
+ vector.Append(disposed);
+ bindableVector.Append(DisposableClass());
+ EXPECT_EQ(vector.Size(), 4);
+ EXPECT_EQ(bindableVector.Size(), 4);
+
+ auto first = vector.First();
+ EXPECT_TRUE(first.HasCurrent());
+ EXPECT_FALSE(first.Current().IsDisposed());
+ auto bindableFirst = bindable.First();
+ EXPECT_TRUE(bindableFirst.HasCurrent());
+ EXPECT_FALSE(bindableFirst.Current().as().IsDisposed());
+ bindableFirst.Current().as().Close();
+ EXPECT_TRUE(first.Current().IsDisposed());
+ EXPECT_FALSE(vector.GetAt(1).IsDisposed());
+ EXPECT_TRUE(vector.GetAt(2).IsDisposed());
+ EXPECT_TRUE(bindableVector.First().Current().as().IsDisposed());
+ EXPECT_FALSE(bindableVector.GetAt(3).as().IsDisposed());
+ EXPECT_TRUE(bindableVector.GetAt(2).as().IsDisposed());
+ for (auto obj : vector.GetView())
+ {
+ obj.Close();
+ }
+
+ std::array view{};
+ EXPECT_EQ(vector.GetMany(1, view), 2);
+ EXPECT_EQ(view.size(), 2);
+ for (auto& obj : view)
+ {
+ EXPECT_TRUE(obj.IsDisposed());
+ }
+}
+
+TEST(AuthoringWuxTest, PropertyChanged)
+{
+ CustomNotifyPropertyChanged customNotifyPropertyChanged;
+ Windows::UI::Xaml::Data::INotifyPropertyChanged propChanged = customNotifyPropertyChanged;
+ winrt::hstring propName = L"Number";
+ bool eventTriggered = false;
+ auto token = propChanged.PropertyChanged(auto_revoke, [&eventTriggered, &propName](IInspectable sender, Windows::UI::Xaml::Data::PropertyChangedEventArgs args)
+ {
+ eventTriggered = (args.PropertyName() == propName);
+ });
+
+ customNotifyPropertyChanged.RaisePropertyChanged(propName);
+
+ EXPECT_TRUE(eventTriggered);
+}
+
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ winrt::init_apartment(winrt::apartment_type::single_threaded);
+ auto manager = winrt::Windows::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread();
+ int result = RUN_ALL_TESTS();
+ manager.Close();
+ return result;
+}
\ No newline at end of file
diff --git a/src/Tests/AuthoringWuxTest/AuthoringWuxTest.csproj b/src/Tests/AuthoringWuxTest/AuthoringWuxTest.csproj
new file mode 100644
index 000000000..a00cb2c58
--- /dev/null
+++ b/src/Tests/AuthoringWuxTest/AuthoringWuxTest.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net6.0
+ x64;x86
+ true
+ true
+ WindowsUiXaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Tests/AuthoringWuxTest/Directory.Build.props b/src/Tests/AuthoringWuxTest/Directory.Build.props
new file mode 100644
index 000000000..4cf186e3d
--- /dev/null
+++ b/src/Tests/AuthoringWuxTest/Directory.Build.props
@@ -0,0 +1,9 @@
+
+
+
+ true
+
+
+
+
+
diff --git a/src/Tests/AuthoringWuxTest/Directory.Build.targets b/src/Tests/AuthoringWuxTest/Directory.Build.targets
new file mode 100644
index 000000000..8dde12d1b
--- /dev/null
+++ b/src/Tests/AuthoringWuxTest/Directory.Build.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/Tests/AuthoringWuxTest/Module.cs b/src/Tests/AuthoringWuxTest/Module.cs
new file mode 100644
index 000000000..636144eed
--- /dev/null
+++ b/src/Tests/AuthoringWuxTest/Module.cs
@@ -0,0 +1,3 @@
+#if NET
+[assembly: global::System.Runtime.Versioning.SupportedOSPlatform("Windows")]
+#endif
diff --git a/src/Tests/AuthoringWuxTest/Program.cs b/src/Tests/AuthoringWuxTest/Program.cs
new file mode 100644
index 000000000..004a3cb23
--- /dev/null
+++ b/src/Tests/AuthoringWuxTest/Program.cs
@@ -0,0 +1,171 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+
+#pragma warning disable CA1416
+
+namespace AuthoringWuxTest
+{
+ public sealed class DisposableClass : IDisposable
+ {
+ public bool IsDisposed { get; set; }
+
+ public DisposableClass()
+ {
+ IsDisposed = false;
+ }
+
+ public void Dispose()
+ {
+ IsDisposed = true;
+ }
+ }
+ public sealed class CustomNotifyPropertyChanged : INotifyPropertyChanged
+ {
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public void RaisePropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+ public sealed class CustomNotifyCollectionChanged : INotifyCollectionChanged
+ {
+ public event NotifyCollectionChangedEventHandler CollectionChanged;
+
+ public void RaiseCollectionChanged(NotifyCollectionChangedEventArgs args)
+ {
+ CollectionChanged?.Invoke(this, args);
+ }
+ }
+
+ public sealed class CustomEnumerable : IEnumerable
+ {
+ private IEnumerable _enumerable;
+
+ public CustomEnumerable(IEnumerable enumerable)
+ {
+ _enumerable = enumerable;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return _enumerable.GetEnumerator();
+ }
+ }
+
+ public sealed class MultipleInterfaceMappingClass : IList, IList
+ {
+ private List _list = new List();
+
+ DisposableClass IList.this[int index] { get => _list[index]; set => _list[index] = value; }
+ object IList.this[int index] { get => _list[index]; set => ((IList)_list) [index] = value; }
+
+ int ICollection.Count => _list.Count;
+
+ int ICollection.Count => _list.Count;
+
+ bool ICollection.IsReadOnly => true;
+
+ bool IList.IsReadOnly => true;
+
+ bool IList.IsFixedSize => false;
+
+ bool ICollection.IsSynchronized => true;
+
+ object ICollection.SyncRoot => ((ICollection) _list).SyncRoot;
+
+ void ICollection.Add(DisposableClass item)
+ {
+ _list.Add(item);
+ }
+
+ int IList.Add(object value)
+ {
+ return ((IList) _list).Add(value);
+ }
+
+ void ICollection.Clear()
+ {
+ _list.Clear();
+ }
+
+ void IList.Clear()
+ {
+ _list.Clear();
+ }
+
+ bool ICollection.Contains(DisposableClass item)
+ {
+ return _list.Contains(item);
+ }
+
+ bool IList.Contains(object value)
+ {
+ return ((IList) _list).Contains(value);
+ }
+
+ void ICollection.CopyTo(DisposableClass[] array, int arrayIndex)
+ {
+ _list.CopyTo(array, arrayIndex);
+ }
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ ((ICollection) _list).CopyTo(array, index);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _list.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _list.GetEnumerator();
+ }
+
+ int IList.IndexOf(DisposableClass item)
+ {
+ return _list.IndexOf(item);
+ }
+
+ int IList.IndexOf(object value)
+ {
+ return ((IList) _list).IndexOf(value);
+ }
+
+ void IList.Insert(int index, DisposableClass item)
+ {
+ _list.Insert(index, item);
+ }
+
+ void IList.Insert(int index, object value)
+ {
+ ((IList) _list).Insert(index, value);
+ }
+
+ bool ICollection.Remove(DisposableClass item)
+ {
+ return _list.Remove(item);
+ }
+
+ void IList.Remove(object value)
+ {
+ ((IList) _list).Remove(value);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ _list.RemoveAt(index);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ _list.RemoveAt(index);
+ }
+ }
+}
diff --git a/src/Tests/AuthoringWuxTest/Properties/launchSettings.json b/src/Tests/AuthoringWuxTest/Properties/launchSettings.json
new file mode 100644
index 000000000..c05aeebf5
--- /dev/null
+++ b/src/Tests/AuthoringWuxTest/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "AuthoringSample": {
+ "commandName": "Project",
+ "nativeDebugging": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WinRT.Runtime/GuidGenerator.cs b/src/WinRT.Runtime/GuidGenerator.cs
index 8f028fa9e..0b8f71cb0 100644
--- a/src/WinRT.Runtime/GuidGenerator.cs
+++ b/src/WinRT.Runtime/GuidGenerator.cs
@@ -7,6 +7,7 @@
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
+using WinRT.Interop;
namespace WinRT
{
@@ -19,16 +20,25 @@ static class GuidGenerator
{
public static Guid GetGUID(Type type)
{
- return type.GetGuidType().GUID;
+ type = type.GetGuidType();
+ if (type.GetCustomAttribute() is {} wuxMuxAttribute)
+ {
+ return GetWuxMuxIID(wuxMuxAttribute);
+ }
+ return type.GUID;
}
- public static Guid GetIID(
+ public static Guid GetIID(
#if NET
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
#endif
Type type)
{
type = type.GetGuidType();
+ if (type.GetCustomAttribute() is {} wuxMuxAttribute)
+ {
+ return GetWuxMuxIID(wuxMuxAttribute);
+ }
if (!type.IsGenericType)
{
return type.GUID;
@@ -36,21 +46,31 @@ public static Guid GetIID(
return (Guid)type.GetField("PIID").GetValue(null);
}
- public static string GetSignature(
+ internal static Guid GetWuxMuxIID(WuxMuxProjectedTypeAttribute wuxMuxAttribute)
+ {
+ return Projections.UiXamlModeSetting switch
+ {
+ Projections.UiXamlMode.WindowsUiXaml => wuxMuxAttribute.WuxIID,
+ Projections.UiXamlMode.MicrosoftUiXaml => wuxMuxAttribute.MuxIID,
+ _ => throw new InvalidOperationException("Invalid UI XAML mode")
+ };
+ }
+
+ public static string GetSignature(
#if NET
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
#endif
Type type)
- {
+ {
if (type == typeof(object))
{
return "cinterface(IInspectable)";
- }
-
+ }
+
if (type == typeof(string))
{
return "string";
- }
+ }
var helperType = type.FindHelperType();
if (helperType != null)
@@ -89,38 +109,38 @@ public static string GetSignature(
if (!type.IsPrimitive)
{
var winrtTypeAttribute = type.GetCustomAttribute();
- if (winrtTypeAttribute != null && !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature))
- {
- return winrtTypeAttribute.GuidSignature;
+ if (winrtTypeAttribute != null && !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature))
+ {
+ return winrtTypeAttribute.GuidSignature;
}
- else if (winrtTypeAttribute == null &&
- (winrtTypeAttribute = type.GetAuthoringMetadataType()?.GetCustomAttribute()) != null &&
- !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature))
- {
- return winrtTypeAttribute.GuidSignature;
+ else if (winrtTypeAttribute == null &&
+ (winrtTypeAttribute = type.GetAuthoringMetadataType()?.GetCustomAttribute()) != null &&
+ !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature))
+ {
+ return winrtTypeAttribute.GuidSignature;
}
- else
- {
- var args = type.GetFields(BindingFlags.Instance | BindingFlags.Public).Select(fi => GetSignature(fi.FieldType));
- return "struct(" + type.FullName + ";" + String.Join(";", args) + ")";
+ else
+ {
+ var args = type.GetFields(BindingFlags.Instance | BindingFlags.Public).Select(fi => GetSignature(fi.FieldType));
+ return "struct(" + type.FullName + ";" + String.Join(";", args) + ")";
}
}
throw new InvalidOperationException("unsupported value type");
}
}
}
-
- // For authoring interfaces, we can use the metadata type or the helper type to get the guid.
- // For built-in system interfaces that are custom type mapped, we use the helper type to get the guid.
- // For others, either the type itself or the helper type has the same guid and can be used.
+
+ // For authoring interfaces, we can use the metadata type or the helper type to get the guid.
+ // For built-in system interfaces that are custom type mapped, we use the helper type to get the guid.
+ // For others, either the type itself or the helper type has the same guid and can be used.
type = type.IsInterface ? (helperType ?? type) : type;
if (type.IsGenericType)
{
var args = type.GetGenericArguments().Select(t => GetSignature(t));
return "pinterface({" + GetGUID(type) + "};" + String.Join(";", args) + ")";
- }
-
+ }
+
if (type.IsDelegate())
{
return "delegate({" + GetGUID(type) + "})";
@@ -172,14 +192,14 @@ public static Guid CreateIID(Type type)
{
return new Guid(sig);
}
- else
- {
- return CreateIIDForGenericType(sig);
+ else
+ {
+ return CreateIIDForGenericType(sig);
}
}
- internal static Guid CreateIIDForGenericType(string signature)
- {
+ internal static Guid CreateIIDForGenericType(string signature)
+ {
#if !NET
var data = wrt_pinterface_namespace.ToByteArray().Concat(UTF8Encoding.UTF8.GetBytes(signature)).ToArray();
@@ -194,10 +214,10 @@ internal static Guid CreateIIDForGenericType(string signature)
Span dataSpan = data;
wrt_pinterface_namespace.TryWriteBytes(dataSpan);
var numBytes = UTF8Encoding.UTF8.GetBytes(signature, dataSpan[16..]);
- data = data[..(16 + numBytes)];
-
- return encode_guid(SHA1.HashData(data));
-#endif
+ data = data[..(16 + numBytes)];
+
+ return encode_guid(SHA1.HashData(data));
+#endif
}
}
}
diff --git a/src/WinRT.Runtime/Interop/WuxMuxProjectedInterfaceAttribute.cs b/src/WinRT.Runtime/Interop/WuxMuxProjectedInterfaceAttribute.cs
new file mode 100644
index 000000000..b30aa7dc4
--- /dev/null
+++ b/src/WinRT.Runtime/Interop/WuxMuxProjectedInterfaceAttribute.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace WinRT.Interop
+{
+ ///
+ /// This type signals that the type it is applied to is projected into .NET from either a Windows.UI.Xaml type or a Microsoft.UI.Xaml type.
+ /// For this type, the GuidAttribute is not used and instead the GetGuidSignature method must be called to get the IID or generic IID signature part of the type.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
+ internal sealed class WuxMuxProjectedTypeAttribute : Attribute
+ {
+ public Guid WuxIID { get; }
+
+ public Guid MuxIID { get; }
+
+ public WuxMuxProjectedTypeAttribute(string wuxIID, string muxIID)
+ {
+ WuxIID = Guid.Parse(wuxIID);
+ MuxIID = Guid.Parse(muxIID);
+ }
+ }
+}
diff --git a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
index 212a3ac2d..8407ff19d 100644
--- a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
+++ b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
@@ -129,4 +129,9 @@ TypesMustExist : Type 'WinRT.StructTypeDetails' does not exist in the r
MembersMustExist : Member 'public void WinRT.WindowsRuntimeTypeAttribute..ctor(System.String, System.String)' does not exist in the reference but it does exist in the implementation.
MembersMustExist : Member 'public System.String WinRT.WindowsRuntimeTypeAttribute.GuidSignature.get()' does not exist in the reference but it does exist in the implementation.
TypesMustExist : Type 'WinRT.WinRTExposedTypeAttribute' does not exist in the reference but it does exist in the implementation.
-Total Issues: 130
+MembersMustExist : Member 'public System.Boolean WinRT.ComWrappersSupport.RegisterDelegateFactory(System.Type, System.Func)' does not exist in the reference but it does exist in the implementation.
+MembersMustExist : Member 'public void WinRT.ComWrappersSupport.RegisterComInterfaceEntries(System.Type, System.Runtime.InteropServices.ComWrappers.ComInterfaceEntry[])' does not exist in the reference but it does exist in the implementation.
+MembersMustExist : Member 'public System.ReadOnlySpan WinRT.MarshalString.FromAbiUnsafe(System.IntPtr)' does not exist in the reference but it does exist in the implementation.
+CannotRemoveAttribute : Attribute 'WinRT.Interop.WuxMuxProjectedTypeAttribute' exists on 'ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler' in the implementation but not the reference.
+CannotRemoveAttribute : Attribute 'WinRT.Interop.WuxMuxProjectedTypeAttribute' exists on 'ABI.System.ComponentModel.PropertyChangedEventHandler' in the implementation but not the reference.
+Total Issues: 135
diff --git a/src/WinRT.Runtime/Projections.cs b/src/WinRT.Runtime/Projections.cs
index 1f4d66d43..fab580b15 100644
--- a/src/WinRT.Runtime/Projections.cs
+++ b/src/WinRT.Runtime/Projections.cs
@@ -25,9 +25,33 @@ namespace WinRT
#endif
static class Projections
{
+ internal enum UiXamlMode
+ {
+ MicrosoftUiXaml,
+ WindowsUiXaml
+ }
+
+ private static UiXamlMode GetUIXamlModeSetting()
+ {
+ if (AppContext.GetData("CsWinRT.UiXamlMode") is string str && Enum.TryParse(str, out var mode))
+ {
+#if !NET5_0_OR_GREATER
+ if (mode == UiXamlMode.WindowsUiXaml)
+ {
+ throw new NotSupportedException("Windows.UI.Xaml is not supported before .NET 5. Please use built-in WinRT interop for Windows.UI.Xaml experiences");
+ }
+#endif
+ return mode;
+ }
+ return UiXamlMode.MicrosoftUiXaml; // We default to MUX for back-compat with existing projects.
+ }
+
+ internal static UiXamlMode UiXamlModeSetting { get; } = GetUIXamlModeSetting();
+
private static readonly ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim();
private static readonly Dictionary CustomTypeToHelperTypeMappings = new Dictionary();
+ private static readonly Dictionary CustomTypeToIIDMappings = new Dictionary();
private static readonly Dictionary CustomAbiTypeToTypeMappings = new Dictionary();
private static readonly Dictionary CustomAbiTypeNameToTypeMappings = new Dictionary(StringComparer.Ordinal);
private static readonly Dictionary CustomTypeToAbiTypeNameMappings = new Dictionary();
@@ -36,7 +60,7 @@ static class Projections
static Projections()
{
- // This should be in sync with cswinrt/helpers.h and the reverse mapping from WinRT.SourceGenerator/WinRTTypeWriter.cs.
+ // This should be in sync with cswinrt/helpers.h and the reverse mapping from WinRT.SourceGenerator/TypeMapper.cs.
RegisterCustomAbiTypeMappingNoLock(typeof(bool), typeof(ABI.System.Boolean), "Boolean");
RegisterCustomAbiTypeMappingNoLock(typeof(char), typeof(ABI.System.Char), "Char");
RegisterCustomAbiTypeMappingNoLock(typeof(EventRegistrationToken), typeof(ABI.WinRT.EventRegistrationToken), "Windows.Foundation.EventRegistrationToken");
@@ -62,13 +86,41 @@ static Projections()
RegisterCustomAbiTypeMappingNoLock(typeof(Exception), typeof(ABI.System.Exception), "Windows.Foundation.HResult");
RegisterCustomAbiTypeMappingNoLock(typeof(TimeSpan), typeof(ABI.System.TimeSpan), "Windows.Foundation.TimeSpan");
RegisterCustomAbiTypeMappingNoLock(typeof(Uri), typeof(ABI.System.Uri), "Windows.Foundation.Uri", isRuntimeClass: true);
- RegisterCustomAbiTypeMappingNoLock(typeof(DataErrorsChangedEventArgs), typeof(ABI.System.ComponentModel.DataErrorsChangedEventArgs), "Microsoft.UI.Xaml.Data.DataErrorsChangedEventArgs", isRuntimeClass: true);
- RegisterCustomAbiTypeMappingNoLock(typeof(PropertyChangedEventArgs), typeof(ABI.System.ComponentModel.PropertyChangedEventArgs), "Microsoft.UI.Xaml.Data.PropertyChangedEventArgs", isRuntimeClass: true);
- RegisterCustomAbiTypeMappingNoLock(typeof(PropertyChangedEventHandler), typeof(ABI.System.ComponentModel.PropertyChangedEventHandler), "Microsoft.UI.Xaml.Data.PropertyChangedEventHandler");
- RegisterCustomAbiTypeMappingNoLock(typeof(INotifyDataErrorInfo), typeof(ABI.System.ComponentModel.INotifyDataErrorInfo), "Microsoft.UI.Xaml.Data.INotifyDataErrorInfo");
- RegisterCustomAbiTypeMappingNoLock(typeof(INotifyPropertyChanged), typeof(ABI.System.ComponentModel.INotifyPropertyChanged), "Microsoft.UI.Xaml.Data.INotifyPropertyChanged");
- RegisterCustomAbiTypeMappingNoLock(typeof(ICommand), typeof(ABI.System.Windows.Input.ICommand), "Microsoft.UI.Xaml.Interop.ICommand");
- RegisterCustomAbiTypeMappingNoLock(typeof(IServiceProvider), typeof(ABI.System.IServiceProvider), "Microsoft.UI.Xaml.IXamlServiceProvider");
+
+ if (UiXamlModeSetting == UiXamlMode.MicrosoftUiXaml)
+ {
+ RegisterCustomAbiTypeMappingNoLock(typeof(DataErrorsChangedEventArgs), typeof(ABI.System.ComponentModel.DataErrorsChangedEventArgs), "Microsoft.UI.Xaml.Data.DataErrorsChangedEventArgs", isRuntimeClass: true);
+ RegisterCustomAbiTypeMappingNoLock(typeof(PropertyChangedEventArgs), typeof(ABI.System.ComponentModel.PropertyChangedEventArgs), "Microsoft.UI.Xaml.Data.PropertyChangedEventArgs", isRuntimeClass: true);
+ RegisterCustomAbiTypeMappingNoLock(typeof(PropertyChangedEventHandler), typeof(ABI.System.ComponentModel.PropertyChangedEventHandler), "Microsoft.UI.Xaml.Data.PropertyChangedEventHandler");
+ RegisterCustomAbiTypeMappingNoLock(typeof(INotifyDataErrorInfo), typeof(ABI.System.ComponentModel.INotifyDataErrorInfo), "Microsoft.UI.Xaml.Data.INotifyDataErrorInfo");
+ RegisterCustomAbiTypeMappingNoLock(typeof(INotifyPropertyChanged), typeof(ABI.System.ComponentModel.INotifyPropertyChanged), "Microsoft.UI.Xaml.Data.INotifyPropertyChanged");
+ RegisterCustomAbiTypeMappingNoLock(typeof(ICommand), typeof(ABI.System.Windows.Input.ICommand), "Microsoft.UI.Xaml.Interop.ICommand");
+ RegisterCustomAbiTypeMappingNoLock(typeof(IServiceProvider), typeof(ABI.System.IServiceProvider), "Microsoft.UI.Xaml.IXamlServiceProvider");
+ RegisterCustomAbiTypeMappingNoLock(typeof(IEnumerable), typeof(ABI.System.Collections.IEnumerable), "Microsoft.UI.Xaml.Interop.IBindableIterable");
+ RegisterCustomAbiTypeMappingNoLock(typeof(IList), typeof(ABI.System.Collections.IList), "Microsoft.UI.Xaml.Interop.IBindableVector");
+ RegisterCustomAbiTypeMappingNoLock(typeof(INotifyCollectionChanged), typeof(ABI.System.Collections.Specialized.INotifyCollectionChanged), "Microsoft.UI.Xaml.Interop.INotifyCollectionChanged");
+ RegisterCustomAbiTypeMappingNoLock(typeof(NotifyCollectionChangedAction), typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedAction), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedAction");
+ RegisterCustomAbiTypeMappingNoLock(typeof(NotifyCollectionChangedEventArgs), typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventArgs", isRuntimeClass: true);
+ RegisterCustomAbiTypeMappingNoLock(typeof(NotifyCollectionChangedEventHandler), typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventHandler");
+ CustomTypeToHelperTypeMappings.Add(typeof(Microsoft.UI.Xaml.Interop.IBindableVector), typeof(ABI.System.Collections.IList));
+ }
+#if NET5_0_OR_GREATER
+ else if (UiXamlModeSetting == UiXamlMode.WindowsUiXaml)
+ {
+ RegisterCustomAbiTypeMappingNoLock(typeof(PropertyChangedEventArgs), typeof(ABI.System.ComponentModel.PropertyChangedEventArgs), "Windows.UI.Xaml.Data.PropertyChangedEventArgs", isRuntimeClass: true);
+ RegisterCustomAbiTypeMappingNoLock(typeof(PropertyChangedEventHandler), typeof(ABI.System.ComponentModel.PropertyChangedEventHandler), "Windows.UI.Xaml.Data.PropertyChangedEventHandler");
+ RegisterCustomAbiTypeMappingNoLock(typeof(INotifyPropertyChanged), typeof(ABI.System.ComponentModel.INotifyPropertyChanged), "Windows.UI.Xaml.Data.INotifyPropertyChanged");
+ RegisterCustomAbiTypeMappingNoLock(typeof(ICommand), typeof(ABI.System.Windows.Input.ICommand), "Windows.UI.Xaml.Interop.ICommand");
+ RegisterCustomAbiTypeMappingNoLock(typeof(IEnumerable), typeof(ABI.System.Collections.IEnumerable), "Windows.UI.Xaml.Interop.IBindableIterable");
+ RegisterCustomAbiTypeMappingNoLock(typeof(IList), typeof(ABI.System.Collections.IList), "Windows.UI.Xaml.Interop.IBindableVector");
+ RegisterCustomAbiTypeMappingNoLock(typeof(INotifyCollectionChanged), typeof(ABI.System.Collections.Specialized.INotifyCollectionChanged), "Windows.UI.Xaml.Interop.INotifyCollectionChanged");
+ RegisterCustomAbiTypeMappingNoLock(typeof(NotifyCollectionChangedAction), typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedAction), "Windows.UI.Xaml.Interop.NotifyCollectionChangedAction");
+ RegisterCustomAbiTypeMappingNoLock(typeof(NotifyCollectionChangedEventArgs), typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs), "Windows.UI.Xaml.Interop.NotifyCollectionChangedEventArgs", isRuntimeClass: true);
+ RegisterCustomAbiTypeMappingNoLock(typeof(NotifyCollectionChangedEventHandler), typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler), "Windows.UI.Xaml.Interop.NotifyCollectionChangedEventHandler");
+ CustomTypeToHelperTypeMappings.Add(typeof(Windows.UI.Xaml.Interop.IBindableVector), typeof(ABI.System.Collections.IList));
+ }
+#endif
+
RegisterCustomAbiTypeMappingNoLock(typeof(EventHandler<>), typeof(ABI.System.EventHandler<>), "Windows.Foundation.EventHandler`1");
RegisterCustomAbiTypeMappingNoLock(typeof(KeyValuePair<,>), typeof(ABI.System.Collections.Generic.KeyValuePair<,>), "Windows.Foundation.Collections.IKeyValuePair`2");
@@ -80,12 +132,6 @@ static Projections()
RegisterCustomAbiTypeMappingNoLock(typeof(IReadOnlyDictionary<,>), typeof(ABI.System.Collections.Generic.IReadOnlyDictionary<,>), "Windows.Foundation.Collections.IMapView`2");
RegisterCustomAbiTypeMappingNoLock(typeof(IDisposable), typeof(ABI.System.IDisposable), "Windows.Foundation.IClosable");
- RegisterCustomAbiTypeMappingNoLock(typeof(IEnumerable), typeof(ABI.System.Collections.IEnumerable), "Microsoft.UI.Xaml.Interop.IBindableIterable");
- RegisterCustomAbiTypeMappingNoLock(typeof(IList), typeof(ABI.System.Collections.IList), "Microsoft.UI.Xaml.Interop.IBindableVector");
- RegisterCustomAbiTypeMappingNoLock(typeof(INotifyCollectionChanged), typeof(ABI.System.Collections.Specialized.INotifyCollectionChanged), "Microsoft.UI.Xaml.Interop.INotifyCollectionChanged");
- RegisterCustomAbiTypeMappingNoLock(typeof(NotifyCollectionChangedAction), typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedAction), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedAction");
- RegisterCustomAbiTypeMappingNoLock(typeof(NotifyCollectionChangedEventArgs), typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventArgs", isRuntimeClass: true);
- RegisterCustomAbiTypeMappingNoLock(typeof(NotifyCollectionChangedEventHandler), typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventHandler");
RegisterCustomAbiTypeMappingNoLock(typeof(Matrix3x2), typeof(ABI.System.Numerics.Matrix3x2), "Windows.Foundation.Numerics.Matrix3x2");
RegisterCustomAbiTypeMappingNoLock(typeof(Matrix4x4), typeof(ABI.System.Numerics.Matrix4x4), "Windows.Foundation.Numerics.Matrix4x4");
@@ -100,7 +146,6 @@ static Projections()
CustomTypeToHelperTypeMappings.Add(typeof(IVector<>), typeof(ABI.System.Collections.Generic.IList<>));
CustomTypeToHelperTypeMappings.Add(typeof(IMapView<,>), typeof(ABI.System.Collections.Generic.IReadOnlyDictionary<,>));
CustomTypeToHelperTypeMappings.Add(typeof(IVectorView<>), typeof(ABI.System.Collections.Generic.IReadOnlyList<>));
- CustomTypeToHelperTypeMappings.Add(typeof(Microsoft.UI.Xaml.Interop.IBindableVector), typeof(ABI.System.Collections.IList));
#if NET
CustomTypeToHelperTypeMappings.Add(typeof(ICollection<>), typeof(ABI.System.Collections.Generic.ICollection<>));
@@ -260,6 +305,11 @@ public static string FindCustomAbiTypeNameForType(Type type)
}
}
+ internal static Guid? FindCustomIIDForAbiType(Type type)
+ {
+ return CustomTypeToIIDMappings.TryGetValue(type, out Guid iid) ? iid : null;
+ }
+
private readonly static ConcurrentDictionary IsTypeWindowsRuntimeTypeCache = new();
public static bool IsTypeWindowsRuntimeType(Type type)
{
diff --git a/src/WinRT.Runtime/Projections/Bindable.net5.cs b/src/WinRT.Runtime/Projections/Bindable.net5.cs
index 721c00255..f400c74d6 100644
--- a/src/WinRT.Runtime/Projections/Bindable.net5.cs
+++ b/src/WinRT.Runtime/Projections/Bindable.net5.cs
@@ -1,101 +1,162 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using WinRT;
+using System.Runtime.InteropServices;
+using WinRT;
using WinRT.Interop;
-#pragma warning disable 0169 // warning CS0169: The field '...' is never used
-#pragma warning disable 0649 // warning CS0169: Field '...' is never assigned to
-
-namespace Microsoft.UI.Xaml.Interop
-{
- [global::WinRT.WindowsRuntimeType]
- [Guid("036D2C08-DF29-41AF-8AA2-D774BE62BA6F")]
- [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Interop.IBindableIterable))]
- internal interface IBindableIterable
- {
- IBindableIterator First();
- }
- [global::WinRT.WindowsRuntimeType]
- [Guid("6A1D6C07-076D-49F2-8314-F52C9C9A8331")]
- [global::WinRT.WindowsRuntimeHelperType(typeof(global::ABI.Microsoft.UI.Xaml.Interop.IBindableIterator))]
- internal interface IBindableIterator
- {
- bool MoveNext();
- // GetMany is not implemented by IBindableIterator, but it is here
- // for compat purposes with WinUI where there are scenarios they do
- // reinterpret_cast from IBindableIterator to IIterable