如何在没有SymbolFinder的诊断中获得符号引用?

时间:2018-01-16 15:20:10

标签: c# roslyn roslyn-code-analysis

目前我已经有了这段代码:

    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做了类似的事情,这很容易做 - 但我如何从诊断中的功能中做到这一点?

我错过了一些明显的东西吗?

1 个答案:

答案 0 :(得分:1)

您可以简单地使用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相对应的类型 - 该类型应位于层次结构中的某个位置。