Skip to content

Commit 53f9abf

Browse files
committed
Add diagnostics for name collision for [ObservableProperty]
1 parent 2372ea9 commit 53f9abf

File tree

4 files changed

+46
-0
lines changed

4 files changed

+46
-0
lines changed

CommunityToolkit.Mvvm.SourceGenerators/AnalyzerReleases.Unshipped.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ MVVMTK0010 | CommunityToolkit.Mvvm.SourceGenerators.ICommandGenerator | Error |
1818
MVVMTK0011 | CommunityToolkit.Mvvm.SourceGenerators.ICommandGenerator | Error | See https://aka.ms/mvvmtoolkit/error
1919
MVVMTK0012 | CommunityToolkit.Mvvm.SourceGenerators.ICommandGenerator | Error | See https://aka.ms/mvvmtoolkit/error
2020
MVVMTK0013 | CommunityToolkit.Mvvm.SourceGenerators.ICommandGenerator | Error | See https://aka.ms/mvvmtoolkit/error
21+
MVVMTK0014 | CommunityToolkit.Mvvm.SourceGenerators.ICommandGenerator | Error | See https://aka.ms/mvvmtoolkit/error

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ public static PropertyInfo GetInfo(IFieldSymbol fieldSymbol, out ImmutableArray<
4646
string fieldName = fieldSymbol.Name;
4747
string propertyName = GetGeneratedPropertyName(fieldSymbol);
4848

49+
// Check for name collisions
50+
if (fieldName == propertyName)
51+
{
52+
builder.Add(
53+
ObservablePropertyNameCollisionError,
54+
fieldSymbol,
55+
fieldSymbol.ContainingType,
56+
fieldSymbol.Name);
57+
}
58+
4959
ImmutableArray<string>.Builder propertyChangedNames = ImmutableArray.CreateBuilder<string>();
5060
ImmutableArray<string>.Builder propertyChangingNames = ImmutableArray.CreateBuilder<string>();
5161
ImmutableArray<string>.Builder notifiedCommandNames = ImmutableArray.CreateBuilder<string>();

CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,20 @@ internal static class DiagnosticDescriptors
219219
isEnabledByDefault: true,
220220
description: "Cannot apply the [ICommand] attribute specifying to include a cancel command to methods not mapping to an asynchronous command type accepting a cancellation token.",
221221
helpLinkUri: "https://aka.ms/mvvmtoolkit");
222+
223+
/// <summary>
224+
/// Gets a <see cref="DiagnosticDescriptor"/> indicating when a generated property created with <c>[ObservableProperty]</c> would collide with the source field.
225+
/// <para>
226+
/// Format: <c>"The field {0}.{1} cannot be used to generate an observable property, as its name would collide with the field name (instance fields should use the "lowerCamel", "_lowerCamel" or "m_lowerCamel" pattern)</c>.
227+
/// </para>
228+
/// </summary>
229+
public static readonly DiagnosticDescriptor ObservablePropertyNameCollisionError = new DiagnosticDescriptor(
230+
id: "MVVMTK0014",
231+
title: "Name collision for generated property",
232+
messageFormat: "The field {0}.{1} cannot be used to generate an observable property, as its name would collide with the field name (instance fields should use the \"lowerCamel\", \"_lowerCamel\" or \"m_lowerCamel\" pattern)",
233+
category: typeof(ObservablePropertyGenerator).FullName,
234+
defaultSeverity: DiagnosticSeverity.Error,
235+
isEnabledByDefault: true,
236+
description: $"The name of fields annotated with [ObservableProperty] should use \"lowerCamel\", \"_lowerCamel\" or \"m_lowerCamel\" pattern to avoid collisions with the generated properties.",
237+
helpLinkUri: "https://aka.ms/mvvmtoolkit");
222238
}

tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsDiagnostics.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,25 @@ private async Task GreetUserAsync(User user)
616616
VerifyGeneratedDiagnostics<ICommandGenerator>(source, "MVVMTK0013");
617617
}
618618

619+
[TestMethod]
620+
public void NameCollisionForGeneratedObservableProperty()
621+
{
622+
string source = @"
623+
using System.ComponentModel.DataAnnotations;
624+
using CommunityToolkit.Mvvm.ComponentModel;
625+
626+
namespace MyApp
627+
{
628+
public partial class SampleViewModel : ObservableObject
629+
{
630+
[ObservableProperty]
631+
private string Name;
632+
}
633+
}";
634+
635+
VerifyGeneratedDiagnostics<ObservablePropertyGenerator>(source, "MVVMTK0014");
636+
}
637+
619638
/// <summary>
620639
/// Verifies the output of a source generator.
621640
/// </summary>

0 commit comments

Comments
 (0)