ReSharper Web Help

How do external annotation work?

If you are using an external library, whose sources are not available to you, it does not seem feasible to use the attributes there for specifying code annotations.

In this case, you can use External Annotations, which allow you to complement the already compiled entities with attributes recognized by ReSharper's code analysis engine. External annotations let you 'cheat' the engine, by making it see the attributes (for methods, parameters and other declarations), which were not declared at the time the library was compiled.

External annotations are psecified in XML files. When loading solution, ReShareper looks for specifically named XML files in specific locations and reads annotatons from there. These XML files have a structure similar to XmlDoc. For example, to annotate the method XmlReader.Create(Stream input) from the assembly System.Xml of .NET Framework 4.0, with the NotNull contracts, the XML file would look as follows:

<assembly name="System.Xml, Version=4.0.0.0">
    <!--The attribute name contains the assembly name. If you don't specify the version,
    this file's attributes will be applied to all versions of the assemblies of that name -->
    <member name="M:System.Xml.XmlReader.Create(System.IO.Stream)">
        <!--This shows the name of the member whose attributes are complemented;
        the notation is the same as XmlDoc -->
        <attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" />
            <!--attribute constructor names are also specified using XmlDoc notation -->
        <parameter name="input">
            <attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" />
        </parameter>
    </member>
</assembly>

ReSharper external annotations

The approach described above was used to annotate a huge amount of symbols in the .NET Framework Class Library, as well as in other frequently used libraries. External annotations for these libraries are installed with ReSharper to ensure better code analysis. Some features (e.g. ASP.NET MVC 5 support) are also rely on external annotations.

Starting from ReSharper 8.2, these external annotations are supplied with the ReSharper.ExternalAnnotations bundled plugin. If necessary, you can install this plugin for older versions.

Creating external annotations

You can create external annotations to specify contracts for any compiled assembly. To make sure ReSharper recognizes the XML file with external annotations, this file should be named [AssemblyName].ExternalAnnotations.xml and placed in the same folder with the the assembly *.dll file.

Tip

You can use ReSharper annotations as a reference when createing your own annotations. To get XML files with ReSharper external annotations, find the corresponding NuGet package in [ReSharper install directory]\Bin\\packages and unpack it using your favorite zip tool.

To illustrate creating external annotations, imagine that you use a TestLib assembly that has MyTestClass class with static string ReverseString(String inputString) method. Suppose, that from the assembly documentation, you know that the method is pure and never returns null, and its parameter should never be null.

Initially, ReSharper is not aware of how ReverseString works, and therefore it finds no problems in the following code:

External annotations

To create external annotations for a compiled assembly
  1. Locate the TestLib.dll on your file system and create a file named TestLib.ExternalAnnotations.xml in the same folder.
  2. Open TestLib.ExternalAnnotations.xml for editing and type in the following:

    <assembly name="TestLib">
        <member name="M:TestLib.MyTestClass.ReverseString(System.String)">
            <attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" />
            <attribute ctor="M:JetBrains.Annotations.PureAttribute.#ctor" />
            <parameter name="inputString">
                <attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" />
            </parameter>
        </member>
    </assembly>

  3. Reload your solution. Now ReSharper detects incorrect usage of ReverseString and highlights the problem with the null parameter:

    External annotations

    ... and the unnecessary check of the return value:

    External annotations

  4. To see, which external annotations are applied to a library symbol, you can use the Quick Documentation feature. Just press Ctrl+QCtrl+Shift+F1 over the symbol to study its attributes. In our case, we can see that ReverseString is annotated with [NotNull] and [Pure] attributes and the parameter is annotated with [NotNull]:

    Viewing quick documentation

    The grey color of the attribues means that they come not from assembly code, but from external annotations.

Distributing external annotations

Another case of using external annotations is publishing external annotations for a library that you distribute, or for any library you like. In this case, the users of your library who also use ReSharper, will get more suggestions and fixes.

External annotations for libraries can be published on and installed from ReSharper gallery as NuGet packages. To learn more about packaging external annotations, see ReSharper plugin development guide.