Using File Lists

StyleCop makes it easy to configure the rules that should run for a particular project, but until now there hasn’t been a straightforward way to set up alternate rules for specific files within a project. There are various ways to exclude generated code, selectively exclude a rule using an in-code suppression attribute, or mark a particular file as excluded in the csproj file, but each of these options are limited.

There are cases where you need to have fine grained control over exactly what rules will run for particular files in your solution. In StyleCop 4.4, it’s now possible to specify one or more file lists for a project, and apply custom settings to those files in a number of powerful and flexible ways.

For example, consider a small project which has a StyleCop settings file in place. The settings file disables a couple of layout rules for the project:

<StyleCopSettings Version="4.3">
  <Analyzers>
    <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.LayoutRules">
      <Rules>
        <Rule Name="StatementMustNotBeOnSingleLine">
          <RuleSettings>
            <BooleanProperty Name="Enabled">False</BooleanProperty>
          </RuleSettings>
        </Rule>
        <Rule Name="ElementMustNotBeOnSingleLine">
          <RuleSettings>
            <BooleanProperty Name="Enabled">False</BooleanProperty>
          </RuleSettings>
        </Rule>
      </Rules>
      <AnalyzerSettings />
    </Analyzer>
  </Analyzers>
</StyleCopSettings>

Now consider a situation where you’d like to disable some additional rules for a couple of specific files in the project, Class3.cs and Class4.cs. In StyleCop 4.4, this can be accomplished by adding a <SourceFileList> section within the settings file:

  <SourceFileList>
    <SourceFile>Class3.cs</SourceFile>
    <SourceFile>Class4.cs</SourceFile>
    <Settings>
      <Analyzers>
        <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.MaintainabilityRules">
          <Rules>
            <Rule Name="AccessModifierMustBeDeclared">
              <RuleSettings>
                <BooleanProperty Name="Enabled">False/BooleanProperty>
              </RuleSettings>
            </Rule>
          </Rules>
        </Analyzer>
      </Analyzers>
    </Settings>
  </SourceFileList>

As you can see, this is simply a standard set of StyleCop settings which is wrapped by a <SourceFileList> node. Here I’ve declared two <SourceFile> nodes which identify the names of the files which should inherit these settings.

One important thing to note is that, by default, the files called out in the file list still inherit the default project settings, except that the custom settings specified in the file list override the default settings. In the example shown above, this means that for Class3.cs and Class4.cs, the two layout rules will still be disabled, since are disabled at the project level, but the AccessModifierMustBeDeclared rule will also be disabled for just these two files.

Enabled Or Disabled By Default

In addition, a new setting allows you to determine whether rules should be enabled or disabled by default. This can be set either at the project level or at the SourceFileList level. For example, here’s how you would set up a project with all rules disabled by default, and only two rules explicitly enabled:

<StyleCopSettings Version="4.3">
 <GlobalSettings>
   <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
 </GlobalSettings>
  <Analyzers>
    <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.LayoutRules">
      <Rules>
        <Rule Name="StatementMustNotBeOnSingleLine">
          <RuleSettings>
            <BooleanProperty Name="Enabled">True</BooleanProperty>
          </RuleSettings>
        </Rule>
        <Rule Name="ElementMustNotBeOnSingleLine">
          <RuleSettings>
            <BooleanProperty Name="Enabled">True</BooleanProperty>
          </RuleSettings>
        </Rule>
      </Rules>
      <AnalyzerSettings />
    </Analyzer>
  </Analyzers>
</StyleCopSettings>

This is identical to the original settings file shown above, except that a new global property has been declared which disables all rules by default, and we’re now explicitly enabling two rules. With these settings, only these two rules will run for all files in the project.

The same can be done within a SourceFileList:

  <SourceFileList>
    <SourceFile>Class3.cs</SourceFile>
    <SourceFile>Class4.cs</SourceFile>
    <Settings>
      <GlobalSettings>
        <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
      </GlobalSettings>
      <Analyzers>
        <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.MaintainabilityRules">
          <Rules>
            <Rule Name="AccessModifierMustBeDeclared">
              <RuleSettings>
                <BooleanProperty Name="Enabled">True</BooleanProperty>
              </RuleSettings>
            </Rule>
          </Rules>
        </Analyzer>
      </Analyzers>
    </Settings>
  </SourceFileList>

Examples

Disable all rules for a subset of files.

In some cases, it may be desirable to completely disable StyleCop for a certain subset of rules in your project. This can be accomplished by creating a SourceFileList which disables all rules by default, and then does not enable any rules:

