目前我有这段代码:
private async Task<bool> IsMentionedInDisposeCallAsync(SyntaxNodeAnalysisContext context, FieldDeclarationSyntax fieldDeclarationSyntax)
{
foreach (var variableDeclaratorSyntax in fieldDeclarationSyntax.Declaration.Variables)
{
var declaredSymbol = context.SemanticModel.GetDeclaredSymbol(variableDeclaratorSyntax);
if (declaredSymbol is IFieldSymbol fieldSymbol)
{
// SymbolFinder.FindReferencesAsync()
var b = fieldSymbol.Locations;
// context.SemanticModel.Compilation.
}
}
return false;
}
而这个场景:
private static readonly string TestSourceImplementsDisposableAndDoesMentionDisposableField = @"
using System;
using System.IO;
namespace ConsoleApplication1
{
public class SampleDisposable : IDisposable
{
public void Dispose()
{
}
}
public class SampleConsumer : IDisposable
{
private SampleDisposable _disposable = new SampleDisposable();
private IDisposable _ms = new MemoryStream();
public void Dispose()
{
_disposable?.Dispose();
_ms?.Dispose();
}
}
}";
最终,我的愿望是弄清楚处置方法是否正在访问一次性领域。不幸的是,我似乎找不到一种方法来不使用 SymbolFinder,这需要一个解决方案。
我用 SymbolFinder 做了类似的事情,这是一件容易的事情 - 但是我如何从诊断中可用的功能中做到这一点?
我在这里错过了一些明显的东西吗?
您可以简单地使用 SemanticModel 来分析用于字段的类型,如下所示:
private async Task<bool> IsMentionedInDisposeCallAsync(SyntaxNodeAnalysisContext context, FieldDeclarationSyntax fieldDeclarationSyntax)
{
foreach (var variableDeclaratorSyntax in fieldDeclarationSyntax.Declaration.Variables)
{
var declaredSymbol = context.SemanticModel.GetDeclaredSymbol(variableDeclaratorSyntax);
if (declaredSymbol is IFieldSymbol fieldSymbol)
{
var isDisposeable = CheckIsTypeIDisposeable(fieldSymbol.Type as INamedTypeSymbol);
// SymbolFinder.FindReferencesAsync()
var b = fieldSymbol.Locations;
// context.SemanticModel.Compilation.
}
}
return false;
}
private string fullQualifiedAssemblyNameOfIDisposeable = typeof(IDisposable).AssemblyQualifiedName;
private bool CheckIsTypeIDisposeable(INamedTypeSymbol type)
{
// Identify the IDisposable class. You can use any method to do this here
// A type.ToDisplayString() == "System.IDisposable" might do it for you
if(fullQualifiedAssemblyNameOfIDisposeable ==
type.ToDisplayString() + ", " + type.ContainingAssembly.ToDisplayString())
{
return true;
}
if(type.BaseType != null)
{
if (CheckIsTypeIDisposeable(type.BaseType))
{
return true;
}
}
foreach(var @interface in type.AllInterfaces)
{
if (CheckIsTypeIDisposeable(@interface))
{
return true;
}
}
return false;
}
基本上,您将递归搜索类和基类的所有接口,以找到与 IDisposeable 对应的类型 - 它应该在层次结构中的某个位置。