Skip to content

Commit e78e9c8

Browse files
committed
Generate [DynamicallyAccessedMembers] for __IMessengerExtensions
1 parent fa9114b commit e78e9c8

File tree

2 files changed

+55
-26
lines changed

2 files changed

+55
-26
lines changed

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

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,54 @@ public static RecipientInfo GetInfo(INamedTypeSymbol typeSymbol, ImmutableArray<
6767
/// Gets the head <see cref="CompilationUnitSyntax"/> instance.
6868
/// </summary>
6969
/// <returns>The head <see cref="CompilationUnitSyntax"/> instance with the type attributes.</returns>
70-
public static CompilationUnitSyntax GetSyntax()
70+
public static CompilationUnitSyntax GetSyntax(bool isDynamicallyAccessedMembersAttributeAvailable)
7171
{
72+
int numberOfAttributes = 5 + (isDynamicallyAccessedMembersAttributeAvailable ? 1 : 0);
73+
ImmutableArray<AttributeListSyntax>.Builder attributes = ImmutableArray.CreateBuilder<AttributeListSyntax>(numberOfAttributes);
74+
75+
// Prepare the base attributes with are always present:
76+
//
77+
// [global::System.CodeDom.Compiler.GeneratedCode("...", "...")]
78+
// [global::System.Diagnostics.DebuggerNonUserCode]
79+
// [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
80+
// [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
81+
// [global::System.Obsolete("This type is not intended to be used directly by user code")]
82+
attributes.Add(
83+
AttributeList(SingletonSeparatedList(
84+
Attribute(IdentifierName($"global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments(
85+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IMessengerRegisterAllGenerator).FullName))),
86+
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IMessengerRegisterAllGenerator).Assembly.GetName().Version.ToString())))))));
87+
attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))));
88+
attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))));
89+
attributes.Add(
90+
AttributeList(SingletonSeparatedList(
91+
Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments(
92+
AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never"))))));
93+
attributes.Add(
94+
AttributeList(SingletonSeparatedList(
95+
Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments(
96+
AttributeArgument(LiteralExpression(
97+
SyntaxKind.StringLiteralExpression,
98+
Literal("This type is not intended to be used directly by user code")))))));
99+
100+
if (isDynamicallyAccessedMembersAttributeAvailable)
101+
{
102+
// Conditionally add the attribute to inform trimming, if the type is available:
103+
//
104+
// [global::System.CodeDom.Compiler.DynamicallyAccessedMembersAttribute(global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods)]
105+
attributes.Add(
106+
AttributeList(SingletonSeparatedList(
107+
Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute")).AddArgumentListArguments(
108+
AttributeArgument(ParseExpression("global::System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicMethods"))))));
109+
}
110+
72111
// This code produces a compilation unit as follows:
73112
//
74113
// // <auto-generated/>
75114
// #pragma warning disable
76115
// namespace CommunityToolkit.Mvvm.Messaging.__Internals
77116
// {
78-
// [global::System.CodeDom.Compiler.GeneratedCode("...", "...")]
79-
// [global::System.Diagnostics.DebuggerNonUserCode]
80-
// [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
81-
// [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
82-
// [global::System.Obsolete("This type is not intended to be used directly by user code")]
117+
// <ATTRIBUTES>
83118
// internal static partial class __IMessengerExtensions
84119
// {
85120
// }
@@ -93,21 +128,7 @@ public static CompilationUnitSyntax GetSyntax()
93128
Token(SyntaxKind.InternalKeyword),
94129
Token(SyntaxKind.StaticKeyword),
95130
Token(SyntaxKind.PartialKeyword))
96-
.AddAttributeLists(
97-
AttributeList(SingletonSeparatedList(
98-
Attribute(IdentifierName($"global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments(
99-
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IMessengerRegisterAllGenerator).FullName))),
100-
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IMessengerRegisterAllGenerator).Assembly.GetName().Version.ToString())))))),
101-
AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))),
102-
AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))),
103-
AttributeList(SingletonSeparatedList(
104-
Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments(
105-
AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never"))))),
106-
AttributeList(SingletonSeparatedList(
107-
Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments(
108-
AttributeArgument(LiteralExpression(
109-
SyntaxKind.StringLiteralExpression,
110-
Literal("This type is not intended to be used directly by user code")))))))))
131+
.AddAttributeLists(attributes.MoveToImmutable().ToArray())))
111132
.NormalizeWhitespace();
112133
}
113134

CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,22 @@ item.Symbol.DeclaringSyntaxReferences[0] is SyntaxReference syntaxReference &&
5757
.Collect()
5858
.Select(static (item, _) => item.Length > 0);
5959

60+
// Check whether [DynamicallyAccessedMembers] is available
61+
IncrementalValueProvider<bool> isDynamicallyAccessedMembersAttributeAvailable =
62+
context.CompilationProvider
63+
.Select(static (item, _) => item.GetTypeByMetadataName("System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute") is { DeclaredAccessibility: Accessibility.Public });
64+
6065
// Generate the header file with the attributes
61-
context.RegisterConditionalImplementationSourceOutput(isHeaderFileNeeded, static context =>
66+
context.RegisterImplementationSourceOutput(isHeaderFileNeeded.Combine(isDynamicallyAccessedMembersAttributeAvailable), static (context, item) =>
6267
{
63-
CompilationUnitSyntax compilationUnit = Execute.GetSyntax();
68+
if (item.Left)
69+
{
70+
CompilationUnitSyntax compilationUnit = Execute.GetSyntax(item.Right);
6471

65-
context.AddSource(
66-
hintName: "__IMessengerExtensions.cs",
67-
sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8));
72+
context.AddSource(
73+
hintName: "__IMessengerExtensions.cs",
74+
sourceText: SourceText.From(compilationUnit.ToFullString(), Encoding.UTF8));
75+
}
6876
});
6977

7078
// Generate the class with all registration methods

0 commit comments

Comments
 (0)