如何在 StyleCop 设置和并发中的单个“自定义规则”节点下组合多个自定义 StyleCop 规则

2024-03-17

基于几篇好文章,我已经能够成功创建一些自定义 StyleCop 规则。作为参考,这里列出了我发现关于该主题非常有用的几篇文章:

  • 如何实施自定义 StyleCop 规则 https://sites.google.com/a/rees.biz/main/Home/customstylecoprules
  • 为 Microsoft Source Analyzer 创建自定义规则 - 第一部分 http://www.lovethedot.net/2008/05/creating-custom-rules-for-microsoft.html
  • 为 Microsoft Source Analyzer 创建自定义规则 - 第 II 部分 http://www.lovethedot.net/2008/05/creating-custom-rules-for-microsoft_27.html
  • 为 Microsoft Source Analyzer 创建自定义规则 - 第 III 部分 http://www.lovethedot.net/2008/05/creating-custom-rules-for-microsoft_6976.html

我正在使用 Visual Studio 2010 Ultimate 版本和 StyleCop 版本 4.4.0.14。

创建自定义 StyleCop 规则需要创建一个类文件以及相应的 XML 文件,该文件用于将规则添加到 StyleCop 设置中。当我这样做时,我的所有自定义规则都会正确执行。然而,我不喜欢的是,在 StyleCop 设置树中,您最终会获得多个“自定义规则”节点,每个 XML 文件对应一个节点。

跳过不同规则的实现细节,这就是我所做的。让我们采用以下两个简单的自定义规则类及其相应的 XML 文件:

文件:CustomRule1.cs

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) && !csDocument.RootElement.Generated)
            {
                // Do something...
            }
        }
    }
}

文件:CustomRule2.cs

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) && !csDocument.RootElement.Generated)
            {
                // Do something...
            }
        }
    }
}

文件:CustomRule1.xml

<?xml version="1.0" encoding="utf-8" ?>
<SourceAnalyzer Name="Custom Rules">
  <Description>
    These custom rules provide extensions to the ones provided with StyleCop.
  </Description>
  <Rules>
    <Rule Name="CustomRule1" CheckId="CR1001">
      <Context>Test rule 1.</Context>
      <Description>Test rule 1.</Description>
    </Rule>
  </Rules>
</SourceAnalyzer>

文件:CustomRule2.xml

<?xml version="1.0" encoding="utf-8" ?>
<SourceAnalyzer Name="Custom Rules">
  <Description>
    These custom rules provide extensions to the ones provided with StyleCop.
  </Description>
  <Rules>
    <Rule Name="CustomRule2" CheckId="CR1002">
      <Context>Test rule 2.</Context>
      <Description>Test rule 2.</Description>
    </Rule>
  </Rules>
</SourceAnalyzer>

通过以上内容,我的所有(两个)规则都得到了正确执行。以下内容出现在 StyleCop 设置树中(方括号代表复选框):

[] C#
    [] {} Custom Rules
        [] {} CR1001: CustomRule1
    [] {} Custom Rules
        [] {} CR1002: CustomRule2
    [] {} Documentation Rules
    [] {} Layout Rules
    etc.

我想要的是将我的自定义规则放在 StyleCop 设置文件中名为“自定义规则”的一个节点下,如下所示:

[] C#
    [] {} Custom Rules
        [] {} CR1001: CustomRule1
        [] {} CR1002: CustomRule2
    [] {} Documentation Rules
    [] {} Layout Rules
    etc.

通过将两个 XML 文件合并为一个,我能够将规则合并到 StyleCop 设置中的单个“自定义规则”节点中,如下所示:

文件:CustomRule1.xml

<?xml version="1.0" encoding="utf-8" ?>
<SourceAnalyzer Name="Custom Rules">
  <Description>
    These custom rules provide extensions to the ones provided with StyleCop.
  </Description>
  <Rules>
    <Rule Name="CustomRule1" CheckId="CR1001">
      <Context>Test rule 1.</Context>
      <Description>Test rule 1.</Description>
    </Rule>
    <Rule Name="CustomRule2" CheckId="CR1002">
      <Context>Test rule 2.</Context>
      <Description>Test rule 2.</Description>
    </Rule>
  </Rules>
</SourceAnalyzer>

