Skip to content

Commit 69707bf

Browse files
committed
Fix false positive diagnostics for inherited members
1 parent e0016b7 commit 69707bf

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,13 @@ private static bool TryGatherDependentPropertyChangedNames(
187187
// Validates a property name using existing properties
188188
bool IsPropertyNameValid(string propertyName)
189189
{
190-
return fieldSymbol.ContainingType.GetMembers(propertyName).OfType<IPropertySymbol>().Any();
190+
return fieldSymbol.ContainingType.GetAllMembers(propertyName).OfType<IPropertySymbol>().Any();
191191
}
192192

193193
// Validate a property name including generated properties too
194194
bool IsPropertyNameValidWithGeneratedMembers(string propertyName)
195195
{
196-
foreach (ISymbol member in fieldSymbol.ContainingType.GetMembers())
196+
foreach (ISymbol member in fieldSymbol.ContainingType.GetAllMembers())
197197
{
198198
if (member is IFieldSymbol otherFieldSymbol &&
199199
!SymbolEqualityComparer.Default.Equals(fieldSymbol, otherFieldSymbol) &&
@@ -256,7 +256,7 @@ bool IsCommandNameValid(string commandName, out bool shouldLookForGeneratedMembe
256256
{
257257
// Each target must be a string matching the name of a property from the containing type of the annotated field, and the
258258
// property must be of type IRelayCommand, or any type that implements that interface (to avoid generating invalid code).
259-
if (fieldSymbol.ContainingType.GetMembers(commandName).OfType<IPropertySymbol>().FirstOrDefault() is IPropertySymbol propertySymbol)
259+
if (fieldSymbol.ContainingType.GetAllMembers(commandName).OfType<IPropertySymbol>().FirstOrDefault() is IPropertySymbol propertySymbol)
260260
{
261261
// If there is a property member with the specified name, check that it's valid. If it isn't, the
262262
// target is definitely not valid, and the additional checks below can just be skipped. The property
@@ -285,7 +285,7 @@ bool IsCommandNameValid(string commandName, out bool shouldLookForGeneratedMembe
285285
// Validate a command name including generated command too
286286
bool IsCommandNameValidWithGeneratedMembers(string commandName)
287287
{
288-
foreach (ISymbol member in fieldSymbol.ContainingType.GetMembers())
288+
foreach (ISymbol member in fieldSymbol.ContainingType.GetAllMembers())
289289
{
290290
if (member is IMethodSymbol methodSymbol &&
291291
methodSymbol.HasAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.Input.ICommandAttribute") &&

CommunityToolkit.Mvvm.SourceGenerators/Extensions/INamedTypeSymbolExtensions.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Collections.Generic;
56
using System.Text;
67
using Microsoft.CodeAnalysis;
78

@@ -39,4 +40,37 @@ static StringBuilder BuildFrom(ISymbol? symbol, StringBuilder builder)
3940
// those characters at the moment, see: https://github.com/dotnet/roslyn/issues/58476.
4041
return BuildFrom(symbol, new StringBuilder(256)).ToString().Replace('`', '-').Replace('+', '.');
4142
}
43+
44+
/// <summary>
45+
/// Gets all member symbols from a given <see cref="INamedTypeSymbol"/> instance, including inherited ones.
46+
/// </summary>
47+
/// <param name="symbol">The input <see cref="INamedTypeSymbol"/> instance.</param>
48+
/// <returns>A sequence of all member symbols for <paramref name="symbol"/>.</returns>
49+
public static IEnumerable<ISymbol> GetAllMembers(this INamedTypeSymbol symbol)
50+
{
51+
for (INamedTypeSymbol? currentSymbol = symbol; currentSymbol is { SpecialType: not SpecialType.System_Object }; currentSymbol = currentSymbol.BaseType)
52+
{
53+
foreach (ISymbol memberSymbol in currentSymbol.GetMembers())
54+
{
55+
yield return memberSymbol;
56+
}
57+
}
58+
}
59+
60+
/// <summary>
61+
/// Gets all member symbols from a given <see cref="INamedTypeSymbol"/> instance, including inherited ones.
62+
/// </summary>
63+
/// <param name="symbol">The input <see cref="INamedTypeSymbol"/> instance.</param>
64+
/// <param name="name">The name of the members to look for.</param>
65+
/// <returns>A sequence of all member symbols for <paramref name="symbol"/>.</returns>
66+
public static IEnumerable<ISymbol> GetAllMembers(this INamedTypeSymbol symbol, string name)
67+
{
68+
for (INamedTypeSymbol? currentSymbol = symbol; currentSymbol is not null; currentSymbol = currentSymbol.BaseType)
69+
{
70+
foreach (ISymbol memberSymbol in currentSymbol.GetMembers(name))
71+
{
72+
yield return memberSymbol;
73+
}
74+
}
75+
}
4276
}

0 commit comments

Comments
 (0)