StackExchange.Precompilation - 如何对预编译诊断进行单元测试?

时间:2016-12-14 05:23:23

标签: c# unit-testing roslyn precompile

背景

我使用StackExchange.Precompilation在C#中实现面向方面的编程。 See my repository on GitHub.

基本思想是客户端代码将能够在成员上放置自定义属性,预编译器将对具有这些属性的任何成员执行语法转换。一个简单的例子是我创建的NonNullAttribute。将NonNullAttribute放置在参数p上时,预编译器将插入

if (Object.Equals(p, null)) throw new ArgumentNullException(nameof(p));

在方法体的开头。

诊断非常棒......

我想让错误地使用这些属性变得困难。我发现的最佳方法(除了直观设计)是为了无效或不合逻辑地使用属性而创建编译时Diagnostic

例如,NonNullAttribute对值类型成员使用没有意义。 (即使对于可以为空的值类型,因为如果你想保证它们不是null,那么应该使用非可空类型。)创建Diagnostic是告知用户这个的好方法。错误,不会像构建异常那样使构建崩溃。

...但我如何测试它们?

诊断是突出显示错误的好方法,但我也想确保我的诊断创建代码没有错误。我希望能够设置一个单元测试,可以预编译像这样的代码示例

public class TestClass {
    public void ShouldCreateDiagnostic([NonNull] int n) { }       
}

并确认已创建正确的诊断(或在某些情况下未创建诊断)。

任何熟悉StackExchange.Precompilation的人都能给我一些指导吗?

解决方案:

@ m0sa给出的答案非常有帮助。实现有很多细节,所以这里的单元测试看起来很像(使用NUnit 3)。请注意using static的{​​{1}},这样可以消除语法树构造中的大量混乱。

SyntaxFactory

1 个答案:

答案 0 :(得分:2)

我想你想在实际的发射/编译之前添加诊断信息,所以步骤如下:

  1. 创建您的CSharpCompilation,确保在进一步操作之前没有诊断错误
  2. 创建BeforeCompileContext,并使用汇编填充它并使用空List<Diagnostic>
  3. 创建ICompileModule的实例并使用第2步中的上下文调用ICompileModule.BeforeCompile
  4. 检查它是否包含所需的Diagnostic