Skip to content
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

Add support for destructured records #7

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 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 @@ -20,9 +20,9 @@ Task EnsureNotSuppressed(string code, NullableContextOptions nullableContextOpti
nullableContextOptions,
("IDE0072", IDE0072Analyzer));

Task EnsureSuppressed(string code, NullableContextOptions nullableContextOptions) =>
Task EnsureSuppressed(string code, NullableContextOptions nullableContextOptions, bool allowRecords = false) =>
DiagnosticSuppressorAnalyer.EnsureSuppressed(
new SwitchExpressionSuppressor(),
new SwitchExpressionSuppressor(allowRecords),
SwitchExpressionSuppressor.SuppressionDescriptorByDiagnosticId.Values,
code,
nullableContextOptions,
Expand Down Expand Up @@ -87,6 +87,26 @@ public static int DoSwitch(Root root)

return EnsureNotSuppressed(code, NullableContextOptions.Disable);
}

[Test]
public Task When_record_with_destructure_And_all_subtypes_match_Then_suppress()
{
var code = CodeHelper.WrapInNamespace(TypeHierarchies.ProtectedCopyConstructorOnly.PositionalParameter + @"
static class SwitchTest
{
public static int DoSwitch(Root root)
{
return root switch
{
Root.Leaf1(var v) => 0,
Root.Leaf2 => 1,
};
}
}
");

return EnsureSuppressed(code, NullableContextOptions.Enable, allowRecords: true);
}

[Test]
public Task When_nullable_is_disabled_And_null_is_matched_on_its_own_Then_suppress()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ Task EnsureNotSuppressed(string code, NullableContextOptions nullableContextOpti
nullableContextOptions,
("IDE0010", IDE0010Analyzer));

Task EnsureSuppressed(string code, NullableContextOptions nullableContextOptions) =>
Task EnsureSuppressed(string code, NullableContextOptions nullableContextOptions, bool allowRecords = false) =>
DiagnosticSuppressorAnalyer.EnsureSuppressed(
new SwitchStatementSuppressor(),
new SwitchStatementSuppressor(allowRecords),
SwitchStatementSuppressor.SuppressionDescriptorByDiagnosticId.Values,
code,
nullableContextOptions,
Expand Down Expand Up @@ -94,6 +94,28 @@ public static void DoSwitch(Root root)
return EnsureNotSuppressed(code, NullableContextOptions.Disable);
}

[Test]
public Task When_record_with_destructure_And_all_subtypes_match_Then_suppress()
{
var code = CodeHelper.WrapInNamespace(TypeHierarchies.ProtectedCopyConstructorOnly.PositionalParameter + @"
static class SwitchTest
{
public static void DoSwitch(Root root)
{
switch(root)
{
case Root.Leaf1(var v):
rfvgyhn marked this conversation as resolved.
Show resolved Hide resolved
break;
case Root.Leaf2:
break;
}
}
}
");

return EnsureSuppressed(code, NullableContextOptions.Enable, allowRecords: true);
}

[Test]
public Task When_nullable_is_disabled_And_null_is_matched_on_its_own_Then_suppress()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ abstract record Root
public sealed record Leaf1 : Root {}
public sealed record Leaf2 : Root {}
}
";
public const string PositionalParameter = @"
abstract record Root
{
Root() {}
public sealed record Leaf1(int Value) : Root {}
public sealed record Leaf2 : Root {}
}
";
}

Expand Down
3 changes: 2 additions & 1 deletion ClosedTypeHierarchyDiagnosticSuppressor/PatternHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ bool IsSubpatternNonRestrictive(SubpatternSyntax subpatternSyntax) =>
};

bool IsRecursivePatternNonRestrictive(RecursivePatternSyntax recursivePatternSyntax) =>
recursivePatternSyntax.PropertyPatternClause?.Subpatterns.All(IsSubpatternNonRestrictive) ?? false;
(recursivePatternSyntax.PropertyPatternClause?.Subpatterns ?? recursivePatternSyntax.PositionalPatternClause?.Subpatterns)
?.All(IsSubpatternNonRestrictive) ?? false;

bool IsDeclarationPatternNonRestrictive(DeclarationPatternSyntax declarationPatternSyntax, SubpatternSyntax containingSubpatternSyntax)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ namespace SvSoft.Analyzers.ClosedTypeHerarchyDiagnosticSuppression;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class SwitchExpressionSuppressor : DiagnosticSuppressor
{
readonly bool _forceAllowRecords;

public SwitchExpressionSuppressor() : this(false) { }

public SwitchExpressionSuppressor(bool forceAllowRecords)
rfvgyhn marked this conversation as resolved.
Show resolved Hide resolved
{
_forceAllowRecords = forceAllowRecords;
}

static readonly string[] SuppressedDiagnosticIds = { "CS8509", "IDE0072" };

public static readonly IReadOnlyDictionary<string, SuppressionDescriptor> SuppressionDescriptorByDiagnosticId = SuppressedDiagnosticIds.ToDictionary(
Expand Down Expand Up @@ -42,7 +51,7 @@ void HandleDiagnostic(Diagnostic diagnostic)
return;
}

bool allowRecords = context.AreRecordHierarchiesAllowed(node.SyntaxTree);
bool allowRecords = _forceAllowRecords || context.AreRecordHierarchiesAllowed(node.SyntaxTree);

var switchExpression = node.DescendantNodesAndSelf().OfType<SwitchExpressionSyntax>().FirstOrDefault();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ namespace SvSoft.Analyzers.ClosedTypeHerarchyDiagnosticSuppression;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class SwitchStatementSuppressor : DiagnosticSuppressor
{
readonly bool _forceAllowRecords;

public SwitchStatementSuppressor() : this(false) { }

public SwitchStatementSuppressor(bool forceAllowRecords)
{
_forceAllowRecords = forceAllowRecords;
}

static readonly string[] SuppressedDiagnosticIds = { "IDE0010" };

public static readonly IReadOnlyDictionary<string, SuppressionDescriptor> SuppressionDescriptorByDiagnosticId = SuppressedDiagnosticIds.ToDictionary(
Expand Down Expand Up @@ -40,7 +49,7 @@ void HandleDiagnostic(Diagnostic diagnostic)
return;
}

bool allowRecords = context.AreRecordHierarchiesAllowed(node.SyntaxTree);
bool allowRecords = _forceAllowRecords || context.AreRecordHierarchiesAllowed(node.SyntaxTree);

ExpressionSyntax switchee = switchStatement.Expression;
var switcheeModel = context.GetSemanticModel(switchee.SyntaxTree);
Expand Down