ALM Rangers

使用 StyleCop 实现静态代码分析

Hamid Shahid

您多久遇到一次不能理解的代码?通常,不一致的格式设置、无效的注释以及缺少命名约定会使代码无法读懂。这种不一致情况通常被视为不重要的异常,但它们会使代码的总体可维护性出现很大的差异。

StyleCop 是一种用于维护源代码中的样式和格式一致性的强大工具。与 Visual Studio 代码分析一样,StyleCop 执行静态代码分析。但与 Visual Studio 代码分析不同,它扫描源代码文件而不是托管代码。而且,StyleCop 仅验证样式是否不一致,而不执行代码优化和性能检查。

在本文中,我将介绍 StyleCop,向您演示其工作方式,并讨论在项目中采用它时应考虑的因素。最后,我将演示如何在 Visual Studio Team Foundation Server (TFS) 版本中包含 StyleCop 执行。

StyleCop 基础

StyleCop (stylecop.codeplex.com) 是一种对 C# 源文件执行静态代码分析的开放源代码工具。它与 Visual Studio 集成并显示在上下文菜单中,您可以选择它来扫描当前文件或任何所选的文件或项目。图 1 显示上下文菜单中适用于 Visual Studio 项目的 StyleCop 选项。


图 1 StyleCop 上下文菜单选项

选择“运行 StyleCop”或“运行 StyleCop (全部重新扫描)”选项时,StyleCop 将分析所有 C# 文件并针对指定的 StyleCop 规则验证这些文件。如果存在冲突,则“错误列表”窗口中将显示警告。

StyleCop 设置文件:这是 StyleCop 保留其所有配置选项的位置。此文件包含诸如选定规则这样的信息;诸如自定义单词或缩写词这样的词汇信息;以及是否将此设置文件与父目录中的设置文件(如果有)合并。

假定 StyleCop 在源文件的父目录中递归查找此设置文件,则最佳做法是保留单一版本的 Settings.StyleCop 文件。维护一个文件并将其存储在团队项目的根目录处可确保在整个团队项目中使用相同的规则集。

自定义字典文件:除允许将单词和缩写词添加到设置文件之外,StyleCop 还使用 CustomDictionary.xml 文件,该文件使用与 Visual Studio 代码分析字典相同的格式。这让您可以将相同的字典文件用于这二者。图 2 显示了此字典文件的格式。

图 2 自定义字典文件

 

<Dictionary>
  <Words>
    <Unrecognized>
      <Word/>
    </Unrecognized>
    <Recognized>
      <Word/>
    </Recognized>
    <Deprecated>
      <Term PreferredAlternate=""/>
    </Deprecated>
    <Compound>
      <Term CompoundAlternate=""/>
    </Compound>
    <DiscreteExceptions>
      <Term />
    </DiscreteExceptions>
  </Words>
  <Acronyms>
    <CastingException>
      <Acronym />
    </CastingException>
  </Acronyms>
</Dictionary>

 

在解释 StyleCop 的用途和基础知识之后,现在我将介绍哪些功能使得 StyleCop 成为开发团队工作实践不可或缺的一部分。

StyleCop 规则:这是 StyleCop 对代码文件执行的检查。现有很多可用的规则,您也可以根据需要选择编写自己的自定义规则。StyleCop wiki 详述了如何编写您自己的 StyleCop 规则(请参阅 bit.ly/12P665L)。

使用 StyleCop 的第一步是:决定要使用的 StyleCop 规则。强烈建议使用所有 StyleCop 规则。但是,开发团队通常具有其自己的编码标准,可能会强烈不支持采用某些 StyleCop 规则。您必须平衡一致样式、可维护代码的长期利益与它可能带来的小小不便。像许多好的做法一样,一旦您习惯了使用 StyleCop,它就会得心应手。在任何情况下,就您的团队将广泛使用的 StyleCop 规则达成一致是非常重要的。

StyleCop 规则分为以下七个类别:

  1. 文档规则:验证源文件中的文档元素的适用性。
  2. 布局规则:验证源文件中的布局和行距。
  3. 可维护性规则:验证源文件的可维护性方面,例如,不需要的括号或单个文件中存在多个类。
  4. 命名规则:验证方法和变量名称的可代替性。
  5. 排序规则:验证代码内容是否正确排序。
  6. 可读性规则:验证代码是否格式正确且可读。
  7. 间距规则:验证代码内容中的间距是否有效且适当。

您可以在 bit.ly/191GgiQ 处的 StyleCop 规则文档中阅读有关 StyleCop 类别及其各自规则的更多信息。

将 StyleCop 添加到 Team Build

选定 StyleCop 规则并将其存储在设置文件中是一种不错的方式,但确保针对所有源代码一致执行 StyleCop 的唯一方式是在生成过程中运行它。

“隐藏”注释有两种方式:

  1. 将 StyleCop 与 C# 项目的 MSBuild 文件集成,这样只要编译项目就会执行它。StyleCop 文档 (bit.ly/13ZX2xL) 中介绍了具体操作。
  2. 将 StyleCop 添加到持续集成 Team Build 中,以便每次签入时都会执行它。

