Нахождение эффективной доступности полей и типов в анализаторе Roslyn - PullRequest
0 голосов
/ 01 февраля 2019

Я пишу анализатор 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;

Однако он не учитывает доступность родительских типов, поэтому свойство DeclaredAccessibility для символа, соответствующего PublicFieldInInternal, возвращает Accessibility.Public.Есть ли способ запросить семантическую модель напрямую, чтобы получить эффективную доступность, или мне нужно рекурсивно взглянуть на содержащие типы?

1 Ответ

0 голосов
/ 08 февраля 2019

Я закончил с этим подходом, и он проходит все юнит-тесты:

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;
...