<commit_before>﻿// 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.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.LanguageServices
{
    internal abstract partial class AbstractStructuralTypeDisplayService : IStructuralTypeDisplayService
    {
        public abstract ImmutableArray<SymbolDisplayPart> GetTypeParts(
            INamedTypeSymbol anonymousType, SemanticModel semanticModel, int position);

        public StructuralTypeDisplayInfo GetTypeDisplayInfo(
            ISymbol orderSymbol,
            IEnumerable<INamedTypeSymbol> directStructuralTypeReferences,
            SemanticModel semanticModel,
            int position)
        {
            if (!directStructuralTypeReferences.Any())
            {
                return new StructuralTypeDisplayInfo(
                    SpecializedCollections.EmptyDictionary<INamedTypeSymbol, string>(),
                    SpecializedCollections.EmptyList<SymbolDisplayPart>());
            }

            var transitiveStructuralTypeReferences = GetTransitiveNormalAnonymousTypeReferences(directStructuralTypeReferences.ToSet());
            transitiveStructuralTypeReferences = OrderAnonymousTypes(transitiveStructuralTypeReferences, orderSymbol);

            IList<SymbolDisplayPart> typeParts = new List<SymbolDisplayPart>();
            typeParts.Add(PlainText(FeaturesResources.Structural_Types_colon));
            typeParts.AddRange(LineBreak());

            for (var i = 0; i < transitiveStructuralTypeReferences.Count; i++)
            {
                if (i != 0)
                {
                    typeParts.AddRange(LineBreak());
                }

                var structuralType = transitiveStructuralTypeReferences[i];
                typeParts.AddRange(Space(count: 4));
                typeParts.Add(Part(SymbolDisplayPartKind.ClassName, structuralType, structuralType.Name));
                typeParts.AddRange(Space());
                typeParts.Add(PlainText(FeaturesResources.is_));
                typeParts.AddRange(Space());
                typeParts.AddRange(GetTypeParts(structuralType, semanticModel, position));
            }

            // Now, inline any delegate anonymous types we've got.
            typeParts = this.InlineDelegateAnonymousTypes(typeParts, semanticModel, position);

            // Finally, assign a name to all the anonymous types.
            var anonymousTypeToName = GenerateAnonymousTypeNames(transitiveStructuralTypeReferences);
            typeParts = StructuralTypeDisplayInfo.ReplaceStructuralTypes(typeParts, anonymousTypeToName);

            return new StructuralTypeDisplayInfo(anonymousTypeToName, typeParts);
        }

        private static Dictionary<INamedTypeSymbol, string> GenerateAnonymousTypeNames(
            IList<INamedTypeSymbol> anonymousTypes)
        {
            var current = 0;
            var anonymousTypeToName = new Dictionary<INamedTypeSymbol, string>();
            foreach (var type in anonymousTypes)
            {
                anonymousTypeToName[type] = GenerateAnonymousTypeName(current);
                current++;
            }

            return anonymousTypeToName;
        }

        private static string GenerateAnonymousTypeName(int current)
        {
            var c = (char)('a' + current);
            if (c is >= 'a' and <= 'z')
            {
                return "'" + c.ToString();
            }

            return "'" + current.ToString();
        }

        private static IList<INamedTypeSymbol> OrderAnonymousTypes(
            IList<INamedTypeSymbol> transitiveAnonymousTypeReferences,
            ISymbol symbol)
        {
            if (symbol is IMethodSymbol method)
            {
                return transitiveAnonymousTypeReferences.OrderBy(
                    (n1, n2) =>
                    {
                        var index1 = method.TypeArguments.IndexOf(n1);
                        var index2 = method.TypeArguments.IndexOf(n2);
                        index1 = index1 < 0 ? int.MaxValue : index1;
                        index2 = index2 < 0 ? int.MaxValue : index2;

                        return index1 - index2;
                    }).ToList();
            }
            else if (symbol is IPropertySymbol property)
            {
                return transitiveAnonymousTypeReferences.OrderBy(
                    (n1, n2) =>
                    {
                        if (n1.Equals(property.ContainingType) && !n2.Equals(property.ContainingType))
                        {
                            return -1;
                        }
                        else if (!n1.Equals(property.ContainingType) && n2.Equals(property.ContainingType))
                        {
                            return 1;
                        }
                        else
                        {
                            return 0;
                        }
                    }).ToList();
            }

            return transitiveAnonymousTypeReferences;
        }

        private static IList<INamedTypeSymbol> GetTransitiveNormalAnonymousTypeReferences(
            ISet<INamedTypeSymbol> anonymousTypeReferences)
        {
            var transitiveReferences = new List<INamedTypeSymbol>();
            var visitor = new NormalAnonymousTypeCollectorVisitor(transitiveReferences);<commit_msg>Rename<commit_after>﻿// 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.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.LanguageServices
{
    internal abstract partial class AbstractStructuralTypeDisplayService : IStructuralTypeDisplayService
    {
        public abstract ImmutableArray<SymbolDisplayPart> GetTypeParts(
            INamedTypeSymbol anonymousType, SemanticModel semanticModel, int position);

        public StructuralTypeDisplayInfo GetTypeDisplayInfo(
            ISymbol orderSymbol,
            IEnumerable<INamedTypeSymbol> directStructuralTypeReferences,
            SemanticModel semanticModel,
            int position)
        {
            if (!directStructuralTypeReferences.Any())
            {
                return new StructuralTypeDisplayInfo(
                    SpecializedCollections.EmptyDictionary<INamedTypeSymbol, string>(),
                    SpecializedCollections.EmptyList<SymbolDisplayPart>());
            }

            var transitiveStructuralTypeReferences = GetTransitiveStructuralTypeReferences(directStructuralTypeReferences.ToSet());
            transitiveStructuralTypeReferences = OrderStructuralTypes(transitiveStructuralTypeReferences, orderSymbol);

            IList<SymbolDisplayPart> typeParts = new List<SymbolDisplayPart>();
            typeParts.Add(PlainText(FeaturesResources.Structural_Types_colon));
            typeParts.AddRange(LineBreak());

            for (var i = 0; i < transitiveStructuralTypeReferences.Count; i++)
            {
                if (i != 0)
                {
                    typeParts.AddRange(LineBreak());
                }

                var structuralType = transitiveStructuralTypeReferences[i];
                typeParts.AddRange(Space(count: 4));
                typeParts.Add(Part(
                    structuralType.IsValueType ? SymbolDisplayPartKind.StructName : SymbolDisplayPartKind.ClassName,
                    structuralType, structuralType.Name));
                typeParts.AddRange(Space());
                typeParts.Add(PlainText(FeaturesResources.is_));
                typeParts.AddRange(Space());
                typeParts.AddRange(GetTypeParts(structuralType, semanticModel, position));
            }

            // Now, inline any delegate anonymous types we've got.
            typeParts = this.InlineDelegateAnonymousTypes(typeParts, semanticModel, position);

            // Finally, assign a name to all the anonymous types.
            var anonymousTypeToName = GenerateAnonymousTypeNames(transitiveStructuralTypeReferences);
            typeParts = StructuralTypeDisplayInfo.ReplaceStructuralTypes(typeParts, anonymousTypeToName);

            return new StructuralTypeDisplayInfo(anonymousTypeToName, typeParts);
        }

        private static Dictionary<INamedTypeSymbol, string> GenerateAnonymousTypeNames(
            IList<INamedTypeSymbol> anonymousTypes)
        {
            var current = 0;
            var anonymousTypeToName = new Dictionary<INamedTypeSymbol, string>();
            foreach (var type in anonymousTypes)
            {
                anonymousTypeToName[type] = GenerateAnonymousTypeName(current);
                current++;
            }

            return anonymousTypeToName;
        }

        private static string GenerateAnonymousTypeName(int current)
        {
            var c = (char)('a' + current);
            if (c is >= 'a' and <= 'z')
            {
                return "'" + c.ToString();
            }

            return "'" + current.ToString();
        }

        private static IList<INamedTypeSymbol> OrderStructuralTypes(
            IList<INamedTypeSymbol> transitiveAnonymousTypeReferences,
            ISymbol symbol)
        {
            if (symbol is IMethodSymbol method)
            {
                return transitiveAnonymousTypeReferences.OrderBy(
                    (n1, n2) =>
                    {
                        var index1 = method.TypeArguments.IndexOf(n1);
                        var index2 = method.TypeArguments.IndexOf(n2);
                        index1 = index1 < 0 ? int.MaxValue : index1;
                        index2 = index2 < 0 ? int.MaxValue : index2;

                        return index1 - index2;
                    }).ToList();
            }
            else if (symbol is IPropertySymbol property)
            {
                return transitiveAnonymousTypeReferences.OrderBy(
                    (n1, n2) =>
                    {
                        if (n1.Equals(property.ContainingType) && !n2.Equals(property.ContainingType))
                        {
                            return -1;
                        }
                        else if (!n1.Equals(property.ContainingType) && n2.Equals(property.ContainingType))
                        {
                            return 1;
                        }
                        else
                        {
                            return 0;
                        }
                    }).ToList();
            }

            return transitiveAnonymousTypeReferences;
        }

        private static IList<INamedTypeSymbol> GetTransitiveStructuralTypeReferences(
            ISet<INamedTypeSymbol> anonymousTypeReferences)
        {
            var transitiveReferences = new List<INamedTypeSymbol>();
            var visitor = new NormalAnonymousTypeCollectorVisitor(transitiveReferences);
{'fraction_non_alphanumeric': 0.07169410515135423, 'fraction_numerical': 0.005133651973800672, 'mean_word_length': 1.8360943775100402, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7397615', 'n_tokens_mistral': 2669, 'n_tokens_neox': 2466, 'n_words': 544}