title: How to combine multiple custom StyleCop rules under a single "Custom Rules" node in StyleCop settings and concurrency
body: <p>Based on several good articles I have been able to successfully create a few custom StyleCop rules. For reference, a few articles I found very useful on this topic are listed here:</p>
  
  <ul>
  <li><a href="https://sites.google.com/a/rees.biz/main/Home/customstylecoprules" rel="nofollow">How to Implement a Custom StyleCop Rule</a></li>
  <li><a href="http://www.lovethedot.net/2008/05/creating-custom-rules-for-microsoft.html" rel="nofollow">Creating Custom Rules for Microsoft Source Analyzer - Part I</a></li>
  <li><a href="http://www.lovethedot.net/2008/05/creating-custom-rules-for-microsoft_27.html" rel="nofollow">Creating Custom Rules for Microsoft Source Analyzer - Part II</a></li>
  <li><a href="http://www.lovethedot.net/2008/05/creating-custom-rules-for-microsoft_6976.html" rel="nofollow">Creating Custom Rules for Microsoft Source Analyzer - Part III</a></li>
  </ul>
  
  <p>I am using Visual Studio 2010 Ultimate edition along with StyleCop version 4.4.0.14.</p>
  
  <p>Creating a custom StyleCop rule calls for creating a class file along with a corresponding XML file, which is used to add the rules to the StyleCop settings. When I do this, all my custom rules get executed correctly. However, what I do not like about this is that in the StyleCop settings tree, you end up getting multiple "Custom Rules" nodes, one for every XML file.</p>
  
  <p>Skipping the implementation details of the different rules, here is what I did. Let's take the below two simple custom rules classes along their corresponding XML files:</p>
  
  <p><strong>File: CustomRule1.cs</strong></p>
  
  <pre><code>namespace StyleCop.CustomRules
  {
      [SourceAnalyzer(typeof(CsParser))]
      public class CustomRule1 : SourceAnalyzer
      {
          public override void AnalyzeDocument(CodeDocument document)
          {
              Param.RequireNotNull(document, "document");
              CsDocument csDocument = document as CsDocument;
              if ((csDocument.RootElement != null) &amp;&amp; !csDocument.RootElement.Generated)
              {
                  // Do something...
              }
          }
      }
  }
  </code></pre>
  
  <p><strong>File: CustomRule2.cs</strong></p>
  
  <pre><code>namespace StyleCop.CustomRules
  {
      [SourceAnalyzer(typeof(CsParser))]
      public class CustomRule2 : SourceAnalyzer
      {
          public override void AnalyzeDocument(CodeDocument document)
          {
              Param.RequireNotNull(document, "document");
              CsDocument csDocument = document as CsDocument;
              if ((csDocument.RootElement != null) &amp;&amp; !csDocument.RootElement.Generated)
              {
                  // Do something...
              }
          }
      }
  }
  </code></pre>
  
  <p><strong>File: CustomRule1.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;SourceAnalyzer Name="Custom Rules"&gt;
    &lt;Description&gt;
      These custom rules provide extensions to the ones provided with StyleCop.
    &lt;/Description&gt;
    &lt;Rules&gt;
      &lt;Rule Name="CustomRule1" CheckId="CR1001"&gt;
        &lt;Context&gt;Test rule 1.&lt;/Context&gt;
        &lt;Description&gt;Test rule 1.&lt;/Description&gt;
      &lt;/Rule&gt;
    &lt;/Rules&gt;
  &lt;/SourceAnalyzer&gt;
  </code></pre>
  
  <p><strong>File: CustomRule2.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;SourceAnalyzer Name="Custom Rules"&gt;
    &lt;Description&gt;
      These custom rules provide extensions to the ones provided with StyleCop.
    &lt;/Description&gt;
    &lt;Rules&gt;
      &lt;Rule Name="CustomRule2" CheckId="CR1002"&gt;
        &lt;Context&gt;Test rule 2.&lt;/Context&gt;
        &lt;Description&gt;Test rule 2.&lt;/Description&gt;
      &lt;/Rule&gt;
    &lt;/Rules&gt;
  &lt;/SourceAnalyzer&gt;
  </code></pre>
  
  <p>With the above, all (both) my rules got correctly executed. The following appeared in the StyleCop settings tree (the square brackets represent a checkbox):</p>
  
  <pre><code>[] C#
      [] {} Custom Rules
          [] {} CR1001: CustomRule1
      [] {} Custom Rules
          [] {} CR1002: CustomRule2
      [] {} Documentation Rules
      [] {} Layout Rules
      etc.
  </code></pre>
  
  <p>What I would like, is to have my custom rules under one node called "Custom Rules" in the StyleCop settings file as follows:</p>
  
  <pre><code>[] C#
      [] {} Custom Rules
          [] {} CR1001: CustomRule1
          [] {} CR1002: CustomRule2
      [] {} Documentation Rules
      [] {} Layout Rules
      etc.
  </code></pre>
  
  <p>I was able to combine the rules into a single "Custom Rules" node in the StyleCop settings by combining the two XML files into one as follows:</p>
  
  <p><strong>File: CustomRule1.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
  &lt;SourceAnalyzer Name="Custom Rules"&gt;
    &lt;Description&gt;
      These custom rules provide extensions to the ones provided with StyleCop.
    &lt;/Description&gt;
    &lt;Rules&gt;
      &lt;Rule Name="CustomRule1" CheckId="CR1001"&gt;
        &lt;Context&gt;Test rule 1.&lt;/Context&gt;
        &lt;Description&gt;Test rule 1.&lt;/Description&gt;
      &lt;/Rule&gt;
      &lt;Rule Name="CustomRule2" CheckId="CR1002"&gt;
        &lt;Context&gt;Test rule 2.&lt;/Context&gt;
        &lt;Description&gt;Test rule 2.&lt;/Description&gt;
      &lt;/Rule&gt;
    &lt;/Rules&gt;
  &lt;/SourceAnalyzer&gt;
  </code></pre>
  
  <p>However, once I did this, ONLY one custom rule got executed and that was <em>CustomRule1</em>, the rule where the class (file) name matched the XML file name.</p>
  
  <p>I attempted to set the attribute on <em>CustomRule2</em> to indicate the XML file as follows:</p>
  
  <pre><code>namespace StyleCop.CustomRules
  {
      [SourceAnalyzer(typeof(CsParser), "CustomRule1.xml")]
      public class CustomRule2 : SourceAnalyzer
      {
          public override void AnalyzeDocument(CodeDocument document)
          {
              Param.RequireNotNull(document, "document");
              CsDocument csDocument = document as CsDocument;
              if ((csDocument.RootElement != null) &amp;&amp; !csDocument.RootElement.Generated)
              {
                  // Do nothing.
              }
          }
      }
  }
  </code></pre>
  
  <p>Setting the attribute as shown above to the XML file did not resolve this issue either. Both rules appear in the StyleCop settings, but only <em>CustomRule1</em> gets executed.</p>
  
  <p>How can I resolve this?</p>
  
  <p><strong>Update:</strong></p>
  
  <p>Based on the accepted answer, I took the approach of checking all my custom rules within a single analyzer.</p>
  
  <p>From my understanding, each expression tree walker runs on its own thread, and thus state cannot be easily shared during the process. If I go with the approach of using a single analyzer, can I safely do the following?</p>
  
  <pre><code>[SourceAnalyzer(typeof(CsParser))]
  public class CustomRules : SourceAnalyzer
  {
      private enum CustomRuleName
      {
          CustomRule1,
          CustomRule2
      }
  
      private CustomRuleName currentRule;
  
      public override void AnalyzeDocument(CodeDocument document)
      {
          Param.RequireNotNull(document, "document");
          CsDocument doc = document as CsDocument;
  
          // Do not analyze empty documents, code generated files and files that
          // are to be skipped.
          if (doc.RootElement == null || doc.RootElement.Generated)
          {
              return;
          }
  
          // Check Rule: CustomRule1
          this.currentRule = CustomRuleName.CustomRule1;
          doc.WalkDocument(VisitElement);
  
          // Check Rule: CustomRule2
          this.currentRule = CustomRuleName.CustomRule2;
          doc.WalkDocument(VisitElement);
      }
  
      private bool VisitElement(CsElement element, CsElement parentElement, object context)
      {
          if (this.currentRule == CustomRuleName.CustomRule1)
          {
              // Do checks only applicable to custom rule #1
          }
          else if (this.currentRule == CustomRuleName.CustomRule2)
          {
              // Do checks only applicable to custom rule #2
          }
      }
  }
  </code></pre>
  
  <p><strong>Update:</strong></p>
  
  <p>Based on further testing the above is <strong>NOT</strong> safe. One cannot use instance fields to maintain state.</p>
  
  <ol>
  <li><p>When running StyleCop on a project with multiple source code files, multiple threads will share the same instance of the analyzer.</p></li>
  <li><p>Further, given the below code, multiple threads and concurrency also come into play on  each source code document being analyzed when the call to <code>doc.WalkDocument(...)</code> method is made. Each expression tree walker runs on its own thread.</p></li>
  </ol>
  
  <p>In other words, in addition to the fact that multiple source code files may be analyzed concurrently on multiple threads, the callbacks <code>VisitElement</code>, <code>StatementWalker</code> and <code>ExpressionWalker</code> are also executed on separate threads.</p>
  
  <pre><code>[SourceAnalyzer(typeof(CsParser))]
  public class CustomRules : SourceAnalyzer
  {
      public override void AnalyzeDocument(CodeDocument document)
      {
          Param.RequireNotNull(document, "document");
          CsDocument doc = document as CsDocument;
  
          // Do not analyze empty documents, code generated files and files that
          // are to be skipped.
          if (doc.RootElement == null || doc.RootElement.Generated)
          {
              return;
          }
  
          IDictionary&lt;string, Field&gt; fields = new Dictionary&lt;string, Field&gt;();
          doc.WalkDocument(VisitElement, StatementWalker, ExpressionWalker, fields);
      }
  
      private bool VisitElement(CsElement element, CsElement parentElement, object context)
      {
          // Do something...
          return true;
      }
  
      private bool StatementWalker(Statement statement, Expression parentExpression, Statement parentStatement, CsElement parentElement, object context)
      {
          // Do something...
          return true;
      }
  
      private bool ExpressionWalker(Expression expression, Expression parentExpression, Statement parentStatement, CsElement parentElement, object context)
      {
          // Do something...
          return true;
      }
  }
  </code></pre>