Skip to content

Commit

Permalink
Update RSPEC
Browse files Browse the repository at this point in the history
  • Loading branch information
zsolt-kolbay-sonarsource committed Apr 17, 2023
1 parent 2538061 commit 5314099
Showing 1 changed file with 35 additions and 22 deletions.
57 changes: 35 additions & 22 deletions analyzers/rspec/cs/S3900_c#.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<p>A publicly accessible method can be called from anywhere, which means you should validate parameters to be within the expected constraints. In
general, checking against <code>null</code> is recommended defensive programming.</p>
<p>Methods declared as <code>public</code>, <code>protected</code>, or <code>protected internal</code> can be accessed from other assemblies, which
means you should validate parameters to be within the expected constraints. In general, checking against <code>null</code> is recommended in defensive
programming.</p>
<p>This rule raises an issue when a parameter of a publicly accessible method is not validated against <code>null</code> before being
dereferenced.</p>
<h2>Noncompliant Code Example</h2>
Expand All @@ -9,16 +10,11 @@ <h2>Noncompliant Code Example</h2>
private MyOtherClass other;

public void Foo(MyOtherClass other)
{
this.other = other; // Compliant: other not being dereferenced
}

public void Bar(MyOtherClass other)
{
this.other = other.Clone(); // Noncompliant
}

protected void FooBar(MyOtherClass other)
protected void Bar(MyOtherClass other)
{
this.other = other.Clone(); // Noncompliant
}
Expand All @@ -31,38 +27,58 @@ <h2>Compliant Solution</h2>
private MyOtherClass other;

public void Foo(MyOtherClass other)
{
this.other = other;
}

public void Bar(MyOtherClass other)
{
if (other != null)
{
this.other = other.Clone();
}
}

protected void FooBar(MyOtherClass other)
protected void Bar(MyOtherClass other)
{
if (other != null)
{
this.other = other.Clone();
}
}

public void Baz(MyOtherClass other)
{
ArgumentNullException.ThrowIfNull(other);

this.other = other.Clone();
}

public void Qux(MyOtherClass other)
{
this.other = other; // Compliant: "other" is not being dereferenced
}

private void Xyzzy(MyOtherClass other)
{
this.other = other; // Compliant: method is not publicly accessible
}
}
</pre>
<h2>Exceptions</h2>
<p>To create a custom null validation method declare an attribute with name <code>ValidatedNotNullAttribute</code> and mark the parameter that is
validated for null in your method declaration with it:</p>
<ul>
<li> Arguments validated for <code>null</code> via helper methods should be annotated with the <a
href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/nullable-analysis#postconditions-maybenull-and-notnull"><code>[NotNull</code></a>] attribute. </li>
<li> Method parameters marked with the <code>[NotNull]</code> <a
href="https://www.jetbrains.com/help/resharper/Reference__Code_Annotation_Attributes.html#ItemNotNullAttribute">Resharper code annotation
attribute</a> are supported as well. </li>
<li> To create a custom null validation method declare an attribute with name <code>ValidatedNotNullAttribute</code> and mark the parameter that is
validated for null in your method declaration with it: </li>
</ul>
<pre>
using System;

[AttributeUsage(AttributeTargets.Parameter, Inherited=false)]
public sealed class ValidatedNotNullAttribute : Attribute { }

public static class Guard
{
public static void NotNull&lt;T&gt;([ValidatedNotNullAttribute] this T value, string name) where T : class
public static void NotNull&lt;T&gt;([ValidatedNotNullAttribute] T value, [CallerArgumentExpression("value")] string name = "") where T : class
{
if (value == null)
throw new ArgumentNullException(name);
Expand All @@ -73,11 +89,8 @@ <h2>Exceptions</h2>
{
public static string ToUpper(string value)
{
Guard.NotNull(value, nameof(value));
if (value == null)
{
return value.ToString();
}
Guard.NotNull(value);

return value.ToUpper(); // Compliant
}
}
Expand Down

0 comments on commit 5314099

Please sign in to comment.