protected async Task <LSP.TextEdit[]?> GetTextEditsAsync( RequestContext context, LSP.FormattingOptions options, CancellationToken cancellationToken, LSP.Range?range = null) { var document = context.Document; if (document == null) { return(null); } var edits = new ArrayBuilder <LSP.TextEdit>(); var formattingService = document.Project.LanguageServices.GetRequiredService <IFormattingInteractionService>(); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); TextSpan?textSpan = null; if (range != null) { textSpan = ProtocolConversions.RangeToTextSpan(range, text); } // We should use the options passed in by LSP instead of the document's options. var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync( options, document, cancellationToken).ConfigureAwait(false); var textChanges = await GetFormattingChangesAsync(formattingService, document, textSpan, documentOptions, cancellationToken).ConfigureAwait(false); edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text))); return(edits.ToArrayAndFree()); }
public override async Task <LSP.VSInternalDocumentOnAutoInsertResponseItem?> HandleRequestAsync( LSP.VSInternalDocumentOnAutoInsertParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) { return(null); } var service = document.GetRequiredLanguageService <IDocumentationCommentSnippetService>(); // We should use the options passed in by LSP instead of the document's options. var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync( request.Options, document, cancellationToken).ConfigureAwait(false); var options = DocumentationCommentOptions.From(documentOptions); // The editor calls this handler for C# and VB comment characters, but we only need to process the one for the language that matches the document if (request.Character == "\n" || request.Character == service.DocumentationCommentCharacter) { var documentationCommentResponse = await GetDocumentationCommentResponseAsync( request, document, service, options, cancellationToken).ConfigureAwait(false); if (documentationCommentResponse != null) { return(documentationCommentResponse); } } // Only support this for razor as LSP doesn't support overtype yet. // https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1165179/ // Once LSP supports overtype we can move all of brace completion to LSP. if (request.Character == "\n" && context.ServerKind == WellKnownLspServerKinds.RazorLspServer) { var indentationOptions = IndentationOptions.From(documentOptions, document.Project.Solution.Workspace.Services, document.Project.Language); var braceCompletionAfterReturnResponse = await GetBraceCompletionAfterReturnResponseAsync( request, document, indentationOptions, cancellationToken).ConfigureAwait(false); if (braceCompletionAfterReturnResponse != null) { return(braceCompletionAfterReturnResponse); } } return(null); }
public override async Task <TextEdit[]?> HandleRequestAsync( DocumentOnTypeFormattingParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) { return(null); } var edits = new ArrayBuilder <TextEdit>(); var formattingService = document.Project.LanguageServices.GetRequiredService <IFormattingInteractionService>(); var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(request.Character)) { return(edits.ToArrayAndFree()); } // We should use the options passed in by LSP instead of the document's options. var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync( request.Options, document, cancellationToken).ConfigureAwait(false); IList <TextChange>?textChanges; if (SyntaxFacts.IsNewLine(request.Character[0])) { textChanges = await GetFormattingChangesOnReturnAsync( formattingService, document, position, documentOptions, cancellationToken).ConfigureAwait(false); } else { textChanges = await GetFormattingChangesAsync( formattingService, document, request.Character[0], position, documentOptions, cancellationToken).ConfigureAwait(false); } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); if (textChanges != null) { edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text))); } return(edits.ToArrayAndFree()); }
public override async Task <VSInternalInlineCompletionList?> HandleRequestAsync(VSInternalInlineCompletionRequest request, RequestContext context, CancellationToken cancellationToken) { Contract.ThrowIfNull(context.Document); // First get available snippets if any. var snippetInfoService = context.Document.Project.GetRequiredLanguageService <ISnippetInfoService>(); var snippetInfo = snippetInfoService.GetSnippetsIfAvailable(); if (!snippetInfo.Any()) { return(null); } // Then attempt to get the word at the requested position. var sourceText = await context.Document.GetTextAsync(cancellationToken).ConfigureAwait(false); var syntaxFactsService = context.Document.Project.GetRequiredLanguageService <ISyntaxFactsService>(); var linePosition = ProtocolConversions.PositionToLinePosition(request.Position); var position = sourceText.Lines.GetPosition(linePosition); if (!SnippetUtilities.TryGetWordOnLeft(position, sourceText, syntaxFactsService, out var wordOnLeft)) { return(null); } // Find the snippet with shortcut text that matches the typed word. var wordText = sourceText.GetSubText(wordOnLeft.Value).ToString(); if (!BuiltInSnippets.Contains(wordText, StringComparer.OrdinalIgnoreCase)) { return(null); } var matchingSnippetInfo = snippetInfo.First(s => wordText.Equals(s.Shortcut, StringComparison.OrdinalIgnoreCase)); var parsedSnippet = _xmlSnippetParser.GetParsedXmlSnippet(matchingSnippetInfo, context); if (parsedSnippet == null) { return(null); } // Use the formatting options specified by the client to format the snippet. var documentOptions = await ProtocolConversions.FormattingOptionsToDocumentOptionsAsync( request.Options, context.Document, cancellationToken).ConfigureAwait(false); var formattedLspSnippet = await GetFormattedLspSnippetAsync(parsedSnippet, wordOnLeft.Value, context.Document, sourceText, documentOptions, cancellationToken).ConfigureAwait(false); return(new VSInternalInlineCompletionList { Items = new VSInternalInlineCompletionItem[] { new VSInternalInlineCompletionItem { Range = ProtocolConversions.TextSpanToRange(wordOnLeft.Value, sourceText), Text = formattedLspSnippet, TextFormat = InsertTextFormat.Snippet, } } }); }