Skip to content

MSBuild task to export JetBrains annotations (and optionally strip them) from a compiled assembly.

License

Notifications You must be signed in to change notification settings

Tenacom/ReSharper.ExportAnnotations

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ReSharper.ExportAnnotations

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

Last commit Open issues Closed issues

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.



Quick start

  1. Add package references to both ReSharper.ExportAnnotations.Task and JetBrains.Annotations to your library's .csproj or .vbproj file. You can either do it manually, or use Visual Studio Package Manager.
  2. Do NOT add JETBRAINS_ANNOTATIONS to your project's DefineConstants! Remove the constant if you had previously added it. Again, you can either manually edit the project file, or use Visual Studio's UI.
  3. Build and pack your library as usual.
  4. 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. No JetBrains.Annotations dependency will be propagated to projects referencing your library.

How it works

Here is, in a nutshell, how ReSharper.ExportAnnotations.Task performs its magic:

  1. Add JETBRAINS_ANNOTATIONS to the project's DefineConstants.
  2. 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.
  3. 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 the JETBRAINS_ANNOTATIONS constant. The resulting assembly will have no annotations built in.
  4. If an XML file was generated in step 2, carry out some MSBuild trickery to make it an "official" part of the build output.

FAQ

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:

  1. implement incremental building to make sure a target does not run again if its outputs are already in sync with its inputs;
  2. check the value of the RebuildingWithoutJetBrainsAnnotations property and skip your target if it is equal to true, 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.

Configuration

The behavior of ReSharper.ExportAnnotations.Task may be controlled using MSBuild properties.

Exporting / not exporting code annotations

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.

Stripping / not stripping code annotations

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.

Using a different package for code annotations

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.

Skipping the check for the code annotations package reference

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.

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.


(*) 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.