IParameterSymbol.GetAttributes() 不 return 实际符号

IParameterSymbol.GetAttributes() does not return actual symbols

我正在编写 roslyn 分析器,它应该检查方法的参数是否在当前方法声明或接口之一中使用 [NotNull] 属性声明,并对其方法主体进行一些检查。我用 RegisterCodeBlockAction 注册了 CodeBlockAction,但是当我试图从 interfaces/base classes 中的参数声明中获取属性时,它有它,有时它是 returns 空数组。

我发现,如果 interface/base class 位于其他程序集,并且当 Intelisense 运行s 它时,实际上分析器工作正常,但有构建输出中没有 warnings\errors。我认为发生这种情况是因为引用程序集的语义分析没有完全完成(但有点奇怪)。

我写了一些日志

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)
        {

        }
    }

好的,我明白了。这是因为来自 Jetbrains.Annotations 的 NotNullAttribute 上的条件编译属性,所以编译器显示来自实际引用符号的数据(它跳过 [NotNull] 因为 JETBRAINS_ANNOTATIONS 未定义)和 Visual Studio从代码中提供真实的属性列表,条件编译不考虑这种方式。 它看起来不一致,但我必须在我的项目中定义 JETBRAINS_ANNOTATIONS 才能使分析器工作。