Home

Awesome

VSDiagnostics

A collection of code-quality analyzers based on the Roslyn compiler platform. This project aims to ensure code-quality as you type it in your editor rather than having to do this as a separate build-step. By performing static analysis while you're writing code, certain convention violations and hidden pitfalls can be avoided as early in the process as possible.

<img src="https://cloud.githubusercontent.com/assets/2777107/12633986/2e05fc66-c576-11e5-92a2-3c192f2f0d89.gif" />

Get it from NuGet!

Build status Test status

Keep in mind that this project is under active development. If you encounter bugs, let us know!

What is an analyzer exactly?

With the release of Visual Studio 2015 RC, we also received the pretty much final implementation of the Diagnostics implementation. This SDK allows us to create our own diagnostics to help us write proper code that’s being verified against those rules in real-time: you don’t have to perform the verification at a separate build-step. What’s more is that we can combine that with a code fix: a shortcut integrated in Visual Studio that provides us a solution to what we determine to be a problem.

This might sound a little abstract but if you’ve been using Visual Studio (and/or Resharper) then you know what I mean: have you ever written your classname as class rather than Class? This is a violation of the C# naming conventions and visual studio will warn you about it and provide you a quickfix to turn it into a proper capitalized word. This is exactly the behaviour we can create and which is integrated seemlessly in Visual Studio.

Full text available on my blog.

What is available?

Currently these diagnostics are implemented:

CategoryNameDescription
ArithmeticVSD0045The operands of a divisive expression are both integers and result in an implicit rounding.
AsyncVSD0001Asynchronous methods should end with the -Async suffix.
AsyncVSD0041A non-async, non-Task method should not end with -Async.
AsyncVSD0064Async methods should return a Task to make them awaitable.
AttributesVSD0002An attribute should not have an empty argument list.
AttributesVSD0003Gives an enum the [Flags] attribute.
AttributesVSD0004A [Flags] enum its values are not explicit powers of 2
AttributesVSD0039A [Flags] enum its values are not explicit powers of 2 and its values dont fit in the specified enum type.
AttributesVSD0005The [Obsolete] attribute doesn't have a reason.
AttributesVSD0006OnPropertyChanged() can use the [CallerMemberName] attribute to automatically pass the property name.
ExceptionsVSD0007An ArgumentException should use nameof() to refer to a variable.
ExceptionsVSD0008Verifies no NullReferenceException is caught.
ExceptionsVSD0009Verifies whether an ArgumentException is thrown with a message.
ExceptionsVSD0010Warns when an exception catch block is empty.
ExceptionsVSD0011Warns when an exception is rethrown in a way that it loses the stacktrace.
ExceptionsVSD0012Verifies whether a try-catch block does not defer all exception handling to a single Exception clause.
ExceptionsVSD0052An exception is thrown from an implicit operator.
ExceptionsVSD0053An exception is thrown from a property getter.
ExceptionsVSD0054An exception is thrown from a static constructor.
ExceptionsVSD0055An exception is thrown from a finally block.
ExceptionsVSD0056An exception is thrown from an equality operator.
ExceptionsVSD0057An exception is thrown from a Dispose method.
ExceptionsVSD0058An exception is thrown from a finalizer method.
ExceptionsVSD0059An exception is thrown from a GetHashCode() method.
ExceptionsVSD0060An exception is thrown from an Equals() method.
ExceptionsVSD0065A null object is attempted to get thrown.
GeneralVSD0013Changes an as expression to a cast.
GeneralVSD0014Changes a cast expression to as.
GeneralVSD0015A boolean expression comparing to false can be simplified.
GeneralVSD0016A boolean expression comparing to true can be simplified.
GeneralVSD0017The conditional operator shouldn't return redundant default options.
GeneralVSD0018The conditional operator shouldn't return redundant inverted default options.
GeneralVSD0019The condition is a constant (false) and thus unnecessary.
GeneralVSD0020The condition is a constant (true) and thus unnecessary.
GeneralVSD0021Inserts the default access modifier for a declaration.
GeneralVSD0022Detects usage of the goto keyword.
GeneralVSD0023Requires braces for if, else, for, foreach, while, do, using, lock, fixed and switch constructs.
GeneralVSD0025Implements the most common configuration of naming conventions.
GeneralVSD0026A public, internal or protected internal non-const, non-readonly field should be used as a property.
GeneralVSD0027Changes Nullable<T> to T?.
GeneralVSD0028Use the nameof() operator in conjunction with OnPropertyChanged.
GeneralVSD0029Simplify the expression using an expression-bodied member.
GeneralVSD0030A constructor is the same as a default constructor and can be removed.
GeneralVSD0031Use as/null instead of is/as.
GeneralVSD0032Use var instead of the explicit type.
GeneralVSD0033Use the built-in type alias instead of the concrete type.
GeneralVSD0044Add cases for missing enum members.
GeneralVSD0043An instance of type System.Random is created in a loop.
GeneralVSD0046Equals() and GetHashCode() must be implemented together.
GeneralVSD0047Implement elementary methods for a type used in a collection.
GeneralVSD0048A property with a private setter can become a read-only property instead.
GeneralVSD0049A switch is missing a default label.\
GeneralVSD0052Implement Equals() and GetHashCode() using existing fields and properties.
GeneralVSD0063A GetHashCode implementation refers to a mutable field.
StringsVSD0034Replaces an empty string literal with the more expressive string.Empty.
StringsVSD0035Orders the arguments of a string.Format() call in ascending order according to index.
StringsVSD0042A string.Format() call lacks arguments and will cause a runtime exception.
StructsVSD0036Warns when a struct replaces this with a new instance.
StructsVSD0050Structs should implement Equals(), GetHashCode(), and ToString().
TestsVSD0037A test method should not end with -Test.
TestsVSD0038Verifies whether a test method has the public modifier.
TestsVSD0062A method might be missing a test attribute.

How do I use this?

Simply head over to NuGet and install it! If you don't immediately find it: make sure you're also looking through the NuGet V2 package source.

Can I request diagnostics?

Yes, you can! Create an issue and we'll take a look at your proposal.

What if I don't like a diagnostic?

Every diagnostic can be turned off for a single line or for the entire project. At most, you will have to ignore the diagnostic once. For this reason every diagnostic is turned on by default. In order to do so, right click on 'Analyzers' under your references and select 'Open Active Rule Set'. This presents you with the following window to configure which diagnostics should be turned on and their default severity. If you wish to do so, you can change the severity to a more strict or more forgiving setting.

<img src="https://cloud.githubusercontent.com/assets/2777107/10696693/a1a2c82a-79a9-11e5-97bf-21f7e8c37356.PNG" />

What's on the roadmap?

Most things are filed as an issue so if you want the complete picture -- head over there. However in broad terms:

Can I contribute?

Definitely! Take a look at the open issues and see if there's anything that interests you. Submit your pull request and we'll take a look at it as soon as possible.

If you think you're going to make larger changes than a single implementation then we would ask you to get in contact with us first so we can discuss it and prevent unneeded work.

You'll need Visual Studio 2015 and the SDK to get started.

Where can I find more information about every diagnostic?

Release 2.0.0 will come with a website where we document every diagnostic including reasoning behind its implementation choices. In the meantime you can take a look at the tests that belong to each diagnostic to see what exact scenarios we have accounted for.

How can I get in contact?

You're always free to open an issue but if you would like something more direct you can drop by in the StackExchange chat channel where the main contributors reside or send an email to jer_vannevel@outlook.com.