File: src\runtime\src\coreclr\tools\Common\Compiler\DisplayNameHelpers.cs
Web Access
Project: src\src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Text;

using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;

namespace ILCompiler
{
    public static class DisplayNameHelpers
    {
        public static string GetDisplayName(this TypeSystemEntity entity)
        {
            return entity switch
            {
                MethodDesc method => method.GetDisplayName(),
                FieldDesc field => field.GetDisplayName(),
                TypeDesc type => type.GetDisplayName(),
#if !READYTORUN
                PropertyPseudoDesc property => property.GetDisplayName(),
                EventPseudoDesc @event => @event.GetDisplayName(),
#endif
                _ => null,
            };
        }

        public static string GetDisplayName(this MethodDesc method)
        {
            var sb = new StringBuilder();

            sb.Append(method.OwningType.GetDisplayName());
            sb.Append('.');

            if (method.IsConstructor && method.OwningType is DefType defType)
            {
                sb.Append(defType.GetName());
            }
#if !READYTORUN
            else if (method.GetPropertyForAccessor() is PropertyPseudoDesc property)
            {
                MethodDesc typicalMethod = method.GetTypicalMethodDefinition();
                sb.Append(property.Name);
                sb.Append('.');
                sb.Append(property.GetMethod == typicalMethod ? "get" : "set");
                return sb.ToString();
            }
            else if (method.GetEventForAccessor() is EventPseudoDesc @event)
            {
                MethodDesc typicalMethod = method.GetTypicalMethodDefinition();
                sb.Append(@event.Name);
                sb.Append('.');
                string accessor;
                if (typicalMethod == @event.AddMethod)
                {
                    accessor = "add";
                }
                else if (typicalMethod == @event.RemoveMethod)
                {
                    accessor = "remove";
                }
                else
                {
                    Debug.Assert(typicalMethod == @event.RaiseMethod);
                    accessor = "raise";
                }
                sb.Append(accessor);
            }
#endif
            else
            {
                sb.Append(method.GetName());
            }

            if (method.HasInstantiation)
            {
                sb.Append('<');
                for (int i = 0; i < method.Instantiation.Length - 1; i++)
                    sb.Append(method.Instantiation[i].GetDisplayNameWithoutNamespace()).Append(',');

                sb.Append(method.Instantiation[method.Instantiation.Length - 1].GetDisplayNameWithoutNamespace());
                sb.Append('>');
            }

            // Append parameters
            sb.Append('(');
            if (method.Signature.Length > 0)
            {
                for (int i = 0; i < method.Signature.Length - 1; i++)
                {
                    TypeDesc instantiatedType = method.Signature[i].InstantiateSignature(method.OwningType.Instantiation, method.Instantiation);
                    sb.Append(instantiatedType.GetDisplayNameWithoutNamespace()).Append(',');
                }

                sb.Append(method.Signature[method.Signature.Length - 1].GetDisplayNameWithoutNamespace());
            }

            sb.Append(')');

            return sb.ToString();
        }

        public static string GetParameterDisplayName(this EcmaMethod method, int parameterIndex)
        {
            var reader = method.MetadataReader;
            var methodDefinition = reader.GetMethodDefinition(method.Handle);
            foreach (var parameterHandle in methodDefinition.GetParameters())
            {
                var parameter = reader.GetParameter(parameterHandle);
                if (parameter.SequenceNumber == parameterIndex + 1)
                    return reader.GetString(parameter.Name);
            }

            return $"#{parameterIndex}";
        }

        public static string GetDisplayName(this FieldDesc field)
        {
            return new StringBuilder(field.OwningType.GetDisplayName())
                .Append('.')
                .Append(field.GetName()).ToString();
        }

#if !READYTORUN
        public static string GetDisplayName(this PropertyPseudoDesc property)
        {
            return new StringBuilder(property.OwningType.GetDisplayName())
                .Append('.')
                .Append(property.Name).ToString();
        }

