背景
我使用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
答案 0 :(得分:2)
我想你想在实际的发射/编译之前添加诊断信息,所以步骤如下:
CSharpCompilation
,确保在进一步操作之前没有诊断错误BeforeCompileContext
,并使用汇编填充它并使用空List<Diagnostic>
ICompileModule
的实例并使用第2步中的上下文调用ICompileModule.BeforeCompile
Diagnostic