我将说明如何在持续集成 Team Build 中运行 StyleCop。如果您使用的是封闭生成,则执行 StyleCop 将确保不签入任何存在冲突的代码文件。如果未在封闭生成中使用,则中断生成仍将在您签入代码时提示您修复冲突。

若要在 Team Build 中运行 StyleCop,必须从生成工作流的活动中调用此过程。我将从一个称为 Community TFS Build Extensions (tfsbuildextensions.codeplex.com) 的开放源代码项目使用 StyleCop 活动。Community TFS Build Extensions 是一组包含许多可重用工作流活动的库,您只需将这些活动拖放到 Team Build 过程模板即可。

生成控制器更改:在自定义 Team Build 之前,您需要做的第一件事就是设置生成控制器的自定义程序集路径。这是生成代理为其在生成工作流中找到的任何自定义活动加载程序集的位置。

要添加自定义程序集,请在团队项目中的适当位置创建新文件夹。我将该新文件夹命名为“Custom Assemblies”,并在团队项目根文件夹正下方的 BuildProcessTemplate 下创建该文件夹。现在,签入以下程序集:

  • StyleCop.dll
  • StyleCop.CSharp.dll
  • StyleCop.CSharp.Rules.dll
  • TFSBuildExtensions.Activities.dll
  • TFSBuildExtensions.Activities.StyleCop.dll

下一步是配置生成控制器以使用这些程序集。为此,请执行以下操作:

  1. 在团队资源管理器中单击生成链接。单击“操作”,然后选择“管理生成控制器”。
  2. 从出现的对话框中,选择生成控制器并单击“属性”按钮。
  3. 在“生成控制器属性”对话框中,将“自定义程序集的版本控制路径”属性设置为之前在团队项目中创建的 Custom Assemblies 文件夹,如图 3 中所示。


图 3 生成控制器属性

单击“确定”并关闭属性对话框。此时,生成控制器已配置为加载您的自定义活动。下一步是自定义您的生成模板。

StyleCop 注意事项

下面是一些需要注意的事项:

  • 与 Visual Studio 代码分析不同,StyleCop 不支持 Visual Basic .NET,只能用于使用 C# 编写的源文件。
  • 编写本文时,StyleCop 尚不可用于 Visual Studio 2013。
  • 托管生成控制器是 Visual Studio Team Foundation Service 在云中托管的生成控制器。如果您使用的是内部部署生成服务器,则配置此生成控制器的步骤是相同的。
  • 本文使用了 Team Foundation Server (TFS) 2012。对于 TFS 2010 和 TFS 2013,步骤是相同的。确保您使用的是正确版本的 TFS Build Extensions。

自定义生成模板

对于每个新团队项目,TFS 都会创建一些现成的生成模板。在一个名为 ProcessBuildTemplates 的文件夹中创建这些生成模板,该文件夹位于团队项目的根目录中。首先复制 DefaultTemplate.11.1.xaml 模板,然后自定义该模板以添加 StyleCop 活动。我创建了文件 DefaultTemplate.11.1.xaml 的副本并将其重命名为 CustomTemplate.xaml。

要自定义生成工作流,您需要将自定义活动添加到开发环境中。为此,请在 Visual Studio 中创建一个新的工作流活动库项目。在“添加新项目”对话框中,确保选定 Microsoft .NET Framework 4.5 作为目标平台。下一步是在新创建的项目中添加指向文件 CustomTem­plate.xaml 的链接。为此,请右键单击该项目,选择“添加现有项”,浏览到文件 CustomTemplate.xml 并单击“添加为链接”按钮。

设置开发环境的最后一步是:在“工具箱”窗口中添加 StyleCop 活动以允许拖放操作。为此,请右键单击“工具箱”窗口中的“活动”下方的区域,然后选择“添加选项卡”选项。将新选项卡命名为“TFS Build Extensions”。右键单击选项卡名称并选择“选择项”。浏览到程序集 TfsBuildExtensions.Activities.Stylecop.dll 并单击“确定”。现在,您即可打开 CustomTemplate.xaml 文件并向其中拖动 StyleCop 活动。

生成模板自定义设置:您应在生成过程中尽早运行 StyleCop。这样在遇到任何冲突时生成操作就会立即失败。因为 StyleCop 要求扫描源文件,所以可以执行 StyleCop 的第一个位置就是:“在代理上运行”序列内的“初始化工作区”序列之后,如图 4 中所示。


图 4:StyleCop 活动放置位置

在确定生成工作流中添加 StyleCop 活动的适当位置之后,下一步即是添加序列活动。将序列活动重命名为“运行 StyleCop”。图 5 中显示了我的“运行 StyleCop”序列的最终列表。


图 5 “运行 StyleCop”序列

代码演练图 6 详述了“运行 StyleCop”序列中定义的变量、变量类型及其各自的用途。

图 6 “运行 StyleCop”序列中定义的变量

变量名 类型 说明
SourceCodeFiles IEnumerable<String> 存储 StyleCop 将扫描的所有文件的名称。
IsSuccess Boolean 存储 StyleCop 活动是否发现了任何冲突。
ViolationCount Int32 存储 StyleCop 冲突计数。

