Skip to content

Commit f34c0f3

Browse files
committed
Fix generation for nested types that are not classes
1 parent f3bd3d8 commit f34c0f3

File tree

3 files changed

+52
-15
lines changed

3 files changed

+52
-15
lines changed

CommunityToolkit.Mvvm.SourceGenerators/Models/HierarchyInfo.Syntax.cs

+6-8
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,26 @@ public CompilationUnitSyntax GetCompilationUnit(
3030
// Create the partial type declaration with the given member declarations.
3131
// This code produces a class declaration as follows:
3232
//
33-
// partial class <TYPE_NAME>
33+
// partial <TYPE_KIND> TYPE_NAME>
3434
// {
3535
// <MEMBERS>
3636
// }
37-
ClassDeclarationSyntax classDeclarationSyntax =
38-
ClassDeclaration(Names[0])
37+
TypeDeclarationSyntax typeDeclarationSyntax =
38+
Hierarchy[0].GetSyntax()
3939
.AddModifiers(Token(SyntaxKind.PartialKeyword))
4040
.AddMembers(memberDeclarations.ToArray());
4141

4242
// Add the base list, if present
4343
if (baseList is not null)
4444
{
45-
classDeclarationSyntax = classDeclarationSyntax.WithBaseList(baseList);
45+
typeDeclarationSyntax = typeDeclarationSyntax.WithBaseList(baseList);
4646
}
4747

48-
TypeDeclarationSyntax typeDeclarationSyntax = classDeclarationSyntax;
49-
5048
// Add all parent types in ascending order, if any
51-
foreach (string parentType in Names.AsSpan().Slice(1))
49+
foreach (TypeInfo parentType in Hierarchy.AsSpan().Slice(1))
5250
{
5351
typeDeclarationSyntax =
54-
ClassDeclaration(parentType)
52+
parentType.GetSyntax()
5553
.AddModifiers(Token(SyntaxKind.PartialKeyword))
5654
.AddMembers(typeDeclarationSyntax);
5755
}

CommunityToolkit.Mvvm.SourceGenerators/Models/HierarchyInfo.cs

+9-7
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ namespace CommunityToolkit.Mvvm.SourceGenerators.Models;
2222
/// <param name="FilenameHint">The filename hint for the current type.</param>
2323
/// <param name="MetadataName">The metadata name for the current type.</param>
2424
/// <param name="Namespace">Gets the namespace for the current type.</param>
25-
/// <param name="Names">Gets the sequence of type definitions containing the current type.</param>
26-
internal sealed partial record HierarchyInfo(string FilenameHint, string MetadataName, string Namespace, ImmutableArray<string> Names)
25+
/// <param name="Hierarchy">Gets the sequence of type definitions containing the current type.</param>
26+
internal sealed partial record HierarchyInfo(string FilenameHint, string MetadataName, string Namespace, ImmutableArray<TypeInfo> Hierarchy)
2727
{
2828
/// <summary>
2929
/// Creates a new <see cref="HierarchyInfo"/> instance from a given <see cref="INamedTypeSymbol"/>.
@@ -32,20 +32,22 @@ internal sealed partial record HierarchyInfo(string FilenameHint, string Metadat
3232
/// <returns>A <see cref="HierarchyInfo"/> instance describing <paramref name="typeSymbol"/>.</returns>
3333
public static HierarchyInfo From(INamedTypeSymbol typeSymbol)
3434
{
35-
ImmutableArray<string>.Builder names = ImmutableArray.CreateBuilder<string>();
35+
ImmutableArray<TypeInfo>.Builder hierarchy = ImmutableArray.CreateBuilder<TypeInfo>();
3636

3737
for (INamedTypeSymbol? parent = typeSymbol;
3838
parent is not null;
3939
parent = parent.ContainingType)
4040
{
41-
names.Add(parent.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat));
41+
hierarchy.Add(new TypeInfo(
42+
parent.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
43+
parent.TypeKind));
4244
}
4345

4446
return new(
4547
typeSymbol.GetFullMetadataNameForFileName(),
4648
typeSymbol.MetadataName,
4749
typeSymbol.ContainingNamespace.ToDisplayString(new(typeQualificationStyle: NameAndContainingTypesAndNamespaces)),
48-
names.ToImmutable());
50+
hierarchy.ToImmutable());
4951
}
5052

5153
/// <summary>
@@ -59,7 +61,7 @@ protected override void AddToHashCode(ref HashCode hashCode, HierarchyInfo obj)
5961
hashCode.Add(obj.FilenameHint);
6062
hashCode.Add(obj.MetadataName);
6163
hashCode.Add(obj.Namespace);
62-
hashCode.AddRange(obj.Names);
64+
hashCode.AddRange(obj.Hierarchy);
6365
}
6466

6567
/// <inheritdoc/>
@@ -69,7 +71,7 @@ protected override bool AreEqual(HierarchyInfo x, HierarchyInfo y)
6971
x.FilenameHint == y.FilenameHint &&
7072
x.MetadataName == y.MetadataName &&
7173
x.Namespace == y.Namespace &&
72-
x.Names.SequenceEqual(y.Names);
74+
x.Hierarchy.SequenceEqual(y.Hierarchy);
7375
}
7476
}
7577
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Microsoft.CodeAnalysis;
6+
using Microsoft.CodeAnalysis.CSharp.Syntax;
7+
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
8+
9+
namespace CommunityToolkit.Mvvm.SourceGenerators.Models;
10+
11+
/// <summary>
12+
/// A model describing a type info in a type hierarchy.
13+
/// </summary>
14+
/// <param name="QualifiedName">The qualified name for the type.</param>
15+
/// <param name="Kind">The type of the type in the hierarchy.</param>
16+
internal sealed record TypeInfo(string QualifiedName, TypeKind Kind)
17+
{
18+
/// <summary>
19+
/// Creates a <see cref="TypeDeclarationSyntax"/> instance for the current info.
20+
/// </summary>
21+
/// <returns>A <see cref="TypeDeclarationSyntax"/> instance for the current info.</returns>
22+
public TypeDeclarationSyntax GetSyntax()
23+
{
24+
// Create the partial type declaration with the kind.
25+
// This code produces a class declaration as follows:
26+
//
27+
// <TYPE_KIND> <TYPE_NAME>
28+
// {
29+
// }
30+
return Kind switch
31+
{
32+
TypeKind.Struct => StructDeclaration(QualifiedName),
33+
TypeKind.Interface => InterfaceDeclaration(QualifiedName),
34+
_ => ClassDeclaration(QualifiedName)
35+
};
36+
}
37+
}

0 commit comments

Comments
 (0)