查找领域和类型的有效辅助功能在罗斯林分析

问题描述 投票:3回答:1

我写一个罗斯林分析仪来执行一些文档的规则。该规则规定,需要记录仅领域和类型的组件外部可见。这使我找出一个字段或类型是否清晰可见,可以申报组件之外使用的问题。

鉴于此声明:

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;

然而,它没有考虑父类型考虑的可访问性,因此对应于DeclaredAccessibility回报PublicFieldInInternal符号的Accessibility.Public财产。有没有一种方法直接查询语义模型,以获得有效的可访问性,或者我需要递归看含类型?

c# roslyn roslyn-code-analysis
1个回答
0
投票

我结束了这种方法,并通过所有的单元测试:

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;
© www.soinside.com 2019 - 2024. All rights reserved.