然而,一旦我这样做了,只有一个自定义规则被执行,那就是自定义规则1,类(文件)名与 XML 文件名匹配的规则。

我尝试将属性设置为自定义规则2表示 XML 文件如下:

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) && !csDocument.RootElement.Generated)
            {
                // Do nothing.
            }
        }
    }
}

将如上所示的属性设置为 XML 文件也无法解决此问题。这两个规则都出现在 StyleCop 设置中,但仅自定义规则1被处决。

我该如何解决这个问题?

Update:

根据接受的答案,我采取了在单个分析器中检查所有自定义规则的方法。

根据我的理解,每个表达式树遍历器都在自己的线程上运行,因此在此过程中状态无法轻松共享。如果我采用使用单个分析器的方法,我可以安全地执行以下操作吗?

[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
        }
    }
}

Update:

根据进一步测试,上述结果是NOT安全的。不能使用实例字段来维护状态。

  1. 当在具有多个源代码文件的项目上运行 StyleCop 时,多个线程将共享分析器的同一实例。

  2. 此外,考虑到下面的代码,当调用时,多线程和并发也会在正在分析的每个源代码文档上发挥作用doc.WalkDocument(...)方法做出来。每个表达式树遍历器都在自己的线程上运行。

换句话说,除了可以在多个线程上同时分析多个源代码文件之外,回调VisitElement, StatementWalker and ExpressionWalker也在单独的线程上执行。

[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<string, Field> fields = new Dictionary<string, Field>();
        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;
    }
}

通常分析器包含多个规则(否则会很奇怪)。 每个分析器在设置 UI 中显示为单独的节点。

如果您希望设置 UI 中有一个节点,那么您肯定只需要一个分析器,它将执行您的两项检查。

namespace StyleCop.CustomRules
{
    [SourceAnalyzer(typeof(CsParser))]
    public class MyCustomRules : SourceAnalyzer
    {
        public override void AnalyzeDocument(CodeDocument document)
        {
            // ...
            // code here can raise CR1001 as well as CR1002
        }
    }
}

文件:MyCustomRules.xml

<?xml version="1.0" encoding="utf-8" ?>
<SourceAnalyzer Name="My Custom Rules">
  <Description>
    These custom rules provide extensions to the ones provided with StyleCop.
  </Description>
  <Rules>
    <Rule Name="CustomRule1" CheckId="CR1001">
      <Context>Test rule 1.</Context>
      <Description>Test rule 1.</Description>
    </Rule>
    <Rule Name="CustomRule2" CheckId="CR1002">
      <Context>Test rule 2.</Context>
      <Description>Test rule 2.</Description>
    </Rule>
  </Rules>
</SourceAnalyzer>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 StyleCop 设置和并发中的单个“自定义规则”节点下组合多个自定义 StyleCop 规则 的相关文章

