ReSharper.ExportAnnotations.Core 1.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package ReSharper.ExportAnnotations.Core --version 1.2.0                
NuGet\Install-Package ReSharper.ExportAnnotations.Core -Version 1.2.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ReSharper.ExportAnnotations.Core" Version="1.2.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ReSharper.ExportAnnotations.Core --version 1.2.0                
#r "nuget: ReSharper.ExportAnnotations.Core, 1.2.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install ReSharper.ExportAnnotations.Core as a Cake Addin
#addin nuget:?package=ReSharper.ExportAnnotations.Core&version=1.2.0

// Install ReSharper.ExportAnnotations.Core as a Cake Tool
#tool nuget:?package=ReSharper.ExportAnnotations.Core&version=1.2.0                

alternate text is missing from this package README image ReSharper.ExportAnnotations

License GitHub release (latest by date including pre-releases) Changelog

Last commit Open issues Closed issues

If you find this project useful, please :star: star it. Thank you!

The problem

Let's say you have written a wonderful .NET library that you want to share with the whole world, or just among your own projects.

Let's also say that you, just like me, use ReSharper for static code analysis, and have constellated your library's code with those nice annotations: [NotNull], [CanBeNull], [ItemNotNull], [InstantHandle], etc. etc. (the complete list is here in case you're curious).

Code annotations are cool, but once you've wrapped your library in a nice NuGet package, how can ReSharper know about the annotations it contains? So far, your options were:

  1. Either reference the JetBrains.Annotations package in your NuGet package, making it a transient dependency for all projects using your library, and ending up with JetBrains.Annotations.dll in your executable directory, where it definitely serves no purpose at all...
  2. ...or you can embed code annotation declarations in your cource code. For each project. If you call this an option, that is. I personally do not.
  3. You may also not define the JETBRAINS_ANNOTATIONS constant when you build your package, thus giving up annotations completely and making code analysis harder and less precise in dependent projects.

Let's be honest: all three options above suck. Either you have to distribute an utterly useless assembly, or you end up with more code to build and maintain, or you just give up a big part of what makes ReSharper worth its price (not to mention loading time).

A fourth option would be to use Fody with the JetBrainsAnnotations.Fody plugin, that does exactly what this task does. Which is fine, if you already use Fody; otherwise, you have to create a configuration file for it, then reference two packages (Fody itself and the plugin). I've never tried it: it most probably works fine. I was looking for a simpler solution, though, so here it is.

The solution


<Project Sdk="Microsoft.NET.Sdk"> 

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework> 
  </PropertyGroup>

  <PropertyGroup>
    <ExportJetBrainsAnnotations>true</ExportJetBrainsAnnotations> 
    <StripJetBrainsAnnotations>true</StripJetBrainsAnnotations> 
  </PropertyGroup>

  <ItemGroup>
    
    <PackageReference Include="JetBrains.Annotations" Version="2019.1.3" PrivateAssets="All" /> 
    <PackageReference Include="ReSharper.ExportAnnotations.Task" Version="1.0.0" PrivateAssets="All" /> 
  </ItemGroup>

</Project>

That's all you need to do. Here's what happens when you build your project:

  • the JETBRAINS_ANNOTATIONS constant is automatically defined;
  • just after the compiler runs, your compiled assembly is scanned for ReSharper annotations;
  • all annotations of exposed types and members of exposed types are exported in an external annotations file;
  • the external annotations file is part of the build output, so it is also included in your NuGet package;
  • code annotations attributes, as well as the reference to JetBrains.Annotations.dll, are stripped from your assembly.

Now, when you reference your library from another project, ReSharper will automatically load annotations from the external annotations file and use them just as if they were compiled into your assembly!

Compatibility

In short, if you use MSBuild, you can use this task.

.NET Framework Mono .NET Core
Windows Yes Yes Yes
OS/X (n/a) Yes Yes
Linux (n/a) Yes Yes

Caveats

Building under Non-Windows operating systems

If you build under a non-Windows operating system, the process of stripping annotations will also strip away debug symbols from your assembly. This is a limitation of the Mono.Cecil library.

You may want to only strip annotations in Release mode. Be aware that this way your debug mode assembly will still reference JetBrains.Annotations.dll, which will become a transient dependency.

For example, given the project file above, to strip annotations only in Release mode you can add the following lines at the bottom of the file, just before the </Project> line:

  <PropertyGroup Condition="'$(Configuration)' != 'Release'">
    <StripJetBrainsAnnotations>false</StripJetBrainsAnnotations>
  </PropertyGroup>

  <ItemGroup Condition="'$(Configuration)' != 'Release'">
    <PackageReference Update="JetBrains.Annotations" PrivateAssets="" />
  </ItemGroup>

Supported project types

This task has been tested on .csproj project files, both "old-style" (no SDK) and using Microsoft.NET.Sdk.

It may or may not work with other SDKs.

You should have no problems with .vbproj projects, other than the limitations stated above. Projects in languages other than C# and VB are currently not supported.

Signed assemblies

When stripping annotations from a signed assembly, the signature will be stripped as well.

Work on this is being tracked in issue #2.

Credits

The font used in the package icon is Inconsolata Bold by Raph Levien, Kirill Tkachev (cyreal.org), from Font Library.

The font used in the logo is BloggerSans.otf by Sergiy S. Tkachenko, from Font Library.


Disclaimer: The author of this library is in no way affiliated to JetBrains s.r.o. (the makers of ReSharper) other than being a satisfied cutomer.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.4.0 519 4/1/2022
1.3.2 389 9/13/2021
1.3.1 551 10/10/2020
1.3.0 458 10/6/2020
1.2.1 459 10/4/2020
1.2.0 441 10/3/2020
1.1.0 442 9/17/2020