Skip to content

Commit e5c04a6

Browse files
committed
Improved filenames for generated files
1 parent a670a12 commit e5c04a6

File tree

3 files changed

+44
-8
lines changed

3 files changed

+44
-8
lines changed

Microsoft.Toolkit.Mvvm.SourceGenerators/ComponentModel/TransitiveMembersGenerator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Microsoft.CodeAnalysis.Text;
1616
using Microsoft.Toolkit.Mvvm.ComponentModel;
1717
using Microsoft.Toolkit.Mvvm.SourceGenerators.Diagnostics;
18+
using Microsoft.Toolkit.Mvvm.SourceGenerators.Extensions;
1819
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
1920
using static Microsoft.CodeAnalysis.SymbolDisplayTypeQualificationStyle;
2021

@@ -164,7 +165,7 @@ private void OnExecute(
164165
.ToFullString();
165166

166167
// Add the partial type
167-
context.AddSource($"[{typeof(TAttribute).Name}]_[{classDeclaration.Identifier.Text}].cs", SourceText.From(source, Encoding.UTF8));
168+
context.AddSource($"[{typeof(TAttribute).Name}]_[{classDeclarationSymbol.GetFullMetadataNameForFileName()}].cs", SourceText.From(source, Encoding.UTF8));
168169
}
169170

170171
/// <summary>

Microsoft.Toolkit.Mvvm.SourceGenerators/Extensions/INamedTypeSymbolExtensions.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System.Diagnostics.Contracts;
6+
using System.Text;
67
using Microsoft.CodeAnalysis;
78

89
namespace Microsoft.Toolkit.Mvvm.SourceGenerators.Extensions
@@ -12,6 +13,42 @@ namespace Microsoft.Toolkit.Mvvm.SourceGenerators.Extensions
1213
/// </summary>
1314
internal static class INamedTypeSymbolExtensions
1415
{
16+
/// <summary>
17+
/// Gets the full metadata name for a given <see cref="INamedTypeSymbol"/> instance.
18+
/// </summary>
19+
/// <param name="symbol">The input <see cref="INamedTypeSymbol"/> instance.</param>
20+
/// <returns>The full metadata name for <paramref name="symbol"/>.</returns>
21+
[Pure]
22+
public static string GetFullMetadataName(this INamedTypeSymbol symbol)
23+
{
24+
static StringBuilder BuildFrom(ISymbol? symbol, StringBuilder builder)
25+
{
26+
return symbol switch
27+
{
28+
INamespaceSymbol ns when ns.IsGlobalNamespace => builder,
29+
INamespaceSymbol ns when ns.ContainingNamespace is { IsGlobalNamespace: false }
30+
=> BuildFrom(ns.ContainingNamespace, builder.Insert(0, $".{ns.MetadataName}")),
31+
ITypeSymbol ts when ts.ContainingType is ISymbol pt => BuildFrom(pt, builder.Insert(0, $"+{ts.MetadataName}")),
32+
ITypeSymbol ts when ts.ContainingNamespace is ISymbol pn => BuildFrom(pn, builder.Insert(0, $".{ts.MetadataName}")),
33+
ISymbol => BuildFrom(symbol.ContainingSymbol, builder.Insert(0, symbol.MetadataName)),
34+
_ => builder
35+
};
36+
}
37+
38+
return BuildFrom(symbol, new StringBuilder(256)).ToString();
39+
}
40+
41+
/// <summary>
42+
/// Gets a valid filename for a given <see cref="INamedTypeSymbol"/> instance.
43+
/// </summary>
44+
/// <param name="symbol">The input <see cref="INamedTypeSymbol"/> instance.</param>
45+
/// <returns>The full metadata name for <paramref name="symbol"/> that is also a valid filename.</returns>
46+
[Pure]
47+
public static string GetFullMetadataNameForFileName(this INamedTypeSymbol symbol)
48+
{
49+
return symbol.GetFullMetadataName().Replace('`', '-').Replace('+', '.');
50+
}
51+
1552
/// <summary>
1653
/// Checks whether or not a given <see cref="INamedTypeSymbol"/> inherits from a specified type.
1754
/// </summary>

Microsoft.Toolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Microsoft.CodeAnalysis.CSharp;
1212
using Microsoft.CodeAnalysis.CSharp.Syntax;
1313
using Microsoft.CodeAnalysis.Text;
14+
using Microsoft.Toolkit.Mvvm.SourceGenerators.Extensions;
1415
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
1516

1617
namespace Microsoft.Toolkit.Mvvm.SourceGenerators
@@ -55,9 +56,6 @@ from classDeclaration in syntaxTree.GetRoot().DescendantNodes().OfType<ClassDecl
5556
Literal("This type is not intended to be used directly by user code"))))))
5657
};
5758

58-
// Local counter to avoid filename conflicts in case of different types with the same name
59-
int i = 0;
60-
6159
foreach (INamedTypeSymbol classSymbol in classSymbols)
6260
{
6361
// Create a static method to register all messages for a given recipient type.
@@ -154,7 +152,7 @@ from classDeclaration in syntaxTree.GetRoot().DescendantNodes().OfType<ClassDecl
154152
classAttributes = Array.Empty<AttributeListSyntax>();
155153

156154
// Add the partial type
157-
context.AddSource($"[IRecipient{{T}}]_[{classSymbol.Name}]_[{i++}].cs", SourceText.From(source, Encoding.UTF8));
155+
context.AddSource($"[IRecipient{{T}}]_[{classSymbol.GetFullMetadataNameForFileName()}].cs", SourceText.From(source, Encoding.UTF8));
158156
}
159157
}
160158

@@ -176,10 +174,10 @@ private static IEnumerable<StatementSyntax> EnumerateRegistrationStatements(INam
176174

177175
// This enumerator produces a sequence of statements as follows:
178176
//
179-
// messenger.Register<<TYPE_0>, TToken>(recipient);
180-
// messenger.Register<<TYPE_1>, TToken>(recipient);
177+
// messenger.Register<<TYPE_0>>(recipient);
178+
// messenger.Register<<TYPE_1>>(recipient);
181179
// // ...
182-
// messenger.Register<<TYPE_N>, TToken>(recipient);
180+
// messenger.Register<<TYPE_N>>(recipient);
183181
yield return
184182
ExpressionStatement(
185183
InvocationExpression(

0 commit comments

Comments
 (0)