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

How to rewrite AST dynamically in resharper plugin?

要求:

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

动机:

我们的代码中到处都是 ABTest,这些 ABTest 可以处于部署状态或活动状态,并带有控制组和变体组。 确定测试的状态是通过数据库查找完成的。 对于与控制组一起部署的测试,以下形式的任何语句都将评估为 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 解析发生之前重写树(或者,好吧,只是第二次解析)。 这些应该只触发一次并允许我们用另一个替换某个表达式。这将允许我将所有这些实验调用交换为 true 和 false 文字。

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

显然这只是一个示例,我不确定它的可行性如何。非常欢迎任何关于适当功能或已经存在的东西的建议。

这不足以真正保证赏金,但可能适用于 developer documentation is to create a custom language 并扩展基本规则的一种解决方案。

你说

I'm trying to provide tooling to make this easier to deal with at develop time by greying it out in this scenario.

将相应部分变灰可能只是通过更改语法突出显示规则来完成。

this example for .tt files.

我认为没有一种方法是不折衷的。

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

您可以通过对 if 块的内容应用 "dead code" 突出显示来编写一个使代码变灰的分析器,但是正如您所说,您需要解析代码并分析控制流以使其正确,我认为这将非常困难(ReSharper 确实提供了一个控制流图,因此您可以遍历它,但这取决于您 A. 找到 IsInVariantB 的 return 值。 通过任何条件跟踪该值,&&|| 语句直到找到合适的 if 块)。

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

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

这会告诉 ReSharper 的分析,这个方法 always returns false (你也可以说它会 return true/false/null/not null 基于特定的输入)。因为它总是 returns false,ReSharper 会将 if 语句中的代码或 else 分支中的代码变灰,如果您执行 if (!IsInVariant(…)).

这里的缺点是 ReSharper 还会向 if 语句添加警告,告诉您表达式总是 returns false。所以,这是一种妥协,但您可以将该警告的严重性更改为提示,这样它就不会那么具有干扰性。