private static ImmutableArray <SerializableImportCompletionItem> ConvertSymbolsToCompletionItems(ImmutableArray <IMethodSymbol> extentsionMethodSymbols, CancellationToken cancellationToken)
        {
            using var _1 = PooledDictionary <INamespaceSymbol, string> .GetInstance(out var namespaceNameCache);

            using var _2 = PooledDictionary <(string containingNamespace, string methodName, bool isGeneric), (IMethodSymbol bestSymbol, int overloadCount)> .GetInstance(out var overloadMap);

            // Aggregate overloads
            foreach (var symbol in extentsionMethodSymbols)
            {
                IMethodSymbol bestSymbol;
                int           overloadCount;

                var containingNamespacename = GetFullyQualifiedNamespaceName(symbol.ContainingNamespace, namespaceNameCache);
                var overloadKey             = (containingNamespacename, symbol.Name, isGeneric : symbol.Arity > 0);

                // Select the overload with minimum number of parameters to display
                if (overloadMap.TryGetValue(overloadKey, out var currentValue))
                {
                    bestSymbol    = currentValue.bestSymbol.Parameters.Length > symbol.Parameters.Length ? symbol : currentValue.bestSymbol;
                    overloadCount = currentValue.overloadCount + 1;
                }
                else
                {
                    bestSymbol    = symbol;
                    overloadCount = 1;
                }

                overloadMap[overloadKey] = (bestSymbol, overloadCount);
            }

            // Then convert symbols into completion items
            using var _3 = ArrayBuilder <SerializableImportCompletionItem> .GetInstance(out var itemsBuilder);

            foreach (var((containingNamespace, _, _), (bestSymbol, overloadCount)) in overloadMap)
            {
                // To display the count of of additional overloads, we need to substract total by 1.
                var item = new SerializableImportCompletionItem(
                    SymbolKey.CreateString(bestSymbol, cancellationToken),
                    bestSymbol.Name,
                    bestSymbol.Arity,
                    bestSymbol.GetGlyph(),
                    containingNamespace,
                    additionalOverloadCount: overloadCount - 1);

                itemsBuilder.Add(item);
            }

            return(itemsBuilder.ToImmutable());
        }
        private static ImmutableArray <SerializableImportCompletionItem> ConvertSymbolsToCompletionItems(
            Compilation compilation, ImmutableArray <IMethodSymbol> extentsionMethodSymbols, ImmutableArray <ITypeSymbol> targetTypeSymbols, CancellationToken cancellationToken)
        {
            Dictionary <ITypeSymbol, bool> typeConvertibilityCache = new();

            using var _1 = PooledDictionary <INamespaceSymbol, string> .GetInstance(out var namespaceNameCache);

            using var _2 = PooledDictionary <(string containingNamespace, string methodName, bool isGeneric), (IMethodSymbol bestSymbol, int overloadCount, bool includeInTargetTypedCompletion)>
                           .GetInstance(out var overloadMap);

            // Aggregate overloads
            foreach (var symbol in extentsionMethodSymbols)
            {
                cancellationToken.ThrowIfCancellationRequested();

                IMethodSymbol bestSymbol;
                int           overloadCount;
                var           includeInTargetTypedCompletion = ShouldIncludeInTargetTypedCompletion(compilation, symbol, targetTypeSymbols, typeConvertibilityCache);

                var containingNamespacename = GetFullyQualifiedNamespaceName(symbol.ContainingNamespace, namespaceNameCache);
                var overloadKey             = (containingNamespacename, symbol.Name, isGeneric : symbol.Arity > 0);

                // Select the overload convertible to any targeted type (if any) and with minimum number of parameters to display
                if (overloadMap.TryGetValue(overloadKey, out var currentValue))
                {
                    if (currentValue.includeInTargetTypedCompletion == includeInTargetTypedCompletion)
                    {
                        bestSymbol = currentValue.bestSymbol.Parameters.Length > symbol.Parameters.Length ? symbol : currentValue.bestSymbol;
                    }
                    else if (currentValue.includeInTargetTypedCompletion)
                    {
                        bestSymbol = currentValue.bestSymbol;
                    }
                    else
                    {
                        bestSymbol = symbol;
                    }

                    overloadCount = currentValue.overloadCount + 1;
                    includeInTargetTypedCompletion = includeInTargetTypedCompletion || currentValue.includeInTargetTypedCompletion;
                }
                else
                {
                    bestSymbol    = symbol;
                    overloadCount = 1;
                }

                overloadMap[overloadKey] = (bestSymbol, overloadCount, includeInTargetTypedCompletion);
            }

            // Then convert symbols into completion items
            using var _3 = ArrayBuilder <SerializableImportCompletionItem> .GetInstance(out var itemsBuilder);

            foreach (var((containingNamespace, _, _), (bestSymbol, overloadCount, includeInTargetTypedCompletion)) in overloadMap)
            {
                // To display the count of additional overloads, we need to subtract total by 1.
                var item = new SerializableImportCompletionItem(
                    SymbolKey.CreateString(bestSymbol, cancellationToken),
                    bestSymbol.Name,
                    bestSymbol.Arity,
                    bestSymbol.GetGlyph(),
                    containingNamespace,
                    additionalOverloadCount: overloadCount - 1,
                    includeInTargetTypedCompletion);

                itemsBuilder.Add(item);
            }

            return(itemsBuilder.ToImmutable());
        }