Skip to content

Annotations

Michael Damatov edited this page Dec 15, 2024 · 9 revisions

Purity and Disposability Analysis

The analyzer enforces the following rules:

for types and constructors

  • Disposable* classes and (class) records should be annotated with [MustDisposeResource] or [MustDisposeResource(false)] (to indicate explicitly that objects should not be disposed).
  • The [MustDisposeResource] annotation is inherited by derived types.
  • Constructors inherit the [MustDisposeResource] annotation from their types.
  • The [MustDisposeResource(false)] annotation is not inherited by derived types, which should be applied again.
  • Constructors do not inherit the [MustDisposeResource(false)] annotation, which should be applied explicitly.
  • Disposable structs and (struct) records should have a constructor annotated with [MustDisposeResource] or [MustDisposeResource(false)].
  • Disposable ref structs** should also have a constructor annotated with [MustDisposeResource] or [MustDisposeResource(false)].

* Disposable types means that the type implements the IDisposable or the IAsyncDisposable interface. ** Disposable ref structs means that the ref struct has a non-private void Dispose(), or a ValueTask DisposeAsync(), or any other non-static method annotated with [HandlesResourceDisposal]

for methods, local functions, and parameters

  • Pure methods and local functions should be annotated with [Pure].
  • Methods and local functions, which return values must be consumed, should be annotated with [MustUseReturnValue].
  • Methods and local functions with disposable return types* should be annotated with [MustDisposeResource] or [MustDisposeResource(false)].
  • Non-input parameters of disposable types should be annotated with [MustUseReturnValue] or [MustUseReturnValue(false)].
  • The [MustDisposeResource] and the [HandlesResourceDisposal] annotation is inherited by overridden methods.
  • The [MustDisposeResource(false)] annotation is not inherited by overridden methods, which should be applied again.

* Disposable types means that the type implements the IDisposable or the IAsyncDisposable interface, or the type is a disposable ref struct. The Task and Task<T> types are not considered disposable, however, the Task<T> and ValueTask<T> types are considered disposable when T is disposable.

💡 A quick-fix is available to remove the invalid, redundant, and conflicting annotations. 💡 A context action is available to apply the missing annotations.

Nullability Analysis

When Nullable Annotation Context is Enabled

Detects redundant nullable mark applied to return types of iterator or async methods or local functions.

💡 A quick-fix is available to remove the nullable mark.

When Nullable Annotation Context is not Enabled

Pessimistic Analysis Mode

when entity doesn't have explicit [NotNull] attribute

Member No annotation Annotated with [NotNull] Annotated with [CanBeNull]
Inherited members* not allowed 💡 not allowed 💡
Iterator methods (not inherited*) [NotNull] is missing not allowed 💡
Async methods (not inherited*) redundant 💡 not allowed 💡
Other members (not inherited*, reference-type declaration) and reference-type parameters redundant 💡

Optimistic Analysis Mode

when explicitly marked with [CanBeNull] attribute, or checked for 'null'

Member No annotation Annotated with [NotNull] Annotated with [CanBeNull]
Inherited members* not allowed 💡 not allowed 💡
Iterator methods (not inherited*) [NotNull] is missing not allowed 💡
Async methods (not inherited*) redundant 💡 not allowed 💡
Other members (not inherited*, reference-type declaration) and reference-type parameters [NotNull] or [CanBeNull] is missing

* overriding or implementing interface member

💡 A quick-fix is available to remove the annotation.

Element (Value) Nullability Analysis

The [ItemNotNull] annotation is not allowed, if:

  • the member overrides a virtual member or implements an interface member
  • the type is not an IEnumerable<T> (or any type, which implements it), a Task<T>, a ValueTask<T>, or a Lazy<T>
  • the element type T is not a reference type

💡 A quick-fix is available to remove the annotation.

Missing Justification for Suppressions

Shows a warning when the Justification property is missing (or empty) in the [SuppressMessage] or in the [ExcludeFromCodeCoverage] attribute.

The warning is not displayed for the unit test projects.

Note: currently only MS-Test, NUnit, and xUnit projects are identified as unit test projects.

Local Suppressions

Shows a warning when the ReSharper inspection is suppressed within a member body (as a code comment). A method- or type-level suppression should be used instead. This also enforces to write a justification.

[NonNegativeValue]

  • Shows a warning if the [NonNegativeValue] annotation is applied to a non-intergral numeric type.
  • Highlights the [NonNegativeValue] annotation as redundant when it's applied to an unsigned numeric type or to a constant.

💡 A quick-fix is available to remove the annotation.

[ValueRange(...)]

  • Shows a warning if the [ValueRange(...)] annotation is applied to a non-intergral numeric type.
  • Shows a warning when the from value is greater than the to value.
  • Shows a warning when the [ValueRange(...)] represents an interval, which is not compatible to the numeric type.
  • Highlights the [ValueRange(...)] annotation as redundant when its range fully includes the type's range or it's applied to a constant.

💡 A quick-fix is available to remove the annotation.

  • Shows a warning when the from or to value is out of the valid range for the numeric type.

💡 A quick-fix is available to fix the invalid boundary.

[AttributeUsage(...)]

  • Shows a warning if the [AttributeUsage(...)] annotation is missing.

💡 A context action is available to add the annotation.

💡 The analyzer can be deactivated in the ReSharper Options dialog.

References

Clone this wiki locally