Skip to content

Annotations

Michael Damatov edited this page Apr 15, 2024 · 8 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 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