diff --git a/src/CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.projitems b/src/CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.projitems
index 988d87a15..86d4254a3 100644
--- a/src/CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.projitems
+++ b/src/CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.projitems
@@ -40,6 +40,9 @@
+
+
+
diff --git a/src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs b/src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs
index 6dc483e6b..ce3c5d98c 100644
--- a/src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs
+++ b/src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs
@@ -145,13 +145,6 @@ public static bool TryGetInfo(
// Validate the target type
if (!IsTargetTypeValid(memberSymbol, out bool shouldInvokeOnPropertyChanging))
{
- builder.Add(
- InvalidContainingTypeForObservablePropertyMemberError,
- memberSymbol,
- memberSyntax.Kind().ToFieldOrPropertyKeyword(),
- memberSymbol.ContainingType,
- memberSymbol.Name);
-
propertyInfo = null;
diagnostics = builder.ToImmutable();
@@ -173,12 +166,6 @@ public static bool TryGetInfo(
// Check for name collisions (only for fields)
if (fieldName == propertyName && memberSyntax.IsKind(SyntaxKind.FieldDeclaration))
{
- builder.Add(
- ObservablePropertyNameCollisionError,
- memberSymbol,
- memberSymbol.ContainingType,
- memberSymbol.Name);
-
propertyInfo = null;
diagnostics = builder.ToImmutable();
@@ -193,12 +180,6 @@ public static bool TryGetInfo(
// Check for special cases that are explicitly not allowed
if (IsGeneratedPropertyInvalid(propertyName, GetPropertyType(memberSymbol)))
{
- builder.Add(
- InvalidObservablePropertyError,
- memberSymbol,
- memberSymbol.ContainingType,
- memberSymbol.Name);
-
propertyInfo = null;
diagnostics = builder.ToImmutable();
@@ -440,7 +421,7 @@ private static bool IsTargetTypeValid(ISymbol memberSymbol, out bool shouldInvok
/// The property name.
/// The property type.
/// Whether the generated property is invalid.
- private static bool IsGeneratedPropertyInvalid(string propertyName, ITypeSymbol propertyType)
+ public static bool IsGeneratedPropertyInvalid(string propertyName, ITypeSymbol propertyType)
{
// If the generated property name is called "Property" and the type is either object or it is PropertyChangedEventArgs or
// PropertyChangingEventArgs (or a type derived from either of those two types), consider it invalid. This is needed because
@@ -1506,7 +1487,7 @@ public static ImmutableArray GetOnPropertyChangeMethods
///
/// The input instance to process.
/// The type of .
- private static ITypeSymbol GetPropertyType(ISymbol memberSymbol)
+ public static ITypeSymbol GetPropertyType(ISymbol memberSymbol)
{
// Check if the member is a property first
if (memberSymbol is IPropertySymbol propertySymbol)
diff --git a/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/InvalidGeneratedPropertyObservablePropertyAttributeAnalyzer.cs b/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/InvalidGeneratedPropertyObservablePropertyAttributeAnalyzer.cs
new file mode 100644
index 000000000..e960cf47e
--- /dev/null
+++ b/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/InvalidGeneratedPropertyObservablePropertyAttributeAnalyzer.cs
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Immutable;
+using System.Linq;
+using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using static CommunityToolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
+
+namespace CommunityToolkit.Mvvm.SourceGenerators;
+
+///
+/// A diagnostic analyzer that generates an error when a field or property with [ObservableProperty] is not valid (special cases)
+///
+[DiagnosticAnalyzer(LanguageNames.CSharp)]
+public sealed class InvalidGeneratedPropertyObservablePropertyAttributeAnalyzer : DiagnosticAnalyzer
+{
+ ///
+ public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(InvalidObservablePropertyError);
+
+ ///
+ public override void Initialize(AnalysisContext context)
+ {
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+ context.EnableConcurrentExecution();
+
+ context.RegisterCompilationStartAction(static context =>
+ {
+ // Get the symbol for [ObservableProperty] and the event args we need
+ if (context.Compilation.GetTypeByMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservablePropertyAttribute") is not INamedTypeSymbol observablePropertySymbol ||
+ context.Compilation.GetTypeByMetadataName("System.ComponentModel.PropertyChangedEventArgs") is not INamedTypeSymbol propertyChangedEventArgsSymbol ||
+ context.Compilation.GetTypeByMetadataName("System.ComponentModel.PropertyChangingEventArgs") is not INamedTypeSymbol propertyChangingEventArgsSymbol)
+ {
+ return;
+ }
+
+ context.RegisterSymbolAction(context =>
+ {
+ // Validate that we do have a field or a property
+ if (context.Symbol is not (IFieldSymbol or IPropertySymbol))
+ {
+ return;
+ }
+
+ // Ensure we do have the [ObservableProperty] attribute
+ if (!context.Symbol.HasAttributeWithType(observablePropertySymbol))
+ {
+ return;
+ }
+
+ ITypeSymbol propertyType = ObservablePropertyGenerator.Execute.GetPropertyType(context.Symbol);
+ string propertyName = ObservablePropertyGenerator.Execute.GetGeneratedPropertyName(context.Symbol);
+
+ // Same logic as 'IsGeneratedPropertyInvalid' in the generator
+ if (propertyName == "Property")
+ {
+ // Check for collisions with the generated helpers and the property, only happens with these 3 types
+ if (propertyType.SpecialType == SpecialType.System_Object ||
+ propertyType.HasOrInheritsFromType(propertyChangedEventArgsSymbol) ||
+ propertyType.HasOrInheritsFromType(propertyChangingEventArgsSymbol))
+ {
+ context.ReportDiagnostic(Diagnostic.Create(
+ InvalidObservablePropertyError,
+ context.Symbol.Locations.FirstOrDefault(),
+ context.Symbol.Kind.ToFieldOrPropertyKeyword(),
+ context.Symbol.ContainingType,
+ context.Symbol.Name));
+ }
+ }
+ }, SymbolKind.Field, SymbolKind.Property);
+ });
+ }
+}
diff --git a/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/InvalidTargetObservablePropertyAttributeAnalyzer.cs b/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/InvalidTargetObservablePropertyAttributeAnalyzer.cs
new file mode 100644
index 000000000..70c645227
--- /dev/null
+++ b/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/InvalidTargetObservablePropertyAttributeAnalyzer.cs
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Immutable;
+using System.Linq;
+using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using static CommunityToolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
+
+namespace CommunityToolkit.Mvvm.SourceGenerators;
+
+///
+/// A diagnostic analyzer that generates an error when a field or property with [ObservableProperty] is not a valid target.
+///
+[DiagnosticAnalyzer(LanguageNames.CSharp)]
+public sealed class InvalidTargetObservablePropertyAttributeAnalyzer : DiagnosticAnalyzer
+{
+ ///
+ public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(InvalidContainingTypeForObservablePropertyMemberError);
+
+ ///
+ public override void Initialize(AnalysisContext context)
+ {
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+ context.EnableConcurrentExecution();
+
+ context.RegisterCompilationStartAction(static context =>
+ {
+ // Get the required symbols for the analyzer
+ if (context.Compilation.GetTypeByMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservablePropertyAttribute") is not INamedTypeSymbol observablePropertySymbol ||
+ context.Compilation.GetTypeByMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableObject") is not INamedTypeSymbol observableObjectSymbol ||
+ context.Compilation.GetTypeByMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableObjectAttribute") is not INamedTypeSymbol observableObjectAttributeSymbol ||
+ context.Compilation.GetTypeByMetadataName("CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute") is not INamedTypeSymbol notifyPropertyChangedAttributeSymbol)
+ {
+ return;
+ }
+
+ context.RegisterSymbolAction(context =>
+ {
+ // Validate that we do have a field or a property
+ if (context.Symbol is not (IFieldSymbol or IPropertySymbol))
+ {
+ return;
+ }
+
+ // Ensure we do have the [ObservableProperty] attribute
+ if (!context.Symbol.HasAttributeWithType(observablePropertySymbol))
+ {
+ return;
+ }
+
+ // Same logic as in 'IsTargetTypeValid' in the generator
+ bool isObservableObject = context.Symbol.ContainingType.InheritsFromType(observableObjectSymbol);
+ bool hasObservableObjectAttribute = context.Symbol.ContainingType.HasOrInheritsAttributeWithType(observableObjectAttributeSymbol);
+ bool hasINotifyPropertyChangedAttribute = context.Symbol.ContainingType.HasOrInheritsAttributeWithType(notifyPropertyChangedAttributeSymbol);
+
+ // Emit the diagnostic if the target is not valid
+ if (!isObservableObject && !hasObservableObjectAttribute && !hasINotifyPropertyChangedAttribute)
+ {
+ context.ReportDiagnostic(Diagnostic.Create(
+ InvalidContainingTypeForObservablePropertyMemberError,
+ context.Symbol.Locations.FirstOrDefault(),
+ context.Symbol.Kind.ToFieldOrPropertyKeyword(),
+ context.Symbol.ContainingType,
+ context.Symbol.Name));
+ }
+ }, SymbolKind.Field, SymbolKind.Property);
+ });
+ }
+}
diff --git a/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/PropertyNameCollisionObservablePropertyAttributeAnalyzer.cs b/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/PropertyNameCollisionObservablePropertyAttributeAnalyzer.cs
new file mode 100644
index 000000000..06894ac25
--- /dev/null
+++ b/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/PropertyNameCollisionObservablePropertyAttributeAnalyzer.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Immutable;
+using System.Linq;
+using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using static CommunityToolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
+
+namespace CommunityToolkit.Mvvm.SourceGenerators;
+
+///
+/// A diagnostic analyzer that generates an error when a generated property from [ObservableProperty] would collide with the field name.
+///
+[DiagnosticAnalyzer(LanguageNames.CSharp)]
+public sealed class PropertyNameCollisionObservablePropertyAttributeAnalyzer : DiagnosticAnalyzer
+{
+ ///
+ public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(ObservablePropertyNameCollisionError);
+
+ ///
+ public override void Initialize(AnalysisContext context)
+ {
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+ context.EnableConcurrentExecution();
+
+ context.RegisterCompilationStartAction(static context =>
+ {
+ // Get the symbol for [ObservableProperty]
+ if (context.Compilation.GetTypeByMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservablePropertyAttribute") is not INamedTypeSymbol observablePropertySymbol)
+ {
+ return;
+ }
+
+ context.RegisterSymbolAction(context =>
+ {
+ // Ensure we do have a valid field
+ if (context.Symbol is not IFieldSymbol fieldSymbol)
+ {
+ return;
+ }
+
+ // We only care if the field has [ObservableProperty]
+ if (!fieldSymbol.HasAttributeWithType(observablePropertySymbol))
+ {
+ return;
+ }
+
+ // Emit the diagnostic if there is a name collision
+ if (fieldSymbol.Name == ObservablePropertyGenerator.Execute.GetGeneratedPropertyName(fieldSymbol))
+ {
+ context.ReportDiagnostic(Diagnostic.Create(
+ ObservablePropertyNameCollisionError,
+ fieldSymbol.Locations.FirstOrDefault(),
+ fieldSymbol.ContainingType,
+ fieldSymbol.Name));
+ }
+ }, SymbolKind.Field);
+ });
+ }
+}
diff --git a/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs b/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs
index 74986d3ce..6ac4c7950 100644
--- a/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs
+++ b/src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs
@@ -407,17 +407,17 @@ internal static class DiagnosticDescriptors
///
/// Gets a indicating when a generated property created with [ObservableProperty] would cause conflicts with other generated members.
///
- /// Format: "The field {0}.{1} cannot be used to generate an observable property, as its name or type would cause conflicts with other generated members".
+ /// Format: "The {0} {1}.{2} cannot be used to generate an observable property, as its name or type would cause conflicts with other generated members".
///
///
public static readonly DiagnosticDescriptor InvalidObservablePropertyError = new DiagnosticDescriptor(
id: "MVVMTK0024",
title: "Invalid generated property declaration",
- messageFormat: "The field {0}.{1} cannot be used to generate an observable property, as its name or type would cause conflicts with other generated members",
+ messageFormat: "The {0} {1}.{2} cannot be used to generate an observable property, as its name or type would cause conflicts with other generated members",
category: typeof(ObservablePropertyGenerator).FullName,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true,
- description: "The fields annotated with [ObservableProperty] cannot result in a property name or have a type that would cause conflicts with other generated members.",
+ description: "The fields and properties annotated with [ObservableProperty] cannot result in a property name or have a type that would cause conflicts with other generated members.",
helpLinkUri: "https://aka.ms/mvvmtoolkit/errors/mvvmtk0024");
///
diff --git a/src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/ITypeSymbolExtensions.cs b/src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/ITypeSymbolExtensions.cs
index 6e976501b..b79f743b3 100644
--- a/src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/ITypeSymbolExtensions.cs
+++ b/src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/ITypeSymbolExtensions.cs
@@ -33,6 +33,25 @@ public static bool HasOrInheritsFromFullyQualifiedMetadataName(this ITypeSymbol
return false;
}
+ ///
+ /// Checks whether or not a given has or inherits from a specified type.
+ ///
+ /// The target instance to check.
+ /// The type to check for inheritance.
+ /// Whether or not is or inherits from .
+ public static bool HasOrInheritsFromType(this ITypeSymbol typeSymbol, ITypeSymbol baseTypeSymbol)
+ {
+ for (ITypeSymbol? currentType = typeSymbol; currentType is not null; currentType = currentType.BaseType)
+ {
+ if (SymbolEqualityComparer.Default.Equals(currentType, baseTypeSymbol))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
///
/// Checks whether or not a given inherits from a specified type.
///
@@ -60,7 +79,7 @@ public static bool InheritsFromFullyQualifiedMetadataName(this ITypeSymbol typeS
/// Checks whether or not a given inherits from a specified type.
///
/// The target instance to check.
- /// The instane to check for inheritance from.
+ /// The instance to check for inheritance from.
/// Whether or not inherits from .
public static bool InheritsFromType(this ITypeSymbol typeSymbol, ITypeSymbol baseTypeSymbol)
{
diff --git a/tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsDiagnostics.cs b/tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsDiagnostics.cs
index 605651520..bef6d9c35 100644
--- a/tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsDiagnostics.cs
+++ b/tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsDiagnostics.cs
@@ -664,7 +664,7 @@ private async Task GreetUserAsync(User user)
}
[TestMethod]
- public void NameCollisionForGeneratedObservableProperty()
+ public async Task NameCollisionForGeneratedObservableProperty_PascalCaseField_Warns()
{
string source = """
using CommunityToolkit.Mvvm.ComponentModel;
@@ -674,12 +674,51 @@ namespace MyApp
public partial class SampleViewModel : ObservableObject
{
[ObservableProperty]
- private string Name;
+ private string {|MVVMTK0014:Name|};
}
}
""";
- VerifyGeneratedDiagnostics(source, "MVVMTK0014");
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp8);
+ }
+
+ [TestMethod]
+ public async Task NameCollisionForGeneratedObservableProperty_CamelCaseField_DoesNotWarn()
+ {
+ string source = """
+ using CommunityToolkit.Mvvm.ComponentModel;
+
+ namespace MyApp
+ {
+ public partial class SampleViewModel : ObservableObject
+ {
+ [ObservableProperty]
+ private string name;
+ }
+ }
+ """;
+
+ // Using C# 9 here because the generated code will emit [MemberNotNull] on the property setter, which requires C# 9
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp9);
+ }
+
+ [TestMethod]
+ public async Task NameCollisionForGeneratedObservableProperty_PascalCaseProperty_DoesNotWarn()
+ {
+ string source = """
+ using CommunityToolkit.Mvvm.ComponentModel;
+
+ namespace MyApp
+ {
+ public partial class SampleViewModel : ObservableObject
+ {
+ [ObservableProperty]
+ private string Name { get; set; }
+ }
+ }
+ """;
+
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp8);
}
[TestMethod]
@@ -1006,24 +1045,85 @@ public partial class A
}
[TestMethod]
- public void InvalidContainingTypeForObservablePropertyFieldError()
+ public async Task InvalidContainingTypeForObservableProperty_OnField_Warns()
{
string source = """
+ using System.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
namespace MyApp
{
public partial class MyViewModel : INotifyPropertyChanged
+ {
+ [ObservableProperty]
+ public int {|MVVMTK0019:number|};
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ }
+ }
+ """;
+
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp8);
+ }
+
+ [TestMethod]
+ public async Task InvalidContainingTypeForObservableProperty_OnField_InValidType_DoesNotWarn()
+ {
+ string source = """
+ using CommunityToolkit.Mvvm.ComponentModel;
+
+ namespace MyApp
+ {
+ public partial class MyViewModel : ObservableObject
{
[ObservableProperty]
public int number;
+ }
+ }
+ """;
+
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp8);
+ }
+
+ [TestMethod]
+ public async Task InvalidContainingTypeForObservableProperty_OnPartialProperty_Warns()
+ {
+ string source = """
+ using System.ComponentModel;
+ using CommunityToolkit.Mvvm.ComponentModel;
+
+ namespace MyApp
+ {
+ public partial class MyViewModel : INotifyPropertyChanged
+ {
+ [ObservableProperty]
+ public int {|MVVMTK0019:Number|} { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
}
""";
- VerifyGeneratedDiagnostics(source, "MVVMTK0019");
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp8);
+ }
+
+ [TestMethod]
+ public async Task InvalidContainingTypeForObservableProperty_OnPartialProperty_InValidType_DoesNotWarn()
+ {
+ string source = """
+ using CommunityToolkit.Mvvm.ComponentModel;
+
+ namespace MyApp
+ {
+ public partial class MyViewModel : ObservableObject
+ {
+ [ObservableProperty]
+ public int Number { get; set; }
+ }
+ }
+ """;
+
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp8);
}
[TestMethod]
@@ -1206,7 +1306,26 @@ private void GreetUser(object value)
}
[TestMethod]
- public void InvalidObservablePropertyError_Object()
+ public async Task InvalidObservablePropertyError_Object()
+ {
+ string source = """
+ using CommunityToolkit.Mvvm.ComponentModel;
+
+ namespace MyApp
+ {
+ public partial class MyViewModel : ObservableObject
+ {
+ [ObservableProperty]
+ public object {|MVVMTK0024:property|};
+ }
+ }
+ """;
+
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp9);
+ }
+
+ [TestMethod]
+ public async Task InvalidObservablePropertyError_Object_WithProperty()
{
string source = """
using CommunityToolkit.Mvvm.ComponentModel;
@@ -1216,16 +1335,16 @@ namespace MyApp
public partial class MyViewModel : ObservableObject
{
[ObservableProperty]
- public object property;
+ public object {|MVVMTK0024:Property|} { get; set; }
}
}
""";
- VerifyGeneratedDiagnostics(source, "MVVMTK0024");
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.Preview);
}
[TestMethod]
- public void InvalidObservablePropertyError_PropertyChangingEventArgs()
+ public async Task InvalidObservablePropertyError_PropertyChangingEventArgs()
{
string source = """
using System.ComponentModel;
@@ -1236,16 +1355,16 @@ namespace MyApp
public partial class MyViewModel : ObservableObject
{
[ObservableProperty]
- public PropertyChangingEventArgs property;
+ public PropertyChangingEventArgs {|MVVMTK0024:property|};
}
}
""";
- VerifyGeneratedDiagnostics(source, "MVVMTK0024");
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp9);
}
[TestMethod]
- public void InvalidObservablePropertyError_PropertyChangedEventArgs()
+ public async Task InvalidObservablePropertyError_PropertyChangedEventArgs()
{
string source = """
using System.ComponentModel;
@@ -1256,16 +1375,16 @@ namespace MyApp
public partial class MyViewModel : ObservableObject
{
[ObservableProperty]
- public PropertyChangedEventArgs property;
+ public PropertyChangedEventArgs {|MVVMTK0024:property|};
}
}
""";
- VerifyGeneratedDiagnostics(source, "MVVMTK0024");
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp9);
}
[TestMethod]
- public void InvalidObservablePropertyError_CustomTypeDerivedFromPropertyChangedEventArgs()
+ public async Task InvalidObservablePropertyError_CustomTypeDerivedFromPropertyChangedEventArgs()
{
string source = """
using System.ComponentModel;
@@ -1284,12 +1403,12 @@ public MyPropertyChangedEventArgs(string propertyName)
public partial class MyViewModel : ObservableObject
{
[ObservableProperty]
- public MyPropertyChangedEventArgs property;
+ public MyPropertyChangedEventArgs {|MVVMTK0024:property|};
}
}
""";
- VerifyGeneratedDiagnostics(source, "MVVMTK0024");
+ await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp9);
}
[TestMethod]