我正在编写roslyn分析器,该分析器应检查当前方法声明或接口之一中是否使用[NotNull]属性声明的方法参数,并对其方法主体进行一些检查。我用RegisterCodeBlockAction注册了CodeBlockAction,但是当我尝试从接口/基类中的参数声明中获取属性时,它具有该属性,有时它返回空数组。
我发现,如果接口/基类位于其他程序集中,并且当Intelisense运行它时,实际上分析器可以正常工作,但在构建输出中没有警告\错误的情况下,会发生这种情况。我认为发生这种情况是因为尚未完全完成对引用装配的语义分析(但这有点奇怪)。
我写了一些日志
6/6/2019 13:59:47 Analize method symbol "ClassLibrary1.Program.Foo(string)" with 1 interfaces
6/6/2019 13:59:47 declaration ClassLibrary2.IFoo.Foo(string): [0 attributes] string s
6/6/2019 13:59:47 declaration ClassLibrary1.Program.Foo(string): [0 attributes] string s
6/6/2019 13:59:59 Analize method symbol "ClassLibrary1.Program.Foo(string)" with 1 interfaces
6/6/2019 13:59:59 declaration ClassLibrary2.IFoo.Foo(string): [1 attributes] string s
6/6/2019 13:59:59 declaration ClassLibrary1.Program.Foo(string): [0 attributes] string s
所以您可以看到,在13:59:47(msbuild运行)没有属性,但是在13:59:59(我在Visual Studio中打开了文档)只有一个属性。
这是我获取迭代器和参数的方法:
var allMethodDeclarations = //some code using methodSymbol.ContainingType.Interfaces
for (var i = 0; i < methodSymbol.Parameters.Length; ++i)
{
var currentParameter = methodSymbol.Parameters[i];
//parameters can be renamed, the only way is to use the order
var hasNotNull = allMethodDeclarations
.Select(d => d.Parameters[i])
.SelectMany(p => p.GetAttributes())
.Any(a => a.AttributeClass.Name == nameof(NotNullAttribute));
if (hasNotNull)
{
//do something
}
}
再现错误的示例代码:
在汇编1中
public interface IFoo
{
void Foo([NotNull] string s);
}
在程序集2中,引用程序集1
public class Program : IFoo
{
public void Foo(string s)
{
}
}
答案 0 :(得分:0)
好的,我明白了。这是由于Jetbrains.Annotations的NotNullAttribute上有条件的编译属性,因此编译器显示了来自实际引用符号的数据(由于未定义JETBRAINS_ANNOTATIONS,因此跳过了[NotNull]),而Visual Studio提供了代码中的真实属性列表,并且有条件的编译不考虑这种方式。 它看起来不一致,但是我必须在项目中定义JETBRAINS_ANNOTATIONS才能使分析仪正常工作。