【问题标题】:Finding the effective accessibility of fields and types in a Roslyn analyzer在 Roslyn 分析器中查找字段和类型的有效可访问性
【发布时间】:2019-02-01 13:39:57
【问题描述】:

我正在编写一个 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。有没有办法直接查询语义模型以获得有效的可访问性,还是我需要递归查看包含类型?

【问题讨论】:

  • 我很确定您必须递归查看包含类型。见IsMemberAccessible。他们检查包含类型的IsNamedTypeAccessible

标签: c# roslyn roslyn-code-analysis


【解决方案1】:

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

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2021-04-23
    • 1970-01-01
    相关资源
    最近更新 更多