File: CSharpAddAccessibilityModifiers.cs
Web Access
Project: ..\..\..\src\Features\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Features.csproj (Microsoft.CodeAnalysis.CSharp.Features)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using Microsoft.CodeAnalysis.AddAccessibilityModifiers;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.Shared.Extensions;
 
namespace Microsoft.CodeAnalysis.CSharp.AddAccessibilityModifiers
{
    internal class CSharpAddAccessibilityModifiers : AbstractAddAccessibilityModifiers<MemberDeclarationSyntax>
    {
        public static readonly CSharpAddAccessibilityModifiers Instance = new();
 
        protected CSharpAddAccessibilityModifiers()
        {
        }
 
        public override bool ShouldUpdateAccessibilityModifier(
            IAccessibilityFacts accessibilityFacts,
            MemberDeclarationSyntax member,
            AccessibilityModifiersRequired option,
            out SyntaxToken name,
            out bool modifierAdded)
        {
            modifierAdded = false;
 
            // Have to have a name to report the issue on.
            name = member.GetNameToken();
            if (name.Kind() == SyntaxKind.None)
                return false;
 
            // Certain members never have accessibility. Don't bother reporting on them.
            if (!accessibilityFacts.CanHaveAccessibility(member))
                return false;
 
            // This analyzer bases all of its decisions on the accessibility
            var accessibility = accessibilityFacts.GetAccessibility(member);
 
            // Omit will flag any accessibility values that exist and are default
            // The other options will remove or ignore accessibility
            var isOmit = option == AccessibilityModifiersRequired.OmitIfDefault;
            modifierAdded = !isOmit;
 
            if (isOmit)
            {
                if (accessibility == Accessibility.NotApplicable)
                    return false;
 
                var parentKind = member.GetRequiredParent().Kind();
                switch (parentKind)
                {
                    // Check for default modifiers in namespace and outside of namespace
                    case SyntaxKind.CompilationUnit:
                    case SyntaxKind.FileScopedNamespaceDeclaration:
                    case SyntaxKind.NamespaceDeclaration:
                        {
                            // Default is internal
                            if (accessibility != Accessibility.Internal)
                                return false;
                        }
 
                        break;
 
                    case SyntaxKind.ClassDeclaration:
                    case SyntaxKind.RecordDeclaration:
                    case SyntaxKind.StructDeclaration:
                    case SyntaxKind.RecordStructDeclaration:
                        {
                            // Inside a type, default is private
                            if (accessibility != Accessibility.Private)
                                return false;
                        }
 
                        break;
 
                    default:
                        return false; // Unknown parent kind, don't do anything
                }
            }
            else
            {
                // Mode is always, so we have to flag missing modifiers
                if (accessibility != Accessibility.NotApplicable)
                    return false;
            }
 
            return true;
        }
    }
}