Skip to content

Commit 40b492d

Browse files
committed
Generate [DynamicallyAccessedMembers] for __ObservableValidatorExtensions
1 parent e78e9c8 commit 40b492d

File tree

3 files changed

+57
-26
lines changed

3 files changed

+57
-26
lines changed

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.Execute.cs

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -108,20 +108,56 @@ public static RecipientInfo GetInfo(INamedTypeSymbol typeSymbol, ImmutableArray<
108108
/// <summary>
109109
/// Gets the head <see cref="CompilationUnitSyntax"/> instance.
110110
/// </summary>
111+
/// <param name="isDynamicallyAccessedMembersAttributeAvailable">Indicates whether <c>[DynamicallyAccessedMembers]</c> should be generated.</param>
111112
/// <returns>The head <see cref="CompilationUnitSyntax"/> instance with the type attributes.</returns>
112-
public static CompilationUnitSyntax GetSyntax()
113+
public static CompilationUnitSyntax GetSyntax(bool isDynamicallyAccessedMembersAttributeAvailable)
113114
{
115+
int numberOfAttributes = 5 + (isDynamicallyAccessedMembersAttributeAvailable ? 1 : 0);
116+
ImmutableArray<AttributeListSyntax>.Builder attributes = ImmutableArray.CreateBuilder<AttributeListSyntax>(numberOfAttributes);
117+
118+
// Prepare the base attributes with are always present:
119+
//
120+
// [global::System.CodeDom.Compiler.GeneratedCode("...", "...")]
121+
// [global::System.Diagnostics.DebuggerNonUserCode]
122+
// [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
123+
// [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
124+
// [global::System.Obsolete("This type is not intended to be used directly by user code")]
125+
attributes.Add(
126+
AttributeList(SingletonSeparatedList(
127+
Attribute(IdentifierName($"global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments(
128+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ObservableValidatorValidateAllPropertiesGenerator).FullName))),
129+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ObservableValidatorValidateAllPropertiesGenerator).Assembly.GetName().Version.ToString())))))));
130+
attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))));
131+
attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))));
132+
attributes.Add(
133+
AttributeList(SingletonSeparatedList(
134+
Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments(
135+
AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never"))))));
136+
attributes.Add(
137+
AttributeList(SingletonSeparatedList(
138+
Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments(
139+
AttributeArgument(LiteralExpression(
140+
SyntaxKind.StringLiteralExpression,
141+
Literal("This type is not intended to be used directly by user code")))))));
142+
143+
if (isDynamicallyAccessedMembersAttributeAvailable)
144+
{
145+
// Conditionally add the attribute to inform trimming, if the type is available:
146+
//
147+
// [global::System.CodeDom.Compiler.DynamicallyAccessedMembersAttribute(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)]
148+
attributes.Add(
149+
AttributeList(SingletonSeparatedList(
150+
Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute")).AddArgumentListArguments(
151+
AttributeArgument(ParseExpression("global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods"))))));
152+
}
153+
114154
// This code produces a compilation unit as follows:
115155
//
116156
// // <auto-generated/>
117157
// #pragma warning disable
118158
// namespace CommunityToolkit.Mvvm.ComponentModel.__Internals
119159
// {
120-
// [global::System.CodeDom.Compiler.GeneratedCode("...", "...")]
121-
// [global::System.Diagnostics.DebuggerNonUserCode]
122-
// [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
123-
// [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
124-
// [global::System.Obsolete("This type is not intended to be used directly by user code")]
160+
// <ATTRIBUTES>
125161
// internal static partial class __ObservableValidatorExtensions
126162
// {
127163
// }
@@ -135,21 +171,7 @@ public static CompilationUnitSyntax GetSyntax()
135171
Token(SyntaxKind.InternalKeyword),
136172
Token(SyntaxKind.StaticKeyword),
137173
Token(SyntaxKind.PartialKeyword))
138-
.AddAttributeLists(
139-
AttributeList(SingletonSeparatedList(
140-
Attribute(IdentifierName($"global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments(
141-
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ObservableValidatorValidateAllPropertiesGenerator).FullName))),
142-
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ObservableValidatorValidateAllPropertiesGenerator).Assembly.GetName().Version.ToString())))))),
143-
AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))),
144-
AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))),
145-
AttributeList(SingletonSeparatedList(
146-
Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments(
147-
AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never"))))),
148-
AttributeList(SingletonSeparatedList(
149-
Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments(
150-
AttributeArgument(LiteralExpression(
151-
SyntaxKind.StringLiteralExpression,
152-
Literal("This type is not intended to be used directly by user code")))))))))
174+
.AddAttributeLists(attributes.MoveToImmutable().ToArray())))
153175
.NormalizeWhitespace();
154176
}
155177

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,22 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
4242
.Collect()
4343
.Select(static (item, _) => item.Length > 0);
4444

45+
// Check whether [DynamicallyAccessedMembers] is available
46+
IncrementalValueProvider<bool> isDynamicallyAccessedMembersAttributeAvailable =
47+
context.CompilationProvider
48+
.Select(static (item, _) => item.GetTypeByMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute") is { DeclaredAccessibility: Accessibility.Public });
49+
4550
// Generate the header file with the attributes
46-
context.RegisterConditionalImplementationSourceOutput(isHeaderFileNeeded, static context =>
51+
context.RegisterImplementationSourceOutput(isHeaderFileNeeded.Combine(isDynamicallyAccessedMembersAttributeAvailable), static (context, item) =>
4752
{
48-
CompilationUnitSyntax compilationUnit = Execute.GetSyntax();
53+
if (item.Left)
54+
{
55+
CompilationUnitSyntax compilationUnit = Execute.GetSyntax(item.Right);
4956

50-
context.AddSource(
51-
hintName: "__ObservableValidatorExtensions.cs",
52-
sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8));
57+
context.AddSource(
58+
hintName: "__ObservableValidatorExtensions.cs",
59+
sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8));
60+
}
5361
});
5462

5563
// Generate the class with all validation methods

CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.Execute.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public static RecipientInfo GetInfo(INamedTypeSymbol typeSymbol, ImmutableArray<
6666
/// <summary>
6767
/// Gets the head <see cref="CompilationUnitSyntax"/> instance.
6868
/// </summary>
69+
/// <param name="isDynamicallyAccessedMembersAttributeAvailable">Indicates whether <c>[DynamicallyAccessedMembers]</c> should be generated.</param>
6970
/// <returns>The head <see cref="CompilationUnitSyntax"/> instance with the type attributes.</returns>
7071
public static CompilationUnitSyntax GetSyntax(bool isDynamicallyAccessedMembersAttributeAvailable)
7172
{

0 commit comments

Comments
 (0)