<StyleCopSettings Version="4.3">
  <SourceFileList>
    <SourceFile>Class3.cs</SourceFile>
    <SourceFile>Class4.cs</SourceFile>
    <Settings>
    <GlobalSettings>
      <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
    </GlobalSettings>
    </Settings>
  </SourceFileList>
</StyleCopSettings>

This settings file leaves all the default rules in place at the project level, so most of the files in the project will just run the default rules. Class3.cs and Class4.cs, however, will be completely ignored by StyleCop, because they are called out in a SourceFileList which disables all rules.

Create multiple file lists

There is no restriction to the number of file lists that can be created within a project settings file. For example:

<StyleCopSettings Version="4.3">
  <Analyzers>
    <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.LayoutRules">
      <Rules>
        <Rule Name="StatementMustNotBeOnSingleLine">
          <RuleSettings>
            <BooleanProperty Name="Enabled">False</BooleanProperty>
          </RuleSettings>
        </Rule>
      </Rules>
    </Analyzer>
  </Analyzers>

  <SourceFileList>
    <SourceFile>Class3.cs</SourceFile>
    <SourceFile>Class4.cs</SourceFile>
    <Settings>
    <GlobalSettings>
      <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
    </GlobalSettings>
    </Settings>
  </SourceFileList>

  <SourceFileList>
    <SourceFile>Class1.cs</SourceFile>
    <Settings>
      <Analyzers>
        <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.DocumentationRules">
          <AnalyzerSettings>
            <BooleanProperty Name="IgnorePrivates">True</BooleanProperty>
            <BooleanProperty Name="IgnoreInternals">True</BooleanProperty>
          </AnalyzerSettings>
        </Analyzer>
      </Analyzers>
    </Settings>
  </SourceFileList>
</StyleCopSettings>

This settings file disables a single rule for all files in the project. Further, it disables ALL rules for Class3.cs and Class4.cs. Finally, it sets a couple of additional properties for the Class1.cs file, to loosen up the documentation rules a bit for that file.

Ignore all project level settings

By default, file lists inherit all the project level settings and simply override or extend those settings. It is also possible to set up the file list so that it completely ignores all project level settings and only uses its own settings:

<StyleCopSettings Version="4.3">
  <Analyzers>
    <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.LayoutRules">
      <Rules>
        <Rule Name="StatementMustNotBeOnSingleLine">
          <RuleSettings>
            <BooleanProperty Name="Enabled">False</BooleanProperty>
          </RuleSettings>
        </Rule>
      </Rules>
      <AnalyzerSettings />
    </Analyzer>
  </Analyzers>

  <SourceFileList>
    <SourceFile>Class1.cs</SourceFile>
    <Settings>
      <GlobalSettings>
        <StringProperty Name="MergeSettingsFiles">NoMerge</StringProperty>
      </GlobalSettings>
      <Analyzers>
        <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.DocumentationRules">
          <AnalyzerSettings>
            <BooleanProperty Name="IgnorePrivates">True</BooleanProperty>
            <BooleanProperty Name="IgnoreInternals">True</BooleanProperty>
          </AnalyzerSettings>
        </Analyzer>
      </Analyzers>
    </Settings>
  </SourceFileList>
</StyleCopSettings>

By setting the NoMerge option on the file list settings, StyleCop will not apply the project-level settings when analyzing Class1.cs. The project-level settings disable the StatementMustNotBeOnSingleLine rule, but this rule will still run for Class1.cs.

Limitations

Of course, there are a few limitations to what you can do with file lists in 4.4. For one, it’s not possible to use wildcards and regular expressions to match the names of files specified in the file list. The file name must match exactly (case insensitive).

A second limitation is that StyleCop will not detect when you rename a file which happens to be included in a StyleCop file list. You will have to manually edit the settings file and update the name of the file.

Lastly, the StyleCop settings wizard does not have any knowledge of file lists in 4.4. Not only will you not be able to use this dialog to create and edit file list settings, if you edit a settings file containing a file list with the settings wizard, the wizard will overwrite the file and wipe out your file lists completely.

From 4.7.15.0 the StyleCop Settings Editor will save any existing SourceFileLists.

Wrapping It Up

File lists are a simple, convenient, and powerful way to set up custom settings for specific files in your solution. You may find them particularly useful when introducing StyleCop on a legacy project, since you can slowly turn on rules one by one for individual files as you clean them up.

(Originally from Jason Allor's blog at http://devjitsu.com/blog/2010/06/29/stylecop-file-lists-in-4-4/

Last edited Mar 17, 2012 at 6:00 PM by andyr, version 8