Close

May 12, 2018

Stylecop: A Detailed Guide to Starting and Using It

Editorial note: I originally wrote this post for the Submain blog. You can check out the original here, at their site.

Put two developers together and they’re bound to have a discussion about coding style. No two developers write code in the exact same way. More often than not, one isn’t better than the other and it’s just a matter of taste. In a team or in a single project, it’s more important to be consistent than it is to choose the right style. Agreeing on a style can be hard enough, but enforcing it shouldn’t be something you do manually. It will be tedious and error-prone.

StyleCop is a tool that can automate this. Let’s have a look at how to set it up and what it brings to the table.

What Is StyleCop?

The GitHub page for the old StyleCop tool says this:

StyleCop analyzes C# source code to enforce a set of style and consistency rules.

We’ll get into what this means exactly, but first a little word about the “old” and the “new” StyleCop. StyleCop used to be a Visual Studio plugin and a NuGet package. You can still use this in Visual Studio 2017, but the current recommended way to use StyleCop is to use the Roslyn-based analyzers. These analyzers will continue to be supported in the future, whereas the Visual Studio plugin and the NuGet package will no longer receive any major improvements. So for this article, I’ll focus on the StyleCop Analyzers project.

OK, now that we’ve got that out of the way, let’s look at a specific example of what StyleCop provides us. Let’s say your team has agreed to avoid one-line statements like this:

Rather, you want it to be

StyleCop provides a way of identifying all places in your code where these one-liners occur and optionally enforcing the multi-line statement by not allowing the project to be built.

The merits of the above example are something to discuss with your team, but every team should have guidelines on how they choose to write their code. This increases readability and predictability, making your daily lives a lot more pleasant and helping you avoid useless discussions. These guidelines can range from whitespace rules to member-naming guidelines and from the order of members in your file to XML documentation guidelines. Whichever style guidelines you choose, StyleCop will allow you to enforce them automatically.

So how do we get started with StyleCop?

Installing StyleCop

To add StyleCop to your project, install the “StyleCop.Analyzers” package:

There’s really nothing more to it.

Running StyleCop

Now, build your project in Visual Studio and chances are, you will see several warnings in the output window. For example, take this simple console application:

This file alone has 12 StyleCop warnings:

If you want to know more about a rule, click on the code and your browser will open a page with documentation on the rule.

To fix the rule violations, we must

  • Add XML comments
  • Generate an XML documentation file (this can be set in the project properties)
  • Add a file header (e.g., copyright information)
  • Put the “using” statements inside the “namespace” block
  • Put braces on a new line
  • Add an empty line between the two method definitions (Output2 and Output3)

This makes our application now look like this:

You might not agree with all these rules. Luckily, you can tune StyleCop to your own needs.

Configuring StyleCop

Configuring StyleCop is done in two optional steps. First, you can use rule set files to configure what rules are checked and how strongly you feel about them. Second, you can add a stylecop.json file to your project to fine-tune some rules.

Rule Sets

Rule set files are files containing the rules you want to check. In the project we’ve created above, right-click on the project and choose “Properties.” In the screen that just opened, select “Code Analysis”:

By default, the “Microsoft Managed Recommended Rules” will be selected. Click on “Open” and you’ll see a long list of rules you can select or deselect:

Notice that you can also change the action for the rules. Select a rule and open the dropdown to change the severity of the rule:

The “Action” dropdown allows you to tell Visual Studio what to do with the rule:

  • “Warning” means a violation will be shown as a warning when building the solution.
  • “Error” means a violation will be shown as an error. This also means you’ll see the red squiggly lines in the editor, and the build will fail.
  • “Info” means a violation will be shown as an information message.
  • “Hidden” means the rule is still checked, but you won’t see it in Visual Studio. This setting is more for use in custom tools than in Visual Studio.
  • “None” means the rule will not be checked. This is, in essence, the same as deselecting the rule.
  • <Inherit> means the action will be inherited from the rule group. You can specify an action at the level of a rule group too.

If you change any of the settings in these default Microsoft rules, it will create a new rule set file and add it to the project. This is now the rule set for your project. Later in this article, we’ll cover solution-wide rule sets.

The default Microsoft rule sets are a great starting point. By customizing them for your project, you can have an automated analysis that fits your need with little effort. Be sure to add the resulting .ruleset file to your source control system, and let it evolve as your needs evolve.

Stylecop.json

The stylecop.json file is a settings file to further configure StyleCop. The easiest way to add the file is to open a file that violates rule SA1633. This is the rule that requires a file header (e.g., a copyright notice). Press “CTRL + .” and you’ll see an option to add the file:

A JSON file with just a few lines will be added to your project:

The “$schema” property is to provide IntelliSense.

The “settings.documentationRules.companyName” will be used to automatically create a copyright notice when you fix rule SA1633.

However, if you go back to the file without a header, press CTRL + . again and choose the option to add the file header, you will see that the header still contains “PlaceholderCompany,” even if you’ve changed the stylecop.json file. This is due to an issue that’s not yet resolved at the time of writing. To fix this, open the properties of the stylecop.json file and set the Build Action to “Additional Files.” If you’re writing a .NET Core or .NET Standard project, choose “C# analyzer additional file.”

Now that that’s done, you can add the file header again, and you’ll see the correct copyright notice.

