2021 年 C# 代码检查和格式化工具
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
简而言之:使用 SonarLint,并可选择使用 StyleCop。
JavaScript 生态系统拥有强大的代码格式化和静态分析工具:Prettier和ESLint。这两款工具几乎被所有开发者广泛采用,并能带来显著的价值。
但是,C# 代码的检查和格式化呢?
格式化方面,可以使用 Visual Studio 的自动格式化工具(编辑 > 高级 > 格式化文档),但它一次只能格式化一个文件,而且主要用于修复缩进和空格问题。它不会拆分长行,拒绝格式化某些语言结构,而且通常比 Prettier 更灵活。
对于代码检查,C# 编译器已经提供了一些类似 lint 的警告,例如提醒你忘记await调用异步方法。这些警告虽然有用,但与 ESLint 相比只是冰山一角。
鉴于这些内置解决方案的局限性,我开始寻找更好的解决方案。
格式化:dotnet-format 🤔
dotnet-format是一个格式化工具,它将包含在即将发布的 .NET 6 SDK 中。如果您尚未升级到 .NET 6,仍然可以轻松安装 dotnet-format dotnet tool install dotnet-format(需要选择-g全局安装选项)。Johnny Reilly 写了一篇很棒的文章,介绍了如何将 dotnet-format 与 lint-staged 结合使用。
我听说 dotnet-format 的时候非常兴奋,但可惜的是,它并没有达到我的预期。我用它重新格式化了一个中等规模的 C# 9 代码库,并检查了差异。结果…… dotnet-format 所做的只是删除了多余的空格。dotnet -format 并没有……
- 将过长的代码行拆分成小段。
- 确保花括号位置一致
- 添加或删除空行
- 重新格式化方法签名和调用,解决参数格式不一致的问题,例如:
void AddDocument(string name, FileId fileId, long fileSize,
DocType type,
bool discoverable,
CategoryId? categoryId
);
为dotnet-format辩护:
- 安装起来极其简单。
- 它可以完全自动化——无需人工干预。
- 我的测试代码库格式已经相当不错了。
格式:StyleCop 🙂
StyleCop.Analyzers是一套开源的 C# 代码分析器,通过NuGet 包安装。首次安装 StyleCop 并重新生成解决方案时,您可能会看到超过 10,000 条警告。哇!不过别担心;StyleCop 会自动修复其中大部分问题,而且许多警告都只是关于一些无关紧要的小问题,例如using语句是否按字母顺序排序。
安装说明
Directory.Build.props在解决方案文件旁边创建一个文件,并将以下 XML 粘贴到该文件中。
<Project>
<ItemGroup>
<PackageReference
Include="StyleCop.Analyzers"
Version="1.2.0-beta.354"
PrivateAssets="all"
Condition="$(MSBuildProjectExtension) == '.csproj'"
/>
</ItemGroup>
</Project>
这会将 StyleCop.Analyzers NuGet 包添加到解决方案中的每个项目中。您应该将版本号更新为 NuGet.org 上的最新版本。1.2.0 版本引入了对最新 C# 特性的支持,因此即使它目前仍处于 beta 测试阶段,我也推荐您使用它。
.editorconfig接下来,在与解决方案文件相同的目录下添加一个文件。.editorconfig这是微软推荐的配置分析器的方法——.ruleset文件现在已被弃用。您可以使用 Visual Studio 的图形用户.editorconfig界面 (GUI) 来调整格式和代码样式设置,但使用文本编辑器配置分析器要方便得多。这是我的.editorconfig文件,您可以随意复制。
最后,重新构建解决方案。StyleCop 的建议将出现在错误列表中,并且您会看到绿色的智能感知波浪线。
修正 StyleCop 的建议
StyleCop 的默认规则集非常固执己见,我建议禁用那些对团队没有价值的规则。例如,SA1200规则要求using语句必须放在namespace命名空间内。虽然这种编码风格本身没有问题,但由于 Visual Studiousing在创建新的 C# 文件时会将语句放在命名空间之外,因此这种风格并不常用。两种约定同样有效,所以我建议禁用此规则。您可以通过在以下代码中添加一行来实现.editorconfig:
# Using directive should appear within a namespace declaration
dotnet_diagnostic.SA1200.severity = None
在逐一检查 StyleCop 违规时,你会发现一些非常有用的规则。每次我都能够通过快速修复菜单自动修复整个解决方案中的违规问题。
我的评价
StyleCop是个不错的工具,我推荐使用它。
我并不完全认同 StyleCop 的很多规则(确切地说是 27 条),但它确实让我的代码库变得非常整洁,而且自动代码修复功能也很棒。我有点担心,当我重新投入到实际开发工作中时,StyleCop 会不会分散我的注意力,不过我们拭目以待吧。
顾名思义,StyleCop 主要关注代码风格,而非正确性。如果我们想修复代码中的错误,就必须继续查找原因……
毛絮清理:SonarLint 🤩
SonarLint是一款 IDE 扩展和NuGet 包,用于分析代码中的错误、漏洞和代码异味。其核心产品是开源的,但该公司似乎更倾向于推广与其商业产品集成的 IDE 扩展。
我试用了扩展程序和 NuGet 包,更喜欢 NuGet 包。两种方法都能提供 Intellisense 警告,但只有 NuGet 包 SonarAnalyzer.CSharp 能立即显示代码库中所有违反规则的地方。此外,在团队协作环境中,NuGet 包更胜一筹,因为它会在构建过程中自动下载。
安装说明
SonarAnalyzer.CSharp 和 StyleCop 一样,都是 Roslyn 分析器的集合,因此设置方法非常相似。我将展示包含 StyleCop 和 SonarLint 的配置文件,但您完全可以单独使用 SonarLint。
编辑Default.Build.props解决方案旁边的文件,将 SonarAnalyzer.CSharp 安装到所有项目中:
<Project>
<ItemGroup>
<PackageReference
Include="StyleCop.Analyzers"
Version="1.2.0-beta.354"
PrivateAssets="all"
Condition="$(MSBuildProjectExtension) == '.csproj'"
/>
<PackageReference
Include="SonarAnalyzer.CSharp"
Version="8.29.0.36737"
PrivateAssets="all"
Condition="$(MSBuildProjectExtension) == '.csproj'"
/>
</ItemGroup>
</Project>
您的 SonarLint 规则自定义设置将放在.editorconfig我们之前创建的同一个文件中。这是我完成的配置.editorconfig。如果您不使用 StyleCop,可以安全地删除其中的相关内容。
完成上述步骤后,重新构建解决方案,您应该会看到新的警告。
修复 SonarLint 的建议
在逐条查看警告时,你会发现有些警告会自动修复,而有些则不会。如果你遇到不喜欢的规则,可以使用我之前在 StyleCop 中展示的相同方法将其禁用。我基本同意 SonarLint 的建议,只禁用了 409 条规则中的 8 条。
当您遇到不知道如何解决的规则违规时,请查阅SonarLint 的庞大规则数据库。
我的评价
SonarLint NuGet 包完全符合我的预期,我强烈推荐它。
通过逐一解决 SonarLint 警告,我得以……
- 了解一个容易导致 bug 的C# 陷阱。
- 找出几个没有做出任何断言的薄弱测试。
- 将代码中的待办事项(TODO)在错误列表中显示为警告。
- 修复大量命名不一致的变量
- 修复未使用其参数的方法
static为只有静态方法的类添加缺失的修饰符- 还有更多!
毛絮:ReSharper 🙁
ReSharper是 JetBrains 出品的 Visual Studio 扩展,它提供了高级重构和静态分析功能。在我职业生涯的前两年,我一直使用 ReSharper,发现它对于学习 C# 的高级特性非常有帮助。不过,由于 ReSharper 存在诸多缺点,我后来停止了使用它,并且从未后悔过。
- ReSharper 个人版起价为每年 129 美元,组织版起价为每用户每年 299 美元。
- Visual Studio + ReSharper 组合起来速度慢、漏洞百出,简直一团糟。
- Visual Studio 的内置重构功能一直在稳步赶上 ReSharper 的功能。
- 一旦你熟悉了 C#,ReSharper 的警告就会变得烦人而不是有帮助。
JetBrains 确实有自己的 .NET IDE,名为Rider,或许值得一看。
结论
我强烈推荐使用 SonarLint 来识别 bug 和代码异味。
我将使用 StyleCop 来强制执行代码格式化最佳实践,不过 dotnet-format 也是一个可行的选择。这有利有弊:StyleCop 功能更强大,但需要持续维护。dotnet-format 安装简便,并且可以完全自动化地集成到 precommit hook 中,但它无法解决许多常见的代码风格问题。
延伸阅读
更新于2021年10月5日
- 请用新文件替换已弃用的
.ruleset文件.editorconfig。非常感谢 Honza Rameš 指出这一点! - 请说明ReSharper的定价。谢谢Valentine Palazkov。