我想要能够编写一个可以为特定表达式提供代理值的分析器,并触发文档的重新解析.
动机:
我们的代码散布在ABTests中,可以在部署或活动状态下使用控件和变体组.@H_403_7@通过数据库查找来确定测试的状态.@H_403_7@对于与控制组一起部署的测试,以下表单的任何语句都将评估为false:
if(ExperimentService.IsInVariant(ABTest.Test1)) { }
我正在尝试提供工具,以便在开发过程中更容易处理,在这种情况下将其变灰.@H_403_7@就这样,这是相当有限的,不健壮的,因为我基本上必须自己解析.
如果实际代码怎么办?
if(!ExperimentService.IsInVariant(ABTest.Test1))
要么
if(ExperimentService.IsInVariant(ABTest.Test1) || true)
要么
var val = ..... && (ExperimentService.IsInVariant(ABTest.Test1); if(val){ // val is always going to be false if we deployed control. }
我可以看到提供的一种可能的方法是允许我们编写一次被解析的分析器,并在实际的IDE解析之前重写树(或者,再次分析它).@H_403_7@这些只能开火一次,并允许我们用另一个替换一个表达式.这将允许我将所有这些实验调用交换为真实和虚假的文字.
因此,这些部分可以从所有其他IDE功能中受益,例如不可达代码的代码灰色,但也可能是更复杂的IDE,就像永远不会有不同值的变量
解决方法
ReSharper不支持在分析之前重写AST,只会重写文件中的文本.
您可以编写一个分析器,通过对if块的内容应用“死亡代码”突出显示,您可以编写一个分析器,但是如您所言,您需要解析代码并分析控制流程才能正确,我认为这将是非常困难的(ReSharper确实提供了一个控制流图,所以你可以走它,但是由A.找到IsInVariant和B的返回值跟踪该值通过任何条件,&&或||语句,直到找到适当的if块).
或者,您可以使用ContractAnnotation属性标记IsInVariant方法,如下所示:
[ContractAnnotation("=> false")] public bool IsInVariant(string identifier) { // whatever... }
这将告诉ReSharper的分析,这种方法总是返回false(你也可以说它会根据具体的输入返回true / false / null / not null).因为它总是返回false,所以ReSharper将灰色的if语句中的代码,或者else分支(如果你做的话)(!IsInVariant(…)).
这里的缺点是,ReSharper还会向if语句添加一个警告,告诉您表达式总是返回false.所以这是一个妥协,但是你可以将警告的严重性改为提示,所以不是那么干扰.