Skip to content

Re-add JetBrains Annotations #288

@nseguin42

Description

@nseguin42

The dependency on JetBrains.Annotations was removed in v4.1.0 (see: #236 and #216 ). The reasoning is to avoid propagating a dependency on a third-party package, which is valid. An alternate solution to this problem (and the officially recommended one) is to include the annotation source code directly. This way, the annotations can still be used, but no dependencies are propagated.

My approach would be to simply copy the original Annotations.cs file (maybe rename it to JetBrains.Annotations.g.cs so our analyzers leave it alone), remove the conditional attributes, and replace each public sealed class with internal sealed class. The annotations can be cherry-picked, but they should remain in the JetBrains.Annotations namespace so that Rider/ReSharper pick up the annotations automatically.


The annotations that were previously used in this package are:

  • NotNullAttribute: Useful in non-nullable contexts to hint the IDE that the input is guaranteed not-null after the method returns.
  /// <summary>
  /// Indicates that the value of the marked element can never be <c>null</c>.
  /// </summary>
  /// <example><code>
  /// [NotNull] object Foo() {
  ///   return null; // Warning: Possible 'null' assignment
  /// }
  /// </code></example>
  [AttributeUsage(
    AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property |
    AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event |
    AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)]
  internal sealed class NotNullAttribute : Attribute { }
  • InvokerParameterNameAttribute: Useful in NETSTANDARD/NETFRAMEWORK where CallerArgumentExpressionAttribute is not available.
  /// <summary>
  /// Indicates that the function argument should be a string literal and match
  /// one of the parameters of the caller function. This annotation is used for parameters
  /// like 'string paramName' parameter of the <see cref="System.ArgumentNullException"/> constructor.
  /// </summary>
  /// <example><code>
  /// void Foo(string param) {
  ///   if (param == null)
  ///     throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol
  /// }
  /// </code></example>
  [AttributeUsage(AttributeTargets.Parameter)]
  internal sealed class InvokerParameterNameAttribute : Attribute { }
  • NoEnumerationAttribute: Used to suppress false "possible multiple enumeration" warnings when a method accepts an IEnumerable.
  /// <summary>
  /// Indicates that IEnumerable passed as a parameter is not enumerated.
  /// Use this annotation to suppress the 'Possible multiple enumeration of IEnumerable' inspection.
  /// </summary>
  /// <example><code>
  /// static void ThrowIfNull&lt;T&gt;([NoEnumeration] T v, string n) where T : class
  /// {
  ///   // custom check for null but no enumeration
  /// }
  ///
  /// void Foo(IEnumerable&lt;string&gt; values)
  /// {
  ///   ThrowIfNull(values, nameof(values));
  ///   var x = values.ToList(); // No warnings about multiple enumeration
  /// }
  /// </code></example>
  [AttributeUsage(AttributeTargets.Parameter)]
  internal sealed class NoEnumerationAttribute : Attribute { }
  • RegexPatternAttribute: Used to indicate that a parameter should be parsed as a RegEx pattern.
  /// <summary>
  /// Indicates that the marked parameter, field, or property is a regular expression pattern.
  /// </summary>
  [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property)]
  internal sealed class RegexPatternAttribute : Attribute { }

Some additional annotations that might be worth bringing in:

  • ContractAnnotationAttribute: Can be used for e.g. Guard.Against.Null as [ContractAnnotation("input:null => halt")] to indicate that the method will not return when input is null.

  • AssertionMethodAttribute: Indicates that a method is an assertion method that checks if a parameter is null, not null, true, or false (depending on the parameter passed to AssertionConditionAttribute).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions