Repository: dotnet/roslyn
File: src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs (C#)

Code before:
            if (typeSymbol is not null)
            {
                item = SymbolCompletionItem.AddShouldProvideParenthesisCompletion(item);

                // When committing with `.`, we don't want to automatically appending parenthesis for types
                // that has accessible nested types (user might want to access nested types like Bar.Foo)
                if (HasAccessibleNestedTypes(typeSymbol))
                {
                    item = SymbolCompletionItem.AddHasAccessibleNestedTypes(item);
                }
            }
        }

        return item;

        bool HasAccessibleNestedTypes(INamedTypeSymbol typeSymbol)
        {
            foreach (var typeMember in typeSymbol.GetTypeMembers())
            {
                if (typeMember.DeclaredAccessibility <= Accessibility.Protected)
                    continue;

                if (typeMember.DeclaredAccessibility is Accessibility.Public)
                    return true;

                // Don't check accessibility from within containing type/member symbol,
                // we might be passed a speculative member semantic model so won't be able to get them
                if (typeMember.IsAccessibleWithin(context.SemanticModel.Compilation.Assembly))
                    return true;
            }

            return false;
        }
    }

    protected override string GetInsertionText(CompletionItem item, char ch)
    {
        if (SymbolCompletionItem.GetShouldProvideParenthesisCompletion(item))
        {
            // For '.', don't add parentheses if the type has accessible nested types
            // (user might want to access nested types like Bar.Foo)
            if (ch is ';' ||
                ch is '.' && !SymbolCompletionItem.GetHasAccessibleNestedTypes(item))
            {
                CompletionProvidersLogger.LogCustomizedCommitToAddParenthesis(ch);
                return SymbolCompletionItem.GetInsertionText(item) + "()";
            }
        }

        return base.GetInsertionText(item, ch);
    }

Review comment (suggestion):
note: this is not really accurate.  for example, you can have protected/private nested types that are then referencable from *within* the inner type.    i think you want `if (typeMember.IsAccessibleWithin(` and then pass the .ContainingType for where the operation was invokved from.  Which i think is on hte syntax context.  So basically, get rid of the first two 'if' checks, and update the bottom one. 

these are good to test as well.

Code after:
            if (typeSymbol is not null)
            {
                item = SymbolCompletionItem.AddShouldProvideParenthesisCompletion(item);

                // When committing with `.`, we don't want to automatically appending parenthesis for types
                // that has accessible nested types (user might want to access nested types like Bar.Foo)
                if (HasAccessibleNestedTypes(typeSymbol))
                {
                    item = SymbolCompletionItem.AddHasAccessibleNestedTypes(item);
                }
            }
        }

        return item;

        bool HasAccessibleNestedTypes(INamedTypeSymbol typeSymbol)
        {
            // This is intended to be a heuristic to cover common cases.
            // Because we might be passed a speculative member semantic model, we won't be able to get
            // symbols for containing type/member symbol to check accessibility using `IsAccessibleWithin`.
            // While this check is inaccurate in some cases (e.g. from within nested/derived types),
            // it's likely fine because people typically don't access the nested types via the outer one
            // when they are within the inner or derived type.
            foreach (var typeMember in typeSymbol.GetTypeMembers())
            {
                if (typeMember.DeclaredAccessibility <= Accessibility.Protected)
                    continue;

                if (typeMember.DeclaredAccessibility is Accessibility.Public)
                    return true;

                if (typeMember.IsAccessibleWithin(context.SemanticModel.Compilation.Assembly))
                    return true;
            }

            return false;
        }
    }

    protected override string GetInsertionText(CompletionItem item, char ch)
    {
        if (SymbolCompletionItem.GetShouldProvideParenthesisCompletion(item))
        {
            // For '.', don't add parentheses if the type has accessible nested types
            // (user might want to access nested types like Bar.Foo)
            if (ch is ';' ||
                ch is '.' && !SymbolCompletionItem.GetHasAccessibleNestedTypes(item))
            {
                CompletionProvidersLogger.LogCustomizedCommitToAddParenthesis(ch);
                return SymbolCompletionItem.GetInsertionText(item) + "()";
            }