Skip to content
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 @@ -37,10 +37,13 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var diagnostic = context.Diagnostics[0];
var ifStatement = root.FindNode(diagnostic.Location.SourceSpan).FirstAncestorOrSelf<IfStatementSyntax>();

if (ifStatement is null)
{
return;
}

if (
ifStatement is null
|| !ThrowIfCountAnalyzer.TryGetCountComparison(ifStatement.Condition, out var comparison)
|| comparison is null
!ThrowIfCountAnalyzer.TryGetCountComparison(ifStatement.Condition, out var comparison) || comparison is null
)
{
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var diagnostic = context.Diagnostics[0];
var ifStatement = root.FindNode(diagnostic.Location.SourceSpan).FirstAncestorOrSelf<IfStatementSyntax>();

if (ifStatement is null)
{
return;
}

if (
ifStatement is null
|| !ThrowIfLengthAnalyzer.TryGetLengthComparison(ifStatement.Condition, out var comparison)
!ThrowIfLengthAnalyzer.TryGetLengthComparison(ifStatement.Condition, out var comparison)
|| comparison is null
)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var diagnostic = context.Diagnostics[0];
var ifStatement = root.FindNode(diagnostic.Location.SourceSpan).FirstAncestorOrSelf<IfStatementSyntax>();

if (ifStatement is null)
{
return;
}

if (
ifStatement is null
|| !ThrowIfNullOrEmptyAnalyzer.TryGetStringCheck(ifStatement.Condition, out _, out var helperName)
!ThrowIfNullOrEmptyAnalyzer.TryGetStringCheck(ifStatement.Condition, out _, out var helperName)
|| helperName is null
)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var diagnostic = context.Diagnostics[0];
var ifStatement = root.FindNode(diagnostic.Location.SourceSpan).FirstAncestorOrSelf<IfStatementSyntax>();

if (ifStatement is null)
{
return;
}

if (
ifStatement is null
|| !ThrowIfOutOfRangeAnalyzer.TryGetComparison(ifStatement.Condition, out var comparison)
|| comparison is null
!ThrowIfOutOfRangeAnalyzer.TryGetComparison(ifStatement.Condition, out var comparison) || comparison is null
)
{
return;
Expand Down
38 changes: 38 additions & 0 deletions tests/NetEvolve.Arguments.Analyser.Tests.Unit/AnalyzerVerifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,44 @@ public static Task<string> ApplyFixAllAsync(
CancellationToken cancellationToken = default
) => ApplyFixAllCoreAsync(analyzer, codeFix, source, useLegacyReferences, cancellationToken: cancellationToken);

/// <summary>
/// Raises a synthetic diagnostic at the first occurrence of <paramref name="spanText"/> and returns how many
/// code actions the provider registers for it (used to cover the defensive "pattern no longer matches" exits).
/// </summary>
public static async Task<int> CountRegisteredFixesAsync(
CodeFixProvider codeFix,
string source,
string spanText,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();

using var workspace = new AdhocWorkspace();
var project = workspace
.AddProject("TestProject", LanguageNames.CSharp)
.WithMetadataReferences(ModernReferences);
var document = workspace.AddDocument(project.Id, "Test.cs", SourceText.From(source));
var tree = (await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false))!;

var descriptor = new DiagnosticDescriptor(
codeFix.FixableDiagnosticIds[0],
"t",
"t",
"t",
DiagnosticSeverity.Warning,
true
);
var start = source.IndexOf(spanText, StringComparison.Ordinal);
var diagnostic = Diagnostic.Create(descriptor, Location.Create(tree, new TextSpan(start, spanText.Length)));

var count = 0;
var fixContext = new CodeFixContext(document, diagnostic, (_, _) => count++, cancellationToken);
await codeFix.RegisterCodeFixesAsync(fixContext).ConfigureAwait(false);

return count;
}

private static async Task<ImmutableArray<Diagnostic>> GetDiagnosticsCoreAsync(
DiagnosticAnalyzer analyzer,
string source,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
namespace NetEvolve.Arguments.Analyser.Tests.Unit;

using System.Threading;
using Microsoft.CodeAnalysis.CodeFixes;

public sealed class CodeFixProviderDefensiveTests
{
private const string Source = """
class C
{
void M(bool argument)
{
if (argument) { }
}
}
""";

[Test]
[Arguments(typeof(ThrowIfCountCodeFixProvider))]
[Arguments(typeof(ThrowIfLengthCodeFixProvider))]
[Arguments(typeof(ThrowIfNullOrEmptyCodeFixProvider))]
[Arguments(typeof(ThrowIfOutOfRangeCodeFixProvider))]
public async Task RegisterCodeFixes_WhenDiagnosticIsOutsideIfStatement_RegistersNothing(
Type providerType,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();

var provider = (CodeFixProvider)Activator.CreateInstance(providerType)!;

var count = await AnalyzerVerifier.CountRegisteredFixesAsync(provider, Source, "void M", cancellationToken);

_ = await Assert.That(count).IsEqualTo(0);
}

[Test]
[Arguments(typeof(ThrowIfCountCodeFixProvider))]
[Arguments(typeof(ThrowIfLengthCodeFixProvider))]
[Arguments(typeof(ThrowIfNullOrEmptyCodeFixProvider))]
[Arguments(typeof(ThrowIfOutOfRangeCodeFixProvider))]
public async Task RegisterCodeFixes_WhenIfConditionDoesNotMatchPattern_RegistersNothing(
Type providerType,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();

var provider = (CodeFixProvider)Activator.CreateInstance(providerType)!;

var count = await AnalyzerVerifier.CountRegisteredFixesAsync(
provider,
Source,
"if (argument)",
cancellationToken
);

_ = await Assert.That(count).IsEqualTo(0);
}
}
Loading