public static async Task <IndentationOptions> GetIndentationOptionsAsync(this Document document, IGlobalOptionService globalOptions, CancellationToken cancellationToken) { var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(globalOptions, cancellationToken).ConfigureAwait(false); var autoFormattingOptions = globalOptions.GetAutoFormattingOptions(document.Project.Language); var indentStyle = globalOptions.GetOption(SmartIndent, document.Project.Language); return(new(formattingOptions, autoFormattingOptions, indentStyle)); }
public bool SupportsFormattingOnTypedCharacter(Document document, char ch) { var isSmartIndent = _globalOptions.GetOption(IndentationOptionsStorage.SmartIndent, LanguageNames.CSharp) == FormattingOptions2.IndentStyle.Smart; // We consider the proper placement of a close curly or open curly when it is typed at // the start of the line to be a smart-indentation operation. As such, even if "format // on typing" is off, if "smart indent" is on, we'll still format this. (However, we // won't touch anything else in the block this close curly belongs to.). // // See extended comment in GetFormattingChangesAsync for more details on this. if (isSmartIndent && ch is '{' or '}') { return(true); } var options = _globalOptions.GetAutoFormattingOptions(LanguageNames.CSharp); // If format-on-typing is not on, then we don't support formatting on any other characters. var autoFormattingOnTyping = options.FormatOnTyping; if (!autoFormattingOnTyping) { return(false); } if (ch == '}' && !options.FormatOnCloseBrace) { return(false); } if (ch == ';' && !options.FormatOnSemicolon) { return(false); } // don't auto format after these keys if smart indenting is not on. if (ch is '#' or 'n' && !isSmartIndent) { return(false); } return(_supportedChars.Contains(ch)); }
public 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 formattingOptions = await ProtocolConversions.GetFormattingOptionsAsync(request.Options, document, _globalOptions, cancellationToken).ConfigureAwait(false); // 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 docCommentOptions = _globalOptions.GetDocumentationCommentOptions(formattingOptions, document.Project.Language); var documentationCommentResponse = await GetDocumentationCommentResponseAsync( request, document, service, docCommentOptions, 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 = new IndentationOptions(formattingOptions) { AutoFormattingOptions = _globalOptions.GetAutoFormattingOptions(document.Project.Language) }; var braceCompletionAfterReturnResponse = await GetBraceCompletionAfterReturnResponseAsync( request, document, indentationOptions, cancellationToken).ConfigureAwait(false); if (braceCompletionAfterReturnResponse != null) { return(braceCompletionAfterReturnResponse); } } return(null); }
public bool SupportsFormattingOnTypedCharacter(Document document, char ch) { if (_service is IFSharpEditorFormattingServiceWithOptions serviceWithOptions) { var indentStyle = _globalOptions.GetOption(IndentationOptionsStorage.SmartIndent, LanguageNames.FSharp); var options = _globalOptions.GetAutoFormattingOptions(LanguageNames.FSharp); return(serviceWithOptions.SupportsFormattingOnTypedCharacter(document, new AutoFormattingOptionsWrapper(options, indentStyle), ch)); } else { return(_service.SupportsFormattingOnTypedCharacter(document, ch)); } }
public async Task <TextEdit[]?> HandleRequestAsync( DocumentOnTypeFormattingParams 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); if (string.IsNullOrEmpty(request.Character) || SyntaxFacts.IsNewLine(request.Character[0])) { return(Array.Empty <TextEdit>()); } var formattingService = document.Project.LanguageServices.GetRequiredService <ISyntaxFormattingService>(); var documentSyntax = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false); if (!formattingService.ShouldFormatOnTypedCharacter(documentSyntax, request.Character[0], position, cancellationToken)) { return(Array.Empty <TextEdit>()); } // We should use the options passed in by LSP instead of the document's options. var formattingOptions = await ProtocolConversions.GetFormattingOptionsAsync(request.Options, document, _globalOptions, cancellationToken).ConfigureAwait(false); var indentationOptions = new IndentationOptions(formattingOptions) { AutoFormattingOptions = _globalOptions.GetAutoFormattingOptions(document.Project.Language) }; var textChanges = formattingService.GetFormattingChangesOnTypedCharacter(documentSyntax, position, indentationOptions, cancellationToken); if (textChanges.IsEmpty) { return(Array.Empty <TextEdit>()); } var edits = new ArrayBuilder <TextEdit>(); edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, documentSyntax.Text))); return(edits.ToArrayAndFree()); }