        public static string GetDisplayName(this EventPseudoDesc @event)
        {
            return new StringBuilder(@event.OwningType.GetDisplayName())
                .Append('.')
                .Append(@event.Name).ToString();
        }
#endif

        public static string GetDisplayName(this TypeDesc type)
        {
            return Formatter.Instance.FormatName(type, FormatOptions.NamespaceQualify);
        }

        public static string GetDisplayNameWithoutNamespace(this TypeDesc type)
        {
            return Formatter.Instance.FormatName(type, FormatOptions.None);
        }

        private sealed class Formatter : TypeNameFormatter<Formatter.Unit, FormatOptions>
        {
            public static readonly Formatter Instance = new Formatter();

            public override Unit AppendName(StringBuilder sb, ArrayType type, FormatOptions options)
            {
                AppendName(sb, type.ElementType, options);
                sb.Append('[');
                if (type.Rank > 1)
                    sb.Append(',', type.Rank - 1);
                sb.Append(']');
                return default;
            }

            public override Unit AppendName(StringBuilder sb, ByRefType type, FormatOptions options)
            {
                AppendName(sb, type.ParameterType, options);
                sb.Append('&');
                return default;
            }

            public override Unit AppendName(StringBuilder sb, PointerType type, FormatOptions options)
            {
                AppendName(sb, type.ParameterType, options);
                sb.Append('*');
                return default;
            }

            public override Unit AppendName(StringBuilder sb, FunctionPointerType type, FormatOptions options)
            {
                MethodSignature signature = type.Signature;

                sb.Append("delegate*<");
                for (int i = 0; i < signature.Length; i++)
                {
                    AppendName(sb, signature[i], options);
                    sb.Append(',');
                }
                AppendName(sb, signature.ReturnType, options);
                sb.Append('>');

                return default;
            }

            public override Unit AppendName(StringBuilder sb, GenericParameterDesc type, FormatOptions options)
            {
                sb.Append(type.Name);
                return default;
            }

            public override Unit AppendName(StringBuilder sb, SignatureMethodVariable type, FormatOptions options)
            {
                sb.Append("!!" + type.Index);
                return default;
            }

            public override Unit AppendName(StringBuilder sb, SignatureTypeVariable type, FormatOptions options)
            {
                sb.Append("!" + type.Index);
                return default;
            }

            protected override Unit AppendNameForInstantiatedType(StringBuilder sb, DefType type, FormatOptions options)
            {
                AppendName(sb, type.GetTypeDefinition(), options);

                FormatOptions parameterOptions = options & ~FormatOptions.NamespaceQualify;

                sb.Append('<');

                for (int i = 0; i < type.Instantiation.Length; i++)
                {
                    if (i != 0)
                        sb.Append(',');

                    AppendName(sb, type.Instantiation[i], parameterOptions);
                }

                sb.Append('>');

                return default;
            }

            protected override Unit AppendNameForNamespaceType(StringBuilder sb, DefType type, FormatOptions options)
            {
                NamespaceQualify(sb, type, options);
                sb.Append(type.GetName());
                return default;
            }

            protected override Unit AppendNameForNestedType(StringBuilder sb, DefType nestedType, DefType containingType, FormatOptions options)
            {
                AppendName(sb, containingType, options);
                sb.Append('.');
                sb.Append(nestedType.GetName());

                return default;
            }

            private static void NamespaceQualify(StringBuilder sb, DefType type, FormatOptions options)
            {
                if ((options & FormatOptions.NamespaceQualify) != 0)
                {
                    string ns = type.GetNamespace();
                    if (!string.IsNullOrEmpty(ns))
                    {
                        sb.Append(ns);
                        sb.Append('.');
                    }
                }
            }

            public struct Unit { }
        }

        private enum FormatOptions
        {
            None = 0,
            NamespaceQualify = 1,
        }
    }
}