Skip to content

Commit

Permalink
Implement the base TODO-WuxMux items that must be completed to suppor…
Browse files Browse the repository at this point in the history
…t a runtime configuration WUX/MUX switch.
  • Loading branch information
jkoritzinsky committed Dec 15, 2023
1 parent 0a7f955 commit 4bb2d41
Show file tree
Hide file tree
Showing 33 changed files with 2,514 additions and 1,564 deletions.
101 changes: 56 additions & 45 deletions src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions src/Authoring/WinRT.SourceGenerator/DiagnosticUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ public WinRTComponentScanner(GeneratorExecutionContext context, string assemblyN
_assemblyName = assemblyName;
_context = context;
_flag = false;
_typeMapper = new TypeMapper(context.AnalyzerConfigOptions.GlobalOptions.GetUiXamlMode());
}

private readonly string _assemblyName;
private readonly GeneratorExecutionContext _context;
private bool _flag;
private readonly TypeMapper _typeMapper;

public bool Found() { return _flag; }

Expand Down Expand Up @@ -105,7 +107,7 @@ private void CheckDeclarations()
var props = @class.DescendantNodes().OfType<PropertyDeclarationSyntax>().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)
{
Expand Down Expand Up @@ -137,7 +139,7 @@ private void CheckDeclarations()
var props = @interface.DescendantNodes().OfType<PropertyDeclarationSyntax>().Where(IsPublic);

// filter out methods and properties that will be replaced with our custom type mappings
IgnoreCustomTypeMappings(interfaceSym, ref methods, ref props);
IgnoreCustomTypeMappings(interfaceSym, _typeMapper, ref methods, ref props);

if (interfaceSym.IsGenericType)
{
Expand Down Expand Up @@ -206,6 +208,7 @@ private bool IsMethodImpl(IMethodSymbol m, IMethodSymbol interfaceMethod)
}

private void IgnoreCustomTypeMappings(INamedTypeSymbol typeSymbol,
TypeMapper typeMapper,
ref IEnumerable<MethodDeclarationSyntax> methods,
ref IEnumerable<PropertyDeclarationSyntax> properties)
{
Expand All @@ -217,7 +220,7 @@ string QualifiedName(INamedTypeSymbol sym)
HashSet<ISymbol> classMethods = new();

foreach (var @interface in typeSymbol.AllInterfaces.
Where(symbol => GeneratorHelper.MappedCSharpTypes.ContainsKey(QualifiedName(symbol)) ||
Where(symbol => typeMapper.HasMappingForType(QualifiedName(symbol)) ||
WinRTTypeWriter.ImplementedInterfacesWithoutMapping.Contains(QualifiedName(symbol))))
{
foreach (var interfaceMember in @interface.GetMembers())
Expand Down
6 changes: 5 additions & 1 deletion src/Authoring/WinRT.SourceGenerator/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ public class ComponentGenerator
private Logger Logger { get; }
private readonly GeneratorExecutionContext context;
private string tempFolder;
private readonly TypeMapper mapper;

public ComponentGenerator(GeneratorExecutionContext context)
{
this.context = context;
Logger = new Logger(context);
mapper = new(context.AnalyzerConfigOptions.GlobalOptions.GetUiXamlMode());
// TODO-WuxMux: output a module initializer that validates the MUX/WUX projection mode to ensure that things don't get out of sync.
}

private string GetTempFolder(bool clearSourceFilesFromFolder = false)
Expand Down Expand Up @@ -152,7 +155,8 @@ public void Generate()
assembly,
version,
metadataBuilder,
Logger);
Logger,
mapper);

WinRTSyntaxReceiver syntaxReceiver = (WinRTSyntaxReceiver)context.SyntaxReceiver;
Logger.Log("Found " + syntaxReceiver.Declarations.Count + " types");
Expand Down
82 changes: 11 additions & 71 deletions src/Authoring/WinRT.SourceGenerator/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,21 +177,21 @@ 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)
{
bool isProjectedType = type.GetAttributes().
Any(attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeTypeAttribute") == 0) ||
IsFundamentalType(type);

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(IsWinRTType);
isProjectedType = namedType.TypeArguments.All(type => IsWinRTType(type, mapper));
}
return isProjectedType;
}
Expand Down Expand Up @@ -262,7 +262,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)
{
Expand Down Expand Up @@ -292,9 +292,9 @@ public static bool IsBlittableValueType(ITypeSymbol type)
}

string customTypeMapKey = string.Join(".", type.ContainingNamespace.ToDisplayString(), type.MetadataName);
if (MappedCSharpTypes.ContainsKey(customTypeMapKey))
if (typeMapper.HasMappingForType(customTypeMapKey))
{
return MappedCSharpTypes[customTypeMapKey].IsBlittable();
return typeMapper.GetMappedType(customTypeMapKey).IsBlittable();
}

