|
// 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('?');
}
}
}
}
|