The stylecop.json file allows quite a lot of configuration. Be sure to check out the documentation because it’s too much to handle here. But I will provide one example. The Microsoft guidelines tell you to put the using statements inside the namespace declaration. Because Visual Studio puts them outside the namespace by default, most developers I know consider this awkward. So let’s configure StyleCop to prefer them outside the namespace.

Notice how, in our example application, the code looked like this:

Now let’s add this to the “Settings” property in our stylecop.json:

Next time we build, we will get new warnings telling us the “using directive must appear outside a namespace declaration.” To fix this, we simply need to change our code:

Once again, be sure to check out the documentation to see what’s possible. But don’t worry about getting everything right the first time. Often, the default values are what you want. If not, discuss this with your team and choose the configuration you agree on.

Breaking the Build

Once you have your rules all set up, you have an automated way of checking for style violations. This is important if you want to avoid manual and time-consuming inspection. And keeping your code consistent makes it predictable and more readable. This, in turn, makes developers more productive and generally less frustrated.

Coming to an agreement can sometimes take lengthy discussions. But often, the exact rule isn’t as important as it is to have a rule and not violate it. So whether or not the opening curly brace is on the same line or a new line isn’t very important. What is important is that you stick to the convention for your team or project.

With that said, you might want to start breaking the build when certain rules are violated. You could edit the properties of your project to treat all warnings as errors:

However, that often leads to some frustration when developers see the build failing on issues they don’t regard as being a problem. A better approach would be to identify the rules you have no or few violations against and change the action from “Warning” to “Error.” Fix the few violations and agree with your team that, from now on, those rules will be breaking the build. Then incrementally increase the number of rules that result in an error until you feel you’ve reached a point where the code looks and reads the way you want.

This approach gradually makes the build stricter and stricter without angering your fellow team members.

The Exceptions to the Rule

Inevitably, you’ll encounter specific cases where you deliberately want to violate a rule.

Let’s say we have a class that contains public fields—something rule SA1401 warns against. We’re going to assume we have some legitimate reason that this cannot be a property. Some legacy library might use reflection to get the value of all fields, and this library might be out of our control.

So our code looks like this:

When we press CTRL + . on the “Name” field, we see the option to suppress SA1401:

As you can see, we have the option of suppressing it directly in the .cs file or in a separate file.

If we choose to suppress the warning in the source file, our code changes to this:

The first line we added disables rule SA1401 for all code that follows. The rule remains disabled until the rule is restored again, which happens in the second line that we added.

If we choose to suppress the error in a suppression file, a GlobalSuppressions.cs file is added to the project. In that file, an assembly attribute will have been added. This attribute gives you a little more control than the previous technique because you can scope the suppression.

This line, for example, will suppress the rule for the “Name” property of the customer class:

But by changing the scope and the target, we can suppress this error for all violations in the “Customer” class:

You can also scope to a specific namespace.

Finally, notice how you can provide a justification, which more clearly communicates to other developers why it’s a good idea to suppress the warning.

Analyzing All Projects

In our example, we only added StyleCop to a single library; we added all files to the library. But most solutions consist of multiple projects. In order to use one rule set file for the entire solution, in Visual Studio you can go to Analyze > Configure Code Analysis > For Solution.

This will give you a dialog to choose the rules for all projects in your solution:

In such a case, I would recommend moving the rule set file outside of the project and adding it as a solution item. You can do this by first placing the rule set file next to the solution file (using Windows Explorer). Then right-click the solution in Visual Studio and select “Add existing item.” Finally, select the rule set file and configure your solution analysis with the dialog shown above.

You can use a similar technique for the stylecop.json file. First, put the stylecop.json file next to the solution file. Then right-click on each project and select “Add existing item.” In the file dialog, choose the stylecop.json file, but don’t click on the “Add” button. Rather, click on the dropdown and select “Add As Link.” If you just click “Add,” you’ll create a copy of the file for each project. Any changes to the stylecop.json file would have to be done for each project. When you add it as a link, you keep one copy of the file and only have to edit that one.

Just remember you need to add the StyleCop.Analyzers package to each project you want to analyze and set the Build Action of each linked stylecop.json file to “Additional Files.”

Style Isn’t Everything

Have a consistent style, and have it enforced automatically; it’s a great step forward to writing maintainable and readable code. But it doesn’t stop there. Automating your code quality analysis also includes things like detecting dead code, calculating cyclomatic complexity, and identifying security issues.

StyleCop will not do all of this for you. This requires other tools like FxCop or CodeIt.Right.  (CodeIt.Right, since version 2.5, actually integrates Stylecop into its analysis.)

Let It Evolve

One last word of warning. Too often, I’ve seen teams lose productivity because of rules they don’t agree with. Or maybe they used to agree with them, but times have changed and so have opinions. As an example, I’m thinking of a company where the “var” keyword wasn’t allowed…in any project. This company-wide rule seemed set in stone and frustrated developers wanting to use modern language features.

Teams should come to an agreement on which rules they want to enforce and how severe violations are. And when opinions change, rules should follow.

The idea is to let StyleCop do the work for you and enable you to have a clean, consistent codebase with minimal effort. But the definition of clean and consistent can change over time.

I’ve provided a fairly complete guide to help you get started with StyleCop. So get together with your team and talk about how you want your code to look. Then set up StyleCop with some rules and move on from there. You’ll see the quality of your code improve. Good luck!

 

Leave a Reply

Your email address will not be published. Required fields are marked *