Category Archives: Tools

Leveraging ReSharper annotations

I don’t think it’s really necessary to present ReSharper (often abbreviated R#), but in case you don’t know about it, it’s a tool made by JetBrains that performs real-time analysis of your C# or VB.NET code to warn you about possible bugs, bad practices, convention violations, etc. It also provides many useful refactorings and code generators. I’ve been using it for a few years now, and it has tremendously improved both my productivity and my coding style.

Among other things, R# warns you about incorrect usage of .NET Framework methods. For instance, if you’re calling Path.GetFullPath with a path that might be null, it gives you a warning:

image

How does R# know that Path.GetFullName doesn’t accept a null argument? And how does it know that Console.ReadLine can return null? I guess it could have been hard-coded, but it wouldn’t be a very elegant approach, and wouldn’t allow easy extensibility… Instead, ReSharper uses external annotations. These are XML files that are shipped with R# and contain a lot of metadata about .NET framework classes and methods. This data is then used by the analyzer to detect possible issues with your code.

OK, but what about third-party libraries? Obviously, JetBrains can’t create annotations for those, there are too many. Well, the good news is that you can write your own external annotations for libraries that you use, or for your own code. However, for your own code, there is a much more convenient alternative: you can apply the annotations directly in your code as attributes. There are two ways to get those attributes:

  • Reference the assembly where they are defined (JetBrains.Annotations.dll in the R# installation directory). This is fine if you don’t mind having a reference to something that has nothing to do with your application. That’s probably not a good idea for libraries.
  • Declare the attributes in your own code. You don’t actually have to write them yourself, because R# has an option to copy their implementation to the clipboard, as shown below. You just paste it to a code file in your project.

image

Now that you have the attributes, how do you use them? I’ll show a few examples for the most common annotations.

NotNull

This annotation indicates that the element on which it is applied cannot, or must not be null.

If you apply it to a method or property, it means that the method or property will never return null:

        [NotNull]
        public string GetString()
        {
            return "Hello world!";
        }

When a method has this attribute, if you test if the return value is null (or not null), R# will warn you that the condition is always false (or true):

image

 

If you apply it to a method parameter, it means that null is not a valid argument value:

        public string Repeat([NotNull] string s)
        {
            if (s == null) throw new ArgumentNullException("s");
            return s + s;
        }

If R# determines that the value passed for s can be null, it warns you about it, as shown in the first example.

This annotation can be added automatically using ReSharper’s quick-fix menu. The “Not null” option will just add the annotation; the “Check parameter for null” option will add a check and the annotation:

image

image

 

CanBeNull

This is the opposite of NotNull. Applied to a method or property, it means that the method or property can return a null value. Applied to a method parameter, it means that the argument value is allowed to be null.

Pure

This one is very useful. Applied to a method, it means that the method is pure. A pure method has no observable side effect, so if you don’t use the return value of the method, the call is useless, so it’s probably a mistake. Typical example with String.Replace:

image

 

StringFormatMethod

This annotation indicates that a method works like the String.Format method, i.e. it takes a composite format string followed by arguments that will replace the placeholders in the format string:

        [StringFormatMethod("format")]
        public static void Log(string format, params object[] args)
        {
            ...
        }

It lets R# warn you if the placeholders and arguments don’t match:

image

UsedImplicitly

This one tells ReSharper that a code element is used, even though R# cannot statically detect it. It has the effect of suppressing the “(…) is never used” warning. It’s useful, for instance, when a type or member is used only via reflection.

NoEnumeration

This annotation is applied to an IEnumerable parameter, and means that the method will not enumerate the sequence. R# warns you when you enumerate an IEnumerable multiple times, so using this attribute prevents false positives for this warning:

        public static IEnumerable<T> EmptyIfNull<T>([NoEnumeration] this IEnumerable<T> source)
        {
            return source ?? Enumerable.Empty<T>();
        }

 

InstantHandle

This one is applied to a delegate parameter, and means that the delegate will be executed during the execution of the method. It prevents the “Access to modified closure” warning that occurs when a lambda captures a variable that is later modified.

ContractAnnotation

This annotation is a powerful way to describe how the output of a method depends on its inputs. It lets R# predict how the method will behave. For instance, this method will return null if its argument is null, an not null otherwise:

        [ContractAnnotation("null => null; notnull => notnull")]
        public object Transform(object data)
        {
            ...
        }

Thanks to the annotation, ReSharper will know that if the argument was not null, the result will not be null either.

This method doesn’t return normally (it throws an exception) if its argument is null:

        [ContractAnnotation("value:null => halt")]
        public static void CheckArgumentNull<T>(
            [NoEnumeration] this T value,
            [InvokerParameterName] string paramName)
            where T : class
        {
            if (value == null)
                throw new ArgumentNullException(paramName);
        }

This lets R# know that if you pass a null to this method, the code following the call will never be reached; if it is reached, the value can be assumed to be not null.

LocalizationRequired

This annotation means that a property or method parameter should be localized; if you pass a hard-coded string, R# will warn you and suggest to extract it to a resource file.

image11

Conclusion

Now, you might be wondering, “why should I go through the trouble of adding all those annotations to my code?”. The reason is simple: it helps ReSharper help you! By giving it more information about your code, you allow R# to give you better advice and produce less false positives. Also, if you’re a library author, it makes your library more comfortable to use for ReSharper users. I use R# annotations extensively in my Linq.Extras library, so it’s a good place to find more examples.

Note that I only described a small part of the available annotations. There are many more, mostly related to ASP.NET-specific scenarios. You can see them all in the annotations file generated by ReSharper, or in the documentation (which isn’t quite complete, but is still useful).

Visual Studio Online + Git integration with Team Explorer

I recently started using Visual Studio Online for personal projects, and I must say it’s a pretty good platform, although it would be nice to be able to host public projects as well as private ones. The thing I like the most is the integration with Visual Studio Team Explorer to manage work items and builds.

However, I noticed a little gotcha when using Git for source control : the remote for VS Online must be named origin, otherwise Team Explorer won’t detect that it’s a VS Online project, and it won’t show the “Builds” and “Work items” pages.

 When VSO remote is named "origin" When VSO remote is named "vso"

This is obviously a bug (although a minor one), since the name origin is just a convention and a git remote can have any name; I reported it on Connect. If you encounter it you can easily work around it by renaming your remote to origin:

git remote rename vso origin

Running a custom tool automatically when a file is modified

As far as I can remember, Visual Studio always had something called “custom tools”, also known as single-file generators. When you apply such a tool to a file in your project, it will generate something (typically code, but not necessarily) based on the content of the file. For instance, the default custom tool for resource files is called ResXFileCodeGenerator, and generates a class that provides easy access to the resources defined in the resx file.

image

When you save a file that has a custom tool associated to it, Visual Studio will automatically rerun the custom tool to regenerate its output. You can also do it manually, by invoking the “Run custom tool” command in the context menu of a project item.

Usually, the custom tool needs only one input file to generate its output, but sometimes things are a bit more complex. For instance, consider T4 templates : they have a custom tool associated with them (TextTemplatingFileGenerator), so this tool will be run when the template is saved, but in many cases, the template itself uses other input files to generate its output. So the custom tool needs to be run not only when the template is modified, but also when files on which the template depends are modified. Since there is no way to tell Visual Studio about this dependency, you have to rerun the custom tool manually, which is quite annoying…

Because I was in this situation, and was tired of manually invoking the “Run custom tool” command on my T4 templates, I eventually created a Visual Studio extension to do this automatically: AutoRunCustomTool. The name isn’t very imaginative, but at least it’s descriptive…

This tool is designed to be very simple and unobtrusive; it just does its work silently, without getting in your way. It adds a new property to each project item : “Run custom tool on”. This property is a collection of file names for which the custom tool must be run every time this project item is saved. For instance, if you have a T4 template (Template.tt) that generates a file (Output.txt) based on the content of another file (Input.txt), you just need to add “Template.tt” to the “Run custom tool on” property of Input.txt. Every time you save Input.txt, the custom tool will be automatically rerun on Template.tt, which will regenerate the content of Output.txt. You can see a concrete example on the tool’s page in Visual Studio Gallery.

I created AutoRunCustomTool about 6 months ago, but the initial version was a bit rough around the edges, so I didn’t communicate about it. I released the second version a few days ago, and I think it’s now ready for everyone to use. If you’re interested in the code, you can find it on GitHub, which is also the place to report issues and suggest improvements.