From e96072189de27869e544694b73607830befd496d Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Sun, 29 Sep 2024 02:16:13 -0700 Subject: [PATCH 1/7] Try to improve generator performance by checking properties earlier and checking WinRT.Runtime reference --- .../WinRT.SourceGenerator/AotOptimizer.cs | 92 +++++++++++-------- src/Authoring/WinRT.SourceGenerator/Helper.cs | 11 +++ 2 files changed, 63 insertions(+), 40 deletions(-) diff --git a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs index 3f40f9ada..357c460f5 100644 --- a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs +++ b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs @@ -19,8 +19,14 @@ public class WinRTAotSourceGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { - var properties = context.AnalyzerConfigOptionsProvider.Select(static (provider, _) => - (provider.IsCsWinRTAotOptimizerEnabled(), provider.IsCsWinRTComponent(), provider.IsCsWinRTCcwLookupTableGeneratorEnabled())); + var analyzerConfigProperties = context.AnalyzerConfigOptionsProvider.Select(static (provider, _) => + (provider.IsCsWinRTAotOptimizerEnabled(), provider.IsCsWinRTComponent(), provider.IsCsWinRTCcwLookupTableGeneratorEnabled(), provider.IsCsWinRTAotOptimizerEnabledForBuiltInInterfaces())); + + var hasWinRTRuntimeReference = context.CompilationProvider.Select(static (compilation, ct) => GeneratorHelper.HasWinRTRuntimeReference(compilation, ct)); + + var properties = analyzerConfigProperties.Combine(hasWinRTRuntimeReference).Select( + static (((bool isCsWinRTAotOptimizerEnabled, bool, bool, bool isCsWinRTAotOptimizerEnabledForBuiltInInterfaces) properties, bool hasWinRTRuntimeReference) value, CancellationToken _) => + (value.properties.isCsWinRTAotOptimizerEnabled && (value.hasWinRTRuntimeReference || value.properties.isCsWinRTAotOptimizerEnabledForBuiltInInterfaces), value.properties.Item2, value.properties.Item3)); var assemblyName = context.CompilationProvider.Select(static (compilation, _) => GeneratorHelper.EscapeTypeNameForIdentifier(compilation.AssemblyName)); @@ -32,7 +38,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context) static (n, _) => NeedVtableAttribute(n), static (n, _) => n) .Combine(typeMapper) - .Select((t, _) => GetVtableAttributeToAdd(t.Left, t.Right, false)) + .Combine(properties) + .Select(static (((GeneratorSyntaxContext generatorSyntaxContext, TypeMapper typeMapper) left, (bool isCsWinRTAotOptimizerEnabled, bool, bool isCsWinRTCcwLookupTableGeneratorEnabled) properties) value, CancellationToken _) => + value.properties.isCsWinRTAotOptimizerEnabled ? + GetVtableAttributeToAdd(value.left.generatorSyntaxContext, value.left.typeMapper, false, value.properties.isCsWinRTCcwLookupTableGeneratorEnabled) : default) .Where(static vtableAttribute => vtableAttribute != default); var vtableAttributesToAdd = vtablesToAddFromClassTypes.Select(static (vtable, _) => vtable.Item1); @@ -46,22 +55,23 @@ public void Initialize(IncrementalGeneratorInitializationContext context) static (n, _) => IsComponentType(n), 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); + // Get component types if only authoring scenario and if aot optimizer enabled. + .Select(static (((GeneratorSyntaxContext generatorSyntaxContext, TypeMapper typeMapper) left, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool) properties) value, CancellationToken _) => + value.properties.isCsWinRTAotOptimizerEnabled && value.properties.isCsWinRTComponent ? + GetVtableAttributeToAdd(value.left.generatorSyntaxContext, value.left.typeMapper, true, true) : default) + .Where(static vtableAttribute => vtableAttribute != default); var instantiatedTypesToAddOnLookupTable = context.SyntaxProvider.CreateSyntaxProvider( static (n, _) => NeedVtableOnLookupTable(n), 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) + .Select(static (((GeneratorSyntaxContext generatorSyntaxContext, TypeMapper typeMapper) left, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool isCsWinRTCcwLookupTableGeneratorEnabled) properties) value, + CancellationToken _) => + value.properties.isCsWinRTAotOptimizerEnabled && value.properties.isCsWinRTCcwLookupTableGeneratorEnabled ? + GetVtableAttributesToAddOnLookupTable(value.left.generatorSyntaxContext, value.left.typeMapper, value.properties.isCsWinRTComponent) : + (EquatableArray)ImmutableArray.Empty) .SelectMany(static (vtable, _) => vtable) .Where(static vtableAttribute => vtableAttribute != null); @@ -69,14 +79,13 @@ public void Initialize(IncrementalGeneratorInitializationContext context) static (n, _) => IsAsyncOperationMethodCall(n), 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(); + .Select(static (((GeneratorSyntaxContext generatorSyntaxContext, TypeMapper typeMapper) left, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool isCsWinRTCcwLookupTableGeneratorEnabled) properties) value, + CancellationToken _) => + value.properties.isCsWinRTAotOptimizerEnabled && value.properties.isCsWinRTCcwLookupTableGeneratorEnabled ? + GetVtableAttributesForTaskAdapters(value.left.generatorSyntaxContext, value.left.typeMapper, value.properties.isCsWinRTComponent) : default) + .Where(static vtableAttribute => vtableAttribute != default) + .Collect(); // Merge both adapter types list and instantiated types list var vtablesToAddOnLookupTable = @@ -109,7 +118,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var bindableCustomPropertyAttributes = context.SyntaxProvider.CreateSyntaxProvider( static (n, _) => NeedCustomPropertyImplementation(n), static (n, _) => n) - .Select((data, _) => GetBindableCustomProperties(data)) + .Combine(properties) + .Select(static ((GeneratorSyntaxContext generatorSyntaxContext, (bool isCsWinRTAotOptimizerEnabled, bool, bool) properties) value, CancellationToken _) => + value.properties.isCsWinRTAotOptimizerEnabled ? GetBindableCustomProperties(value.generatorSyntaxContext) : default) .Where(static bindableCustomProperties => bindableCustomProperties != default) .Collect() .Combine(properties); @@ -147,7 +158,8 @@ private static bool NeedCustomPropertyImplementation(SyntaxNode node) private static (VtableAttribute, EquatableArray) GetVtableAttributeToAdd( GeneratorSyntaxContext context, TypeMapper typeMapper, - bool checkForComponentTypes) + bool checkForComponentTypes, + bool isCsWinRTCcwLookupTableGeneratorEnabled) { var isWinRTTypeFunc = checkForComponentTypes ? GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation) : @@ -159,7 +171,10 @@ private static (VtableAttribute, EquatableArray) GetVtableAttri 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, typeMapper, vtableAttributesForLookupTable); + if (isCsWinRTCcwLookupTableGeneratorEnabled) + { + AddVtableAdapterTypeForKnownInterface(symbol, context.SemanticModel.Compilation, isWinRTTypeFunc, typeMapper, vtableAttributesForLookupTable); + } return (vtableAttribute, vtableAttributesForLookupTable.ToImmutableArray()); } @@ -204,7 +219,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, TypeMapper typeMapper) + private static VtableAttribute GetVtableAttributesForTaskAdapters(GeneratorSyntaxContext context, TypeMapper typeMapper, bool isCsWinRTComponent) { // Generic instantiation of task adapters make of use of unsafe. // This will be caught by GetVtableAttributeToAdd, but catching it early here too. @@ -222,8 +237,12 @@ private static (VtableAttribute, VtableAttribute) GetVtableAttributesForTaskAdap if (adpaterType is not null) { var constructedAdapterType = adpaterType.Construct([.. symbol.TypeArguments]); - return (GetVtableAttributeToAdd(constructedAdapterType, GeneratorHelper.IsWinRTType, typeMapper, context.SemanticModel.Compilation, false), - GetVtableAttributeToAdd(constructedAdapterType, GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation), typeMapper, context.SemanticModel.Compilation, false)); + return GetVtableAttributeToAdd( + constructedAdapterType, + !isCsWinRTComponent ? GeneratorHelper.IsWinRTType : GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation), + typeMapper, + context.SemanticModel.Compilation, + false); } } } @@ -1030,23 +1049,16 @@ node is PropertyDeclarationSyntax || node is ReturnStatementSyntax; } - private static (EquatableArray, EquatableArray) GetVtableAttributesToAddOnLookupTable( + private static EquatableArray GetVtableAttributesToAddOnLookupTable( GeneratorSyntaxContext context, - TypeMapper typeMapper) + TypeMapper typeMapper, + bool isCsWinRTComponent) { - // 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, - typeMapper, - GeneratorHelper.IsWinRTType, - GeneratorHelper.IsWinRTClass(context.SemanticModel.Compilation)), - GetVtableAttributesToAddOnLookupTable( - context, - typeMapper, - GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation), - GeneratorHelper.IsWinRTClass(context.SemanticModel.Compilation))); + return GetVtableAttributesToAddOnLookupTable( + context, + typeMapper, + !isCsWinRTComponent ? GeneratorHelper.IsWinRTType : GeneratorHelper.IsWinRTTypeWithPotentialAuthoringComponentTypesFunc(context.SemanticModel.Compilation), + GeneratorHelper.IsWinRTClass(context.SemanticModel.Compilation)); } private static EquatableArray GetVtableAttributesToAddOnLookupTable( diff --git a/src/Authoring/WinRT.SourceGenerator/Helper.cs b/src/Authoring/WinRT.SourceGenerator/Helper.cs index 459de7cab..b3c255f46 100644 --- a/src/Authoring/WinRT.SourceGenerator/Helper.cs +++ b/src/Authoring/WinRT.SourceGenerator/Helper.cs @@ -11,6 +11,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; +using System.Threading; namespace Generator { @@ -174,6 +175,11 @@ public static int GetCsWinRTAotWarningLevel(this AnalyzerConfigOptionsProvider p return 0; } + public static bool IsCsWinRTAotOptimizerEnabledForBuiltInInterfaces(this AnalyzerConfigOptionsProvider provider) + { + return GetCsWinRTAotWarningLevel(provider) == 2; + } + public static bool ShouldGenerateWinMDOnly(this GeneratorExecutionContext context) { if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTGenerateWinMDOnly", out var CsWinRTGenerateWinMDOnlyStr)) @@ -1122,5 +1128,10 @@ public static string GetTaskAdapterIfAsyncMethod(IMethodSymbol symbol) return null; } + + public static bool HasWinRTRuntimeReference(Compilation compilation, CancellationToken ct) + { + return compilation.GetUsedAssemblyReferences(ct).Any(reference => compilation.GetAssemblyOrModuleSymbol(reference).Name == "WinRT.Runtime"); + } } } \ No newline at end of file From a6a9b30bcb303ca367d5853e30f0c6cd7ece83a3 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Sun, 29 Sep 2024 17:31:27 -0700 Subject: [PATCH 2/7] Handle embedded support --- nuget/Microsoft.Windows.CsWinRT.targets | 1 + .../WinRT.SourceGenerator/AotOptimizer.cs | 30 ++++++++++++++----- src/Authoring/WinRT.SourceGenerator/Helper.cs | 13 +++++++- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets index bc2cabaac..a1aa7d766 100644 --- a/nuget/Microsoft.Windows.CsWinRT.targets +++ b/nuget/Microsoft.Windows.CsWinRT.targets @@ -53,6 +53,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. + diff --git a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs index 357c460f5..95810d0c3 100644 --- a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs +++ b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs @@ -19,14 +19,28 @@ public class WinRTAotSourceGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { - var analyzerConfigProperties = context.AnalyzerConfigOptionsProvider.Select(static (provider, _) => - (provider.IsCsWinRTAotOptimizerEnabled(), provider.IsCsWinRTComponent(), provider.IsCsWinRTCcwLookupTableGeneratorEnabled(), provider.IsCsWinRTAotOptimizerEnabledForBuiltInInterfaces())); - - var hasWinRTRuntimeReference = context.CompilationProvider.Select(static (compilation, ct) => GeneratorHelper.HasWinRTRuntimeReference(compilation, ct)); - - var properties = analyzerConfigProperties.Combine(hasWinRTRuntimeReference).Select( - static (((bool isCsWinRTAotOptimizerEnabled, bool, bool, bool isCsWinRTAotOptimizerEnabledForBuiltInInterfaces) properties, bool hasWinRTRuntimeReference) value, CancellationToken _) => - (value.properties.isCsWinRTAotOptimizerEnabled && (value.hasWinRTRuntimeReference || value.properties.isCsWinRTAotOptimizerEnabledForBuiltInInterfaces), value.properties.Item2, value.properties.Item3)); + var analyzerConfigProperties = context.AnalyzerConfigOptionsProvider.Select(static (provider, _) => ( + provider.IsCsWinRTAotOptimizerEnabled(), + provider.IsCsWinRTComponent(), + provider.IsCsWinRTCcwLookupTableGeneratorEnabled(), + provider.IsCsWinRTAotOptimizerEnabledForBuiltInInterfaces(), + provider.IsCsWinRTEmbeddedSupport()) + ); + + var properties = context.CompilationProvider.Combine(analyzerConfigProperties). + Select(static ((Compilation compilation, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool, bool isCsWinRTAotOptimizerEnabledForBuiltInInterfaces, bool isCsWinRTEmbeddedSupport) properties) value, CancellationToken ct) => + // Enable the optimizer if the optimizer property is set and we would have a WinRT.Runtime reference. + // There are a couple scenarios where we might not detect a WinRT.Runtime reference which we explicitly + // check for such as component support where the generator introduces the reference and embedded support. + // We will allow for an override for this by detecting whether CsWinRTAotWarningLevel is set to 2 which + // indicates the component cares about optimization for built-in interfaces. + (value.properties.isCsWinRTAotOptimizerEnabled && + (value.properties.isCsWinRTComponent || + value.properties.isCsWinRTAotOptimizerEnabledForBuiltInInterfaces || + value.properties.isCsWinRTEmbeddedSupport || + GeneratorHelper.HasWinRTRuntimeReference(value.compilation, ct)), + value.properties.isCsWinRTComponent, + value.properties.Item3)); var assemblyName = context.CompilationProvider.Select(static (compilation, _) => GeneratorHelper.EscapeTypeNameForIdentifier(compilation.AssemblyName)); diff --git a/src/Authoring/WinRT.SourceGenerator/Helper.cs b/src/Authoring/WinRT.SourceGenerator/Helper.cs index b3c255f46..2680f764b 100644 --- a/src/Authoring/WinRT.SourceGenerator/Helper.cs +++ b/src/Authoring/WinRT.SourceGenerator/Helper.cs @@ -104,6 +104,16 @@ public static bool IsCsWinRTComponent(this AnalyzerConfigOptionsProvider provide return false; } + public static bool IsCsWinRTEmbeddedSupport(this AnalyzerConfigOptionsProvider provider) + { + if (provider.GlobalOptions.TryGetValue("build_property.CsWinRTEmbedded", out var isCsWinRTEmbeddedStr)) + { + return bool.TryParse(isCsWinRTEmbeddedStr, out var isCsWinRTEmbedded) && isCsWinRTEmbedded; + } + + return false; + } + public static bool IsCsWinRTAotOptimizerEnabled(this AnalyzerConfigOptionsProvider provider) { if (provider.GlobalOptions.TryGetValue("build_property.CsWinRTAotOptimizerEnabled", out var isCsWinRTAotOptimizerEnabledStr)) @@ -1131,7 +1141,8 @@ public static string GetTaskAdapterIfAsyncMethod(IMethodSymbol symbol) public static bool HasWinRTRuntimeReference(Compilation compilation, CancellationToken ct) { - return compilation.GetUsedAssemblyReferences(ct).Any(reference => compilation.GetAssemblyOrModuleSymbol(reference).Name == "WinRT.Runtime"); + return compilation.GetUsedAssemblyReferences(ct).Any(reference => + string.Equals(compilation.GetAssemblyOrModuleSymbol(reference)?.Name, "WinRT.Runtime", StringComparison.OrdinalIgnoreCase)); } } } \ No newline at end of file From f9fba94903d04763dd3d02b92b9ff25e88a623aa Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Sun, 29 Sep 2024 18:15:23 -0700 Subject: [PATCH 3/7] Scope to when lookup generation is enabled --- src/Authoring/WinRT.SourceGenerator/WinRTAotCodeFixer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Authoring/WinRT.SourceGenerator/WinRTAotCodeFixer.cs b/src/Authoring/WinRT.SourceGenerator/WinRTAotCodeFixer.cs index 2a2ad6a5c..030c41c11 100644 --- a/src/Authoring/WinRT.SourceGenerator/WinRTAotCodeFixer.cs +++ b/src/Authoring/WinRT.SourceGenerator/WinRTAotCodeFixer.cs @@ -57,6 +57,7 @@ public override void Initialize(AnalysisContext context) var typeMapper = new TypeMapper(context.Options.AnalyzerConfigOptionsProvider.GetCsWinRTUseWindowsUIXamlProjections()); var csWinRTAotWarningLevel = context.Options.AnalyzerConfigOptionsProvider.GetCsWinRTAotWarningLevel(); var allowUnsafe = GeneratorHelper.AllowUnsafe(context.Compilation); + var isCsWinRTCcwLookupTableGeneratorEnabled = context.Options.AnalyzerConfigOptionsProvider.IsCsWinRTCcwLookupTableGeneratorEnabled(); context.RegisterSymbolAction(context => { @@ -127,7 +128,7 @@ public override void Initialize(AnalysisContext context) } }, SymbolKind.NamedType); - if (!allowUnsafe) + if (!allowUnsafe && isCsWinRTCcwLookupTableGeneratorEnabled) { context.RegisterSyntaxNodeAction(context => { From b2cae3ea9a217bc9c9b3adc415e3e42361f75cb1 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Mon, 7 Oct 2024 23:41:59 -0700 Subject: [PATCH 4/7] Undo check for WinRT.Runtime reference --- nuget/Microsoft.Windows.CsWinRT.targets | 1 - .../WinRT.SourceGenerator/AotOptimizer.cs | 21 ++----------------- src/Authoring/WinRT.SourceGenerator/Helper.cs | 21 ------------------- 3 files changed, 2 insertions(+), 41 deletions(-) diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets index a1aa7d766..bc2cabaac 100644 --- a/nuget/Microsoft.Windows.CsWinRT.targets +++ b/nuget/Microsoft.Windows.CsWinRT.targets @@ -53,7 +53,6 @@ Copyright (C) Microsoft Corporation. All rights reserved. - diff --git a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs index 95810d0c3..6a4ee332c 100644 --- a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs +++ b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs @@ -19,29 +19,12 @@ public class WinRTAotSourceGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { - var analyzerConfigProperties = context.AnalyzerConfigOptionsProvider.Select(static (provider, _) => ( + var properties = context.AnalyzerConfigOptionsProvider.Select(static (provider, _) => ( provider.IsCsWinRTAotOptimizerEnabled(), provider.IsCsWinRTComponent(), - provider.IsCsWinRTCcwLookupTableGeneratorEnabled(), - provider.IsCsWinRTAotOptimizerEnabledForBuiltInInterfaces(), - provider.IsCsWinRTEmbeddedSupport()) + provider.IsCsWinRTCcwLookupTableGeneratorEnabled()) ); - var properties = context.CompilationProvider.Combine(analyzerConfigProperties). - Select(static ((Compilation compilation, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool, bool isCsWinRTAotOptimizerEnabledForBuiltInInterfaces, bool isCsWinRTEmbeddedSupport) properties) value, CancellationToken ct) => - // Enable the optimizer if the optimizer property is set and we would have a WinRT.Runtime reference. - // There are a couple scenarios where we might not detect a WinRT.Runtime reference which we explicitly - // check for such as component support where the generator introduces the reference and embedded support. - // We will allow for an override for this by detecting whether CsWinRTAotWarningLevel is set to 2 which - // indicates the component cares about optimization for built-in interfaces. - (value.properties.isCsWinRTAotOptimizerEnabled && - (value.properties.isCsWinRTComponent || - value.properties.isCsWinRTAotOptimizerEnabledForBuiltInInterfaces || - value.properties.isCsWinRTEmbeddedSupport || - GeneratorHelper.HasWinRTRuntimeReference(value.compilation, ct)), - value.properties.isCsWinRTComponent, - value.properties.Item3)); - var assemblyName = context.CompilationProvider.Select(static (compilation, _) => GeneratorHelper.EscapeTypeNameForIdentifier(compilation.AssemblyName)); var propertiesAndAssemblyName = properties.Combine(assemblyName); diff --git a/src/Authoring/WinRT.SourceGenerator/Helper.cs b/src/Authoring/WinRT.SourceGenerator/Helper.cs index 19a0c9395..85d211ee1 100644 --- a/src/Authoring/WinRT.SourceGenerator/Helper.cs +++ b/src/Authoring/WinRT.SourceGenerator/Helper.cs @@ -104,16 +104,6 @@ public static bool IsCsWinRTComponent(this AnalyzerConfigOptionsProvider provide return false; } - public static bool IsCsWinRTEmbeddedSupport(this AnalyzerConfigOptionsProvider provider) - { - if (provider.GlobalOptions.TryGetValue("build_property.CsWinRTEmbedded", out var isCsWinRTEmbeddedStr)) - { - return bool.TryParse(isCsWinRTEmbeddedStr, out var isCsWinRTEmbedded) && isCsWinRTEmbedded; - } - - return false; - } - public static bool IsCsWinRTAotOptimizerEnabled(this AnalyzerConfigOptionsProvider provider) { if (provider.GlobalOptions.TryGetValue("build_property.CsWinRTAotOptimizerEnabled", out var isCsWinRTAotOptimizerEnabledStr)) @@ -185,11 +175,6 @@ public static int GetCsWinRTAotWarningLevel(this AnalyzerConfigOptionsProvider p return 0; } - public static bool IsCsWinRTAotOptimizerEnabledForBuiltInInterfaces(this AnalyzerConfigOptionsProvider provider) - { - return GetCsWinRTAotWarningLevel(provider) == 2; - } - public static bool ShouldGenerateWinMDOnly(this GeneratorExecutionContext context) { if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTGenerateWinMDOnly", out var CsWinRTGenerateWinMDOnlyStr)) @@ -1138,11 +1123,5 @@ public static string GetTaskAdapterIfAsyncMethod(IMethodSymbol symbol) return null; } - - public static bool HasWinRTRuntimeReference(Compilation compilation, CancellationToken ct) - { - return compilation.GetUsedAssemblyReferences(ct).Any(reference => - string.Equals(compilation.GetAssemblyOrModuleSymbol(reference)?.Name, "WinRT.Runtime", StringComparison.OrdinalIgnoreCase)); - } } } \ No newline at end of file From c3e52eae2c0da13797a150d304b240ca3e5ba0f5 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Tue, 8 Oct 2024 00:29:08 -0700 Subject: [PATCH 5/7] Minor reordering update to improve caching potentially and static --- .../WinRT.SourceGenerator/AotOptimizer.cs | 61 +++++++++---------- src/Authoring/WinRT.SourceGenerator/Helper.cs | 16 ++--- 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs index 6a4ee332c..d23359634 100644 --- a/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs +++ b/src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs @@ -29,16 +29,18 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var propertiesAndAssemblyName = properties.Combine(assemblyName); - var typeMapper = context.AnalyzerConfigOptionsProvider.Select((options, ct) => options.GetCsWinRTUseWindowsUIXamlProjections()).Select((mode, ct) => new TypeMapper(mode)); + var typeMapperAndProperties = context.AnalyzerConfigOptionsProvider + .Select(static (options, ct) => options.GetCsWinRTUseWindowsUIXamlProjections()) + .Select(static (mode, ct) => new TypeMapper(mode)) + .Combine(properties); var vtablesToAddFromClassTypes = context.SyntaxProvider.CreateSyntaxProvider( static (n, _) => NeedVtableAttribute(n), static (n, _) => n) - .Combine(typeMapper) - .Combine(properties) - .Select(static (((GeneratorSyntaxContext generatorSyntaxContext, TypeMapper typeMapper) left, (bool isCsWinRTAotOptimizerEnabled, bool, bool isCsWinRTCcwLookupTableGeneratorEnabled) properties) value, CancellationToken _) => - value.properties.isCsWinRTAotOptimizerEnabled ? - GetVtableAttributeToAdd(value.left.generatorSyntaxContext, value.left.typeMapper, false, value.properties.isCsWinRTCcwLookupTableGeneratorEnabled) : default) + .Combine(typeMapperAndProperties) + .Select(static ((GeneratorSyntaxContext generatorSyntaxContext, (TypeMapper typeMapper, (bool isCsWinRTAotOptimizerEnabled, bool, bool isCsWinRTCcwLookupTableGeneratorEnabled) properties) typeMapperAndProperties) value, CancellationToken _) => + value.typeMapperAndProperties.properties.isCsWinRTAotOptimizerEnabled ? + GetVtableAttributeToAdd(value.generatorSyntaxContext, value.typeMapperAndProperties.typeMapper, false, value.typeMapperAndProperties.properties.isCsWinRTCcwLookupTableGeneratorEnabled) : default) .Where(static vtableAttribute => vtableAttribute != default); var vtableAttributesToAdd = vtablesToAddFromClassTypes.Select(static (vtable, _) => vtable.Item1); @@ -51,23 +53,21 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var vtablesFromComponentTypes = context.SyntaxProvider.CreateSyntaxProvider( static (n, _) => IsComponentType(n), static (n, _) => n) - .Combine(typeMapper) - .Combine(properties) + .Combine(typeMapperAndProperties) // Get component types if only authoring scenario and if aot optimizer enabled. - .Select(static (((GeneratorSyntaxContext generatorSyntaxContext, TypeMapper typeMapper) left, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool) properties) value, CancellationToken _) => - value.properties.isCsWinRTAotOptimizerEnabled && value.properties.isCsWinRTComponent ? - GetVtableAttributeToAdd(value.left.generatorSyntaxContext, value.left.typeMapper, true, true) : default) + .Select(static ((GeneratorSyntaxContext generatorSyntaxContext, (TypeMapper typeMapper, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool) properties) typeMapperAndProperties) value, CancellationToken _) => + value.typeMapperAndProperties.properties.isCsWinRTAotOptimizerEnabled && value.typeMapperAndProperties.properties.isCsWinRTComponent ? + GetVtableAttributeToAdd(value.generatorSyntaxContext, value.typeMapperAndProperties.typeMapper, true, true) : default) .Where(static vtableAttribute => vtableAttribute != default); var instantiatedTypesToAddOnLookupTable = context.SyntaxProvider.CreateSyntaxProvider( static (n, _) => NeedVtableOnLookupTable(n), static (n, _) => n) - .Combine(typeMapper) - .Combine(properties) - .Select(static (((GeneratorSyntaxContext generatorSyntaxContext, TypeMapper typeMapper) left, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool isCsWinRTCcwLookupTableGeneratorEnabled) properties) value, + .Combine(typeMapperAndProperties) + .Select(static ((GeneratorSyntaxContext generatorSyntaxContext, (TypeMapper typeMapper, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool isCsWinRTCcwLookupTableGeneratorEnabled) properties) typeMapperAndProperties) value, CancellationToken _) => - value.properties.isCsWinRTAotOptimizerEnabled && value.properties.isCsWinRTCcwLookupTableGeneratorEnabled ? - GetVtableAttributesToAddOnLookupTable(value.left.generatorSyntaxContext, value.left.typeMapper, value.properties.isCsWinRTComponent) : + value.typeMapperAndProperties.properties.isCsWinRTAotOptimizerEnabled && value.typeMapperAndProperties.properties.isCsWinRTCcwLookupTableGeneratorEnabled ? + GetVtableAttributesToAddOnLookupTable(value.generatorSyntaxContext, value.typeMapperAndProperties.typeMapper, value.typeMapperAndProperties.properties.isCsWinRTComponent) : (EquatableArray)ImmutableArray.Empty) .SelectMany(static (vtable, _) => vtable) .Where(static vtableAttribute => vtableAttribute != null); @@ -75,12 +75,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var instantiatedTaskAdapters = context.SyntaxProvider.CreateSyntaxProvider( static (n, _) => IsAsyncOperationMethodCall(n), static (n, _) => n) - .Combine(typeMapper) - .Combine(properties) - .Select(static (((GeneratorSyntaxContext generatorSyntaxContext, TypeMapper typeMapper) left, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool isCsWinRTCcwLookupTableGeneratorEnabled) properties) value, + .Combine(typeMapperAndProperties) + .Select(static ((GeneratorSyntaxContext generatorSyntaxContext, (TypeMapper typeMapper, (bool isCsWinRTAotOptimizerEnabled, bool isCsWinRTComponent, bool isCsWinRTCcwLookupTableGeneratorEnabled) properties) typeMapperAndProperties) value, CancellationToken _) => - value.properties.isCsWinRTAotOptimizerEnabled && value.properties.isCsWinRTCcwLookupTableGeneratorEnabled ? - GetVtableAttributesForTaskAdapters(value.left.generatorSyntaxContext, value.left.typeMapper, value.properties.isCsWinRTComponent) : default) + value.typeMapperAndProperties.properties.isCsWinRTAotOptimizerEnabled && value.typeMapperAndProperties.properties.isCsWinRTCcwLookupTableGeneratorEnabled ? + GetVtableAttributesForTaskAdapters(value.generatorSyntaxContext, value.typeMapperAndProperties.typeMapper, value.typeMapperAndProperties.properties.isCsWinRTComponent) : default) .Where(static vtableAttribute => vtableAttribute != default) .Collect(); @@ -129,7 +128,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) private static bool NeedVtableAttribute(SyntaxNode node) { return node is ClassDeclarationSyntax declaration && - !declaration.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword) || m.IsKind(SyntaxKind.AbstractKeyword)) && + !declaration.Modifiers.Any(static m => m.IsKind(SyntaxKind.StaticKeyword) || m.IsKind(SyntaxKind.AbstractKeyword)) && GeneratorHelper.IsPartial(declaration) && !GeneratorHelper.IsWinRTType(declaration); // Making sure it isn't an RCW we are projecting. } @@ -139,15 +138,15 @@ private static bool NeedVtableAttribute(SyntaxNode node) private static bool IsComponentType(SyntaxNode node) { return node is ClassDeclarationSyntax declaration && - !declaration.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword) || m.IsKind(SyntaxKind.AbstractKeyword)) && - declaration.Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword)) && + !declaration.Modifiers.Any(static m => m.IsKind(SyntaxKind.StaticKeyword) || m.IsKind(SyntaxKind.AbstractKeyword)) && + declaration.Modifiers.Any(static m => m.IsKind(SyntaxKind.PublicKeyword)) && !GeneratorHelper.IsWinRTType(declaration); // Making sure it isn't an RCW we are projecting. } private static bool NeedCustomPropertyImplementation(SyntaxNode node) { return node is ClassDeclarationSyntax declaration && - !declaration.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword) || m.IsKind(SyntaxKind.AbstractKeyword)) && + !declaration.Modifiers.Any(static m => m.IsKind(SyntaxKind.StaticKeyword) || m.IsKind(SyntaxKind.AbstractKeyword)) && GeneratorHelper.IsPartial(declaration) && GeneratorHelper.HasBindableCustomPropertyAttribute(declaration); } @@ -267,8 +266,8 @@ private static BindableCustomProperties GetBindableCustomProperties(GeneratorSyn for (var curSymbol = symbol; curSymbol != null; curSymbol = curSymbol.BaseType) { foreach (var propertySymbol in curSymbol.GetMembers(). - Where(m => m.Kind == SymbolKind.Property && - m.DeclaredAccessibility == Accessibility.Public)) + Where(static m => m.Kind == SymbolKind.Property && + m.DeclaredAccessibility == Accessibility.Public)) { AddProperty(propertySymbol); } @@ -1414,7 +1413,7 @@ internal static void GenerateVtableLookupTable( // // Note: just like with the authoring metadata function, we don't use a method group expression but rather construct a 'Func' ourselves. // This is done to opt-out of the implicit caching that Roslyn does. We don't need that extra code and overhead, as this is only done once. - var hasRuntimeClasNameEntries = value.vtableAttributes.Any(v => !string.IsNullOrEmpty(v.RuntimeClassName)); + var hasRuntimeClasNameEntries = value.vtableAttributes.Any(static v => !string.IsNullOrEmpty(v.RuntimeClassName)); if (value.vtableAttributes.Any()) { source.AppendLine($$""" @@ -1466,7 +1465,7 @@ private static string LookupRuntimeClassName(Type type) string typeName = type.ToString(); """); - foreach (var vtableAttribute in value.vtableAttributes.ToImmutableHashSet().Where(v => !string.IsNullOrEmpty(v.RuntimeClassName))) + foreach (var vtableAttribute in value.vtableAttributes.ToImmutableHashSet().Where(static v => !string.IsNullOrEmpty(v.RuntimeClassName))) { source.AppendLine($$""" if (typeName == "{{vtableAttribute.VtableLookupClassName}}") @@ -1530,7 +1529,7 @@ partial class {{(classHierarchy.IsEmpty ? bindableCustomProperties.ClassName : c { """); - foreach (var property in bindableCustomProperties.Properties.Where(p => !p.IsIndexer)) + foreach (var property in bindableCustomProperties.Properties.Where(static p => !p.IsIndexer)) { var instanceAccessor = property.IsStatic ? bindableCustomProperties.QualifiedClassName : $$"""(({{bindableCustomProperties.QualifiedClassName}})instance)"""; @@ -1558,7 +1557,7 @@ partial class {{(classHierarchy.IsEmpty ? bindableCustomProperties.ClassName : c { """); - foreach (var property in bindableCustomProperties.Properties.Where(p => p.IsIndexer)) + foreach (var property in bindableCustomProperties.Properties.Where(static p => p.IsIndexer)) { var instanceAccessor = property.IsStatic ? bindableCustomProperties.QualifiedClassName : $$"""(({{bindableCustomProperties.QualifiedClassName}})instance)"""; diff --git a/src/Authoring/WinRT.SourceGenerator/Helper.cs b/src/Authoring/WinRT.SourceGenerator/Helper.cs index 85d211ee1..43ac2a148 100644 --- a/src/Authoring/WinRT.SourceGenerator/Helper.cs +++ b/src/Authoring/WinRT.SourceGenerator/Helper.cs @@ -327,7 +327,7 @@ public static bool IsWinRTType(ISymbol type, TypeMapper mapper) public static bool IsWinRTType(ISymbol type, Func isAuthoringWinRTType, TypeMapper mapper) { bool isProjectedType = type.GetAttributes(). - Any(attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeTypeAttribute") == 0) || + Any(static attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeTypeAttribute") == 0) || IsFundamentalType(type); if (!isProjectedType & type.ContainingNamespace != null) @@ -493,7 +493,7 @@ public static bool IsPartial(INamedTypeSymbol symbol) for (ITypeSymbol parent = symbol; parent is not null; parent = parent.ContainingType) { isPartial &= parent.DeclaringSyntaxReferences.Any( - syntax => syntax.GetSyntax() is BaseTypeDeclarationSyntax declaration && + static syntax => syntax.GetSyntax() is BaseTypeDeclarationSyntax declaration && declaration.Modifiers.Any(SyntaxKind.PartialKeyword)); } return isPartial; @@ -513,13 +513,13 @@ public static bool HasPrivateclass(ITypeSymbol symbol) { return symbol is INamedTypeSymbol namedType && (namedType.DeclaredAccessibility == Accessibility.Private || - namedType.TypeArguments.Any(argument => argument.DeclaredAccessibility == Accessibility.Private)); + namedType.TypeArguments.Any(static argument => argument.DeclaredAccessibility == Accessibility.Private)); } public static bool HasWinRTExposedTypeAttribute(ISymbol type) { return type.GetAttributes(). - Any(attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WinRTExposedTypeAttribute") == 0); + Any(static attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WinRTExposedTypeAttribute") == 0); } public static bool HasWinRTRuntimeClassNameAttribute(ISymbol type, Compilation compilation) @@ -535,14 +535,14 @@ public static bool HasWinRTRuntimeClassNameAttribute(ISymbol type, Compilation c public static bool IsWinRTType(MemberDeclarationSyntax node) { - bool isProjectedType = node.AttributeLists.SelectMany(list => list.Attributes). - Any(attribute => string.CompareOrdinal(attribute.Name.NormalizeWhitespace().ToFullString(), "global::WinRT.WindowsRuntimeType") == 0); + bool isProjectedType = node.AttributeLists.SelectMany(static list => list.Attributes). + Any(static attribute => string.CompareOrdinal(attribute.Name.NormalizeWhitespace().ToFullString(), "global::WinRT.WindowsRuntimeType") == 0); return isProjectedType; } public static bool HasBindableCustomPropertyAttribute(MemberDeclarationSyntax node) { - return node.AttributeLists.SelectMany(list => list.Attributes).Any(IsBindableCustomPropertyAttribute); + return node.AttributeLists.SelectMany(static list => list.Attributes).Any(IsBindableCustomPropertyAttribute); // Check based on identifier name if this is the GeneratedBindableCustomProperty attribute. // Technically this can be a different namespace, but we will confirm later once @@ -713,7 +713,7 @@ public static string GetAbiType(ITypeSymbol type, TypeMapper mapper) if (!IsBlittableValueType(type, mapper)) { var winrtHelperAttribute = type.GetAttributes(). - Where(attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeHelperTypeAttribute") == 0). + Where(static attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeHelperTypeAttribute") == 0). FirstOrDefault(); if (winrtHelperAttribute != null && winrtHelperAttribute.ConstructorArguments.Any()) From 2151bec6f8e974d3a16a01a2ba43c1afbc92aed2 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Tue, 8 Oct 2024 00:36:41 -0700 Subject: [PATCH 6/7] Add missed file --- .../WinRT.SourceGenerator/GenericVtableInitializerStrings.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Authoring/WinRT.SourceGenerator/GenericVtableInitializerStrings.cs b/src/Authoring/WinRT.SourceGenerator/GenericVtableInitializerStrings.cs index 7d23d8401..e703ee909 100644 --- a/src/Authoring/WinRT.SourceGenerator/GenericVtableInitializerStrings.cs +++ b/src/Authoring/WinRT.SourceGenerator/GenericVtableInitializerStrings.cs @@ -4,7 +4,6 @@ using Microsoft.CodeAnalysis; using System.Collections.Immutable; using System.Linq; -using System.Reflection.Metadata; using WinRT.SourceGenerator; namespace Generator @@ -183,7 +182,7 @@ public static string GetInstantiationInitFunction(string genericInterface, Equat // Splitting on the dots and the generic specifier (`) will get us the class name // in the 2nd last element. var interfaceName = genericInterface.Split('.', '`')[^2]; - var genericParametersStr = string.Join("_", genericParameters.Select(genericParameter => GeneratorHelper.EscapeTypeNameForIdentifier(genericParameter.ProjectedType))); + var genericParametersStr = string.Join("_", genericParameters.Select(static genericParameter => GeneratorHelper.EscapeTypeNameForIdentifier(genericParameter.ProjectedType))); return $$""" _ = global::WinRT.{{escapedAssemblyName}}GenericHelpers.{{interfaceName}}_{{genericParametersStr}}.Initialized;"""; } From e2268cad5facbf6107f977ea2f29744ba68ef974 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Tue, 8 Oct 2024 14:26:02 -0700 Subject: [PATCH 7/7] Remove unused namespace --- src/Authoring/WinRT.SourceGenerator/Helper.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Authoring/WinRT.SourceGenerator/Helper.cs b/src/Authoring/WinRT.SourceGenerator/Helper.cs index 43ac2a148..397456121 100644 --- a/src/Authoring/WinRT.SourceGenerator/Helper.cs +++ b/src/Authoring/WinRT.SourceGenerator/Helper.cs @@ -11,7 +11,6 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; -using System.Threading; namespace Generator {