Skip to content

Commit 36a3b82

Browse files
authored
Merge pull request #276 from CommunityToolkit/dev/fix-generators-in-root-namespace
Fix source generators for types in global namespace
2 parents 8742886 + d429e03 commit 36a3b82

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

CommunityToolkit.Mvvm.SourceGenerators/Extensions/INamedTypeSymbolExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ static StringBuilder BuildFrom(ISymbol? symbol, StringBuilder builder)
2727
INamespaceSymbol ns when ns.IsGlobalNamespace => builder,
2828
INamespaceSymbol ns when ns.ContainingNamespace is { IsGlobalNamespace: false }
2929
=> BuildFrom(ns.ContainingNamespace, builder.Insert(0, $".{ns.MetadataName}")),
30-
ITypeSymbol ts when ts.ContainingType is ISymbol pt => BuildFrom(pt, builder.Insert(0, $"+{ts.MetadataName}")),
31-
ITypeSymbol ts when ts.ContainingNamespace is ISymbol pn => BuildFrom(pn, builder.Insert(0, $".{ts.MetadataName}")),
30+
ITypeSymbol ts when ts.ContainingType is ISymbol pt
31+
=> BuildFrom(pt, builder.Insert(0, $"+{ts.MetadataName}")),
32+
ITypeSymbol ts when ts.ContainingNamespace is ISymbol pn and not INamespaceSymbol { IsGlobalNamespace: true }
33+
=> BuildFrom(pn, builder.Insert(0, $".{ts.MetadataName}")),
3234
ISymbol => BuildFrom(symbol.ContainingSymbol, builder.Insert(0, symbol.MetadataName)),
3335
_ => builder
3436
};

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

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,23 +54,42 @@ public CompilationUnitSyntax GetCompilationUnit(
5454
.AddMembers(typeDeclarationSyntax);
5555
}
5656

57-
// Create the compilation unit with disabled warnings, target namespace and generated type.
57+
// Prepare the leading trivia for the generated compilation unit.
5858
// This will produce code as follows:
5959
//
6060
// <auto-generated/>
6161
// #pragma warning disable
6262
// #nullable enable
63+
SyntaxTriviaList syntaxTriviaList = TriviaList(
64+
Comment("// <auto-generated/>"),
65+
Trivia(PragmaWarningDirectiveTrivia(Token(SyntaxKind.DisableKeyword), true)),
66+
Trivia(NullableDirectiveTrivia(Token(SyntaxKind.EnableKeyword), true)));
67+
68+
if (Namespace is "")
69+
{
70+
// If there is no namespace, attach the pragma directly to the declared type,
71+
// and skip the namespace declaration. This will produce code as follows:
72+
//
73+
// <SYNTAX_TRIVIA>
74+
// <TYPE_HIERARCHY>
75+
return
76+
CompilationUnit()
77+
.AddMembers(typeDeclarationSyntax.WithLeadingTrivia(syntaxTriviaList))
78+
.NormalizeWhitespace();
79+
}
80+
81+
// Create the compilation unit with disabled warnings, target namespace and generated type.
82+
// This will produce code as follows:
83+
//
84+
// <SYNTAX_TRIVIA>
6385
// namespace <NAMESPACE>
6486
// {
6587
// <TYPE_HIERARCHY>
6688
// }
6789
return
6890
CompilationUnit().AddMembers(
6991
NamespaceDeclaration(IdentifierName(Namespace))
70-
.WithLeadingTrivia(TriviaList(
71-
Comment("// <auto-generated/>"),
72-
Trivia(PragmaWarningDirectiveTrivia(Token(SyntaxKind.DisableKeyword), true)),
73-
Trivia(NullableDirectiveTrivia(Token(SyntaxKind.EnableKeyword), true))))
92+
.WithLeadingTrivia(syntaxTriviaList)
7493
.AddMembers(typeDeclarationSyntax))
7594
.NormalizeWhitespace();
7695
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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 CommunityToolkit.Mvvm.ComponentModel;
6+
7+
// Test viewmodel for https://github.com/CommunityToolkit/dotnet/issues/271
8+
internal partial class ModelWithObservablePropertyInRootNamespace : ObservableObject
9+
{
10+
[ObservableProperty]
11+
private float number;
12+
}

tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservablePropertyAttribute.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,22 @@ public void Test_ObservableProperty_ForwardsSpecialCasesDataAnnotationAttributes
731731
Assert.IsTrue(scaffoldColumnAttribute!.Scaffold);
732732
}
733733

734+
// See https://github.com/CommunityToolkit/dotnet/issues/271
735+
[TestMethod]
736+
public void Test_ObservableProperty_ModelWithObservablePropertyInRootNamespace()
737+
{
738+
ModelWithObservablePropertyInRootNamespace model = new();
739+
740+
List<string?> propertyNames = new();
741+
742+
model.PropertyChanged += (s, e) => propertyNames.Add(e.PropertyName);
743+
744+
model.Number = 3.14f;
745+
746+
// We mostly just need to verify this class compiles fine with the right generated code
747+
CollectionAssert.AreEqual(propertyNames, new[] { nameof(model.Number) });
748+
}
749+
734750
public abstract partial class BaseViewModel : ObservableObject
735751
{
736752
public string? Content { get; set; }

0 commit comments

Comments
 (0)