Skip to content

Fix S1144 FP: Ignore unused Deconstruct methods #9470

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,16 @@ private static HashSet<ISymbol> GetUnusedSymbols(CSharpSymbolUsageCollector usag
.Except(usageCollector.UsedSymbols)
.Where(x => !IsMentionedInDebuggerDisplay(x, usageCollector)
&& !IsAccessorUsed(x, usageCollector)
&& !IsDeconstructMethod(x)
&& !usageCollector.PrivateAttributes.Contains(x)
&& !IsUsedWithReflection(x, usageCollector.TypesUsedWithReflection))
.ToHashSet();

private static bool IsDeconstructMethod(ISymbol symbol) =>
symbol is IMethodSymbol { Name: "Deconstruct", Parameters.Length: > 0 } method
&& method.ReturnType.Is(KnownType.Void)
&& method.Parameters.All(x => x.RefKind == RefKind.Out);

private static bool IsAccessorUsed(ISymbol symbol, CSharpSymbolUsageCollector usageCollector) =>
symbol is IMethodSymbol { AssociatedSymbol: IPropertySymbol property } accessor
&& usageCollector.PropertyAccess.TryGetValue(property, out var access)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,32 +60,29 @@ private sealed class PublicDeconstructWithInnerType
{
public void Deconstruct(out object a, out InternalDeconstruct b) { a = b = null; }

// deconstructors must be public, internal or protected internal
private void Deconstruct(out object a, out object b) { a = b = null; } // Noncompliant
private void Deconstruct(out object a, out object b) { a = b = null; } // Compliant, Deconstruct methods are ignored
}

internal sealed class InternalDeconstruct
{
internal void Deconstruct(out object a, out object b) { a = b = null; }

// deconstructors must be public, internal or protected internal
private void Deconstruct(out object a, out string b, out string c) { a = b = c = null; } // Noncompliant
private void Deconstruct(out object a, out string b, out string c) { a = b = c = null; } // Compliant, Deconstruct methods are ignored
}

private class PublicDeconstruct
{
public void Deconstruct(out object a, out object b, out object c) { a = b = c = null; }

// deconstructors must be public, internal or protected internal
protected void Deconstruct(out string a, out string b, out string c) { a = b = c = null; } // Noncompliant
private void Deconstruct(out object a, out string b, out string c) { a = b = c = null; } // Noncompliant
protected void Deconstruct(out string a, out string b, out string c) { a = b = c = null; } // Compliant, Deconstruct methods are ignored
private void Deconstruct(out object a, out string b, out string c) { a = b = c = null; } // Compliant, Deconstruct methods are ignored
}

private sealed class MultipleDeconstructors
{
public void Deconstruct(out object a, out object b, out object c) { a = b = c = null; }

public void Deconstruct(out object a, out object b) // Noncompliant
public void Deconstruct(out object a, out object b) // Compliant, Deconstruct methods are ignored
{
a = b = null;
}
Expand All @@ -95,25 +92,37 @@ private class ProtectedInternalDeconstruct
{
protected internal void Deconstruct(out object a, out object b) { a = b = null; }

protected internal void Deconstruct(out object a, out object b, out object c) { a = b = c = null; } // Noncompliant
protected internal void Deconstruct(out object a, out object b, out object c) { a = b = c = null; } // Compliant, Deconstruct methods are ignored
}

private class Ambiguous
{
public void Deconstruct(out string a, out string b, out string c) { a = b = c = null; }
public void Deconstruct(out object a, out object b, out object c) { a = b = c = null; } // Noncompliant FP, actually the one above is not used
public void Deconstruct(out object a, out object b, out object c) { a = b = c = null; } // Compliant, Deconstruct methods are ignored
}

private class NotUsedDifferentArgumentCount
{
public void Deconstruct(out string a, out string b, out string c) { a = b = c = null; } // Noncompliant
public void Deconstruct(out string a, out string b, out string c, out string d) { a = b = c = d = null; } // Noncompliant
public void Deconstruct(out string a, out string b, out string c) { a = b = c = null; } // Compliant, Deconstruct methods are ignored
public void Deconstruct(out string a, out string b, out string c, out string d) { a = b = c = d = null; } // Compliant, Deconstruct methods are ignored
}

private class NotUsedNotVisible
{
protected void Deconstruct(out object a, out object b) { a = b = null; } // Noncompliant
private void Deconstruct(out string a, out string b) { a = b = null; } // Noncompliant
protected void Deconstruct(out object a, out object b) { a = b = null; } // Compliant, Deconstruct methods are ignored
private void Deconstruct(out string a, out string b) { a = b = null; } // Compliant, Deconstruct methods are ignored
}

public class InvalidDeconstruct
{
private void Deconstruct(object a, out object b, out object c) { b = c = a; } // Noncompliant
private void Deconstruct() { } // Noncompliant

private int Deconstruct(out object a, out object b, out object c) // Noncompliant
{
a = b = c = null;
return 42;
}
}

private ForMethod ReturnFromMethod() => null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ public void SomeMethod()

private sealed class ForSwitchArm
{
public void Deconstruct(out object a, out object b) { a = b = null; } // Noncompliant FP
public void Deconstruct(out object a, out object b) { a = b = null; } // Compliant, Deconstruct methods are ignored
}

private sealed class ForIsPattern
{
public void Deconstruct(out string a, out string b) { a = b = null; } // Noncompliant FP
public void Deconstruct(out string a, out string b) { a = b = null; } // Compliant
}
}
}
Expand Down
Loading