工作流还包含一个 String 类型的名为 StyleCopSettingsFile 的参数,用于存储 StyleCop 设置文件的路径。

“运行 StyleCop”序列中的第一个活动是 FindMatchingFiles 活动。该活动包含在 Microsoft.TeamFoundation.Build.Workflow.dll 程序集中,将返回与给定文件模式匹配的所有文件的列表。图 7 描述了如何设置该活动的属性。

图 7:FindMatchingFiles 活动属性

属性名称
DisplayName FindMatchingFiles
IsSuccess String.Format(“{0}\**\*.cs”, BuildDirectory)
Result SourceCodeFiles

将在生成目录中查找所有 C# (*.cs) 文件的模式传递到该活动,然后该活动将以 SourceCodeFiles 枚举形式返回结果。

序列中的下一个活动是 ConvertWorkspaceItem 活动,它位于程序集 Microsoft.TeamFounda­tion.Build.Workflow.Activities.dll 中。该活动将给定 StyleCop 设置文件的服务器路径(作为参数传递)转换为生成服务器上的本地路径。图 8 中显示了此活动的属性。

图 8 获取本地设置文件属性

属性名称
方向 ServerToLocal
DisplayName 获取本地设置文件
输入 StyleCopSettingsFile
Result StyleCopSettingsFileLocalPath
Workspace Workspace

现在已检索源文件名并且建立了 StyleCop 设置的位置,“运行 StyleCop”序列中的下一个活动是 StyleCop 活动。图 9 显示了如何设置 StyleCop 活动的属性。

图 9 执行 StyleCop 属性

属性名称
DisplayName 执行 StyleCop
LogExceptionStack True
SettingsFile StyleCopSettingsFile
ShowOutput True
SourceFiles SourceCodeFiles.ToArray()
Result StyleCopSettingsFileLocalPath
Succeeded IsSuccess
TreatWarningsAsErrors True

该活动采用枚举 SourceCodeFiles(转换为数组)作为输入,并分别使用 IsSuccess 和 ViolationCount 变量返回结果和冲突计数。为该活动指定显示名称“执行 StyleCop”,并且设置为将警告视为错误,并在遇到任何错误时生成失败。

“运行 StyleCop”序列中的最后一个活动是“编写生成消息”活动。该活动设置为显示结果和冲突计数。图 10 显示了如何设置此活动的属性。

图 10 “编写生成消息”活动属性

属性名称
DisplayName 完成消息
重要性 Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.Normal
消息 String.Format(“StyleCop was completed with {0} violations”, StyleCopViolationsCount)

您的自定义生成模板现在即可使用。保存并签入文件 CustomTemplate.xaml。要使用新生成模板,请打开您的生成定义,单击“过程”,展开“生成过程模板”,然后单击“新建”按钮。在显示的“新建过程模板”对话框中,选择选项“选择现有 XAML 文件”并浏览到 CustomTemplate.xaml 文件。

将参数 StyleCopSettingsFile 的值设置为 Settings.StyleCop 文件的位置。单击“保存”以保存生成定义。现在即可使用带有 StyleCop 的生成功能。最好将此生成模板用于封闭生成。这将确保签入的所有源文件都不会有任何 StyleCop 冲突。

后续步骤

我已演示了如何使用 StyleCop 在 Team Build 中强制执行静态代码分析。静态代码分析可提升编码标准,并且它可在 Team Build 中运行以确保所有签入的代码都符合标准。您可以使用类似方式在 Team Build 中强制实现其他最佳实践。Microsoft ALM Ranger 已提供了许多有用的生成模板,您可以在“Team Foundation Build 自定义指南”(vsarbuildguide.codeplex.com) 项目中使用这些模板。而且,您可以选择编写自己的活动或使用 Community TFS Build Extensions 项目中提供的活动。

Hamid Shahid是 Microsoft ALM Ranger 的一位独立顾问,在设计和开发企业软件方面有 12 年多的经验。他一直关注如何提升 Microsoft ALM 技术的最佳实践。可以通过他的博客 (hamidshahid.blogspot.com) 与他联系,也可以关注他的 Twitter (twitter.com/hamid_shahid)。

衷心感谢以下 ALM Rangers 和技术专家对本文的审阅:Mike Fourie(独立顾问)、Willy-Peter Schaub (Microsoft) 和 Patricia Wagner (Microsoft)
Mike Fourie 是一名有着 13 年以上软件开发经验的独立顾问,他的工作重点是生成和部署自动化。他是 Microsoft ALM MVP,同时也是卓越的 ALM Ranger。可通过他的博客与他联系:freetodev.com。您也可以关注他的 Twitter:twitter.com/mikefourie

Willy-Peter Schaub 是 Microsoft 加拿大开发中心的 Visual Studio ALM Rangers 高级项目经理。自上世纪 80 年代中期以来,他一直致力于实现软件工程中的简易性和可维护性。他的博客位于 blogs.msdn.com/b/willy-peter_schaub,您可通过 Twitter (twitter.com/wpschaub) 关注他。