if (type.TypeKind == TypeKind.Enum)
Expand All @@ -306,7 +306,7 @@ public static bool IsBlittableValueType(ITypeSymbol type)
{
foreach (var typeMember in type.GetMembers())
{
if (typeMember is IFieldSymbol field && !IsBlittableValueType(field.Type))
if (typeMember is IFieldSymbol field && !IsBlittableValueType(field.Type, typeMapper))
{
return false;
}
Expand All @@ -315,7 +315,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))
{
Expand All @@ -335,9 +335,9 @@ public static string GetAbiType(ITypeSymbol type)
if (type.IsValueType)
{
string customTypeMapKey = string.Join(".", type.ContainingNamespace.ToDisplayString(), type.MetadataName);
if (MappedCSharpTypes.ContainsKey(customTypeMapKey))
if (mapper.HasMappingForType(customTypeMapKey))
{
string prefix = MappedCSharpTypes[customTypeMapKey].IsBlittable() ? "" : "ABI.";
string prefix = mapper.GetMappedType(customTypeMapKey).IsBlittable() ? "" : "ABI.";
return prefix + typeStr;
}

Expand All @@ -352,7 +352,7 @@ public static string GetAbiType(ITypeSymbol type)
// Handling authoring scenario where Impl type has the attributes and
// if the current component is the one being authored, it may not be
// generated yet to check given it is the same compilation.
else if (!IsBlittableValueType(type))
else if (!IsBlittableValueType(type, mapper))
{
return "ABI." + typeStr;
}
Expand Down Expand Up @@ -698,65 +698,5 @@ public bool IsBlittable()
return isValueType && isBlittable;
}
}

// Based on whether System.Type is used in an attribute declaration or elsewhere, we need to choose the correct custom mapping
// as attributes don't use the TypeName mapping.
internal static (string, string, string, bool, bool) GetSystemTypeCustomMapping(ISymbol containingSymbol)
{
bool isDefinedInAttribute =
containingSymbol != null &&
string.CompareOrdinal((containingSymbol as INamedTypeSymbol).BaseType?.ToString(), "System.Attribute") == 0;
return isDefinedInAttribute ?
("System", "Type", "mscorlib", true, false) :
("Windows.UI.Xaml.Interop", "TypeName", "Windows.Foundation.UniversalApiContract", false, true);
}

