File: Internal\SignatureHelp\FSharpSignatureHelpProvider.cs
Web Access
Project: src\src\VisualStudio\ExternalAccess\FSharp\Microsoft.CodeAnalysis.ExternalAccess.FSharp.csproj (Microsoft.CodeAnalysis.ExternalAccess.FSharp)
// 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;
using System.Linq;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ExternalAccess.FSharp.SignatureHelp;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.SignatureHelp;
using System.Collections.Immutable;
 
namespace Microsoft.CodeAnalysis.ExternalAccess.FSharp.Internal.SignatureHelp;
 
[Shared]
[ExportSignatureHelpProvider(nameof(FSharpSignatureHelpProvider), LanguageNames.FSharp)]
internal class FSharpSignatureHelpProvider : ISignatureHelpProvider
{
#pragma warning disable CS0618 // Type or member is obsolete
    private readonly IFSharpSignatureHelpProvider? _legacyProvider;
#pragma warning restore CS0618 // Type or member is obsolete
    private readonly AbstractFSharpSignatureHelpProvider? _newProvider;
 
    [ImportingConstructor]
    [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
    public FSharpSignatureHelpProvider(
        [Import(AllowDefault = true)] IFSharpSignatureHelpProvider? legacyProvider,
        [Import(AllowDefault = true)] AbstractFSharpSignatureHelpProvider? newProvider)
    {
        _legacyProvider = legacyProvider;
        _newProvider = newProvider;
    }
 
    /// <summary>
    /// Hard coded from https://github.com/dotnet/fsharp/blob/main/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs#L708
    /// </summary>
    public ImmutableArray<char> TriggerCharacters => _newProvider is not null ? _newProvider.TriggerCharacters : ['(', '<', ',', ' '];
 
    /// <summary>
    /// Hard coded from https://github.com/dotnet/fsharp/blob/main/vsintegration/src/FSharp.Editor/Completion/SignatureHelp.fs#L712C48-L712C73
    /// </summary>
    public ImmutableArray<char> RetriggerCharacters => _newProvider is not null ? _newProvider.RetriggerCharacters : [')', '>', '='];
 
    public async Task<SignatureHelpItems?> GetItemsAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, MemberDisplayOptions options, CancellationToken cancellationToken)
    {
        var mappedTriggerReason = FSharpSignatureHelpTriggerReasonHelpers.ConvertFrom(triggerInfo.TriggerReason);
        var mappedTriggerInfo = new FSharpSignatureHelpTriggerInfo(mappedTriggerReason, triggerInfo.TriggerCharacter);
        FSharpSignatureHelpItems mappedSignatureHelpItems;
        if (_newProvider is not null)
        {
            mappedSignatureHelpItems = await _newProvider.GetItemsAsync(document, position, mappedTriggerInfo, cancellationToken).ConfigureAwait(false);
        }
        else
        {
            Contract.ThrowIfNull(_legacyProvider, "Either the new or legacy provider must be available");
            mappedSignatureHelpItems = await _legacyProvider.GetItemsAsync(document, position, mappedTriggerInfo, cancellationToken).ConfigureAwait(false);
        }
 
        if (mappedSignatureHelpItems != null)
        {
            return new SignatureHelpItems(
                mappedSignatureHelpItems.Items.Select(x =>
                    new SignatureHelpItem(
                        x.IsVariadic,
                        x.DocumentationFactory,
                        x.PrefixDisplayParts,
                        x.SeparatorDisplayParts,
                        x.SuffixDisplayParts,
                        x.Parameters.Select(y =>
                            new SignatureHelpParameter(
                                y.Name,
                                y.IsOptional,
                                y.DocumentationFactory,
                                y.DisplayParts,
                                y.PrefixDisplayParts,
                                y.SuffixDisplayParts,
                                y.SelectedDisplayParts)).ToList(),
                        x.DescriptionParts)).ToList(),
                mappedSignatureHelpItems.ApplicableSpan,
                mappedSignatureHelpItems.ArgumentIndex,
                mappedSignatureHelpItems.ArgumentCount,
                mappedSignatureHelpItems.ArgumentName,
                mappedSignatureHelpItems.SelectedItemIndex);
        }
        else
        {
            return null;
        }
    }
}