Skip to content

Commit 333265f

Browse files
authored
Merge pull request #539 from CommunityToolkit/dev/skip-diagnostics-within-constructors
Skip field reference diagnostics from constructors
2 parents 98aff98 + 1953935 commit 333265f

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/Analyzers/FieldReferenceForObservablePropertyFieldAnalyzer.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,25 @@ public override void Initialize(AnalysisContext context)
2828
context.RegisterOperationAction(static context =>
2929
{
3030
// We're only looking for references to fields that could potentially be observable properties
31-
if (context.Operation is not IFieldReferenceOperation { Field: IFieldSymbol { IsStatic: false, IsConst: false, IsImplicitlyDeclared: false, ContainingType: INamedTypeSymbol } fieldSymbol })
31+
if (context.Operation is not IFieldReferenceOperation
32+
{
33+
Field: IFieldSymbol { IsStatic: false, IsConst: false, IsImplicitlyDeclared: false, ContainingType: INamedTypeSymbol } fieldSymbol,
34+
Instance.Type: ITypeSymbol typeSymbol
35+
})
36+
{
37+
return;
38+
}
39+
40+
// Special case field references from within a constructor and don't ever emit warnings for them. The point of this
41+
// analyzer is to prevent mistakes when users assign a field instead of a property and then get confused when the
42+
// property changed event is not raised. But this would never be the case from a constructur anyway, given that
43+
// no handler for that event would possibly be present. Suppressing warnings in this cases though will help to
44+
// avoid scenarios where people get nullability warnings they cannot suppress, in case they were pushed by the
45+
// analyzer in the MVVM Toolkit to not assign a field marked with a non-nullable reference type. Ideally this
46+
// would be solved by habing the generated setter be marked with [MemberNotNullIfNotNull("field", "value")],
47+
// but such an annotation does not currently exist.
48+
if (context.ContainingSymbol is IMethodSymbol { MethodKind: MethodKind.Constructor, ContainingType: INamedTypeSymbol instanceType } &&
49+
SymbolEqualityComparer.Default.Equals(instanceType, typeSymbol))
3250
{
3351
return;
3452
}

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,29 @@ void M()
16021602
await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration<FieldReferenceForObservablePropertyFieldAnalyzer>(source, LanguageVersion.CSharp8);
16031603
}
16041604

1605+
[TestMethod]
1606+
public async Task FieldReferenceToFieldWithObservablePropertyAttribute_DoesNotEmitWarningFromWithinConstructor()
1607+
{
1608+
string source = """
1609+
using CommunityToolkit.Mvvm.ComponentModel;
1610+
1611+
partial class MyViewModel : ObservableObject
1612+
{
1613+
[ObservableProperty]
1614+
int number;
1615+
1616+
public MyViewModel()
1617+
{
1618+
number = 42;
1619+
var temp = number;
1620+
ref var x = ref number;
1621+
}
1622+
}
1623+
""";
1624+
1625+
await VerifyAnalyzerDiagnosticsAndSuccessfulGeneration<FieldReferenceForObservablePropertyFieldAnalyzer>(source, LanguageVersion.CSharp8);
1626+
}
1627+
16051628
/// <summary>
16061629
/// Verifies the diagnostic errors for a given analyzer, and that all available source generators can run successfully with the input source (including subsequent compilation).
16071630
/// </summary>

0 commit comments

Comments
 (0)