c# - 在 Roslyn 分析器中查找字段和类型的有效可访问性

标签 c# roslyn roslyn-code-analysis

我正在编写一个 Roslyn 分析器来执行一些文档规则。规则规定只有在程序集外部可见的字段和类型才需要记录。这让我遇到了一个问题,即查明一个字段或类型是否有效可见并且可以在声明程序集之外使用。

鉴于此声明:

namespace TestApp {
    internal class InternalClass {
        public class InnerClass {
            public int PublicFieldInInternal;
        }
    }
}

我想知道 PublicFieldInInternal 在声明程序集之外是否可见。我使用下面的代码来确定可访问性:

private bool IsNonPrivateMemberDeclaration(SyntaxNodeAnalysisContext context, SyntaxNode node)
{
    if (node is BaseFieldDeclarationSyntax fieldDeclaration)
    {
        var firstField = fieldDeclaration.Declaration.Variables.First();
        var fieldAccessibility = context.SemanticModel.GetDeclaredSymbol(firstField).DeclaredAccessibility;

        return ConstructVisibleFromOtherAssemblies(fieldAccessibility);
    }

    var accessibility = context.SemanticModel.GetDeclaredSymbol(node)?.DeclaredAccessibility;
    if (accessibility != null)
    {
        return ConstructVisibleFromOtherAssemblies(accessibility.Value);
    }

    Debug.Assert(true, "This code should be unreachable as one of the two cases above will catch all calls");
    return false;
}

private static bool ConstructVisibleFromOtherAssemblies(Accessibility accessibility) =>
    accessibility == Accessibility.Public ||
    accessibility == Accessibility.Protected ||
    accessibility == Accessibility.ProtectedOrInternal;

但是,它没有考虑父类型的可访问性,因此对应于 PublicFieldInInternal 的符号的 DeclaredAccessibility 属性返回 Accessibility.Public。有没有办法直接查询语义模型以获得有效的可访问性,或者我是否需要递归地查看包含类型?

最佳答案

我最终采用了这种方法,它通过了所有单元测试:

private bool IsVisibleFromOtherAssemblies(SyntaxNodeAnalysisContext context, SyntaxNode node)
{
    ISymbol declaredSymbol = GetDeclaredSymbol(context, node);

    var accessibility = declaredSymbol.DeclaredAccessibility;
    var visibility = ConstructVisibleFromOtherAssemblies(accessibility);
    var containingType = declaredSymbol.ContainingType;

    return IsSymbolAndContainingTypeVisible(visibility, containingType);
}

private static ISymbol GetDeclaredSymbol(SyntaxNodeAnalysisContext context, SyntaxNode node)
{
    if (node is BaseFieldDeclarationSyntax fieldDeclaration)
    {
        var firstField = fieldDeclaration.Declaration.Variables.First();
        return context.SemanticModel.GetDeclaredSymbol(firstField);
    }

    return context.SemanticModel.GetDeclaredSymbol(node);
}

private bool IsSymbolAndContainingTypeVisible(bool visibility, INamedTypeSymbol containingType)
{
    if (containingType == null)
    {
        return visibility;
    }

    return visibility && IsSymbolAndContainingTypeVisible(
               ConstructVisibleFromOtherAssemblies(containingType.DeclaredAccessibility),
               containingType.ContainingType);
}

private static bool ConstructVisibleFromOtherAssemblies(Accessibility accessibility) =>
    accessibility == Accessibility.Public ||
    accessibility == Accessibility.Protected ||
    accessibility == Accessibility.ProtectedOrInternal;

关于c# - 在 Roslyn 分析器中查找字段和类型的有效可访问性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54480727/

相关文章:

c# - 使用 Roslyn API 编译 .NET Core 应用程序

c# - 使用 MSBuildWorkspace 加载解决方案和项目时出现诊断错误

c# - DiagnosticDescriptor 构造函数的新参数的相关性?

.net - 编译器管道如何对应增量源生成?

c# - Roslyn:从代码分析器访问部分类的 XAML

c# - 如何从数据表中的服务器端jquery数据表获取图像src值?

c# - 如何从 Excel udf 返回数组?

c# - MVC Abstract Base Controller Override modelbinding 参数类型

c# - 允许使用 AES 256 为 HMAC 解密任何数据

visual-studio-2019 - InvalidProjectFileException : "The SDK ' Microsoft. NET.Sdk.Web' not found"from Microsoft.Build.Evaluation.Project 升级到 VS2019 后