Example #1
0
            private async Task <Model> ComputeModelInBackgroundAsync(
                Model currentModel,
                ImmutableArray <ISignatureHelpProvider> providers,
                SnapshotPoint caretPosition,
                DisconnectedBufferGraph disconnectedBufferGraph,
                SignatureHelpTriggerInfo triggerInfo,
                CancellationToken cancellationToken)
            {
                try
                {
                    using (Logger.LogBlock(FunctionId.SignatureHelp_ModelComputation_ComputeModelInBackground, cancellationToken))
                    {
                        AssertIsBackground();
                        cancellationToken.ThrowIfCancellationRequested();

                        var document = Controller.DocumentProvider.GetDocument(caretPosition.Snapshot, cancellationToken);
                        if (document == null)
                        {
                            return(currentModel);
                        }

                        // Let LSP handle signature help in the cloud scenario
                        if (Controller.SubjectBuffer.IsInLspEditorContext())
                        {
                            return(null);
                        }

                        if (triggerInfo.TriggerReason == SignatureHelpTriggerReason.RetriggerCommand)
                        {
                            if (currentModel == null)
                            {
                                return(null);
                            }

                            if (triggerInfo.TriggerCharacter.HasValue &&
                                !currentModel.Provider.IsRetriggerCharacter(triggerInfo.TriggerCharacter.Value))
                            {
                                return(currentModel);
                            }
                        }

                        var options = SignatureHelpOptions.From(document.Project);

                        // first try to query the providers that can trigger on the specified character
                        var(provider, items) = await ComputeItemsAsync(
                            providers, caretPosition, triggerInfo,
                            options, document, cancellationToken).ConfigureAwait(false);

                        if (provider == null)
                        {
                            // No provider produced items. So we can't produce a model
                            return(null);
                        }

                        if (currentModel != null &&
                            currentModel.Provider == provider &&
                            currentModel.GetCurrentSpanInSubjectBuffer(disconnectedBufferGraph.SubjectBufferSnapshot).Span.Start == items.ApplicableSpan.Start &&
                            currentModel.Items.IndexOf(currentModel.SelectedItem) == items.SelectedItemIndex &&
                            currentModel.ArgumentIndex == items.ArgumentIndex &&
                            currentModel.ArgumentCount == items.ArgumentCount &&
                            currentModel.ArgumentName == items.ArgumentName)
                        {
                            // The new model is the same as the current model.  Return the currentModel
                            // so we keep the active selection.
                            return(currentModel);
                        }

                        var selectedItem = GetSelectedItem(currentModel, items, provider, out var userSelected);

                        var model = new Model(disconnectedBufferGraph, items.ApplicableSpan, provider,
                                              items.Items, selectedItem, items.ArgumentIndex, items.ArgumentCount, items.ArgumentName,
                                              selectedParameter: 0, userSelected);

                        var syntaxFactsService = document.GetLanguageService <ISyntaxFactsService>();
                        var isCaseSensitive    = syntaxFactsService == null || syntaxFactsService.IsCaseSensitive;
                        var selection          = DefaultSignatureHelpSelector.GetSelection(model.Items,
                                                                                           model.SelectedItem, model.UserSelected, model.ArgumentIndex, model.ArgumentCount, model.ArgumentName, isCaseSensitive);

                        return(model.WithSelectedItem(selection.SelectedItem, selection.UserSelected)
                               .WithSelectedParameter(selection.SelectedParameter));
                    }
                }
                catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
Example #2
0
        public override async Task <LSP.SignatureHelp?> HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken)
        {
            var document = context.Document;

            if (document == null)
            {
                return(null);
            }

            var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            var providers   = _allProviders.Where(p => p.Metadata.Language == document.Project.Language);
            var triggerInfo = new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.InvokeSignatureHelpCommand);
            var options     = SignatureHelpOptions.From(document.Project);

            foreach (var provider in providers)
            {
                var items = await provider.Value.GetItemsAsync(document, position, triggerInfo, options, cancellationToken).ConfigureAwait(false);

                if (items != null)
                {
                    var sigInfos = new ArrayBuilder <LSP.SignatureInformation>();

                    foreach (var item in items.Items)
                    {
                        LSP.SignatureInformation sigInfo;
                        if (context.ClientCapabilities?.HasVisualStudioLspCapability() == true)
                        {
                            sigInfo = new LSP.VSInternalSignatureInformation
                            {
                                ColorizedLabel = GetSignatureClassifiedText(item)
                            };
                        }
                        else
                        {
                            sigInfo = new LSP.SignatureInformation();
                        }

                        sigInfo.Label         = GetSignatureText(item);
                        sigInfo.Documentation = new LSP.MarkupContent {
                            Kind = LSP.MarkupKind.PlainText, Value = item.DocumentationFactory(cancellationToken).GetFullText()
                        };
                        sigInfo.Parameters = item.Parameters.Select(p => new LSP.ParameterInformation
                        {
                            Label         = p.Name,
                            Documentation = new LSP.MarkupContent {
                                Kind = LSP.MarkupKind.PlainText, Value = p.DocumentationFactory(cancellationToken).GetFullText()
                            }
                        }).ToArray();
                        sigInfos.Add(sigInfo);
                    }

                    var sigHelp = new LSP.SignatureHelp
                    {
                        ActiveSignature = GetActiveSignature(items),
                        ActiveParameter = items.ArgumentIndex,
                        Signatures      = sigInfos.ToArrayAndFree()
                    };

                    return(sigHelp);
                }
            }

            return(null);
        }