The ultimate, one-stop solution to distribute ReSharper(*) code annotations in XML format along with your libraries.
Enjoy ReSharper recognizing your code annotations when working on dependent projects, without dragging transitive dependencies around, and without redeclaring the same attributes over and over.
- Add package references to both
ReSharper.ExportAnnotations.Task
andJetBrains.Annotations
to your library's.csproj
or.vbproj
file. You can either do it manually, or use Visual Studio Package Manager. - Do NOT add
JETBRAINS_ANNOTATIONS
to your project'sDefineConstants
! Remove the constant if you had previously added it. Again, you can either manually edit the project file, or use Visual Studio's UI. - Build and pack your library as usual.
- Just kidding, there is no step 4. :) An
<assembly_name>.ExternalAnnotations.xml
file has been added alongside your compiled assembly, both in the output directory and in the NuGet package. NoJetBrains.Annotations
dependency will be propagated to projects referencing your library.
Here is, in a nutshell, how ReSharper.ExportAnnotations.Task
performs its magic:
- Add
JETBRAINS_ANNOTATIONS
to the project'sDefineConstants
. - Just after the output assembly has been compiled, examine it looking for code annotations and export them in XML format. By default this step is performed only on libraries, not on executables, but this behavior can be configured.
- After the
Build
target has completed, if code annotations stripping is requested (which is true by default but can be configured):- delete the compiled assembly (otherwise the compiler wouldn't be invoked again, due to incremental building);
- run the
Build
target again without theJETBRAINS_ANNOTATIONS
constant. The resulting assembly will have no annotations built in.
- If an XML file was generated in step 2, carry out some MSBuild trickery to make it an "official" part of the build output.
Which languages are supported?
Both C# and Visual Basic projects whose build output is either a .dll
or a .exe
file are supported. Support for other languages may be added on request.
Are legacy (non-SDK) projects supported?
Yes, as long as they use PackageReference
.
Does it work with my development toolchain?
The following versions of .NET SDK are supported: 5.x, 6.x
The following versions of Visual Studio are supported: 2019 (v16.8+), 2022
For other toolchains, check your MSBuild version: if it is 16.8 or 17.x, it is supported and should work.
If you encounter problems when using ReSharper.ExportAnnotations.Task
with a supported toolchain, please open an issue to let us know.
Is the assembly's signature preserved?
In a word, yes. ReSharper.ExportAnnotations.Task
does not modify assemblies: instead, it rebuilds them from scratch, thus ensuring that the final output assembly is every bit as good as if built without annotations from the get-go.
Is the PDB checksum preserved? Will I be able to distribute symbol packages?
Yes, of course. See the answer to the previous question.
What about my custom MSBuild targets running before / after Build? Will they run twice?
By default, yes they will: the Build
target, with all its dependee and attached targets, will run twice for every TargetPlatform
.
There are two ways to prevent a custom build-related target from running twice:
- implement incremental building to make sure a target does not run again if its outputs are already in sync with its inputs;
- check the value of the
RebuildingWithoutJetBrainsAnnotations
property and skip your target if it is equal totrue
, like this:
<Target Name="TargetThatWillNotRunWhenRebuilding"
AfterTargets="Build"
Condition="'RebuildingWithoutJetBrainsAnnotations' != 'true'">
<!-- Anything your target does -->
</Target>
My solution's build process is so complicated that I have to drive it with an external program / a PowerShell script. Can I just export code annotations programmatically and take care of the rest myself?
Of course you can. Just reference ReSharper.ExportAnnotations.Core
(it's a .NET Standard 2.0 library) and take a look at the AnnotationsExporter
class. It's very easy to use, has full XML documentation, and of course the package also contains external annotations.
I use a different package than JetBrains.Annotations
. I get an error upon restore / build because there is no package reference to JetBrains.Annotations
. What do I do?
You can either change the name of the required package, as explained below, or disable the check completely by following these instructions.
I use a custom MSBuild SDK that adds the JetBrains.Annotations
package reference from Sdk.targets
. I get the same error as in the previous question, although the package reference is actually there. What do I do?
Sdk.targets
from SDKs are evaluated after .targets
files from packages; therefore, ReSharper.ExportAnnotations.Task
will check for a PackageReference
item that has yet to be added,
In this case you have no other choice than to disable the check following the instructions below.
The behavior of ReSharper.ExportAnnotations.Task
may be controlled using MSBuild properties.
Set the ExportJetBrainsAnnotations
property to true
to generate a ExternalAnnotations.xml
file, false
to skip the export phase.
The default value is true
for projects whose OutputType
is Library
, false
for other projects.
Please note that "stripping" here does not mean that the assembly is modified: it is simply rebuilt without annotations.
Set the StripJetBrainsAnnotations
property to true
to rebuild the assembly without annotations, false
to skip the rebuild phase.
The default value is true
for all projects.
ReSharper.ExportAnnotations.Task
automatically modifies the PackageReference
item referencing JetBrains.Annotations
to make sure it does not propagate as a transitive dependency.
If for some reason you prefer to use another package to provide code annotations, just set the JetBrainsAnnotationsPackageName
property to the name of your preferred package.
You can also disable this feature completely by setting UpdateJetBrainsAnnotationsPackageReference
to false
. In this case, make sure that the PrivateAssets
metadata on your package reference is set to all
, lest every project referencing your library will also depend on the code annotations package, even if your distributed assembly contains no annotations.
Before building, or even restoring dependencies, ReSharper.ExportAnnotations.Task
checks whether a PackageReference
exists for the package containing the code annotations DLL. This can either be JetBrains.Annotations
, or any other name set via the JetBrainsAnnotationsPackageName
property. If the reference is missing, the build is stopped with an error.
You may disable this check by setting the CheckForJetBrainsAnnotationsPackageReference
property to false
.
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.
(*) ReSharper is a product of JetBrains s.r.o.. The authors and owners of this project are not affiliated with JetBrains in any way. The use of the ReSharper name does not imply endorsement of this project by JetBrains.