File: Completion\CompletionProviders\ExplicitInterfaceMemberCompletionProvider.CompletionSymbolDisplay.cs
Web Access
Project: src\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 System.Collections.Immutable;
using System.Text;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
 
namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers;
 
internal sealed partial class ExplicitInterfaceMemberCompletionProvider
{
    private static class CompletionSymbolDisplay
    {
        public static string ToDisplayString(ISymbol symbol)
            => symbol switch
            {
                IEventSymbol eventSymbol => ToDisplayString(eventSymbol),
                IPropertySymbol propertySymbol => ToDisplayString(propertySymbol),
                IMethodSymbol methodSymbol => ToDisplayString(methodSymbol),
                _ => "" // This shouldn't happen.
            };
 
        private static string ToDisplayString(IEventSymbol symbol)
            => symbol.Name;
 
        private static string ToDisplayString(IPropertySymbol symbol)
        {
            using var _ = PooledStringBuilder.GetInstance(out var builder);
 
            if (symbol.IsIndexer)
            {
                builder.Append("this");
            }
            else
            {
                builder.Append(symbol.Name);
            }
 
            if (symbol.Parameters.Length > 0)
            {
                builder.Append('[');
                AddParameters(symbol.Parameters, builder);
                builder.Append(']');
            }
 
            return builder.ToString();
        }
 
        private static string ToDisplayString(IMethodSymbol symbol)
        {
            using var _ = PooledStringBuilder.GetInstance(out var builder);
            switch (symbol.MethodKind)
            {
                case MethodKind.Ordinary:
                    builder.Append(symbol.Name);
                    break;
                case MethodKind.UserDefinedOperator:
                case MethodKind.BuiltinOperator:
                    AppendOperatorKeywords(symbol, builder);
                    builder.Append(SyntaxFacts.GetText(SyntaxFacts.GetOperatorKind(symbol.MetadataName)));
                    break;
                case MethodKind.Conversion:
                    AppendOperatorKeywords(symbol, builder);
                    AddType(symbol.ReturnType, builder);
                    break;
            }
 
            AddTypeArguments(symbol, builder);
            builder.Append('(');
            AddParameters(symbol.Parameters, builder);
            builder.Append(')');
            return builder.ToString();
 
            static void AppendOperatorKeywords(IMethodSymbol symbol, StringBuilder builder)
            {
                builder.Append("operator ");
                if (SyntaxFacts.IsCheckedOperator(symbol.MetadataName))
                {
                    builder.Append("checked ");
                }
            }
        }
 
        private static void AddParameters(ImmutableArray<IParameterSymbol> parameters, StringBuilder builder)
        {
            builder.AppendJoinedValues(", ", parameters, static (parameter, builder) =>
            {
                builder.Append(parameter.RefKind switch
                {
                    RefKind.Out => "out ",
                    RefKind.Ref => "ref ",
                    RefKind.In => "in ",
                    _ => ""
                });
 
                if (parameter.IsParams)
                {
                    builder.Append("params ");
                }
 
                AddType(parameter.Type, builder);
                builder.Append($" {parameter.Name.EscapeIdentifier()}");
            });
        }
 
        private static void AddTypeArguments(IMethodSymbol symbol, StringBuilder builder)
        {
            if (symbol.TypeArguments.Length > 0)
            {
                builder.Append('<');
                builder.AppendJoinedValues(", ", symbol.TypeArguments, static (symbol, builder) => builder.Append(symbol.Name.EscapeIdentifier()));
                builder.Append('>');
            }
        }
 
        private static void AddType(ITypeSymbol symbol, StringBuilder builder)
        {
            builder.Append(symbol.ToNameDisplayString());
            if (symbol.NullableAnnotation == NullableAnnotation.Annotated)
            {
                builder.Append('?');
            }
        }
    }
}