NSubstitute.Analyzers icon indicating copy to clipboard operation
NSubstitute.Analyzers copied to clipboard

Make NS1004 distinguish between non-virtual members and extension methods

Open petterh opened this issue 1 year ago • 1 comments

Assume an interface and an extension method for that interface:

public interface IHolder
{
    string Value { get; set; }
}

public static class IHolderExtensions
{
    public static void SetValue(this IHolder holder, string value) => holder.Value = value;
}

The following triggers an NS1004:

string? value = null;
var holder = Substitute.For<IHolder>();
holder.SetValue(Arg.Do<string>(v => value = v)); // <==
holder.SetValue("hello");
value.Should().Be("hello");

With the provided definition of SetValue, I can ignore the NS1004: Things work because the call to the extension method basically boils down to this:

holder.Value = Arg.Do<string>(v => value = v);

If I change SetValue to the following, things blow up, of course, so the analyzer is right to flag the issue:

public static void SetValue(this IHolder holder, string value) => throw new InvalidOperationException("Go away");

Proposal

If possible, I'd like to see the message

Argument matcher used with a non-virtual member of a class.

changed to

Argument matcher used with an extension method.

Might require a new rule.

petterh avatar Jun 20 '23 16:06 petterh