Skip to content

Commit

Permalink
Invalid interface/property match in AllowMissingMembers mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
beakona committed Dec 7, 2023
1 parent 20ada85 commit 83080f9
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 16 deletions.
15 changes: 14 additions & 1 deletion AutoInterfaceSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ public static void Main()
//int g = 1;
//p.Method(1, out f, ref g, "t", 1, 2, 3);

//IPrintableComplex p = new Person2();
IPrintableComplex p = new Person2();
//var c = p.Count;
p.Count = 3;
//p.Print();
//p.PrintComplex();
}
Expand All @@ -22,12 +24,23 @@ interface IPrintableComplex
{
void Print();
void PrintComplex();
int Count { set; }
}

public class SimplePrinter // : IPrintableComplex
{
public void Print() { Console.WriteLine("OK"); }
public void PrintComplex() { Console.WriteLine("OKC"); }
public int Count
{
get
{
return 0;
}
set
{
}
}
}

public partial class Person2 /*: IPrintableComplex*/
Expand Down
10 changes: 5 additions & 5 deletions BeaKona.AutoInterfaceGenerator/AutoInterfaceSourceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -534,8 +534,8 @@ private static bool IsDuckImplementation(ITypeSymbol receiverType, ITypeSymbol i
}
else
{
return receiverType.IsAllInterfaceMembersImplementedBySignature(interfaceType) &&
(includeBaseInterfaces == false || interfaceType.AllInterfaces.All(i => receiverType.IsMatchByTypeOrImplementsInterface(i) || receiverType.IsAllInterfaceMembersImplementedBySignature(i)));
return receiverType.IsAllInterfaceMembersImplementedBySignature(interfaceType, true) &&
(includeBaseInterfaces == false || interfaceType.AllInterfaces.All(i => receiverType.IsMatchByTypeOrImplementsInterface(i) || receiverType.IsAllInterfaceMembersImplementedBySignature(i, true)));
}
}

Expand Down Expand Up @@ -619,14 +619,14 @@ bool ShouldGenerate(ISymbol member)
{
if (reference.AllowMissingMembers)
{
if (reference.ReceiverType.IsMemberImplementedBySignature(member) == false)
if (reference.ReceiverType.IsMemberImplementedBySignature(member, false) == false)
{
return false;
}
}
}

var memberImplementedBySignature = type.IsMemberImplementedBySignature(member);
var memberImplementedBySignature = type.IsMemberImplementedBySignature(member, true);
var memberImplementedExplicitly = type.IsMemberImplementedExplicitly(member);

foreach (var reference in references)
Expand All @@ -645,7 +645,7 @@ bool ShouldBeReferenced(ISymbol member, IMemberInfo reference)
if (reference.AllowMissingMembers)
{
//AllowMissingMembers case
return reference.ReceiverType.IsMemberImplementedBySignature(member);
return reference.ReceiverType.IsMemberImplementedBySignature(member, false);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<RepositoryUrl>https://github.com/beakona/AutoInterface</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);_AddAnalyzersToOutput</TargetsForTfmSpecificContentInPackage>
<Version>1.0.34</Version>
<Version>1.0.35</Version>
<IsRoslynComponent>true</IsRoslynComponent>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>
Expand Down
37 changes: 34 additions & 3 deletions BeaKona.AutoInterfaceGenerator/ComparerBySignature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

internal sealed class ComparerBySignature : IEqualityComparer<ISymbol>
{
public ComparerBySignature(bool strict)
{
this.strict = strict;
}

private readonly bool strict;
private readonly Dictionary<ITypeParameterSymbol, List<ITypeParameterSymbol>> aliasesByKey = new(SymbolEqualityComparer.Default);

public int GetHashCode(ISymbol obj) => throw new NotSupportedException();//SymbolEqualityComparer.Default.GetHashCode(obj);
Expand Down Expand Up @@ -108,9 +114,34 @@ public bool Equals(ISymbol s1, ISymbol s2)
{
if (this.Equals(v1.Type, v2.Type))
{
static bool HasGetter(IPropertySymbol p) => p.GetMethod != null;
static bool HasSetter(IPropertySymbol p) => p.SetMethod != null;
if (HasGetter(v1) == HasGetter(v2) && HasSetter(v1) == HasSetter(v2))
static bool IsMatch(IPropertySymbol x, IPropertySymbol y, bool strict)
{
static bool HasGetter(IPropertySymbol p) => p.GetMethod != null;
static bool HasSetter(IPropertySymbol p) => p.SetMethod != null;

var hasGetter = HasGetter(x);
var requireGetter = HasGetter(y);
var hasSetter = HasSetter(x);
var requireSetter = HasSetter(y);

if (strict)
{
return hasGetter == requireGetter && hasSetter == requireSetter;
}
else
{
if ((requireGetter && hasGetter == false) || (requireSetter && hasSetter == false))
{
return false;
}
else
{
return true;
}
}
}

if (IsMatch(v1, v2, this.strict))
{
if (v1.IsIndexer)
{
Expand Down
12 changes: 6 additions & 6 deletions BeaKona.AutoInterfaceGenerator/ITypeSymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ public static bool IsMemberImplementedExplicitly(this ITypeSymbol @this, ISymbol
// return implementation is not null && implementation.IsStatic == false && implementation.ContainingType.Equals(@this, SymbolEqualityComparer.Default);
//}

public static ISymbol? FindImplementationForInterfaceMemberBySignature(this ITypeSymbol @this, ISymbol interfaceMember)
public static ISymbol? FindImplementationForInterfaceMemberBySignature(this ITypeSymbol @this, ISymbol interfaceMember, bool strict)
{
string name = interfaceMember.Name;
if (string.IsNullOrEmpty(name) == false)
{
foreach (ISymbol member in @this.GetMembers(name).Where(i => i.Kind == interfaceMember.Kind))
{
var comparer = new ComparerBySignature();
var comparer = new ComparerBySignature(strict);
if (comparer.Equals(member, interfaceMember))
{
return member;
Expand All @@ -101,12 +101,12 @@ public static bool IsMemberImplementedExplicitly(this ITypeSymbol @this, ISymbol
return null;
}

public static bool IsMemberImplementedBySignature(this ITypeSymbol @this, ISymbol member)
public static bool IsMemberImplementedBySignature(this ITypeSymbol @this, ISymbol member, bool strict)
{
return @this.FindImplementationForInterfaceMemberBySignature(member) != null;
return @this.FindImplementationForInterfaceMemberBySignature(member, strict) != null;
}

public static bool IsAllInterfaceMembersImplementedBySignature(this ITypeSymbol @this, ITypeSymbol @interface)
public static bool IsAllInterfaceMembersImplementedBySignature(this ITypeSymbol @this, ITypeSymbol @interface, bool strict)
{
if (@interface.TypeKind != TypeKind.Interface)
{
Expand All @@ -115,7 +115,7 @@ public static bool IsAllInterfaceMembersImplementedBySignature(this ITypeSymbol

foreach (var member in @interface.GetMembers())
{
if (@this.IsMemberImplementedBySignature(member) == false)
if (@this.IsMemberImplementedBySignature(member, strict) == false)
{
return false;
}
Expand Down

0 comments on commit 83080f9

Please sign in to comment.