From e78e9c82509a8afbe1746af93d0bfcf81ecf7f4a Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 6 Mar 2022 19:26:02 +0100 Subject: [PATCH 1/5] Generate [DynamicallyAccessedMembers] for __IMessengerExtensions --- .../IMessengerRegisterAllGenerator.Execute.cs | 63 ++++++++++++------- .../IMessengerRegisterAllGenerator.cs | 18 ++++-- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.Execute.cs b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.Execute.cs index 3f1d8200..f838865d 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.Execute.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.Execute.cs @@ -67,19 +67,54 @@ public static RecipientInfo GetInfo(INamedTypeSymbol typeSymbol, ImmutableArray< /// Gets the head instance. /// /// The head instance with the type attributes. - public static CompilationUnitSyntax GetSyntax() + public static CompilationUnitSyntax GetSyntax(bool isDynamicallyAccessedMembersAttributeAvailable) { + int numberOfAttributes = 5 + (isDynamicallyAccessedMembersAttributeAvailable ? 1 : 0); + ImmutableArray.Builder attributes = ImmutableArray.CreateBuilder(numberOfAttributes); + + // Prepare the base attributes with are always present: + // + // [global::System.CodeDom.Compiler.GeneratedCode("...", "...")] + // [global::System.Diagnostics.DebuggerNonUserCode] + // [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + // [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + // [global::System.Obsolete("This type is not intended to be used directly by user code")] + attributes.Add( + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName($"global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments( + AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IMessengerRegisterAllGenerator).FullName))), + AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IMessengerRegisterAllGenerator).Assembly.GetName().Version.ToString()))))))); + attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode"))))); + attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage"))))); + attributes.Add( + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments( + AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never")))))); + attributes.Add( + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments( + AttributeArgument(LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal("This type is not intended to be used directly by user code"))))))); + + if (isDynamicallyAccessedMembersAttributeAvailable) + { + // Conditionally add the attribute to inform trimming, if the type is available: + // + // [global::System.CodeDom.Compiler.DynamicallyAccessedMembersAttribute(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)] + attributes.Add( + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute")).AddArgumentListArguments( + AttributeArgument(ParseExpression("global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods")))))); + } + // This code produces a compilation unit as follows: // // // // #pragma warning disable // namespace CommunityToolkit.Mvvm.Messaging.__Internals // { - // [global::System.CodeDom.Compiler.GeneratedCode("...", "...")] - // [global::System.Diagnostics.DebuggerNonUserCode] - // [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - // [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] - // [global::System.Obsolete("This type is not intended to be used directly by user code")] + // // internal static partial class __IMessengerExtensions // { // } @@ -93,21 +128,7 @@ public static CompilationUnitSyntax GetSyntax() Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.PartialKeyword)) - .AddAttributeLists( - AttributeList(SingletonSeparatedList( - Attribute(IdentifierName($"global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments( - AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IMessengerRegisterAllGenerator).FullName))), - AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IMessengerRegisterAllGenerator).Assembly.GetName().Version.ToString())))))), - AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))), - AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))), - AttributeList(SingletonSeparatedList( - Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments( - AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never"))))), - AttributeList(SingletonSeparatedList( - Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments( - AttributeArgument(LiteralExpression( - SyntaxKind.StringLiteralExpression, - Literal("This type is not intended to be used directly by user code"))))))))) + .AddAttributeLists(attributes.MoveToImmutable().ToArray()))) .NormalizeWhitespace(); } diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs index a84cd4c3..465656cf 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs @@ -57,14 +57,22 @@ item.Symbol.DeclaringSyntaxReferences[0] is SyntaxReference syntaxReference && .Collect() .Select(static (item, _) => item.Length > 0); + // Check whether [DynamicallyAccessedMembers] is available + IncrementalValueProvider isDynamicallyAccessedMembersAttributeAvailable = + context.CompilationProvider + .Select(static (item, _) => item.GetTypeByMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute") is { DeclaredAccessibility: Accessibility.Public }); + // Generate the header file with the attributes - context.RegisterConditionalImplementationSourceOutput(isHeaderFileNeeded, static context => + context.RegisterImplementationSourceOutput(isHeaderFileNeeded.Combine(isDynamicallyAccessedMembersAttributeAvailable), static (context, item) => { - CompilationUnitSyntax compilationUnit = Execute.GetSyntax(); + if (item.Left) + { + CompilationUnitSyntax compilationUnit = Execute.GetSyntax(item.Right); - context.AddSource( - hintName: "__IMessengerExtensions.cs", - sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8)); + context.AddSource( + hintName: "__IMessengerExtensions.cs", + sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8)); + } }); // Generate the class with all registration methods From 40b492ddf829e76475a1a683e1d8e47295cc4a27 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 6 Mar 2022 19:29:30 +0100 Subject: [PATCH 2/5] Generate [DynamicallyAccessedMembers] for __ObservableValidatorExtensions --- ...rValidateAllPropertiesGenerator.Execute.cs | 64 +++++++++++++------ ...ValidatorValidateAllPropertiesGenerator.cs | 18 ++++-- .../IMessengerRegisterAllGenerator.Execute.cs | 1 + 3 files changed, 57 insertions(+), 26 deletions(-) diff --git a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.Execute.cs b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.Execute.cs index fcad4998..758d3045 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.Execute.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.Execute.cs @@ -108,20 +108,56 @@ public static RecipientInfo GetInfo(INamedTypeSymbol typeSymbol, ImmutableArray< /// /// Gets the head instance. /// + /// Indicates whether [DynamicallyAccessedMembers] should be generated. /// The head instance with the type attributes. - public static CompilationUnitSyntax GetSyntax() + public static CompilationUnitSyntax GetSyntax(bool isDynamicallyAccessedMembersAttributeAvailable) { + int numberOfAttributes = 5 + (isDynamicallyAccessedMembersAttributeAvailable ? 1 : 0); + ImmutableArray.Builder attributes = ImmutableArray.CreateBuilder(numberOfAttributes); + + // Prepare the base attributes with are always present: + // + // [global::System.CodeDom.Compiler.GeneratedCode("...", "...")] + // [global::System.Diagnostics.DebuggerNonUserCode] + // [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + // [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + // [global::System.Obsolete("This type is not intended to be used directly by user code")] + attributes.Add( + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName($"global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments( + AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ObservableValidatorValidateAllPropertiesGenerator).FullName))), + AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ObservableValidatorValidateAllPropertiesGenerator).Assembly.GetName().Version.ToString()))))))); + attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode"))))); + attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage"))))); + attributes.Add( + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments( + AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never")))))); + attributes.Add( + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments( + AttributeArgument(LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal("This type is not intended to be used directly by user code"))))))); + + if (isDynamicallyAccessedMembersAttributeAvailable) + { + // Conditionally add the attribute to inform trimming, if the type is available: + // + // [global::System.CodeDom.Compiler.DynamicallyAccessedMembersAttribute(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)] + attributes.Add( + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute")).AddArgumentListArguments( + AttributeArgument(ParseExpression("global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods")))))); + } + // This code produces a compilation unit as follows: // // // // #pragma warning disable // namespace CommunityToolkit.Mvvm.ComponentModel.__Internals // { - // [global::System.CodeDom.Compiler.GeneratedCode("...", "...")] - // [global::System.Diagnostics.DebuggerNonUserCode] - // [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] - // [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] - // [global::System.Obsolete("This type is not intended to be used directly by user code")] + // // internal static partial class __ObservableValidatorExtensions // { // } @@ -135,21 +171,7 @@ public static CompilationUnitSyntax GetSyntax() Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.PartialKeyword)) - .AddAttributeLists( - AttributeList(SingletonSeparatedList( - Attribute(IdentifierName($"global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments( - AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ObservableValidatorValidateAllPropertiesGenerator).FullName))), - AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ObservableValidatorValidateAllPropertiesGenerator).Assembly.GetName().Version.ToString())))))), - AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))), - AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))), - AttributeList(SingletonSeparatedList( - Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments( - AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never"))))), - AttributeList(SingletonSeparatedList( - Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments( - AttributeArgument(LiteralExpression( - SyntaxKind.StringLiteralExpression, - Literal("This type is not intended to be used directly by user code"))))))))) + .AddAttributeLists(attributes.MoveToImmutable().ToArray()))) .NormalizeWhitespace(); } diff --git a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs index 111011e0..321e3933 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs @@ -42,14 +42,22 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Collect() .Select(static (item, _) => item.Length > 0); + // Check whether [DynamicallyAccessedMembers] is available + IncrementalValueProvider isDynamicallyAccessedMembersAttributeAvailable = + context.CompilationProvider + .Select(static (item, _) => item.GetTypeByMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute") is { DeclaredAccessibility: Accessibility.Public }); + // Generate the header file with the attributes - context.RegisterConditionalImplementationSourceOutput(isHeaderFileNeeded, static context => + context.RegisterImplementationSourceOutput(isHeaderFileNeeded.Combine(isDynamicallyAccessedMembersAttributeAvailable), static (context, item) => { - CompilationUnitSyntax compilationUnit = Execute.GetSyntax(); + if (item.Left) + { + CompilationUnitSyntax compilationUnit = Execute.GetSyntax(item.Right); - context.AddSource( - hintName: "__ObservableValidatorExtensions.cs", - sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8)); + context.AddSource( + hintName: "__ObservableValidatorExtensions.cs", + sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8)); + } }); // Generate the class with all validation methods diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.Execute.cs b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.Execute.cs index f838865d..a9c13cab 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.Execute.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.Execute.cs @@ -66,6 +66,7 @@ public static RecipientInfo GetInfo(INamedTypeSymbol typeSymbol, ImmutableArray< /// /// Gets the head instance. /// + /// Indicates whether [DynamicallyAccessedMembers] should be generated. /// The head instance with the type attributes. public static CompilationUnitSyntax GetSyntax(bool isDynamicallyAccessedMembersAttributeAvailable) { From baada1ac7066750522329e4ab08fee507d4113bf Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 6 Mar 2022 19:33:30 +0100 Subject: [PATCH 3/5] Update RegisterConditionalImplementationSourceOutput extension --- ...leValidatorValidateAllPropertiesGenerator.cs | 17 +++++++++-------- ...lGeneratorInitializationContextExtensions.cs | 16 ++++++++-------- .../Messaging/IMessengerRegisterAllGenerator.cs | 17 +++++++++-------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs index 321e3933..d4fd92ea 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs @@ -47,17 +47,18 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.CompilationProvider .Select(static (item, _) => item.GetTypeByMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute") is { DeclaredAccessibility: Accessibility.Public }); + // Gather the conditional flag and attribute availability + IncrementalValueProvider<(bool IsHeaderFileNeeded, bool IsDynamicallyAccessedMembersAttributeAvailable)> headerFileInfo = + isHeaderFileNeeded.Combine(isDynamicallyAccessedMembersAttributeAvailable); + // Generate the header file with the attributes - context.RegisterImplementationSourceOutput(isHeaderFileNeeded.Combine(isDynamicallyAccessedMembersAttributeAvailable), static (context, item) => + context.RegisterConditionalImplementationSourceOutput(headerFileInfo, static (context, item) => { - if (item.Left) - { - CompilationUnitSyntax compilationUnit = Execute.GetSyntax(item.Right); + CompilationUnitSyntax compilationUnit = Execute.GetSyntax(item); - context.AddSource( - hintName: "__ObservableValidatorExtensions.cs", - sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8)); - } + context.AddSource( + hintName: "__ObservableValidatorExtensions.cs", + sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8)); }); // Generate the class with all validation methods diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Extensions/IncrementalGeneratorInitializationContextExtensions.cs b/CommunityToolkit.Mvvm.SourceGenerators/Extensions/IncrementalGeneratorInitializationContextExtensions.cs index 2ffc4fa8..b39c074d 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/Extensions/IncrementalGeneratorInitializationContextExtensions.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/Extensions/IncrementalGeneratorInitializationContextExtensions.cs @@ -65,22 +65,22 @@ public static void FilterWithLanguageVersion( } /// - /// Conditionally invokes - /// if the value produced by the input is . + /// Conditionally invokes + /// if the value produced by the input is , and also supplying a given input state. /// /// The input value being used. /// The source instance. /// The conditional to invoke. - public static void RegisterConditionalImplementationSourceOutput( + public static void RegisterConditionalImplementationSourceOutput( this IncrementalGeneratorInitializationContext context, - IncrementalValueProvider source, - Action action) + IncrementalValueProvider<(bool Condition, T State)> source, + Action action) { - context.RegisterImplementationSourceOutput(source, (context, flag) => + context.RegisterImplementationSourceOutput(source, (context, item) => { - if (flag) + if (item.Condition) { - action(context); + action(context, item.State); } }); } diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs index 465656cf..b38faa67 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs @@ -62,17 +62,18 @@ item.Symbol.DeclaringSyntaxReferences[0] is SyntaxReference syntaxReference && context.CompilationProvider .Select(static (item, _) => item.GetTypeByMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute") is { DeclaredAccessibility: Accessibility.Public }); + // Gather the conditional flag and attribute availability + IncrementalValueProvider<(bool IsHeaderFileNeeded, bool IsDynamicallyAccessedMembersAttributeAvailable)> headerFileInfo = + isHeaderFileNeeded.Combine(isDynamicallyAccessedMembersAttributeAvailable); + // Generate the header file with the attributes - context.RegisterImplementationSourceOutput(isHeaderFileNeeded.Combine(isDynamicallyAccessedMembersAttributeAvailable), static (context, item) => + context.RegisterConditionalImplementationSourceOutput(headerFileInfo, static (context, item) => { - if (item.Left) - { - CompilationUnitSyntax compilationUnit = Execute.GetSyntax(item.Right); + CompilationUnitSyntax compilationUnit = Execute.GetSyntax(item); - context.AddSource( - hintName: "__IMessengerExtensions.cs", - sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8)); - } + context.AddSource( + hintName: "__IMessengerExtensions.cs", + sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8)); }); // Generate the class with all registration methods From 1e033f47bbc1b2d45074c3963772a5db390e1981 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 6 Mar 2022 19:34:30 +0100 Subject: [PATCH 4/5] Improve detection of [DynamicallyAccessedMembers] --- .../ObservableValidatorValidateAllPropertiesGenerator.cs | 2 +- .../Messaging/IMessengerRegisterAllGenerator.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs index d4fd92ea..965d5fc0 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs @@ -45,7 +45,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Check whether [DynamicallyAccessedMembers] is available IncrementalValueProvider isDynamicallyAccessedMembersAttributeAvailable = context.CompilationProvider - .Select(static (item, _) => item.GetTypeByMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute") is { DeclaredAccessibility: Accessibility.Public }); + .Select(static (item, _) => item.HasAccessibleTypeWithMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute")); // Gather the conditional flag and attribute availability IncrementalValueProvider<(bool IsHeaderFileNeeded, bool IsDynamicallyAccessedMembersAttributeAvailable)> headerFileInfo = diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs index b38faa67..d6de9352 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs @@ -60,7 +60,7 @@ item.Symbol.DeclaringSyntaxReferences[0] is SyntaxReference syntaxReference && // Check whether [DynamicallyAccessedMembers] is available IncrementalValueProvider isDynamicallyAccessedMembersAttributeAvailable = context.CompilationProvider - .Select(static (item, _) => item.GetTypeByMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute") is { DeclaredAccessibility: Accessibility.Public }); + .Select(static (item, _) => item.HasAccessibleTypeWithMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute")); // Gather the conditional flag and attribute availability IncrementalValueProvider<(bool IsHeaderFileNeeded, bool IsDynamicallyAccessedMembersAttributeAvailable)> headerFileInfo = From 5fb9f7039cef0621684b3580726d6e5c5c9891aa Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 6 Mar 2022 19:46:14 +0100 Subject: [PATCH 5/5] Add unit tests for trimming annotations --- .../Test_ObservableRecipient.cs | 24 +++++++++++++++++++ .../Test_ObservableValidator.cs | 19 +++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservableRecipient.cs b/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservableRecipient.cs index 8d55af0a..99c674dc 100644 --- a/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservableRecipient.cs +++ b/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservableRecipient.cs @@ -3,11 +3,18 @@ // See the LICENSE file in the project root for more information. using System; +#if !NET6_0_OR_GREATER +using System.Collections.Generic; +using System.Linq; +#endif +using System.Reflection; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging.Messages; using Microsoft.VisualStudio.TestTools.UnitTesting; +#pragma warning disable CS0618 + namespace CommunityToolkit.Mvvm.UnitTests; [TestClass] @@ -85,6 +92,23 @@ public void Test_ObservableRecipient_Broadcast(Type type) Assert.AreEqual(message.PropertyName, nameof(SomeRecipient.Data)); } + [TestMethod] + public void Test_IRecipient_VerifyTrimmingAnnotation() + { +#if NET6_0_OR_GREATER + System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute? attribute = + typeof(Messaging.__Internals.__IMessengerExtensions) + .GetCustomAttribute(); + + Assert.IsNotNull(attribute); + Assert.AreEqual(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods, attribute.MemberTypes); +#else + IEnumerable attributes = typeof(Messaging.__Internals.__IMessengerExtensions).GetCustomAttributes(); + + Assert.IsFalse(attributes.Any(static a => a.GetType().Name is "DynamicallyAccessedMembersAttribute")); +#endif + } + public class SomeRecipient : ObservableRecipient { public SomeRecipient() diff --git a/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservableValidator.cs b/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservableValidator.cs index f10e0483..504e2d88 100644 --- a/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservableValidator.cs +++ b/tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservableValidator.cs @@ -12,6 +12,8 @@ using CommunityToolkit.Mvvm.ComponentModel; using Microsoft.VisualStudio.TestTools.UnitTesting; +#pragma warning disable CS0618 + namespace CommunityToolkit.Mvvm.UnitTests; [TestClass] @@ -477,6 +479,23 @@ public void Test_ObservableRecipient_ValidationOnNonValidatableProperties_WithFa validationFunc(viewmodel.GetType())(viewmodel); } + [TestMethod] + public void Test_ObservableValidator_VerifyTrimmingAnnotation() + { +#if NET6_0_OR_GREATER + System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute? attribute = + typeof(ComponentModel.__Internals.__ObservableValidatorExtensions) + .GetCustomAttribute(); + + Assert.IsNotNull(attribute); + Assert.AreEqual(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods, attribute.MemberTypes); +#else + IEnumerable attributes = typeof(ComponentModel.__Internals.__ObservableValidatorExtensions).GetCustomAttributes(); + + Assert.IsFalse(attributes.Any(static a => a.GetType().Name is "DynamicallyAccessedMembersAttribute")); +#endif + } + public class Person : ObservableValidator { private string? name;