随机推荐

  • 无法在 Linux 上安装 sqldf

    我在 Linux 上运行 R 版本 2 14 1 当我尝试安装 sqldf 时 install packages sqldf dependencies TRUE 我收到以下错误 这些错误导致从终端运行命令 就像使用 Rcmdr UI 一样
  • mongoDB 错误:错误:无法连接到 [localhost:27017]

    我正在尝试安装habitrpg https github com busterroni habitrpg在本地 但我在输入后不断收到 mongoDB 错误node src seed js Error failed to connect to
  • C# Mono Linux - 抓取全局剪贴板的内容

    我试图简单地从剪贴板 抓取 文本并将其放入变量中 我在做这件事时遇到了很多麻烦 我尝试过使用 Gtk Clipboard Get Gdk Atom Intern PRIMARY true 到目前为止 我的代码只是将 Gtk Clipboar
  • youtube-api removeEventListener 不工作

    我可以很好地添加事件 addEventListener onStateChange handleStateChange 但当尝试删除该事件时 却没有 removeEventListener onStateChange handleState
  • 获取当前位置div的ID

    我有n个 section 在一个页面中 每个页面都提供了 id 例如 page1 page2 在顶部我放置了 2 个按钮 即 上一个 和 下一个 当按下上一个按钮时 它将滚动到上一个 section 与下一个类似 section 按 下一步
  • JAX-WS - 添加 SOAP 标头

    我正在尝试创建一个独立的客户端来使用一些网络服务 我必须将我的用户名和密码添加到 SOAP 标头中 我尝试添加凭据 如下所示 OTSWebSvcsService service new OTSWebSvcsService OTSWebSvc
  • Facebook 应用程序请求通知未显示在移动网络应用程序的 Facebook iOS 应用程序中

    我有一个配置为 Facebook 画布应用程序的 Facebook 应用程序以及一个包含网站和移动网站 URL 的网站 当应用程序发送应用程序请求 邀请 时 它们仅显示在桌面浏览器中的收件人通知中 而不显示在 Facebook iOS 应用
  • Firebase DatabaseReference 按指定值过滤

    假设我有这个 firebase JSON 结构 我需要获取属性 from 等于 this 的所有问题 我知道我可以使用 Volley 来创建 StringRequest 并从我的 questions json 中获取所有值 然后 在客户端
  • 如何让服务帐户只能访问一个存储桶(Google Cloud)?

    如何提供服务帐号只能访问一个桶 如果你以防万一想再给一个第3方服务访问您的private bucket 问题是默认的 服务帐户 可以访问所有存储桶 但我不知道如何将其限制为仅限一个存储桶 是否可以通过仪表板或仅通过控制台来实现此目的 如果可
  • 向样式组件添加过渡

    我在 React 中有以下组件 const Button styled div width 30px height 30px position absolute right 2em top 50 transform translateY 5
  • 使用秒表分析 .NET 应用程序

    似乎没有免费的 NET 性能分析器可以逐行进行分析 因此 我正在考虑使用秒表进行分析 免费即自由 即许可证包括商业应用程序 编辑 为了回应那些告诉我 购买分析器 的人 我愿意 但如果我能花那么多钱 我会把它花在其他东西上 我试图让我的老板相
  • 如何仅循环 select() 的 fd_set 结果中的活动文件描述符?

    所以在我当前的服务器实现中 目前是这样的 void loop step 1 clear set fd set readfds while true step 1 FD ZERO readfds step 2 loop through soc
  • Node.js UDP (dgram) 处理 DNS 解析错误

    我正在使用 Node 的内置数据报 UDP 套接字进行简单的 UDP 发送 http nodejs org docs v0 3 1 api dgram html http nodejs org docs v0 3 1 api dgram h
  • Django 从注释计数中排除

    我有以下申请 from django db import models class Worker models Model name models CharField max length 60 def str self return se
  • 如何在 C 中处理指针? [复制]

    这个问题在这里已经有答案了 我对 C 很陌生 在学习指针方面遇到了一些问题 我尝试了交换 这就是我能用它们做的所有事情 我知道每个变量在内存单元中都有自己的地址 这是我的讲师告诉我们的 并且每个变量的值都可以通过转到其关联的地址来获取 然后
  • Kendo UI DatePicker - 获取先前的值

    当用户使用日期选择器更改日期时 我尝试进行确认 是否可以从对象模型中获取先前的值 或者我需要推出自己的值 没有 据我所知 但你可以很容易地实现它 如下所示 var datePicker date kendoDatePicker change
  • 为什么 Scala 有时会自动应用 thunk?

    就在 2 点 40 分之后卡特隆之影 http www youtube com user ShadowofCatron s Scala 教程 3 视频 http www youtube com watch v R3gh9jIIbME 指出了
  • InvalidOperationException:撤消操作遇到的上下文与相应设置操作中应用的上下文不同

    我得到以下异常 Exception Type System InvalidOperationException Exception Message The Undo operation encountered a context that
  • JSESSIONID 在什么条件下创建?

    何时 什么条件JSESSIONID被建造 是每个域吗 例如 如果我有一个 Tomcat 应用程序服务器 并且我部署了多个 Web 应用程序 则会有不同的JSESSIONID是根据上下文 Web 应用程序 创建的 还是在 Web 应用程序之间
  • 如何在 StyleCop 设置和并发中的单个“自定义规则”节点下组合多个自定义 StyleCop 规则

    基于几篇好文章 我已经能够成功创建一些自定义 StyleCop 规则 作为参考 这里列出了我发现关于该主题非常有用的几篇文章 如何实施自定义 StyleCop 规则 https sites google com a rees biz mai