// This should be in sync with the reverse mapping from WinRT.Runtime/Projections.cs and cswinrt/helpers.h.
// TODO-WuxMux: Update this table to respect a property the defines WUX vs MUX projections.
// Additionally, output a module initializer that validates the MUX/WUX projection mode to ensure that things don't get out of sync.
public static readonly Dictionary<string, MappedType> MappedCSharpTypes = new(StringComparer.Ordinal)
{
{ "System.DateTimeOffset", new MappedType("Windows.Foundation", "DateTime", "Windows.Foundation.FoundationContract", true, false) },
{ "System.Exception", new MappedType("Windows.Foundation", "HResult", "Windows.Foundation.FoundationContract", true, false) },
{ "System.EventHandler`1", new MappedType("Windows.Foundation", "EventHandler`1", "Windows.Foundation.FoundationContract") },
{ "System.FlagsAttribute", new MappedType("System", "FlagsAttribute", "mscorlib" ) },
{ "System.IDisposable", new MappedType("Windows.Foundation", "IClosable", "Windows.Foundation.FoundationContract") },
{ "System.IServiceProvider", new MappedType("Microsoft.UI.Xaml", "IXamlServiceProvider", "Microsoft.UI") },
{ "System.Nullable`1", new MappedType("Windows.Foundation", "IReference`1", "Windows.Foundation.FoundationContract" ) },
{ "System.Object", new MappedType("System", "Object", "mscorlib" ) },
{ "System.TimeSpan", new MappedType("Windows.Foundation", "TimeSpan", "Windows.Foundation.FoundationContract", true, false) },
{ "System.Uri", new MappedType("Windows.Foundation", "Uri", "Windows.Foundation.FoundationContract") },
{ "System.ComponentModel.DataErrorsChangedEventArgs", new MappedType("Microsoft.UI.Xaml.Data", "DataErrorsChangedEventArgs", "Microsoft.UI") },
{ "System.ComponentModel.INotifyDataErrorInfo", new MappedType("Microsoft.UI.Xaml.Data", "INotifyDataErrorInfo", "Microsoft.UI") },
{ "System.ComponentModel.INotifyPropertyChanged", new MappedType("Microsoft.UI.Xaml.Data", "INotifyPropertyChanged", "Microsoft.UI") },
{ "System.ComponentModel.PropertyChangedEventArgs", new MappedType("Microsoft.UI.Xaml.Data", "PropertyChangedEventArgs", "Microsoft.UI") },
{ "System.ComponentModel.PropertyChangedEventHandler", new MappedType("Microsoft.UI.Xaml.Data", "PropertyChangedEventHandler", "Microsoft.UI") },
{ "System.Windows.Input.ICommand", new MappedType("Microsoft.UI.Xaml.Input", "ICommand", "Microsoft.UI") },
{ "System.Collections.IEnumerable", new MappedType("Microsoft.UI.Xaml.Interop", "IBindableIterable", "Microsoft.UI") },
{ "System.Collections.IList", new MappedType("Microsoft.UI.Xaml.Interop", "IBindableVector", "Microsoft.UI") },
{ "System.Collections.Specialized.INotifyCollectionChanged", new MappedType("Microsoft.UI.Xaml.Interop", "INotifyCollectionChanged", "Microsoft.UI") },
{ "System.Collections.Specialized.NotifyCollectionChangedAction", new MappedType("Microsoft.UI.Xaml.Interop", "NotifyCollectionChangedAction", "Microsoft.UI") },
{ "System.Collections.Specialized.NotifyCollectionChangedEventArgs", new MappedType("Microsoft.UI.Xaml.Interop", "NotifyCollectionChangedEventArgs", "Microsoft.UI") },
{ "System.Collections.Specialized.NotifyCollectionChangedEventHandler", new MappedType("Microsoft.UI.Xaml.Interop", "NotifyCollectionChangedEventHandler", "Microsoft.UI") },
{ "WinRT.EventRegistrationToken", new MappedType("Windows.Foundation", "EventRegistrationToken", "Windows.Foundation.FoundationContract", true, true) },
{ "System.AttributeTargets", new MappedType("Windows.Foundation.Metadata", "AttributeTargets", "Windows.Foundation.FoundationContract", true, true) },
{ "System.AttributeUsageAttribute", new MappedType("Windows.Foundation.Metadata", "AttributeUsageAttribute", "Windows.Foundation.FoundationContract") },
{ "System.Numerics.Matrix3x2", new MappedType("Windows.Foundation.Numerics", "Matrix3x2", "Windows.Foundation.FoundationContract", true, true) },
{ "System.Numerics.Matrix4x4", new MappedType("Windows.Foundation.Numerics", "Matrix4x4", "Windows.Foundation.FoundationContract", true, true) },
{ "System.Numerics.Plane", new MappedType("Windows.Foundation.Numerics", "Plane", "Windows.Foundation.FoundationContract", true, true) },
{ "System.Numerics.Quaternion", new MappedType("Windows.Foundation.Numerics", "Quaternion", "Windows.Foundation.FoundationContract", true, true) },
{ "System.Numerics.Vector2", new MappedType("Windows.Foundation.Numerics", "Vector2", "Windows.Foundation.FoundationContract", true, true) },
{ "System.Numerics.Vector3", new MappedType("Windows.Foundation.Numerics", "Vector3", "Windows.Foundation.FoundationContract", true, true) },
{ "System.Numerics.Vector4", new MappedType("Windows.Foundation.Numerics", "Vector4", "Windows.Foundation.FoundationContract", true, true) },
{ "System.Type", new MappedType(GetSystemTypeCustomMapping) },
{ "System.Collections.Generic.IEnumerable`1", new MappedType("Windows.Foundation.Collections", "IIterable`1", "Windows.Foundation.FoundationContract") },
{ "System.Collections.Generic.IEnumerator`1", new MappedType("Windows.Foundation.Collections", "IIterator`1", "Windows.Foundation.FoundationContract") },
{ "System.Collections.Generic.KeyValuePair`2", new MappedType("Windows.Foundation.Collections", "IKeyValuePair`2", "Windows.Foundation.FoundationContract") },
{ "System.Collections.Generic.IReadOnlyDictionary`2", new MappedType("Windows.Foundation.Collections", "IMapView`2", "Windows.Foundation.FoundationContract") },
{ "System.Collections.Generic.IDictionary`2", new MappedType("Windows.Foundation.Collections", "IMap`2", "Windows.Foundation.FoundationContract") },
{ "System.Collections.Generic.IReadOnlyList`1", new MappedType("Windows.Foundation.Collections", "IVectorView`1", "Windows.Foundation.FoundationContract") },
{ "System.Collections.Generic.IList`1", new MappedType("Windows.Foundation.Collections", "IVector`1", "Windows.Foundation.FoundationContract") },
{ "Windows.UI.Color", new MappedType("Windows.UI", "Color", "Windows.Foundation.UniversalApiContract", true, true) },
};
}
}
Loading

0 comments on commit 4bb2d41

Please sign in to comment.