【发布时间】:2019-06-06 07:44:51
【问题描述】:
我正在编写 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 中打开文档)有一个属性。
我是如何获取 iterfaces 和参数的:
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)
{
}
}
【问题讨论】:
-
我还发现 IFoo 的语法树也没有被解析:IMethodSymbol.DeclaringSyntaxReferences 返回 IFoo.Foo 的空数组
-
RegisterSemanticModelAction 产生相同的结果
-
同RegisterCompilationAction,IMethodSymbol中没有信息,DeclaringSyntaxReferences也没有任何有用的信息。因此,即使在 RegisterCompilationAction 上也无法获取有关引用符号的信息?
标签: c# roslyn roslyn-code-analysis