diff --git a/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml b/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml
index b64b411bb..b99c24e07 100644
--- a/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml
+++ b/build/AzurePipelineTemplates/CsWinRT-BuildAndTest-Stage.yml
@@ -93,6 +93,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 98f03ea58..f020d04fc 100644
--- a/nuget/Microsoft.Windows.CsWinRT.Authoring.targets
+++ b/nuget/Microsoft.Windows.CsWinRT.Authoring.targets
@@ -33,6 +33,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
+
diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets
index 64abdcf40..8fe95eaa2 100644
--- a/nuget/Microsoft.Windows.CsWinRT.targets
+++ b/nuget/Microsoft.Windows.CsWinRT.targets
@@ -289,6 +289,13 @@ $(CsWinRTInternalProjection)
+
+
+ $(CsWinRTUiXamlMode)
+ true
+
+
+
@@ -338,6 +345,16 @@ $(CsWinRTInternalProjection)
+
+
+
+ true
+ true
+
+
+ false
+ true
+
diff --git a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs
index 0df8eaf9a..052078819 100644
--- a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs
+++ b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs
@@ -22,10 +22,14 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
var properties = context.AnalyzerConfigOptionsProvider.Select(static (provider, _) =>
(provider.IsCsWinRTAotOptimizerEnabled(), provider.IsCsWinRTComponent(), provider.IsCsWinRTCcwLookupTableGeneratorEnabled()));
+ var typeMapper = context.AnalyzerConfigOptionsProvider.Select((options, ct) => options.GlobalOptions.GetUIXamlProjectionsMode()).Select((mode, ct) => new TypeMapper(mode));
+
var vtablesToAddFromClassTypes = context.SyntaxProvider.CreateSyntaxProvider(
static (n, _) => NeedVtableAttribute(n),
- static (n, _) => GetVtableAttributeToAdd(n, false)
- ).Where(static vtableAttribute => vtableAttribute != default);
+ static (n, _) => n)
+ .Combine(typeMapper)
+ .Select((t, _) => GetVtableAttributeToAdd(t.Left, t.Right, false))
+ .Where(static vtableAttribute => vtableAttribute != default);
var vtableAttributesToAdd = vtablesToAddFromClassTypes.Select(static (vtable, _) => vtable.Item1);
var adapterTypesToAddOnLookupTable = vtablesToAddFromClassTypes.SelectMany(static (vtable, _) => vtable.Item2);
@@ -36,32 +40,39 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
// that will already be generated by the component generator.
var vtablesFromComponentTypes = context.SyntaxProvider.CreateSyntaxProvider(
static (n, _) => IsComponentType(n),
- static (n, _) => GetVtableAttributeToAdd(n, true)
- ).Where(static vtableAttribute => vtableAttribute != default).Collect().Combine(properties).
- // Get component types if only authoring scenario
- SelectMany(static ((ImmutableArray<(VtableAttribute vtableAttribute, EquatableArray adapterTypes)> classTypes, (bool, bool isCsWinRTComponent, bool) properties) value, CancellationToken _) =>
+ static (n, _) => n)
+ .Combine(typeMapper)
+ .Select((t, _) => GetVtableAttributeToAdd(t.Left, t.Right, true))
+ .Where(static vtableAttribute => vtableAttribute != default).Collect()
+ .Combine(properties)
+ // Get component types if only authoring scenario
+ .SelectMany(static ((ImmutableArray<(VtableAttribute vtableAttribute, EquatableArray adapterTypes)> classTypes, (bool, bool isCsWinRTComponent, bool) properties) value, CancellationToken _) =>
value.properties.isCsWinRTComponent ? value.classTypes : ImmutableArray<(VtableAttribute, EquatableArray)>.Empty);
var instantiatedTypesToAddOnLookupTable = context.SyntaxProvider.CreateSyntaxProvider(
static (n, _) => NeedVtableOnLookupTable(n),
- static (n, _) => GetVtableAttributesToAddOnLookupTable(n)
- ).Combine(properties)
- // Get component types if only authoring scenario
- .Select(static (((EquatableArray lookupTable, EquatableArray componentLookupTable) vtableAttributes, (bool, bool isCsWinRTComponent, bool) properties) value, CancellationToken _) =>
- value.properties.isCsWinRTComponent ? value.vtableAttributes.componentLookupTable : value.vtableAttributes.lookupTable)
- .SelectMany(static (vtable, _) => vtable).
- Where(static vtableAttribute => vtableAttribute != null);
+ static (n, _) => n)
+ .Combine(typeMapper)
+ .Select((t, _) => GetVtableAttributesToAddOnLookupTable(t.Left, t.Right))
+ .Combine(properties)
+ // Get component types if only authoring scenario
+ .Select(static (((EquatableArray lookupTable, EquatableArray componentLookupTable) vtableAttributes, (bool, bool isCsWinRTComponent, bool) properties) value, CancellationToken _) =>
+ value.properties.isCsWinRTComponent ? value.vtableAttributes.componentLookupTable : value.vtableAttributes.lookupTable)
+ .SelectMany(static (vtable, _) => vtable)
+ .Where(static vtableAttribute => vtableAttribute != null);
var instantiatedTaskAdapters = context.SyntaxProvider.CreateSyntaxProvider(
static (n, _) => IsAsyncOperationMethodCall(n),
- static (n, _) => GetVtableAttributesForTaskAdapters(n)
- ).Where(static vtableAttribute => vtableAttribute != default).
- Combine(properties).
- // Get component types if only authoring scenario
- Select(static (((VtableAttribute vtableAttribute, VtableAttribute componentVtableAttribute) vtableAttributes, (bool, bool isCsWinRTComponent, bool) properties) value, CancellationToken _) =>
- value.properties.isCsWinRTComponent ? value.vtableAttributes.componentVtableAttribute : value.vtableAttributes.vtableAttribute).
- Where(static vtableAttribute => vtableAttribute != default).
- Collect();
+ static (n, _) => n)
+ .Combine(typeMapper)
+ .Select((data, ct) => GetVtableAttributesForTaskAdapters(data.Left, data.Right))
+ .Where(static vtableAttribute => vtableAttribute != default)
+ .Combine(properties)
+ // Get component types if only authoring scenario
+ .Select(static (((VtableAttribute vtableAttribute, VtableAttribute componentVtableAttribute) vtableAttributes, (bool, bool isCsWinRTComponent, bool) properties) value, CancellationToken _) =>
+ value.properties.isCsWinRTComponent ? value.vtableAttributes.componentVtableAttribute : value.vtableAttributes.vtableAttribute)
+ .Where(static vtableAttribute => vtableAttribute != default)
+ .Collect();
// Merge both adapter types list and instantiated types list
var vtablesToAddOnLookupTable =
@@ -112,19 +123,22 @@ private static bool IsComponentType(SyntaxNode node)
!GeneratorHelper.IsWinRTType(declaration); // Making sure it isn't an RCW we are projecting.
}
- private static (VtableAttribute, EquatableArray) GetVtableAttributeToAdd(GeneratorSyntaxContext context, bool checkForComponentTypes)
+ private static (VtableAttribute, EquatableArray) GetVtableAttributeToAdd(
+ GeneratorSyntaxContext context,
+ TypeMapper typeMapper,
+ bool checkForComponentTypes)
{
var isWinRTTypeFunc = checkForComponentTypes ?
GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation) :
GeneratorHelper.IsWinRTType;
var symbol = context.SemanticModel.GetDeclaredSymbol(context.Node as ClassDeclarationSyntax);
- var vtableAttribute = GetVtableAttributeToAdd(symbol, isWinRTTypeFunc, context.SemanticModel.Compilation, false);
+ var vtableAttribute = GetVtableAttributeToAdd(symbol, isWinRTTypeFunc, typeMapper, context.SemanticModel.Compilation, false);
if (vtableAttribute != default)
{
HashSet vtableAttributesForLookupTable = [];
// Add any adapter types which may be needed if certain functions
// from some known interfaces are called.
- AddVtableAdapterTypeForKnownInterface(symbol, context.SemanticModel.Compilation, isWinRTTypeFunc, vtableAttributesForLookupTable);
+ AddVtableAdapterTypeForKnownInterface(symbol, context.SemanticModel.Compilation, isWinRTTypeFunc, typeMapper, vtableAttributesForLookupTable);
return (vtableAttribute, vtableAttributesForLookupTable.ToImmutableArray());
}
@@ -187,7 +201,7 @@ static bool IsAsyncOperationMethodCall(SyntaxNode node)
// We do this both assuming this is not an authoring component and is an authoring
// component as we don't know that at this stage and the results can vary based on that.
// We will choose the right one later when we can combine with properties.
- private static (VtableAttribute, VtableAttribute) GetVtableAttributesForTaskAdapters(GeneratorSyntaxContext context)
+ private static (VtableAttribute, VtableAttribute) GetVtableAttributesForTaskAdapters(GeneratorSyntaxContext context, TypeMapper typeMapper)
{
if (context.SemanticModel.GetSymbolInfo(context.Node as InvocationExpressionSyntax).Symbol is IMethodSymbol symbol)
{
@@ -200,8 +214,8 @@ private static (VtableAttribute, VtableAttribute) GetVtableAttributesForTaskAdap
if (adpaterType is not null)
{
var constructedAdapterType = adpaterType.Construct([.. symbol.TypeArguments]);
- return (GetVtableAttributeToAdd(constructedAdapterType, GeneratorHelper.IsWinRTType, context.SemanticModel.Compilation, false),
- GetVtableAttributeToAdd(constructedAdapterType, GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation), context.SemanticModel.Compilation, false));
+ return (GetVtableAttributeToAdd(constructedAdapterType, GeneratorHelper.IsWinRTType, typeMapper, context.SemanticModel.Compilation, false),
+ GetVtableAttributeToAdd(constructedAdapterType, GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation), typeMapper, context.SemanticModel.Compilation, false));
}
}
}
@@ -306,7 +320,8 @@ private static string GetRuntimeClassName(INamedTypeSymbol type, Func isWinRTType,
+ Func isWinRTType,
+ TypeMapper mapper,
Compilation compilation,
bool isAuthoring,
string authoringDefaultInterface = "")
@@ -316,7 +331,7 @@ internal static VtableAttribute GetVtableAttributeToAdd(
return default;
}
- if (GeneratorHelper.HasNonInstantiatedWinRTGeneric(symbol))
+ if (GeneratorHelper.HasNonInstantiatedWinRTGeneric(symbol, mapper))
{
return default;
}
@@ -333,18 +348,18 @@ internal static VtableAttribute GetVtableAttributeToAdd(
// use the specified one. Also for authoring scenarios where we call this for authored WinRT types,
// don't generate the runtimeclass name for them as we will rely on the full name for them as we do today.
var checkForRuntimeClasName = !GeneratorHelper.HasWinRTRuntimeClassNameAttribute(symbol, compilation) &&
- (!isAuthoring || (isAuthoring && !isWinRTType(symbol)));
+ (!isAuthoring || (isAuthoring && !isWinRTType(symbol, mapper)));
INamedTypeSymbol interfaceToUseForRuntimeClassName = null;
foreach (var iface in symbol.AllInterfaces)
{
- if (isWinRTType(iface))
+ if (isWinRTType(iface, mapper))
{
interfacesToAddToVtable.Add(ToFullyQualifiedString(iface));
AddGenericInterfaceInstantiation(iface);
CheckForInterfaceToUseForRuntimeClassName(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)
{
@@ -426,7 +441,7 @@ internal static VtableAttribute GetVtableAttributeToAdd(
symbol is IArrayTypeSymbol,
isDelegate,
symbol.DeclaredAccessibility == Accessibility.Public,
- GetRuntimeClassName(interfaceToUseForRuntimeClassName, isWinRTType));
+ GetRuntimeClassName(interfaceToUseForRuntimeClassName, type => isWinRTType(type, mapper)));
void AddGenericInterfaceInstantiation(INamedTypeSymbol iface)
{
@@ -445,7 +460,7 @@ void AddGenericInterfaceInstantiation(INamedTypeSymbol iface)
genericParameters.Add(new GenericParameter(
ToFullyQualifiedString(genericParameter),
- GeneratorHelper.GetAbiType(genericParameter),
+ GeneratorHelper.GetAbiType(genericParameter, mapper),
genericParameter.TypeKind));
}
@@ -479,7 +494,7 @@ void CheckForInterfaceToUseForRuntimeClassName(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;
@@ -492,7 +507,7 @@ private static bool TryGetCompatibleWindowsRuntimeTypesForVariantType(INamedType
}
var definition = type.OriginalDefinition;
- if (!isWinRTType(definition))
+ if (!isWinRTType(definition, mapper))
{
return false;
}
@@ -512,20 +527,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);
}
@@ -534,7 +549,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);
}
@@ -837,18 +852,21 @@ node is VariableDeclarationSyntax ||
node is ReturnStatementSyntax;
}
- private static (EquatableArray, EquatableArray) GetVtableAttributesToAddOnLookupTable(GeneratorSyntaxContext context)
+ private static (EquatableArray, EquatableArray) GetVtableAttributesToAddOnLookupTable(
+ GeneratorSyntaxContext context,
+ TypeMapper typeMapper)
{
// Get the lookup table as if we are running in an authoring component scenario and as if we are not
// and then use the properties later on when we have access to it to check if we are to choose the right one.
// Otherwise we will end up generating lookup tables which don't have vtable entries for authoring types.
- return (GetVtableAttributesToAddOnLookupTable(context, GeneratorHelper.IsWinRTType),
- GetVtableAttributesToAddOnLookupTable(context, GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation)));
+ return (GetVtableAttributesToAddOnLookupTable(context, typeMapper, GeneratorHelper.IsWinRTType),
+ GetVtableAttributesToAddOnLookupTable(context, typeMapper, GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation)));
}
private static EquatableArray GetVtableAttributesToAddOnLookupTable(
GeneratorSyntaxContext context,
- Func isWinRTType)
+ TypeMapper typeMapper,
+ Func isWinRTType)
{
HashSet visitedTypes = new(SymbolEqualityComparer.Default);
HashSet vtableAttributes = new();
@@ -862,7 +880,7 @@ private static EquatableArray GetVtableAttributesToAddOnLookupT
// and end up calling a projection function (i.e. ones generated by XAML compiler)
// In theory, another library can also be called which can call a projected function
// but not handling those scenarios for now.
- (isWinRTType(methodSymbol.ContainingSymbol) ||
+ (isWinRTType(methodSymbol.ContainingSymbol, typeMapper) ||
SymbolEqualityComparer.Default.Equals(methodSymbol.ContainingAssembly, context.SemanticModel.Compilation.Assembly)))
{
// Get the concrete types directly from the argument rather than
@@ -891,13 +909,13 @@ private static EquatableArray GetVtableAttributesToAddOnLookupT
{
var leftSymbol = context.SemanticModel.GetSymbolInfo(assignment.Left).Symbol;
if (leftSymbol is IPropertySymbol propertySymbol &&
- (isWinRTType(propertySymbol.ContainingSymbol) ||
+ (isWinRTType(propertySymbol.ContainingSymbol, typeMapper) ||
SymbolEqualityComparer.Default.Equals(propertySymbol.ContainingAssembly, context.SemanticModel.Compilation.Assembly)))
{
AddVtableAttributesForType(context.SemanticModel.GetTypeInfo(assignment.Right), propertySymbol.Type);
}
else if (leftSymbol is IFieldSymbol fieldSymbol &&
- (isWinRTType(fieldSymbol.ContainingSymbol) ||
+ (isWinRTType(fieldSymbol.ContainingSymbol, typeMapper) ||
SymbolEqualityComparer.Default.Equals(fieldSymbol.ContainingAssembly, context.SemanticModel.Compilation.Assembly)))
{
AddVtableAttributesForType(context.SemanticModel.GetTypeInfo(assignment.Right), fieldSymbol.Type);
@@ -965,14 +983,14 @@ void AddVtableAttributesForType(Microsoft.CodeAnalysis.TypeInfo instantiatedType
}
visitedTypes.Add(arrayType);
- var vtableAtribute = GetVtableAttributeToAdd(arrayType, isWinRTType, context.SemanticModel.Compilation, false);
+ var vtableAtribute = GetVtableAttributeToAdd(arrayType, isWinRTType, typeMapper, context.SemanticModel.Compilation, 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, isWinRTType, vtableAttributes);
+ AddEnumeratorAdapterForType(arrayType.ElementType, typeMapper, context.SemanticModel.Compilation, isWinRTType, vtableAttributes);
}
}
else if (instantiatedType.Type is not null || instantiatedType.ConvertedType is not null)
@@ -994,11 +1012,11 @@ void AddVtableAttributesForType(Microsoft.CodeAnalysis.TypeInfo instantiatedType
// information is available.
if (instantiatedTypeSymbol.TypeKind == TypeKind.Delegate &&
instantiatedTypeSymbol.MetadataName.Contains("`") &&
- isWinRTType(instantiatedTypeSymbol) &&
+ isWinRTType(instantiatedTypeSymbol, typeMapper) &&
convertedToTypeSymbol.SpecialType == SpecialType.System_Object)
{
var argumentClassNamedTypeSymbol = instantiatedTypeSymbol as INamedTypeSymbol;
- vtableAttributes.Add(GetVtableAttributeToAdd(instantiatedTypeSymbol, isWinRTType, context.SemanticModel.Compilation, false));
+ vtableAttributes.Add(GetVtableAttributeToAdd(instantiatedTypeSymbol, isWinRTType, typeMapper, context.SemanticModel.Compilation, false));
}
// This handles the case where the source generator wasn't able to run
@@ -1010,7 +1028,7 @@ void AddVtableAttributesForType(Microsoft.CodeAnalysis.TypeInfo instantiatedType
// library which happened to not run the AOT optimizer. So as a best effort,
// we handle it here.
if (instantiatedTypeSymbol.TypeKind == TypeKind.Class &&
- (instantiatedTypeSymbol.MetadataName.Contains("`") || !isWinRTType(instantiatedTypeSymbol)) &&
+ (instantiatedTypeSymbol.MetadataName.Contains("`") || !isWinRTType(instantiatedTypeSymbol, typeMapper)) &&
!GeneratorHelper.HasWinRTExposedTypeAttribute(instantiatedTypeSymbol) &&
// 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.
@@ -1018,13 +1036,13 @@ void AddVtableAttributesForType(Microsoft.CodeAnalysis.TypeInfo instantiatedType
// Make sure the type we are passing is being boxed or cast to another interface.
!SymbolEqualityComparer.Default.Equals(instantiatedTypeSymbol, convertedToTypeSymbol))
{
- var vtableAtribute = GetVtableAttributeToAdd(instantiatedTypeSymbol, isWinRTType, context.SemanticModel.Compilation, false);
+ var vtableAtribute = GetVtableAttributeToAdd(instantiatedTypeSymbol, isWinRTType, typeMapper, context.SemanticModel.Compilation, false);
if (vtableAtribute != default)
{
vtableAttributes.Add(vtableAtribute);
}
- AddVtableAdapterTypeForKnownInterface(instantiatedTypeSymbol, context.SemanticModel.Compilation, isWinRTType, vtableAttributes);
+ AddVtableAdapterTypeForKnownInterface(instantiatedTypeSymbol, context.SemanticModel.Compilation, isWinRTType, typeMapper, vtableAttributes);
}
}
}
@@ -1033,13 +1051,13 @@ void AddVtableAttributesForType(Microsoft.CodeAnalysis.TypeInfo instantiatedType
// 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");
if (enumerableType != null)
{
var constructedEnumerableType = enumerableType.Construct(type);
- if (TryGetCompatibleWindowsRuntimeTypesForVariantType(constructedEnumerableType, null, isWinRTType, out var compatibleIfaces))
+ if (TryGetCompatibleWindowsRuntimeTypesForVariantType(constructedEnumerableType, mapper, null, isWinRTType, out var compatibleIfaces))
{
foreach (var compatibleIface in compatibleIfaces)
{
@@ -1050,7 +1068,7 @@ private static void AddEnumeratorAdapterForType(ITypeSymbol type, Compilation co
if (enumeratorAdapterType != null)
{
var constructedEnumeratorAdapterType = enumeratorAdapterType.Construct(compatibleIface.TypeArguments[0]);
- var vtableAttribute = GetVtableAttributeToAdd(constructedEnumeratorAdapterType, isWinRTType, compilation, false);
+ var vtableAttribute = GetVtableAttributeToAdd(constructedEnumeratorAdapterType, isWinRTType, mapper, compilation, false);
if (vtableAttribute != default)
{
vtableAttributes.Add(vtableAttribute);
@@ -1062,13 +1080,13 @@ private static void AddEnumeratorAdapterForType(ITypeSymbol type, Compilation co
}
}
- 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")
{
@@ -1088,7 +1106,7 @@ void LookupAndAddVtableAttributeForGenericType(string type, ImmutableArray namespaceNames = new();
-
- foreach (var @namespace in syntaxReceiver.Namespaces)
- {
- var model = _context.Compilation.GetSemanticModel(@namespace.SyntaxTree);
- var namespaceSymbol = model.GetDeclaredSymbol(@namespace);
-
- string namespaceString = namespaceSymbol.ToString();
-
- bool newNamespaceDeclaration = true;
- // Because modules could have a namespace defined in different places (i.e. defines a partial class)
- // we can't rely on `Contains` so we manually check that namespace names cannot differ by case only
- foreach (var usedNamespaceName in namespaceNames)
- {
- if (String.Equals(namespaceString, usedNamespaceName, StringComparison.OrdinalIgnoreCase) &&
- !String.Equals(namespaceString, usedNamespaceName, StringComparison.Ordinal))
- {
- newNamespaceDeclaration = false;
- Report(WinRTRules.NamespacesDifferByCase, namespaceSymbol.Locations.First(), namespaceString);
- }
- }
-
- if (newNamespaceDeclaration)
- {
- namespaceNames.Add(namespaceString);
- }
-
- if (IsInvalidNamespace(namespaceSymbol, _assemblyName))
- {
- Report(WinRTRules.DisjointNamespaceRule, namespaceSymbol.Locations.First(), _assemblyName, namespaceString);
- }
+
+ // Used to check for conflicting namespace names
+ HashSet namespaceNames = new();
+
+ foreach (var @namespace in syntaxReceiver.Namespaces)
+ {
+ var model = _context.Compilation.GetSemanticModel(@namespace.SyntaxTree);
+ var namespaceSymbol = model.GetDeclaredSymbol(@namespace);
+
+ string namespaceString = namespaceSymbol.ToString();
+
+ bool newNamespaceDeclaration = true;
+ // Because modules could have a namespace defined in different places (i.e. defines a partial class)
+ // we can't rely on `Contains` so we manually check that namespace names cannot differ by case only
+ foreach (var usedNamespaceName in namespaceNames)
+ {
+ if (String.Equals(namespaceString, usedNamespaceName, StringComparison.OrdinalIgnoreCase) &&
+ !String.Equals(namespaceString, usedNamespaceName, StringComparison.Ordinal))
+ {
+ newNamespaceDeclaration = false;
+ Report(WinRTRules.NamespacesDifferByCase, namespaceSymbol.Locations.First(), namespaceString);
+ }
+ }
+
+ if (newNamespaceDeclaration)
+ {
+ namespaceNames.Add(namespaceString);
+ }
+
+ if (IsInvalidNamespace(namespaceSymbol, _assemblyName))
+ {
+ Report(WinRTRules.DisjointNamespaceRule, namespaceSymbol.Locations.First(), _assemblyName, namespaceString);
+ }
}
}
- private void CheckDeclarations()
- {
- WinRTSyntaxReceiver syntaxReceiver = (WinRTSyntaxReceiver)_context.SyntaxReceiver;
-
+ private void CheckDeclarations()
+ {
+ WinRTSyntaxReceiver syntaxReceiver = (WinRTSyntaxReceiver)_context.SyntaxReceiver;
+
foreach (var declaration in syntaxReceiver.Declarations)
{
var model = _context.Compilation.GetSemanticModel(declaration.SyntaxTree);
@@ -91,12 +93,12 @@ private void CheckDeclarations()
// Check symbol information for whether it is public to properly detect partial types
// which can leave out modifier. Also ignore nested types not effectively public
- if (symbol.DeclaredAccessibility != Accessibility.Public ||
- (symbol is ITypeSymbol typeSymbol && !typeSymbol.IsPubliclyAccessible()))
- {
- continue;
- }
-
+ if (symbol.DeclaredAccessibility != Accessibility.Public ||
+ (symbol is ITypeSymbol typeSymbol && !typeSymbol.IsPubliclyAccessible()))
+ {
+ continue;
+ }
+
if (declaration is ClassDeclarationSyntax @class)
{
var classId = @class.Identifier;
@@ -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)
{
@@ -116,112 +118,113 @@ private void CheckDeclarations()
HasMultipleConstructorsOfSameArity(@class);
if (classSymbol.IsGenericType)
- {
+ {
Report(WinRTRules.GenericTypeRule, @class.GetLocation(), classId);
}
// check for things in nonWindowsRuntimeInterfaces
- ImplementsInvalidInterface(classSymbol, @class);
-
- CheckProperties(props, classId);
-
- // check types -- todo: check for !valid types
- CheckMethods(publicMethods, classId);
-
+ ImplementsInvalidInterface(classSymbol, @class);
+
+ CheckProperties(props, classId);
+
+ // check types -- todo: check for !valid types
+ CheckMethods(publicMethods, classId);
+
CheckInterfaces(model, @class);
}
else if (declaration is InterfaceDeclarationSyntax @interface)
{
var interfaceSym = model.GetDeclaredSymbol(@interface);
var methods = @interface.DescendantNodes().OfType();
- 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);
-
+ var props = @interface.DescendantNodes().OfType().Where(IsPublic);
+
+ // filter out methods and properties that will be replaced with our custom type mappings
+ IgnoreCustomTypeMappings(interfaceSym, _typeMapper, ref methods, ref props);
+
if (interfaceSym.IsGenericType)
{
Report(WinRTRules.GenericTypeRule, @interface.GetLocation(), @interface.Identifier);
}
- ImplementsInvalidInterface(interfaceSym, @interface);
-
- CheckProperties(props, @interface.Identifier);
-
+ ImplementsInvalidInterface(interfaceSym, @interface);
+
+ CheckProperties(props, @interface.Identifier);
+
CheckMethods(methods, @interface.Identifier);
- }
- else if (declaration is StructDeclarationSyntax @struct)
- {
- CheckStructFields(@struct);
- }
+ }
+ else if (declaration is StructDeclarationSyntax @struct)
+ {
+ CheckStructFields(@struct);
+ }
}
- }
-
- private void CheckInterfaces(SemanticModel model, ClassDeclarationSyntax @class)
- {
- var classId = @class.Identifier;
+ }
+
+ private void CheckInterfaces(SemanticModel model, ClassDeclarationSyntax @class)
+ {
+ var classId = @class.Identifier;
var classSymbol = model.GetDeclaredSymbol(@class);
-
- var iWinRTObject = model.Compilation.GetTypeByMetadataName("WinRT.IWinRTObject");
- // validate that the class correctly implements all its interfaces
- var methods = classSymbol.GetMembers().OfType().ToList();
- foreach (var iface in classSymbol.AllInterfaces)
- {
- if (SymbolEqualityComparer.Default.Equals(iface, iWinRTObject))
- {
- continue;
- }
- foreach (var member in iface.GetMembers().OfType())
- {
- var impl = classSymbol.FindImplementationForInterfaceMember(member);
- if (impl == null)
- {
- var explicitIfaceImpl = methods.Where(m => IsMethodImpl(m, member));
- if (!explicitIfaceImpl.Any())
- {
- Report(WinRTRules.UnimplementedInterface, @class.GetLocation(), classId.Text, iface.ToDisplayString(), member.ToDisplayString());
- }
- }
- }
- }
- }
-
- private bool IsMethodImpl(IMethodSymbol m, IMethodSymbol interfaceMethod)
- {
- if (m.Name != interfaceMethod.Name)
- {
- return false;
- }
- if (!m.Parameters.SequenceEqual(interfaceMethod.Parameters))
- {
- return false;
- }
-
- // the return type can be covariant with the interface method's return type (i.e. a sub-type)
- if (SymEq(m.ReturnType, interfaceMethod.ReturnType) && !m.ReturnType.AllInterfaces.Contains(interfaceMethod.ReturnType, SymbolEqualityComparer.Default))
- {
- return false;
- }
- return true;
- }
-
- private void IgnoreCustomTypeMappings(INamedTypeSymbol typeSymbol,
- ref IEnumerable methods,
+
+ var iWinRTObject = model.Compilation.GetTypeByMetadataName("WinRT.IWinRTObject");
+ // validate that the class correctly implements all its interfaces
+ var methods = classSymbol.GetMembers().OfType().ToList();
+ foreach (var iface in classSymbol.AllInterfaces)
+ {
+ if (SymbolEqualityComparer.Default.Equals(iface, iWinRTObject))
+ {
+ continue;
+ }
+ foreach (var member in iface.GetMembers().OfType())
+ {
+ var impl = classSymbol.FindImplementationForInterfaceMember(member);
+ if (impl == null)
+ {
+ var explicitIfaceImpl = methods.Where(m => IsMethodImpl(m, member));
+ if (!explicitIfaceImpl.Any())
+ {
+ Report(WinRTRules.UnimplementedInterface, @class.GetLocation(), classId.Text, iface.ToDisplayString(), member.ToDisplayString());
+ }
+ }
+ }
+ }
+ }
+
+ private bool IsMethodImpl(IMethodSymbol m, IMethodSymbol interfaceMethod)
+ {
+ if (m.Name != interfaceMethod.Name)
+ {
+ return false;
+ }
+ if (!m.Parameters.SequenceEqual(interfaceMethod.Parameters))
+ {
+ return false;
+ }
+
+ // the return type can be covariant with the interface method's return type (i.e. a sub-type)
+ if (SymEq(m.ReturnType, interfaceMethod.ReturnType) && !m.ReturnType.AllInterfaces.Contains(interfaceMethod.ReturnType, SymbolEqualityComparer.Default))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private void IgnoreCustomTypeMappings(INamedTypeSymbol typeSymbol,
+ TypeMapper typeMapper,
+ ref IEnumerable methods,
ref IEnumerable properties)
{
- string QualifiedName(INamedTypeSymbol sym)
- {
- return sym.OriginalDefinition.ContainingNamespace + "." + sym.OriginalDefinition.MetadataName;
+ string QualifiedName(INamedTypeSymbol sym)
+ {
+ return sym.OriginalDefinition.ContainingNamespace + "." + sym.OriginalDefinition.MetadataName;
}
HashSet classMethods = new(SymbolEqualityComparer.Default);
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())
- {
+ {
classMethods.Add(typeSymbol.FindImplementationForInterfaceMember(interfaceMember));
}
}
@@ -276,9 +279,9 @@ private void HasConflictingParameterName(MethodDeclarationSyntax method)
bool IsInvalidParameterName(ParameterSyntax stx) { return stx.Identifier.Value.Equals(GeneratedReturnValueName); }
var hasInvalidParams = method.ParameterList.Parameters.Any(IsInvalidParameterName);
- if (hasInvalidParams)
- {
- Report(WinRTRules.ParameterNamedValueRule, method.GetLocation(), method.Identifier);
+ if (hasInvalidParams)
+ {
+ Report(WinRTRules.ParameterNamedValueRule, method.GetLocation(), method.Identifier);
}
}
@@ -307,7 +310,7 @@ private void CheckMethods(IEnumerable methodDeclaration
foreach (var arg in methodSym.Parameters)
{
ReportIfInvalidType(arg.Type, method.GetLocation(), method.Identifier, typeId);
- }
+ }
}
/* Finishes up the work started by `CheckOverloadAttributes` */
foreach (var thing in overloadsWithoutAttributeMap)
@@ -326,9 +329,9 @@ private void CheckProperties(IEnumerable props, Synta
var propSym = GetModel(prop.SyntaxTree).GetDeclaredSymbol(prop);
var loc = prop.GetLocation();
- if (propSym.GetMethod == null || !propSym.GetMethod.DeclaredAccessibility.Equals(Accessibility.Public))
- {
- Report(WinRTRules.PrivateGetterRule, loc, prop.Identifier);
+ if (propSym.GetMethod == null || !propSym.GetMethod.DeclaredAccessibility.Equals(Accessibility.Public))
+ {
+ Report(WinRTRules.PrivateGetterRule, loc, prop.Identifier);
}
ReportIfInvalidType(propSym.Type, loc, prop.Identifier, typeId);
@@ -345,12 +348,12 @@ private void CheckStructFields(StructDeclarationSyntax @struct)
{
// delegates not allowed
if (@struct.DescendantNodes().OfType().Any())
- {
+ {
Report(WinRTRules.StructHasInvalidFieldRule, @struct.GetLocation(), @struct.Identifier, SimplifySyntaxTypeString(typeof(DelegateDeclarationSyntax).Name));
}
// methods not allowed
if (@struct.DescendantNodes().OfType().Any())
- {
+ {
Report(WinRTRules.StructHasInvalidFieldRule, @struct.GetLocation(), @struct.Identifier, SimplifySyntaxTypeString(typeof(MethodDeclarationSyntax).Name));
}
@@ -358,16 +361,16 @@ private void CheckStructFields(StructDeclarationSyntax @struct)
// constructors not allowed
if (structSym.Constructors.Length > 1)
- {
+ {
Report(WinRTRules.StructHasInvalidFieldRule, @struct.GetLocation(), @struct.Identifier, SimplifySyntaxTypeString(typeof(ConstructorDeclarationSyntax).Name));
}
var fields = @struct.DescendantNodes().OfType();
- foreach (var field in fields)
+ foreach (var field in fields)
{
// all fields must be public
if (!IsPublic(field))
- {
+ {
Report(WinRTRules.StructHasPrivateFieldRule, field.GetLocation(), @struct.Identifier);
}
@@ -381,14 +384,14 @@ private void CheckStructFields(StructDeclarationSyntax @struct)
{
IFieldSymbol varFieldSym = (IFieldSymbol)GetModel(variable.SyntaxTree).GetDeclaredSymbol(variable);
- if (ValidStructFieldTypes.Contains(varFieldSym.Type.SpecialType) ||
+ if (ValidStructFieldTypes.Contains(varFieldSym.Type.SpecialType) ||
varFieldSym.Type.TypeKind == TypeKind.Struct ||
varFieldSym.Type.TypeKind == TypeKind.Enum)
{
break;
}
else
- {
+ {
Report(WinRTRules.StructHasInvalidFieldRule, variable.GetLocation(), @struct.Identifier, varFieldSym.Name);
}
}
@@ -406,23 +409,23 @@ private void CheckStructFields(StructDeclarationSyntax @struct)
/// the authored namespace to checkthe name of the component/winmd
/// True iff namespace is disjoint from the assembly name
private bool IsInvalidNamespace(INamespaceSymbol @namespace, string assemblyName)
- {
- if (string.CompareOrdinal(@namespace.ToString(), assemblyName) == 0)
- {
- return false;
- }
-
+ {
+ if (string.CompareOrdinal(@namespace.ToString(), assemblyName) == 0)
+ {
+ return false;
+ }
+
var topLevel = @namespace;
while (!topLevel.ContainingNamespace.IsGlobalNamespace)
- {
- if (string.CompareOrdinal(topLevel.ToString(), assemblyName) == 0)
- {
- return false;
+ {
+ if (string.CompareOrdinal(topLevel.ToString(), assemblyName) == 0)
+ {
+ return false;
}
topLevel = topLevel.ContainingNamespace;
- }
-
- return string.CompareOrdinal(topLevel.ToString(), assemblyName) != 0;
+ }
+
+ return string.CompareOrdinal(topLevel.ToString(), assemblyName) != 0;
}
///Array types can only be one dimensional and not System.Array,
@@ -430,22 +433,22 @@ private bool IsInvalidNamespace(INamespaceSymbol @namespace, string assemblyName
///The type to checkwhere the type is
///The method or property with this type in its signature
/// the type this member (method/prop) lives in
- private void ReportIfInvalidType(ITypeSymbol typeSymbol, Location loc, SyntaxToken memberId, SyntaxToken typeId)
+ private void ReportIfInvalidType(ITypeSymbol typeSymbol, Location loc, SyntaxToken memberId, SyntaxToken typeId)
{
// If it's of the form int[], it has to be one dimensional
- if (typeSymbol.TypeKind == TypeKind.Array)
+ if (typeSymbol.TypeKind == TypeKind.Array)
{
IArrayTypeSymbol arrTypeSym = (IArrayTypeSymbol)typeSymbol;
// [,,]?
- if (arrTypeSym.Rank > 1)
- {
+ if (arrTypeSym.Rank > 1)
+ {
Report(WinRTRules.MultiDimensionalArrayRule, loc, memberId, typeId);
return;
- }
- // [][]?
- if (arrTypeSym.ElementType.TypeKind == TypeKind.Array)
- {
+ }
+ // [][]?
+ if (arrTypeSym.ElementType.TypeKind == TypeKind.Array)
+ {
Report(WinRTRules.JaggedArrayRule, loc, memberId, typeId);
return;
}
@@ -453,7 +456,7 @@ private void ReportIfInvalidType(ITypeSymbol typeSymbol, Location loc, SyntaxTok
// NotValidTypes is an array of types that don't exist in Windows Runtime, so can't be passed between functions in Windows Runtime
foreach (var typeName in NotValidTypes)
- {
+ {
var notValidTypeSym = GetTypeByMetadataName(typeName);
if (SymEq(typeSymbol.OriginalDefinition, notValidTypeSym))
{
@@ -467,21 +470,21 @@ private void ReportIfInvalidType(ITypeSymbol typeSymbol, Location loc, SyntaxTok
if (typeSymbol.ContainingNamespace != null && !typeSymbol.ContainingNamespace.IsGlobalNamespace)
{
// ContainingNamespace for Enumerable is just System, but we need System.Linq which is the ContainingSymbol
- qualifiedName += typeSymbol.ContainingSymbol + ".";
+ qualifiedName += typeSymbol.ContainingSymbol + ".";
}
// instead of TypeName, TypeName`1
qualifiedName += typeSymbol.MetadataName;
// GetTypeByMetadataName fails on "System.Linq.Enumerable" & "System.Collections.ObjectModel.ReadOnlyDictionary`2"
// Would be fixed by issue #678 on the dotnet/roslyn-sdk repo
- foreach (var notValidType in WIPNotValidTypes)
+ foreach (var notValidType in WIPNotValidTypes)
{
if (qualifiedName == notValidType)
- {
+ {
Report(WinRTRules.UnsupportedTypeRule, loc, memberId, notValidType, SuggestType(notValidType));
return;
}
}
- }
+ }
}
}
diff --git a/src/Authoring/WinRT.SourceGenerator/Generator.cs b/src/Authoring/WinRT.SourceGenerator/Generator.cs
index 5f5dd4314..370e2c437 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;
@@ -21,11 +21,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.GetUIXamlProjectionsMode());
+ // TODO-WuxMux: output a module initializer that validates the MUX/WUX projection mode to ensure that things don't get out of sync.
}
[SuppressMessage("MicrosoftCodeAnalysisCorrectness", "RS1035", Justification = "We need to do file IO to invoke the 'cswinrt' tool.")]
@@ -158,7 +161,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 0f72bfbb6..d06a1ff1c 100644
--- a/src/Authoring/WinRT.SourceGenerator/Helper.cs
+++ b/src/Authoring/WinRT.SourceGenerator/Helper.cs
@@ -231,12 +231,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, null, mapper);
}
- public static bool IsWinRTType(ISymbol type, Func isAuthoringWinRTType)
+ public static bool IsWinRTType(ISymbol type, Func isAuthoringWinRTType, TypeMapper mapper)
{
bool isProjectedType = type.GetAttributes().
Any(attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeTypeAttribute") == 0) ||
@@ -244,21 +244,21 @@ 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) ||
- (isAuthoringWinRTType != null && isAuthoringWinRTType(t)));
+ IsWinRTType(t, isAuthoringWinRTType, mapper) ||
+ (isAuthoringWinRTType != null && isAuthoringWinRTType(t, mapper)));
}
return isProjectedType;
}
- public static bool IsWinRTType(ISymbol type, ITypeSymbol winrtRuntimeTypeAttribute, bool isComponentProject, IAssemblySymbol currentAssembly)
+ public static bool IsWinRTType(ISymbol type, ITypeSymbol winrtRuntimeTypeAttribute, TypeMapper mapper, bool isComponentProject, IAssemblySymbol currentAssembly)
{
if (IsFundamentalType(type))
{
@@ -277,7 +277,7 @@ public static bool IsWinRTType(ISymbol type, ITypeSymbol winrtRuntimeTypeAttribu
bool isProjectedType = HasAttributeWithType(type, winrtRuntimeTypeAttribute);
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.
@@ -286,7 +286,7 @@ type is INamedTypeSymbol namedType &&
namedType.IsGenericType &&
!namedType.IsDefinition)
{
- isProjectedType = namedType.TypeArguments.All(t => IsWinRTType(t, winrtRuntimeTypeAttribute, isComponentProject, currentAssembly));
+ isProjectedType = namedType.TypeArguments.All(t => IsWinRTType(t, winrtRuntimeTypeAttribute, mapper, isComponentProject, currentAssembly));
}
return isProjectedType;
@@ -341,14 +341,14 @@ public static bool IsInternalInterfaceFromReferences(INamedTypeSymbol iface, IAs
// and is used by a WinRT interface. For instance, List where T is a generic.
// If the generic isn't used by any WinRT interface, this returns false as for
// instance, we can still generate the vtable attribute for it.
- public static bool HasNonInstantiatedWinRTGeneric(ITypeSymbol symbol)
+ public static bool HasNonInstantiatedWinRTGeneric(ITypeSymbol symbol, TypeMapper mapper)
{
return symbol is INamedTypeSymbol namedType &&
(IsArgumentTypeParameter(namedType) ||
(namedType.TypeArguments.Any(IsArgumentTypeParameter) &&
namedType.AllInterfaces.Any(iface => iface.TypeArguments.Any(IsArgumentTypeParameter) &&
// Checks if without the non-instantiated generic, whether it would be a WinRT type.
- IsWinRTType(iface.OriginalDefinition, null))));
+ IsWinRTType(iface.OriginalDefinition, null, mapper))));
static bool IsArgumentTypeParameter(ITypeSymbol argument)
{
@@ -411,14 +411,14 @@ public static bool HasAttributeWithType(ISymbol symbol, ITypeSymbol attributeTyp
return false;
}
- public static Func IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(Compilation compilation)
+ public static Func IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(Compilation compilation)
{
var winrtTypeAttribute = compilation.GetTypeByMetadataName("WinRT.WindowsRuntimeTypeAttribute");
return IsWinRTTypeHelper;
- bool IsWinRTTypeHelper(ISymbol type)
+ bool IsWinRTTypeHelper(ISymbol type, TypeMapper typeMapper)
{
- return IsWinRTType(type, winrtTypeAttribute, true, compilation.Assembly);
+ return IsWinRTType(type, winrtTypeAttribute, typeMapper, true, compilation.Assembly);
}
}
@@ -452,7 +452,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)
{
@@ -484,9 +484,9 @@ public static bool IsBlittableValueType(ITypeSymbol type)
if (type.ContainingNamespace != null)
{
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();
}
}
@@ -501,7 +501,7 @@ public static bool IsBlittableValueType(ITypeSymbol type)
{
if (typeMember is IFieldSymbol field &&
!field.IsStatic &&
- !IsBlittableValueType(field.Type))
+ !IsBlittableValueType(field.Type, typeMapper))
{
return false;
}
@@ -510,7 +510,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))
{
@@ -530,13 +530,13 @@ 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;
}
- if (!IsBlittableValueType(type))
+ if (!IsBlittableValueType(type, mapper))
{
var winrtHelperAttribute = type.GetAttributes().
Where(attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeHelperTypeAttribute") == 0).
diff --git a/src/Authoring/WinRT.SourceGenerator/Properties/launchSettings.json b/src/Authoring/WinRT.SourceGenerator/Properties/launchSettings.json
new file mode 100644
index 000000000..ef608ed3b
--- /dev/null
+++ b/src/Authoring/WinRT.SourceGenerator/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "WinRT.SourceGenerator": {
+ "commandName": "DebugRoslynComponent",
+ "targetProject": "..\\..\\Projections\\Windows\\Windows.csproj"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Authoring/WinRT.SourceGenerator/TypeMapper.cs b/src/Authoring/WinRT.SourceGenerator/TypeMapper.cs
new file mode 100644
index 000000000..bfec7684a
--- /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(UIXamlProjectionsMode xamlMode)
+ {
+ // This should be in sync with the reverse mapping from WinRT.Runtime/Projections.cs and cswinrt/helpers.h.
+ if (xamlMode == UIXamlProjectionsMode.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/UIXamlProjectionsMode.cs b/src/Authoring/WinRT.SourceGenerator/UIXamlProjectionsMode.cs
new file mode 100644
index 000000000..1bf4cc329
--- /dev/null
+++ b/src/Authoring/WinRT.SourceGenerator/UIXamlProjectionsMode.cs
@@ -0,0 +1,26 @@
+using Microsoft.CodeAnalysis.Diagnostics;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Generator
+{
+ internal enum UIXamlProjectionsMode
+ {
+ MicrosoftUIXaml,
+ WindowsUIXaml,
+ }
+
+ internal static class OptionsHelper
+ {
+ public static UIXamlProjectionsMode GetUIXamlProjectionsMode(this AnalyzerConfigOptions options)
+ {
+ if (options.TryGetValue("build_property.CsWinRTUIXamlProjections", out var value) && Enum.TryParse(value, out UIXamlProjectionsMode mode))
+ {
+ return mode;
+ }
+
+ return UIXamlProjectionsMode.MicrosoftUIXaml;
+ }
+ }
+}
diff --git a/src/Authoring/WinRT.SourceGenerator/WinRT.SourceGenerator.csproj b/src/Authoring/WinRT.SourceGenerator/WinRT.SourceGenerator.csproj
index 66e04a780..357e76314 100644
--- a/src/Authoring/WinRT.SourceGenerator/WinRT.SourceGenerator.csproj
+++ b/src/Authoring/WinRT.SourceGenerator/WinRT.SourceGenerator.csproj
@@ -17,6 +17,7 @@
Copyright (c) Microsoft Corporation. All rights reserved.
true
$(SolutionDir)WinRT.Runtime\key.snk
+ true
true
@@ -31,18 +32,18 @@
-
-
- True
- True
- CsWinRTDiagnosticStrings.resx
-
+
+
+ True
+ True
+ CsWinRTDiagnosticStrings.resx
+
-
-
- ResXFileCodeGenerator
- CsWinRTDiagnosticStrings.Designer.cs
-
+
+
+ ResXFileCodeGenerator
+ CsWinRTDiagnosticStrings.Designer.cs
+
diff --git a/src/Authoring/WinRT.SourceGenerator/WinRTAotCodeFixer.cs b/src/Authoring/WinRT.SourceGenerator/WinRTAotCodeFixer.cs
index ed2c31bc1..f0f009a15 100644
--- a/src/Authoring/WinRT.SourceGenerator/WinRTAotCodeFixer.cs
+++ b/src/Authoring/WinRT.SourceGenerator/WinRTAotCodeFixer.cs
@@ -42,6 +42,8 @@ public override void Initialize(AnalysisContext context)
return;
}
+ var typeMapper = new TypeMapper(context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.GetUIXamlProjectionsMode());
+
context.RegisterSymbolAction(context =>
{
// Filter to classes that can be passed as objects.
@@ -53,13 +55,13 @@ public override void Initialize(AnalysisContext context)
// Make sure this is a class that we would generate the WinRTExposedType attribute on
// and that it isn't already partial.
if (!GeneratorHelper.IsPartial(namedType) &&
- !GeneratorHelper.IsWinRTType(namedType, winrtTypeAttribute, isComponentProject, context.Compilation.Assembly) &&
- !GeneratorHelper.HasNonInstantiatedWinRTGeneric(namedType) &&
+ !GeneratorHelper.IsWinRTType(namedType, winrtTypeAttribute, typeMapper, isComponentProject, context.Compilation.Assembly) &&
+ !GeneratorHelper.HasNonInstantiatedWinRTGeneric(namedType, typeMapper) &&
!GeneratorHelper.HasAttributeWithType(namedType, winrtExposedTypeAttribute))
{
foreach (var iface in namedType.AllInterfaces)
{
- if (GeneratorHelper.IsWinRTType(iface, winrtTypeAttribute, isComponentProject, context.Compilation.Assembly))
+ if (GeneratorHelper.IsWinRTType(iface, winrtTypeAttribute, typeMapper, isComponentProject, context.Compilation.Assembly))
{
context.ReportDiagnostic(Diagnostic.Create(WinRTRules.ClassNotAotCompatible, namedType.Locations[0], namedType.Name));
return;
diff --git a/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs b/src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs
index 5143a1bf5..4154f62a9 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);
@@ -2440,9 +2442,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));
@@ -2534,7 +2536,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)
@@ -2665,11 +2667,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, (symbol, mapper) => IsWinRTType(symbol, mapper), mapper);
}
if (symbol is INamedTypeSymbol namedType)
@@ -2703,8 +2705,8 @@ typeDeclaration.Node is INamedTypeSymbol symbol &&
symbol.TypeKind == TypeKind.Class &&
!symbol.IsStatic)
{
- vtableAttributesToAdd.Add(WinRTAotSourceGenerator.GetVtableAttributeToAdd(symbol, IsWinRTType, context.Compilation, true, typeDeclaration.DefaultInterface));
- WinRTAotSourceGenerator.AddVtableAdapterTypeForKnownInterface(symbol, context.Compilation, IsWinRTType, vtableAttributesToAddOnLookupTable);
+ vtableAttributesToAdd.Add(WinRTAotSourceGenerator.GetVtableAttributeToAdd(symbol, IsWinRTType, mapper, context.Compilation, true, typeDeclaration.DefaultInterface));
+ WinRTAotSourceGenerator.AddVtableAdapterTypeForKnownInterface(symbol, context.Compilation, IsWinRTType, mapper, vtableAttributesToAddOnLookupTable);
}
}
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 009806607..b7d20d0ae 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..e12723150 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();
}
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..ce0e7e2ef 100644
--- a/src/Perf/IIDOptimizer/SignatureGenerator.cs
+++ b/src/Perf/IIDOptimizer/SignatureGenerator.cs
@@ -55,12 +55,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 +172,25 @@ 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)
+ {
+ var getGuidSignatureMethod = new MethodReference("GetGuidSignature", assembly.MainModule.TypeSystem.String, helperType)
+ {
+ HasThis = false
+ };
+
+ if (getGuidSignatureMethod.Resolve() is not null)
+ {
+ return new CustomSignatureMethod(assembly.MainModule.ImportReference(getGuidSignatureMethod));
+ }
+ else
+ {
+ throw new InvalidOperationException($"Unable to resolve GetGuidSignature method for type projected into .NET from WUX/MUX: {type.FullName}.");
+ }
+ }
+
Guid? guidAttributeValue = type.ReadGuidFromAttribute(guidAttributeType, winRTRuntimeAssembly);
if (guidAttributeValue == null)
{
diff --git a/src/Projections/WinAppSDK/WinAppSDK.csproj b/src/Projections/WinAppSDK/WinAppSDK.csproj
index b77e179c6..5fd5ae330 100644
--- a/src/Projections/WinAppSDK/WinAppSDK.csproj
+++ b/src/Projections/WinAppSDK/WinAppSDK.csproj
@@ -35,6 +35,7 @@
-include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute
-include Windows.UI.Xaml.Media.Animation.IndependentlyAnimatableAttribute
-include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute
+ -addition_exclude Windows.UI.Xaml.Media.Animation
$([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.windowsappsdk', '$(MicrosoftWinAppSDKVersion)'))
diff --git a/src/Projections/WinUI/WinUI.csproj b/src/Projections/WinUI/WinUI.csproj
index a3b83d4f6..e5a1e4c35 100644
--- a/src/Projections/WinUI/WinUI.csproj
+++ b/src/Projections/WinUI/WinUI.csproj
@@ -37,7 +37,8 @@
-include Windows.UI.Xaml.Markup.MarkupExtensionReturnTypeAttribute
-include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute
-include Windows.UI.Xaml.Media.Animation.IndependentlyAnimatableAttribute
--include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute
+-include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute
+-addition_exclude Windows.UI.Xaml.Media.Animation
$([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.winui', '$(MicrosoftWinUIVersion)'))
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..f4ca1fa5f
--- /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
+-addition_exclude Windows.UI.Xaml.Media.Animation
+
+
+
+
\ 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..c625b0c81
--- /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_USE_WINDOWS_UI_XAML_PROJECTIONS": "true"
+ }
+ }
+}
\ 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..fbd8d334e
--- /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/Configuration/FeatureSwitches.cs b/src/WinRT.Runtime/Configuration/FeatureSwitches.cs
index dbba4db98..41b785de5 100644
--- a/src/WinRT.Runtime/Configuration/FeatureSwitches.cs
+++ b/src/WinRT.Runtime/Configuration/FeatureSwitches.cs
@@ -4,8 +4,8 @@
using System;
using System.Runtime.CompilerServices;
-namespace WinRT
-{
+namespace WinRT
+{
///
/// A container for all shared configuration switches for CsWinRT.
///
@@ -19,158 +19,177 @@ namespace WinRT
/// For more info, see .
///
///
- internal static class FeatureSwitches
- {
+ internal static class FeatureSwitches
+ {
///
/// The configuration property name for .
///
- private const string EnablesDynamicObjectsSupportPropertyName = "CSWINRT_ENABLE_DYNAMIC_OBJECTS_SUPPORT";
-
+ private const string EnableDynamicObjectsSupportPropertyName = "CSWINRT_ENABLE_DYNAMIC_OBJECTS_SUPPORT";
+
///
/// The configuration property name for .
///
- private const string UseExceptionResourceKeysPropertyName = "CSWINRT_USE_EXCEPTION_RESOURCE_KEYS";
-
+ private const string UseExceptionResourceKeysPropertyName = "CSWINRT_USE_EXCEPTION_RESOURCE_KEYS";
+
///
/// The configuration property name for .
///
- private const string EnableDefaultCustomTypeMappingsPropertyName = "CSWINRT_ENABLE_DEFAULT_CUSTOM_TYPE_MAPPINGS";
-
+ private const string EnableDefaultCustomTypeMappingsPropertyName = "CSWINRT_ENABLE_DEFAULT_CUSTOM_TYPE_MAPPINGS";
+
///
/// The configuration property name for .
///
- private const string EnableICustomPropertyProviderSupportPropertyName = "CSWINRT_ENABLE_ICUSTOMPROPERTYPROVIDER_SUPPORT";
-
+ private const string EnableICustomPropertyProviderSupportPropertyName = "CSWINRT_ENABLE_ICUSTOMPROPERTYPROVIDER_SUPPORT";
+
///
/// The configuration property name for .
///
- private const string EnableIReferenceSupportPropertyName = "CSWINRT_ENABLE_IREFERENCE_SUPPORT";
-
+ private const string EnableIReferenceSupportPropertyName = "CSWINRT_ENABLE_IREFERENCE_SUPPORT";
+
///
/// The configuration property name for .
///
- private const string EnableIDynamicInterfaceCastableSupportPropertyName = "CSWINRT_ENABLE_IDYNAMICINTERFACECASTABLE";
-
+ private const string EnableIDynamicInterfaceCastableSupportPropertyName = "CSWINRT_ENABLE_IDYNAMICINTERFACECASTABLE";
+
+ ///
+ /// The configuration property name for .
+ ///
+ private const string UseWindowsUIXamlProjectionsPropertyName = "CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS";
+
///
/// The backing field for .
///
- private static int _enableDynamicObjectsSupportEnabled;
-
+ private static int _enableDynamicObjectsSupport;
+
///
/// The backing field for .
///
- private static int _useExceptionResourceKeys;
-
+ private static int _useExceptionResourceKeys;
+
///
/// The backing field for .
///
- private static int _enableDefaultCustomTypeMappings;
-
+ private static int _enableDefaultCustomTypeMappings;
+
///
/// The backing field for .
///
- private static int _enableICustomPropertyProviderSupport;
-
+ private static int _enableICustomPropertyProviderSupport;
+
///
/// The backing field for .
///
- private static int _enableIReferenceSupport;
-
+ private static int _enableIReferenceSupport;
+
///
/// The backing field for .
///
- private static int _enableIDynamicInterfaceCastableSupport;
-
+ private static int _enableIDynamicInterfaceCastableSupport;
+
+ ///
+ /// The backing field for .
+ ///
+ private static int _useWindowsUIXamlProjections;
+
///
/// Gets a value indicating whether or not projections support for dynamic objects is enabled (defaults to ).
///
- public static bool EnableDynamicObjectsSupport
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => GetConfigurationValue(EnablesDynamicObjectsSupportPropertyName, ref _enableDynamicObjectsSupportEnabled, true);
- }
-
+ public static bool EnableDynamicObjectsSupport
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => GetConfigurationValue(EnableDynamicObjectsSupportPropertyName, ref _enableDynamicObjectsSupport, true);
+ }
+
///
/// Gets a value indicating whether or not exceptions should use resource keys rather than localized messages (defaults to ).
///
- public static bool UseExceptionResourceKeys
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => GetConfigurationValue(UseExceptionResourceKeysPropertyName, ref _useExceptionResourceKeys, false);
- }
-
+ public static bool UseExceptionResourceKeys
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => GetConfigurationValue(UseExceptionResourceKeysPropertyName, ref _useExceptionResourceKeys, false);
+ }
+
///
/// Gets a value indicating whether or not should initialize all default type mappings automatically (defaults to ).
///
- public static bool EnableDefaultCustomTypeMappings
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => GetConfigurationValue(EnableDefaultCustomTypeMappingsPropertyName, ref _enableDefaultCustomTypeMappings, true);
- }
-
+ public static bool EnableDefaultCustomTypeMappings
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => GetConfigurationValue(EnableDefaultCustomTypeMappingsPropertyName, ref _enableDefaultCustomTypeMappings, true);
+ }
+
///
/// Gets a value indicating whether or not should be enabled (defaults to ).
///
- public static bool EnableICustomPropertyProviderSupport
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => GetConfigurationValue(EnableICustomPropertyProviderSupportPropertyName, ref _enableICustomPropertyProviderSupport, true);
- }
-
+ public static bool EnableICustomPropertyProviderSupport
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => GetConfigurationValue(EnableICustomPropertyProviderSupportPropertyName, ref _enableICustomPropertyProviderSupport, true);
+ }
+
///
/// Gets a value indicating whether or not IReference<T>, IReferenceArray<T> and IPropertyValue CCW implementations should be supported (defaults to ).
///
- public static bool EnableIReferenceSupport
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => GetConfigurationValue(EnableIReferenceSupportPropertyName, ref _enableIReferenceSupport, true);
- }
-
+ public static bool EnableIReferenceSupport
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => GetConfigurationValue(EnableIReferenceSupportPropertyName, ref _enableIReferenceSupport, true);
+ }
+
///
/// Gets a value indicating whether or not should be supported by RCW types (defaults to ).
///
- public static bool EnableIDynamicInterfaceCastableSupport
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => GetConfigurationValue(EnableIDynamicInterfaceCastableSupportPropertyName, ref _enableIDynamicInterfaceCastableSupport, true);
- }
-
+ public static bool EnableIDynamicInterfaceCastableSupport
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => GetConfigurationValue(EnableIDynamicInterfaceCastableSupportPropertyName, ref _enableIDynamicInterfaceCastableSupport, true);
+ }
+
+ ///
+ /// Gets a value indicating whether to project .NET types to their Windows.UI.Xaml equivalents instead of their Microsoft.UI.Xaml equivalents.
+ ///
+ public static bool UseWindowsUIXamlProjections
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => GetConfigurationValue(UseWindowsUIXamlProjectionsPropertyName, ref _useWindowsUIXamlProjections, false);
+ }
+
///
/// Gets a configuration value for a specified property.
///
/// The property name to retrieve the value for.
/// The cached result for the target configuration value.
/// The value of the specified configuration setting.
- private static bool GetConfigurationValue(string propertyName, ref int cachedResult, bool defaultValue)
- {
- // The cached switch value has 3 states:
- // 0: unknown.
- // 1: true
- // -1: false
- //
- // This method doesn't need to worry about concurrent accesses to the cached result,
- // as even if the configuration value is retrieved twice, that'll always be the same.
- if (cachedResult < 0)
- {
- return false;
- }
-
- if (cachedResult > 0)
- {
- return true;
- }
-
- // Get the configuration switch value, or its default.
- // All feature switches have a default set in the .targets file.
- if (!AppContext.TryGetSwitch(propertyName, out bool isEnabled))
- {
- isEnabled = defaultValue;
- }
-
- // Update the cached result
- cachedResult = isEnabled ? 1 : -1;
-
- return isEnabled;
- }
- }
+ private static bool GetConfigurationValue(string propertyName, ref int cachedResult, bool defaultValue)
+ {
+ // The cached switch value has 3 states:
+ // 0: unknown.
+ // 1: true
+ // -1: false
+ //
+ // This method doesn't need to worry about concurrent accesses to the cached result,
+ // as even if the configuration value is retrieved twice, that'll always be the same.
+ if (cachedResult < 0)
+ {
+ return false;
+ }
+
+ if (cachedResult > 0)
+ {
+ return true;
+ }
+
+ // Get the configuration switch value, or its default.
+ // All feature switches have a default set in the .targets file.
+ if (!AppContext.TryGetSwitch(propertyName, out bool isEnabled))
+ {
+ isEnabled = defaultValue;
+ }
+
+ // Update the cached result
+ cachedResult = isEnabled ? 1 : -1;
+
+ return isEnabled;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/WinRT.Runtime/Configuration/ILLink.Substitutions.xml b/src/WinRT.Runtime/Configuration/ILLink.Substitutions.xml
index 8a04a92b3..c962b9db2 100644
--- a/src/WinRT.Runtime/Configuration/ILLink.Substitutions.xml
+++ b/src/WinRT.Runtime/Configuration/ILLink.Substitutions.xml
@@ -25,6 +25,10 @@
+
+
+
+
diff --git a/src/WinRT.Runtime/GuidGenerator.cs b/src/WinRT.Runtime/GuidGenerator.cs
index b02f767ad..b8514f537 100644
--- a/src/WinRT.Runtime/GuidGenerator.cs
+++ b/src/WinRT.Runtime/GuidGenerator.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation.
+// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
@@ -7,6 +7,7 @@
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
+using WinRT.Interop;
namespace WinRT
{
@@ -22,7 +23,19 @@ static class GuidGenerator
#endif
public static Guid GetGUID(Type type)
{
- return type.GetGuidType().GUID;
+ type = type.GetGuidType();
+
+ // Only check the WUX/MUX types if the feature switch is set, to avoid introducing
+ // performance regressions in the standard case where MUX is targeted (default).
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ if (TryGetWindowsUIXamlIID(type, out Guid iid))
+ {
+ return iid;
+ }
+ }
+
+ return type.GUID;
}
public static Guid GetIID(
@@ -32,6 +45,16 @@ public static Guid GetIID(
Type type)
{
type = type.GetGuidType();
+
+ // Same optional check as above
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ if (TryGetWindowsUIXamlIID(type, out Guid iid))
+ {
+ return iid;
+ }
+ }
+
if (!type.IsGenericType)
{
return type.GUID;
@@ -39,6 +62,48 @@ public static Guid GetIID(
return (Guid)type.GetField("PIID").GetValue(null);
}
+ internal static bool TryGetWindowsUIXamlIID(Type type, out Guid iid)
+ {
+ if (type == typeof(global::ABI.System.Collections.Specialized.INotifyCollectionChanged))
+ {
+ iid = IID.IID_WUX_INotifyCollectionChanged;
+
+ return true;
+ }
+
+ if (type == typeof(global::ABI.System.ComponentModel.INotifyPropertyChanged))
+ {
+ iid = IID.IID_WUX_INotifyPropertyChanged;
+
+ return true;
+ }
+
+ if (type == typeof(global::ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs))
+ {
+ iid = IID.IID_WUX_INotifyCollectionChangedEventArgs;
+
+ return true;
+ }
+
+ if (type == typeof(global::ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler))
+ {
+ iid = IID.IID_WUX_NotifyCollectionChangedEventHandler;
+
+ return true;
+ }
+
+ if (type == typeof(global::ABI.System.ComponentModel.PropertyChangedEventHandler))
+ {
+ iid = IID.IID_WUX_PropertyChangedEventHandler;
+
+ return true;
+ }
+
+ iid = default;
+
+ return false;
+ }
+
public static string GetSignature(
#if NET
// This '[DynamicallyAccessedMembers]' annotation is here just for backwards-compatibility with old projections. Those are
diff --git a/src/WinRT.Runtime/Interop/IID.g.cs b/src/WinRT.Runtime/Interop/IID.g.cs
index 94d2a90d7..1929b3cd8 100644
--- a/src/WinRT.Runtime/Interop/IID.g.cs
+++ b/src/WinRT.Runtime/Interop/IID.g.cs
@@ -440,8 +440,108 @@ internal static ref readonly Guid IID_IRestrictedErrorInfo
}
}
- /// The IID for INotifyCollectionChangedEventArgsFactory (5108EBA4-4892-5A20-8374-A96815E0FD27).
- internal static ref readonly Guid IID_INotifyCollectionChangedEventArgsFactory
+ /// The IID for MUX_INotifyPropertyChanged (90B17601-B065-586E-83D9-9ADC3A695284).
+ internal static ref readonly Guid IID_MUX_INotifyPropertyChanged
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0x01, 0x76, 0xB1, 0x90,
+ 0x65, 0xB0,
+ 0x6E, 0x58,
+ 0x83,
+ 0xD9,
+ 0x9A,
+ 0xDC,
+ 0x3A,
+ 0x69,
+ 0x52,
+ 0x84
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for WUX_INotifyPropertyChanged (CF75D69C-F2F4-486B-B302-BB4C09BAEBFA).
+ internal static ref readonly Guid IID_WUX_INotifyPropertyChanged
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0x9C, 0xD6, 0x75, 0xCF,
+ 0xF4, 0xF2,
+ 0x6B, 0x48,
+ 0xB3,
+ 0x02,
+ 0xBB,
+ 0x4C,
+ 0x09,
+ 0xBA,
+ 0xEB,
+ 0xFA
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for MUX_INotifyCollectionChanged (530155E1-28A5-5693-87CE-30724D95A06D).
+ internal static ref readonly Guid IID_MUX_INotifyCollectionChanged
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0xE1, 0x55, 0x01, 0x53,
+ 0xA5, 0x28,
+ 0x93, 0x56,
+ 0x87,
+ 0xCE,
+ 0x30,
+ 0x72,
+ 0x4D,
+ 0x95,
+ 0xA0,
+ 0x6D
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for WUX_INotifyCollectionChanged (28B167D5-1A31-465B-9B25-D5C3AE686C40).
+ internal static ref readonly Guid IID_WUX_INotifyCollectionChanged
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0xD5, 0x67, 0xB1, 0x28,
+ 0x31, 0x1A,
+ 0x5B, 0x46,
+ 0x9B,
+ 0x25,
+ 0xD5,
+ 0xC3,
+ 0xAE,
+ 0x68,
+ 0x6C,
+ 0x40
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for MUX_INotifyCollectionChangedEventArgsFactory (5108EBA4-4892-5A20-8374-A96815E0FD27).
+ internal static ref readonly Guid IID_MUX_INotifyCollectionChangedEventArgsFactory
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
@@ -465,8 +565,33 @@ internal static ref readonly Guid IID_INotifyCollectionChangedEventArgsFactory
}
}
- /// The IID for INotifyCollectionChangedEventArgs (DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F).
- internal static ref readonly Guid IID_INotifyCollectionChangedEventArgs
+ /// The IID for WUX_INotifyCollectionChangedEventArgsFactory (B30C3E3A-DF8D-44A5-9A38-7AC0D08CE63D).
+ internal static ref readonly Guid IID_WUX_INotifyCollectionChangedEventArgsFactory
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0x3A, 0x3E, 0x0C, 0xB3,
+ 0x8D, 0xDF,
+ 0xA5, 0x44,
+ 0x9A,
+ 0x38,
+ 0x7A,
+ 0xC0,
+ 0xD0,
+ 0x8C,
+ 0xE6,
+ 0x3D
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for MUX_INotifyCollectionChangedEventArgs (DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F).
+ internal static ref readonly Guid IID_MUX_INotifyCollectionChangedEventArgs
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
@@ -490,8 +615,83 @@ internal static ref readonly Guid IID_INotifyCollectionChangedEventArgs
}
}
- /// The IID for PropertyChangedEventArgsRuntimeClassFactory (7C0C27A8-0B41-5070-B160-FC9AE960A36C).
- internal static ref readonly Guid IID_PropertyChangedEventArgsRuntimeClassFactory
+ /// The IID for WUX_INotifyCollectionChangedEventArgs (4CF68D33-E3F2-4964-B85E-945B4F7E2F21).
+ internal static ref readonly Guid IID_WUX_INotifyCollectionChangedEventArgs
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0x33, 0x8D, 0xF6, 0x4C,
+ 0xF2, 0xE3,
+ 0x64, 0x49,
+ 0xB8,
+ 0x5E,
+ 0x94,
+ 0x5B,
+ 0x4F,
+ 0x7E,
+ 0x2F,
+ 0x21
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for WUX_MotifyCollectionChangedEventHandler (8B0909DC-2005-5D93-BF8A-725F017BAA8D).
+ internal static ref readonly Guid IID_MUX_NotifyCollectionChangedEventHandler
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0xDC, 0x09, 0x09, 0x8B,
+ 0x05, 0x20,
+ 0x93, 0x5D,
+ 0xBF,
+ 0x8A,
+ 0x72,
+ 0x5F,
+ 0x01,
+ 0x7B,
+ 0xAA,
+ 0x8D
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for WUX_NotifyCollectionChangedEventHandler (CA10B37C-F382-4591-8557-5E24965279B0).
+ internal static ref readonly Guid IID_WUX_NotifyCollectionChangedEventHandler
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0x7C, 0xB3, 0x10, 0xCA,
+ 0x82, 0xF3,
+ 0x91, 0x45,
+ 0x85,
+ 0x57,
+ 0x5E,
+ 0x24,
+ 0x96,
+ 0x52,
+ 0x79,
+ 0xB0
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for MUX_PropertyChangedEventArgsRuntimeClassFactory (7C0C27A8-0B41-5070-B160-FC9AE960A36C).
+ internal static ref readonly Guid IID_MUX_PropertyChangedEventArgsRuntimeClassFactory
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
@@ -515,6 +715,81 @@ internal static ref readonly Guid IID_PropertyChangedEventArgsRuntimeClassFactor
}
}
+ /// The IID for WUX_PropertyChangedEventArgsRuntimeClassFactory (6DCC9C03-E0C7-4EEE-8EA9-37E3406EEB1C).
+ internal static ref readonly Guid IID_WUX_PropertyChangedEventArgsRuntimeClassFactory
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0x03, 0x9C, 0xCC, 0x6D,
+ 0xC7, 0xE0,
+ 0xEE, 0x4E,
+ 0x8E,
+ 0xA9,
+ 0x37,
+ 0xE3,
+ 0x40,
+ 0x6E,
+ 0xEB,
+ 0x1C
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for MUX_PropertyChangedEventHandler (E3DE52F6-1E32-5DA6-BB2D-B5B6096C962D).
+ internal static ref readonly Guid IID_MUX_PropertyChangedEventHandler
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0xF6, 0x52, 0xDE, 0xE3,
+ 0x32, 0x1E,
+ 0xA6, 0x5D,
+ 0xBB,
+ 0x2D,
+ 0xB5,
+ 0xB6,
+ 0x09,
+ 0x6C,
+ 0x96,
+ 0x2D
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
+ /// The IID for WUX_PropertyChangedEventHandler (50F19C16-0A22-4D8E-A089-1EA9951657D2).
+ internal static ref readonly Guid IID_WUX_PropertyChangedEventHandler
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ReadOnlySpan data = new byte[]
+ {
+ 0x16, 0x9C, 0xF1, 0x50,
+ 0x22, 0x0A,
+ 0x8E, 0x4D,
+ 0xA0,
+ 0x89,
+ 0x1E,
+ 0xA9,
+ 0x95,
+ 0x16,
+ 0x57,
+ 0xD2
+ };
+
+ return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
+ }
+ }
+
/// The IID for DataErrorsChangedEventArgsRuntimeClassFactory (62D0BD1E-B85F-5FCC-842A-7CB0DDA37FE5).
internal static ref readonly Guid IID_DataErrorsChangedEventArgsRuntimeClassFactory
{
@@ -590,56 +865,6 @@ internal static ref readonly Guid IID_INotifyDataErrorInfo
}
}
- /// The IID for INotifyPropertyChanged (90B17601-B065-586E-83D9-9ADC3A695284).
- internal static ref readonly Guid IID_INotifyPropertyChanged
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- ReadOnlySpan data = new byte[]
- {
- 0x01, 0x76, 0xB1, 0x90,
- 0x65, 0xB0,
- 0x6E, 0x58,
- 0x83,
- 0xD9,
- 0x9A,
- 0xDC,
- 0x3A,
- 0x69,
- 0x52,
- 0x84
- };
-
- return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
- }
- }
-
- /// The IID for INotifyCollectionChanged (530155E1-28A5-5693-87CE-30724D95A06D).
- internal static ref readonly Guid IID_INotifyCollectionChanged
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- ReadOnlySpan data = new byte[]
- {
- 0xE1, 0x55, 0x01, 0x53,
- 0xA5, 0x28,
- 0x93, 0x56,
- 0x87,
- 0xCE,
- 0x30,
- 0x72,
- 0x4D,
- 0x95,
- 0xA0,
- 0x6D
- };
-
- return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
- }
- }
-
/// The IID for ICommand (E5AF3542-CA67-4081-995B-709DD13792DF).
internal static ref readonly Guid IID_ICommand
{
@@ -690,56 +915,6 @@ internal static ref readonly Guid IID_IGlobalInterfaceTable
}
}
- /// The IID for PropertyChangedEventHandler (E3DE52F6-1E32-5DA6-BB2D-B5B6096C962D).
- internal static ref readonly Guid IID_PropertyChangedEventHandler
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- ReadOnlySpan data = new byte[]
- {
- 0xF6, 0x52, 0xDE, 0xE3,
- 0x32, 0x1E,
- 0xA6, 0x5D,
- 0xBB,
- 0x2D,
- 0xB5,
- 0xB6,
- 0x09,
- 0x6C,
- 0x96,
- 0x2D
- };
-
- return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
- }
- }
-
- /// The IID for NotifyCollectionChangedEventHandler (8B0909DC-2005-5D93-BF8A-725F017BAA8D).
- internal static ref readonly Guid IID_NotifyCollectionChangedEventHandler
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- ReadOnlySpan data = new byte[]
- {
- 0xDC, 0x09, 0x09, 0x8B,
- 0x05, 0x20,
- 0x93, 0x5D,
- 0xBF,
- 0x8A,
- 0x72,
- 0x5F,
- 0x01,
- 0x7B,
- 0xAA,
- 0x8D
- };
-
- return ref Unsafe.As(ref MemoryMarshal.GetReference(data));
- }
- }
-
/// The IID for EventHandler (C50898F6-C536-5F47-8583-8B2C2438A13B).
internal static ref readonly Guid IID_EventHandler
{
diff --git a/src/WinRT.Runtime/Interop/IID.tt b/src/WinRT.Runtime/Interop/IID.tt
index 47e4fc3a9..17d48ca84 100644
--- a/src/WinRT.Runtime/Interop/IID.tt
+++ b/src/WinRT.Runtime/Interop/IID.tt
@@ -39,18 +39,25 @@ var entries = new (string Name, string IID, bool IsPublic)[]
("ISupportErrorInfo", "DF0B3D60-548F-101B-8E65-08002B2BD119", false),
("ILanguageExceptionErrorInfo", "04A2DBF3-DF83-116C-0946-0812ABF6E07D", false),
("IRestrictedErrorInfo", "82BA7092-4C88-427D-A7BC-16DD93FEB67E", false),
- ("INotifyCollectionChangedEventArgsFactory", "5108EBA4-4892-5A20-8374-A96815E0FD27", false),
- ("INotifyCollectionChangedEventArgs", "DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F", false),
- ("PropertyChangedEventArgsRuntimeClassFactory", "7C0C27A8-0B41-5070-B160-FC9AE960A36C", false),
+ ("MUX_INotifyPropertyChanged", "90B17601-B065-586E-83D9-9ADC3A695284", false),
+ ("WUX_INotifyPropertyChanged", "CF75D69C-F2F4-486B-B302-BB4C09BAEBFA", false),
+ ("MUX_INotifyCollectionChanged", "530155E1-28A5-5693-87CE-30724D95A06D", false),
+ ("WUX_INotifyCollectionChanged", "28B167D5-1A31-465B-9B25-D5C3AE686C40", false),
+ ("MUX_INotifyCollectionChangedEventArgsFactory", "5108EBA4-4892-5A20-8374-A96815E0FD27", false),
+ ("WUX_INotifyCollectionChangedEventArgsFactory", "B30C3E3A-DF8D-44A5-9A38-7AC0D08CE63D", false),
+ ("MUX_INotifyCollectionChangedEventArgs", "DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F", false),
+ ("WUX_INotifyCollectionChangedEventArgs", "4CF68D33-E3F2-4964-B85E-945B4F7E2F21", false),
+ ("MUX_NotifyCollectionChangedEventHandler", "8B0909DC-2005-5D93-BF8A-725F017BAA8D", false),
+ ("WUX_NotifyCollectionChangedEventHandler", "CA10B37C-F382-4591-8557-5E24965279B0", false),
+ ("MUX_PropertyChangedEventArgsRuntimeClassFactory", "7C0C27A8-0B41-5070-B160-FC9AE960A36C", false),
+ ("WUX_PropertyChangedEventArgsRuntimeClassFactory", "6DCC9C03-E0C7-4EEE-8EA9-37E3406EEB1C", false),
+ ("MUX_PropertyChangedEventHandler", "E3DE52F6-1E32-5DA6-BB2D-B5B6096C962D", false),
+ ("WUX_PropertyChangedEventHandler", "50F19C16-0A22-4D8E-A089-1EA9951657D2", false),
("DataErrorsChangedEventArgsRuntimeClassFactory", "62D0BD1E-B85F-5FCC-842A-7CB0DDA37FE5", false),
("UriRuntimeClassFactory", "44A9796F-723E-4FDF-A218-033E75B0C084", false),
("INotifyDataErrorInfo", "0EE6C2CC-273E-567D-BC0A-1DD87EE51EBA", false),
- ("INotifyPropertyChanged", "90B17601-B065-586E-83D9-9ADC3A695284", false),
- ("INotifyCollectionChanged", "530155E1-28A5-5693-87CE-30724D95A06D", false),
("ICommand", "E5AF3542-CA67-4081-995B-709DD13792DF", false),
("IGlobalInterfaceTable", "00000146-0000-0000-C000-000000000046", false),
- ("PropertyChangedEventHandler", "E3DE52F6-1E32-5DA6-BB2D-B5B6096C962D", false),
- ("NotifyCollectionChangedEventHandler", "8B0909DC-2005-5D93-BF8A-725F017BAA8D", false),
("EventHandler", "C50898F6-C536-5F47-8583-8B2C2438A13B", false),
("IBindableVectorView", "346DD6E7-976E-4BC3-815D-ECE243BC0F33", false),
("IEnumerable", "036D2C08-DF29-41AF-8AA2-D774BE62BA6F", false),
diff --git a/src/WinRT.Runtime/Interop/WuxMuxProjectedTypeAttribute.cs b/src/WinRT.Runtime/Interop/WuxMuxProjectedTypeAttribute.cs
new file mode 100644
index 000000000..3f56b6dc7
--- /dev/null
+++ b/src/WinRT.Runtime/Interop/WuxMuxProjectedTypeAttribute.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace WinRT.Interop
+{
+ // This attribute is only used by the IIDOptimizer for resolving the signature of a type that has different
+ // IIDs on WUX/MUX targets. The actual IIDs are hardcoded in WinRT.Runtime, so they are not needed here.
+ // TODO: remove this entirely when either IIDOptimizer is removed, or when the option to hardcode IIDs is added.
+
+ ///
+ /// 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, AllowMultiple = false, Inherited = false)]
+ internal sealed class WuxMuxProjectedTypeAttribute : Attribute
+ {
+ }
+}
diff --git a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
index 4040efbcc..1276f8957 100644
--- a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
+++ b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
@@ -232,6 +232,9 @@ CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.Unconditional
CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute' exists on 'ABI.WinRT.Interop.IActivationFactory.AsInterface()' in the implementation but not the reference.
CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute' exists on 'WinRT.IInspectable.As()' in the implementation but not the reference.
CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute' exists on 'WinRT.TypeExtensions.FindHelperType(System.Type)' in the implementation but not the reference.
+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.
+CannotRemoveAttribute : Attribute 'WinRT.Interop.WuxMuxProjectedTypeAttribute' exists on 'ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs' in the implementation but not the reference.
TypesMustExist : Type 'WinRT.WinRTRuntimeClassNameAttribute' does not exist in the reference but it does exist in the implementation.
MembersMustExist : Member 'public void WinRT.ComWrappersSupport.RegisterTypeRuntimeClassNameLookup(System.Func)' does not exist in the reference but it does exist in the implementation.
CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute' exists on 'WinRT.Projections.FindCustomHelperTypeMapping(System.Type, System.Boolean)' in the implementation but not the reference.
@@ -264,4 +267,4 @@ MembersMustExist : Member 'public void WinRT.ComWrappersHelper.Init(System.Boole
MembersMustExist : Member 'public System.Guid ABI.System.EventHandler.IID.get()' does not exist in the reference but it does exist in the implementation.
MembersMustExist : Member 'public System.Guid ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler.IID.get()' does not exist in the reference but it does exist in the implementation.
MembersMustExist : Member 'public System.Guid ABI.System.ComponentModel.PropertyChangedEventHandler.IID.get()' does not exist in the reference but it does exist in the implementation.
-Total Issues: 265
+Total Issues: 268
diff --git a/src/WinRT.Runtime/Projections.CustomTypeMappings.g.cs b/src/WinRT.Runtime/Projections.CustomTypeMappings.g.cs
index a45d5e0e8..86e3658ec 100644
--- a/src/WinRT.Runtime/Projections.CustomTypeMappings.g.cs
+++ b/src/WinRT.Runtime/Projections.CustomTypeMappings.g.cs
@@ -506,6 +506,11 @@ public static void RegisterDataErrorsChangedEventArgsMapping()
return;
}
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ throw new NotSupportedException("The 'DataErrorsChangedEventArgs' type is only supported for WinUI, and not when using System XAML projections (make sure the 'CsWinRTUseWindowsUIXamlProjections' property is not set to 'true').");
+ }
+
if (Interlocked.CompareExchange(ref _DataErrorsChangedEventArgs, 1, 0) == 1)
{
return;
@@ -531,11 +536,22 @@ public static void RegisterPropertyChangedEventArgsMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(PropertyChangedEventArgs),
- typeof(ABI.System.ComponentModel.PropertyChangedEventArgs),
- "Microsoft.UI.Xaml.Data.PropertyChangedEventArgs",
- isRuntimeClass: true);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(PropertyChangedEventArgs),
+ typeof(ABI.System.ComponentModel.PropertyChangedEventArgs),
+ "Windows.UI.Xaml.Data.PropertyChangedEventArgs",
+ isRuntimeClass: true);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(PropertyChangedEventArgs),
+ typeof(ABI.System.ComponentModel.PropertyChangedEventArgs),
+ "Microsoft.UI.Xaml.Data.PropertyChangedEventArgs",
+ isRuntimeClass: true);
+ }
}
/// Registers the custom ABI type mapping for the "Microsoft.UI.Xaml.Data.PropertyChangedEventHandler" WinRT type.
@@ -551,11 +567,22 @@ public static void RegisterPropertyChangedEventHandlerMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(PropertyChangedEventHandler),
- typeof(ABI.System.ComponentModel.PropertyChangedEventHandler),
- "Microsoft.UI.Xaml.Data.PropertyChangedEventHandler",
- isRuntimeClass: false);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(PropertyChangedEventHandler),
+ typeof(ABI.System.ComponentModel.PropertyChangedEventHandler),
+ "Windows.UI.Xaml.Data.PropertyChangedEventHandler",
+ isRuntimeClass: false);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(PropertyChangedEventHandler),
+ typeof(ABI.System.ComponentModel.PropertyChangedEventHandler),
+ "Microsoft.UI.Xaml.Data.PropertyChangedEventHandler",
+ isRuntimeClass: false);
+ }
}
/// Registers the custom ABI type mapping for the "Microsoft.UI.Xaml.Data.INotifyDataErrorInfo" WinRT type.
@@ -566,6 +593,11 @@ public static void RegisterINotifyDataErrorInfoMapping()
return;
}
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ throw new NotSupportedException("The 'INotifyDataErrorInfo' type is only supported for WinUI, and not when using System XAML projections (make sure the 'CsWinRTUseWindowsUIXamlProjections' property is not set to 'true').");
+ }
+
if (Interlocked.CompareExchange(ref _INotifyDataErrorInfo, 1, 0) == 1)
{
return;
@@ -591,11 +623,22 @@ public static void RegisterINotifyPropertyChangedMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(INotifyPropertyChanged),
- typeof(ABI.System.ComponentModel.INotifyPropertyChanged),
- "Microsoft.UI.Xaml.Data.INotifyPropertyChanged",
- isRuntimeClass: false);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(INotifyPropertyChanged),
+ typeof(ABI.System.ComponentModel.INotifyPropertyChanged),
+ "Windows.UI.Xaml.Data.INotifyPropertyChanged",
+ isRuntimeClass: false);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(INotifyPropertyChanged),
+ typeof(ABI.System.ComponentModel.INotifyPropertyChanged),
+ "Microsoft.UI.Xaml.Data.INotifyPropertyChanged",
+ isRuntimeClass: false);
+ }
}
/// Registers the custom ABI type mapping for the "Microsoft.UI.Xaml.Interop.ICommand" WinRT type.
@@ -611,11 +654,22 @@ public static void RegisterICommandMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(ICommand),
- typeof(ABI.System.Windows.Input.ICommand),
- "Microsoft.UI.Xaml.Interop.ICommand",
- isRuntimeClass: false);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(ICommand),
+ typeof(ABI.System.Windows.Input.ICommand),
+ "Windows.UI.Xaml.Interop.ICommand",
+ isRuntimeClass: false);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(ICommand),
+ typeof(ABI.System.Windows.Input.ICommand),
+ "Microsoft.UI.Xaml.Interop.ICommand",
+ isRuntimeClass: false);
+ }
}
/// Registers the custom ABI type mapping for the "Microsoft.UI.Xaml.IXamlServiceProvider" WinRT type.
@@ -626,6 +680,11 @@ public static void RegisterIServiceProviderMapping()
return;
}
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ throw new NotSupportedException("The 'IServiceProvider' type is only supported for WinUI, and not when using System XAML projections (make sure the 'CsWinRTUseWindowsUIXamlProjections' property is not set to 'true').");
+ }
+
if (Interlocked.CompareExchange(ref _IServiceProvider, 1, 0) == 1)
{
return;
@@ -831,11 +890,22 @@ public static void RegisterIEnumerableMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(IEnumerable),
- typeof(ABI.System.Collections.IEnumerable),
- "Microsoft.UI.Xaml.Interop.IBindableIterable",
- isRuntimeClass: false);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(IEnumerable),
+ typeof(ABI.System.Collections.IEnumerable),
+ "Windows.UI.Xaml.Interop.IBindableIterable",
+ isRuntimeClass: false);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(IEnumerable),
+ typeof(ABI.System.Collections.IEnumerable),
+ "Microsoft.UI.Xaml.Interop.IBindableIterable",
+ isRuntimeClass: false);
+ }
}
/// Registers the custom ABI type mapping for the "Microsoft.UI.Xaml.Interop.IBindableVector" WinRT type.
@@ -851,11 +921,22 @@ public static void RegisterIListMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(IList),
- typeof(ABI.System.Collections.IList),
- "Microsoft.UI.Xaml.Interop.IBindableVector",
- isRuntimeClass: false);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(IList),
+ typeof(ABI.System.Collections.IList),
+ "Windows.UI.Xaml.Interop.IBindableVector",
+ isRuntimeClass: false);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(IList),
+ typeof(ABI.System.Collections.IList),
+ "Microsoft.UI.Xaml.Interop.IBindableVector",
+ isRuntimeClass: false);
+ }
}
/// Registers the custom ABI type mapping for the "Microsoft.UI.Xaml.Interop.INotifyCollectionChanged" WinRT type.
@@ -871,11 +952,22 @@ public static void RegisterINotifyCollectionChangedMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(INotifyCollectionChanged),
- typeof(ABI.System.Collections.Specialized.INotifyCollectionChanged),
- "Microsoft.UI.Xaml.Interop.INotifyCollectionChanged",
- isRuntimeClass: false);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(INotifyCollectionChanged),
+ typeof(ABI.System.Collections.Specialized.INotifyCollectionChanged),
+ "Windows.UI.Xaml.Interop.INotifyCollectionChanged",
+ isRuntimeClass: false);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(INotifyCollectionChanged),
+ typeof(ABI.System.Collections.Specialized.INotifyCollectionChanged),
+ "Microsoft.UI.Xaml.Interop.INotifyCollectionChanged",
+ isRuntimeClass: false);
+ }
}
/// Registers the custom ABI type mapping for the "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedAction" WinRT type.
@@ -891,11 +983,22 @@ public static void RegisterNotifyCollectionChangedActionMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(NotifyCollectionChangedAction),
- typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedAction),
- "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedAction",
- isRuntimeClass: false);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(NotifyCollectionChangedAction),
+ typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedAction),
+ "Windows.UI.Xaml.Interop.NotifyCollectionChangedAction",
+ isRuntimeClass: false);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(NotifyCollectionChangedAction),
+ typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedAction),
+ "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedAction",
+ isRuntimeClass: false);
+ }
}
/// Registers the custom ABI type mapping for the "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventArgs" WinRT type.
@@ -911,11 +1014,22 @@ public static void RegisterNotifyCollectionChangedEventArgsMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(NotifyCollectionChangedEventArgs),
- typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs),
- "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventArgs",
- isRuntimeClass: true);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(NotifyCollectionChangedEventArgs),
+ typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs),
+ "Windows.UI.Xaml.Interop.NotifyCollectionChangedEventArgs",
+ isRuntimeClass: true);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(NotifyCollectionChangedEventArgs),
+ typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs),
+ "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventArgs",
+ isRuntimeClass: true);
+ }
}
/// Registers the custom ABI type mapping for the "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventHandler" WinRT type.
@@ -931,11 +1045,22 @@ public static void RegisterNotifyCollectionChangedEventHandlerMapping()
return;
}
- RegisterCustomAbiTypeMapping(
- typeof(NotifyCollectionChangedEventHandler),
- typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler),
- "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventHandler",
- isRuntimeClass: false);
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(NotifyCollectionChangedEventHandler),
+ typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler),
+ "Windows.UI.Xaml.Interop.NotifyCollectionChangedEventHandler",
+ isRuntimeClass: false);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(NotifyCollectionChangedEventHandler),
+ typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandler),
+ "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventHandler",
+ isRuntimeClass: false);
+ }
}
/// Registers the custom ABI type mapping for the "Windows.Foundation.Numerics.Matrix3x2" WinRT type.
diff --git a/src/WinRT.Runtime/Projections.CustomTypeMappings.tt b/src/WinRT.Runtime/Projections.CustomTypeMappings.tt
index 3d244beb8..8457dc046 100644
--- a/src/WinRT.Runtime/Projections.CustomTypeMappings.tt
+++ b/src/WinRT.Runtime/Projections.CustomTypeMappings.tt
@@ -50,6 +50,21 @@ void WriteGuardStatements(string name)
{
return;
}
+<#
+
+ if (name == "DataErrorsChangedEventArgs" ||
+ name == "INotifyDataErrorInfo" ||
+ name == "IServiceProvider")
+ {
+ WriteLine("");
+#>
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ throw new NotSupportedException("The '<#=name#>' type is only supported for WinUI, and not when using System XAML projections (make sure the 'CsWinRTUseWindowsUIXamlProjections' property is not set to 'true').");
+ }
+<#
+ }
+#>
if (Interlocked.CompareExchange(ref _<#=Regex.Replace(name, "[?<>,]", "_")#>, 1, 0) == 1)
{
@@ -110,7 +125,7 @@ var registerCustomAbiTypeMappings = new (string Public, string Abi, string Name,
("Quaternion", "ABI.System.Numerics.Quaternion", "Windows.Foundation.Numerics.Quaternion", null, false),
("Vector2", "ABI.System.Numerics.Vector2", "Windows.Foundation.Numerics.Vector2", null, false),
("Vector3", "ABI.System.Numerics.Vector3", "Windows.Foundation.Numerics.Vector3", null, false),
- ("Vector4", "ABI.System.Numerics.Vector4", "Windows.Foundation.Numerics.Vector4", null, false),
+ ("Vector4", "ABI.System.Numerics.Vector4", "Windows.Foundation.Numerics.Vector4", null, false)
};
// Types for 'RegisterCustomTypeToHelperTypeMapping'
@@ -126,6 +141,21 @@ var registerCustomTypeToHelperTypeMapping = new (string Public, string Helper)[]
("ICollection", "ABI.System.Collections.ICollection")
};
+// Types that have different projections for System XAML
+var systemXamlProjectionTypeMapping = new(string Public, string Name)[]
+{
+ ("PropertyChangedEventArgs", "Windows.UI.Xaml.Data.PropertyChangedEventArgs"),
+ ("PropertyChangedEventHandler", "Windows.UI.Xaml.Data.PropertyChangedEventHandler"),
+ ("INotifyPropertyChanged", "Windows.UI.Xaml.Data.INotifyPropertyChanged"),
+ ("ICommand", "Windows.UI.Xaml.Interop.ICommand"),
+ ("IEnumerable", "Windows.UI.Xaml.Interop.IBindableIterable"),
+ ("IList", "Windows.UI.Xaml.Interop.IBindableVector"),
+ ("INotifyCollectionChanged", "Windows.UI.Xaml.Interop.INotifyCollectionChanged"),
+ ("NotifyCollectionChangedAction", "Windows.UI.Xaml.Interop.NotifyCollectionChangedAction"),
+ ("NotifyCollectionChangedEventArgs", "Windows.UI.Xaml.Interop.NotifyCollectionChangedEventArgs"),
+ ("NotifyCollectionChangedEventHandler", "Windows.UI.Xaml.Interop.NotifyCollectionChangedEventHandler")
+};
+
// Declare all fields
foreach (string fieldName in
registerCustomAbiTypeMappings
@@ -145,40 +175,50 @@ foreach (var type in registerCustomAbiTypeMappings)
{
WriteLine("");
- if (type.Name != null)
- {
#>
/// Registers the custom ABI type mapping for the "<#=type.Name#>" WinRT type.
public static void <#=GetMethodName(type.Public, type.Hint)#>()
{
<#
WriteGuardStatements(type.Public);
-#>
+ WriteLine("");
+
+ int indexOfSystemXamlTypeMapping = Array.FindIndex(systemXamlProjectionTypeMapping, t => t.Public == type.Public);
+ if (indexOfSystemXamlTypeMapping != -1)
+ {
+#>
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(<#=type.Public#>),
+ typeof(<#=type.Abi#>),
+ "<#=systemXamlProjectionTypeMapping[indexOfSystemXamlTypeMapping].Name#>",
+ isRuntimeClass: <#=type.IsRuntimeClass.ToString().ToLowerInvariant()#>);
+ }
+ else
+ {
+ RegisterCustomAbiTypeMapping(
+ typeof(<#=type.Public#>),
+ typeof(<#=type.Abi#>),
+ "<#=type.Name#>",
+ isRuntimeClass: <#=type.IsRuntimeClass.ToString().ToLowerInvariant()#>);
+ }
+<#
+ }
+ else
+ {
+#>
RegisterCustomAbiTypeMapping(
typeof(<#=type.Public#>),
typeof(<#=type.Abi#>),
"<#=type.Name#>",
isRuntimeClass: <#=type.IsRuntimeClass.ToString().ToLowerInvariant()#>);
- }
<#
- }
- else
- {
-#>
- /// Registers the custom ABI type mapping for the type.
- public static void <#=GetMethodName(type.Public, type.Hint)#>()
- {
-<#
- WriteGuardStatements(type.Public);
+ }
#>
-
- RegisterCustomAbiTypeMapping(
- typeof(<#=type.Public#>),
- typeof(<#=type.Abi#>));
}
<#
- }
}
// 'RegisterCustomTypeToHelperTypeMapping' methods
diff --git a/src/WinRT.Runtime/Projections.cs b/src/WinRT.Runtime/Projections.cs
index 734bc8f0d..21e992799 100644
--- a/src/WinRT.Runtime/Projections.cs
+++ b/src/WinRT.Runtime/Projections.cs
@@ -39,6 +39,7 @@ static Projections()
{
// We always register mappings for 'bool' and 'char' as they're primitive types.
// They're also very cheap anyway and commonly used, so this keeps things simpler.
+ // 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");
@@ -56,6 +57,15 @@ static Projections()
}
#endif
+#if !NET
+ // Sanity check: always throw downlevel if System XAML projections are used, as this scenario is not supported.
+ // This also allows other code in WinRT.Runtime to simplify downlevel paths by just assuming this configuration.
+ if (FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ throw new NotSupportedException("Using System XAML projections is only supported on modern .NET (make sure the 'CsWinRTUseWindowsUIXamlProjections' property is not set to 'true').");
+ }
+#endif
+
// This should be in sync with cswinrt/helpers.h and the reverse mapping from WinRT.SourceGenerator/WinRTTypeWriter.cs.
RegisterCustomAbiTypeMappingNoLock(typeof(EventRegistrationToken), typeof(ABI.WinRT.EventRegistrationToken), "Windows.Foundation.EventRegistrationToken");
@@ -65,13 +75,37 @@ 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.Input.ICommand");
- RegisterCustomAbiTypeMappingNoLock(typeof(IServiceProvider), typeof(ABI.System.IServiceProvider), "Microsoft.UI.Xaml.IXamlServiceProvider");
+
+ if (!FeatureSwitches.UseWindowsUIXamlProjections)
+ {
+ 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.Input.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");
+ }
+ else
+ {
+ 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");
+ }
+
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");
@@ -83,12 +117,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");
@@ -105,6 +133,7 @@ static Projections()
RegisterCustomTypeToHelperTypeMappingNoLock(typeof(IVector<>), typeof(ABI.System.Collections.Generic.IList<>));
RegisterCustomTypeToHelperTypeMappingNoLock(typeof(IMapView<,>), typeof(ABI.System.Collections.Generic.IReadOnlyDictionary<,>));
RegisterCustomTypeToHelperTypeMappingNoLock(typeof(IVectorView<>), typeof(ABI.System.Collections.Generic.IReadOnlyList<>));
+ // The IBindable* types have the same IID on both MUX and WUX, so we can use the same type in both scenarios.
RegisterCustomTypeToHelperTypeMappingNoLock(typeof(Microsoft.UI.Xaml.Interop.IBindableVector), typeof(ABI.System.Collections.IList));
#if NET
diff --git a/src/WinRT.Runtime/Projections/ICommand.net5.cs b/src/WinRT.Runtime/Projections/ICommand.net5.cs
index 7f7308629..4fe21ab2f 100644
--- a/src/WinRT.Runtime/Projections/ICommand.net5.cs
+++ b/src/WinRT.Runtime/Projections/ICommand.net5.cs
@@ -74,6 +74,7 @@ public static unsafe EventHandlerEventSource Get_CanExecuteChanged2(IObjectRefer
}
}
+ // ICommand has the same IID for both Windows.UI.Xaml.Input.ICommand and Microsoft.UI.Xaml.Input.ICommand, so we can use one interface definition for both without marking it as a WUX/MUX type.
[EditorBrowsable(EditorBrowsableState.Never)]
[Guid("E5AF3542-CA67-4081-995B-709DD13792DF")]
[DynamicInterfaceCastableImplementation]
diff --git a/src/WinRT.Runtime/Projections/ICustomPropertyProvider.net5.cs b/src/WinRT.Runtime/Projections/ICustomPropertyProvider.net5.cs
index cd63ce463..b982623e9 100644
--- a/src/WinRT.Runtime/Projections/ICustomPropertyProvider.net5.cs
+++ b/src/WinRT.Runtime/Projections/ICustomPropertyProvider.net5.cs
@@ -6,6 +6,8 @@
using System.Runtime.InteropServices;
using WinRT;
+// These types have the same GUIDs in both Microsoft.UI.Xaml and Windows.UI.Xaml,
+// so we don't need to duplicate them for the internal usage here as they can be transparently used by both WUX and MUX.
namespace Microsoft.UI.Xaml.Data
{
[global::WinRT.WindowsRuntimeType]
diff --git a/src/WinRT.Runtime/Projections/INotifyCollectionChanged.net5.cs b/src/WinRT.Runtime/Projections/INotifyCollectionChanged.net5.cs
index 5370dceba..b812db480 100644
--- a/src/WinRT.Runtime/Projections/INotifyCollectionChanged.net5.cs
+++ b/src/WinRT.Runtime/Projections/INotifyCollectionChanged.net5.cs
@@ -3,8 +3,10 @@
using System;
using System.ComponentModel;
+using System.Reflection;
using System.Runtime.InteropServices;
using WinRT;
+using WinRT.Interop;
namespace ABI.System.Collections.Specialized
{
@@ -35,7 +37,9 @@ static class INotifyCollectionChangedMethods
});
}
- public static global::System.Guid IID => global::WinRT.Interop.IID.IID_INotifyCollectionChanged;
+ public static global::System.Guid IID => FeatureSwitches.UseWindowsUIXamlProjections
+ ? global::WinRT.Interop.IID.IID_WUX_INotifyCollectionChanged
+ : global::WinRT.Interop.IID.IID_MUX_INotifyCollectionChanged;
public static IntPtr AbiToProjectionVftablePtr => INotifyCollectionChanged.Vftbl.AbiToProjectionVftablePtr;
}
@@ -43,6 +47,7 @@ static class INotifyCollectionChangedMethods
[DynamicInterfaceCastableImplementation]
[EditorBrowsable(EditorBrowsableState.Never)]
[Guid("530155E1-28A5-5693-87CE-30724D95A06D")]
+ [WuxMuxProjectedType]
internal unsafe interface INotifyCollectionChanged : global::System.Collections.Specialized.INotifyCollectionChanged
{
[Guid("530155E1-28A5-5693-87CE-30724D95A06D")]
@@ -121,7 +126,6 @@ private static unsafe int Do_Abi_remove_CollectionChanged_1(IntPtr thisPtr, glob
}
}
}
- internal static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr, global::WinRT.Interop.IID.IID_INotifyCollectionChanged);
private static global::ABI.WinRT.Interop.EventSource _CollectionChanged(IWinRTObject _this)
{
diff --git a/src/WinRT.Runtime/Projections/INotifyPropertyChanged.net5.cs b/src/WinRT.Runtime/Projections/INotifyPropertyChanged.net5.cs
index ff411bfe5..1b72b7de9 100644
--- a/src/WinRT.Runtime/Projections/INotifyPropertyChanged.net5.cs
+++ b/src/WinRT.Runtime/Projections/INotifyPropertyChanged.net5.cs
@@ -4,20 +4,23 @@
using System;
using System.Runtime.InteropServices;
using WinRT;
+using WinRT.Interop;
namespace ABI.System.ComponentModel
-{
+{
#if EMBED
internal
#else
public
#endif
static class INotifyPropertyChangedMethods
- {
- public static global::System.Guid IID => global::WinRT.Interop.IID.IID_INotifyPropertyChanged;
+ {
+ public static global::System.Guid IID => FeatureSwitches.UseWindowsUIXamlProjections
+ ? global::WinRT.Interop.IID.IID_WUX_INotifyPropertyChanged
+ : global::WinRT.Interop.IID.IID_MUX_INotifyPropertyChanged;
+
+ public static IntPtr AbiToProjectionVftablePtr => INotifyPropertyChanged.Vftbl.AbiToProjectionVftablePtr;
- public static IntPtr AbiToProjectionVftablePtr => INotifyPropertyChanged.Vftbl.AbiToProjectionVftablePtr;
-
private volatile static global::System.Runtime.CompilerServices.ConditionalWeakTable