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; } }
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); }