如何在resharper插件中动态重写AST?

时间:2016-08-09 19:20:49

标签: c# resharper resharper-plugins

请求:

我希望能够编写一个可以为某个表达式提供代理值并触发重新解析文档的分析器。

动机:

我们的代码充斥着ABTests,它可以处于已部署或处于活动状态且具有控制和变体组。 通过数据库查找确定测试的状态。 对于使用控制组部署的测试,以下表单的任何语句都将评估为false:

if(ExperimentService.IsInVariant(ABTest.Test1))
{
}

我尝试提供工具,以便在开发时通过在此方案中将其变灰来更容易处理。 实际上,这是相当有限的而且不健壮,因为我基本上必须自己玩解析器。

如果实际代码是

,该怎么办?
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解析发生之前重写树(或者,好吧,只是再次解析它)。 这些应该只发射一次并允许我们用另一个表达式替换某个表达式。这将允许我将所有这些实验调用交换为真假文字。

因此,这些部分可以受益于所有其他IDE功能,例如代码灰化无法访问的代码,但更复杂的代码,如永远不会有不同值的变量

显然这仅仅是一个例子,我不确定它有多可行。对于正确的功能或已经存在的东西的任何建议都非常受欢迎。

2 个答案:

答案 0 :(得分:1)

这还不足以真正保证赏金,但可能适用于developer documentation的一个解决方案是创建custom language并扩展基本规则。

你说

  

我正在尝试提供工具,以便在开发时更容易处理,方法是在这种情况下将其变灰。

通过改变语法高亮规则,可能只需要完成相应的部分。

请参阅this example for .tt files.

答案 1 :(得分:1)

我不认为有一种方法没有妥协。

ReSharper不支持在分析之前重写AST - 这只会重写文件中的文本。

您可以通过对if块的内容应用“死代码”突出显示来编写一个灰显代码的分析器,但正如您所说,您需要解析代码并分析控件流程是为了使它正确,我认为这将是非常困难的(ReSharper确实提供了一个控制流图,所以你可以走它,但是你可以选择 A。找到它返回值IsInVariant B。通过任何条件&&||语句跟踪该值,直到找到适当的if块为止。

或者,您可以使用IsInVariant属性标记ContractAnnotation方法,例如:

[ContractAnnotation("=> false")]
public bool IsInVariant(string identifier)
{
  // whatever...
}

这将告诉ReSharper分析此方法始终返回false(您还可以说它会返回true / false / null / not null基于特定输入)。因为它始终返回false,所以如果执行if,ReSharper会使else语句或if (!IsInVariant(…))分支中的代码变灰。

这里的缺点是ReSharper还会在if语句中添加警告,告诉您表达式始终返回false。所以,这是一个妥协,但你可以将该警告的严重程度改为Hint,所以它不是那么具有侵入性。