我正在使用由第 3 方大会公开的枚举,例如,
public enum APIEnum
{
Val1,
Val2
}
。但是,其中许多值会导致我的应用程序出现错误行为。如果代码中使用了这些“坏”枚举值之一,我想生成编译器警告,例如,
APIEnum usedVal = APIEnum.Val2;
Compiler Warning: APIEnum.Val2 causes incorrect behavior.
我的最终目标是生成一个警告,如果使用了错误的值(占总体情况的 2%),则必须有意识地 #pragma'd。否则,会出现警告,并且由于我们将警告视为错误,因此会中断编译,直到修复或 #pragma'd。
我查看了有关使用 Obsolete 属性来解决此问题的线程 here 和 here,但我担心 Obsolete 会引起混乱,因为该值并不是真正过时。
我考虑过使用Resharper代码分析插件来解决问题的可能性,这绝对是一个选择。我不是 Resharper 或如何通过 Resharper 最好地解决问题的专家。
您可以在 ReSharper 中使用结构搜索。转到
ReSharper -> Options | Code Inspection -> Custom patterns
,单击 Add Pattern
,在 APIEnum.Val2
字段中输入 Search pattern
,然后在 Description
中输入错误描述。将模式严重性设置为 Show as error
。单击Add
。就这样。唯一的缺点是,如果您的项目中存在另一个具有相同 APIEnum
值的 Val2
,即使在不同的命名空间中,那么它也会被标记为错误。
您还应该打开
ReSharper -> Options | Code Inspection -> Settings | Analyse errors in whole solution
以显示每个文件中的错误。
您可以为此创建自定义代码分析 (FxCop) 规则,或者实际上推出您自己的 Resharper 规则。自定义代码分析规则应该相对简单,查看我的规则,该规则检查正则表达式是否编译,它会找到
RegexOptions
枚举的所有用途。您应该能够从那里构建自己的自定义规则。
自定义代码分析规则的一般优秀网站:
如果您在编写自己的规则时遇到困难,请随时分享到目前为止的代码以寻求更具体的帮助。
使用 VisitAssignment 语句,然后使用
assignment.Target.Type.FullName
获取底层枚举类型。请务必检查 Target.Type 是否为 null,委托可以有 null Type。
方法调用也会看到枚举:
我已经使用 FxCop 方法制作了一个解决方案原型,但我认为 FxCop 实际上无法解决它。我在规则中尝试了以下代码:
public class DoNotUseSpecificEnum : RuleBase
{
private string[] _enumValsToCheck =
{
"APIEnum.Val2"
};
public DoNotUseSpecificEnum ()
: base("DoNotUseSpecificEnum ") { }
public override void VisitBinaryExpression(BinaryExpression binaryExpression)
{
if ( _enumValsToCheck.Contains(
binaryExpression.Operand1.ToString())
|| _enumValsToCheck.Contains( binaryExpression.Operand2.ToString() ) )
{
this.Problems.Add(new Problem(base.GetResolution(),
binaryExpression.SourceContext));
}
base.VisitBinaryExpression(binaryExpression);
}
}
当我跟踪 VisitBinaryExpression 时,我发现 Operand1 值是“1”而不是“APIEnum.Val2”。事后看来,这是有道理的(FxCop 在 MSIL 上工作,它已用数字文字替换了枚举名称/值);我只是希望在深入研究自定义 FxCop 规则的痛苦/荣耀之前就意识到这一点。 :)
我发现的另一种方法是使用 StyleCop 进行语法分析,但这看起来更难弄清楚,而且比自定义 FxCop 规则更不受欢迎。
我将建议使用 Resharper 团队特定的自定义模式作为管理此问题的方式。我仍然担心这种方法(特别是因为我们将在多个解决方案和团队中采用相同的规则),但构建机器的问题比我想象的要小得多。 TeamCity 允许开箱即用地进行“构建时检查 Resharper 规则”,因此我们至少可以配置 CI 服务器来查找和报告尚未使用 Resharper 语法抑制的枚举的使用情况。
进行总结,将包添加到您的项目/解决方案后,将 BannedSymbols.txt
添加到您的项目/解决方案,并将其添加到您的 csproj
<ItemGroup>
<AdditionalFiles Include="path to BannedSymbols.txt"/>
</ItemGroup>
现在您只需填写
BannedSymbols.txt
。 一行应该看起来像
{符号的文档注释 ID 字符串}[;描述文本]考虑到您希望获得有关使用给定枚举值 (
APIEnum.Val2
) 的警告,第一部分应类似于
F:Namespace.Type.Field
,对于您的情况,它会转换为 F:ApiNamespace.APIEnum.Val2
。第二部分是可选的,可让您自定义警告消息。例如使用 F:ApiNamespace.APIEnum.Val2; APIEnum.Val2 causes incorrect behavior.
,执行
var x = APIEnum.Val2;
将会给您以下警告:
RS0030:符号“APIEnum.Val2”在此项目中被禁止:APIEnum.Val2 会导致不正确的行为。