/// <summary> /// True if this service would like to format the document based on the user typing the /// provided character. /// </summary> public static bool SupportsFormattingOnTypedCharacter(Document document, char ch) { Contract.ThrowIfFalse(document.Project.Language is LanguageNames.CSharp); var formattingService = document.GetRequiredLanguageService <IFormattingInteractionService>(); var options = AutoFormattingOptions.From(document.Project); return(formattingService.SupportsFormattingOnTypedCharacter(document, options, ch)); }
private void ExecuteReturnOrTypeCommandWorker(EditorCommandArgs args, CancellationToken cancellationToken) { var textView = args.TextView; var subjectBuffer = args.SubjectBuffer; if (!CanExecuteCommand(subjectBuffer)) { return; } var caretPosition = textView.GetCaretPoint(args.SubjectBuffer); if (!caretPosition.HasValue) { return; } var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } var service = document.GetLanguageService <IFormattingInteractionService>(); if (service == null) { return; } IList <TextChange>?textChanges; // save current caret position if (args is ReturnKeyCommandArgs) { if (!service.SupportsFormatOnReturn) { return; } textChanges = service.GetFormattingChangesOnReturnAsync( document, caretPosition.Value, documentOptions: null, cancellationToken).WaitAndGetResult(cancellationToken); } else if (args is TypeCharCommandArgs typeCharArgs) { var options = AutoFormattingOptions.From(document.Project); if (!service.SupportsFormattingOnTypedCharacter(document, options, typeCharArgs.TypedChar)) { return; } textChanges = service.GetFormattingChangesAsync( document, typeCharArgs.TypedChar, caretPosition.Value, documentOptions: null, cancellationToken).WaitAndGetResult(cancellationToken); } else { throw ExceptionUtilities.UnexpectedValue(args); } if (textChanges == null || textChanges.Count == 0) { return; } using (var transaction = CreateEditTransaction(textView, EditorFeaturesResources.Automatic_Formatting)) { transaction.MergePolicy = AutomaticCodeChangeMergePolicy.Instance; document.Project.Solution.Workspace.ApplyTextChanges(document.Id, textChanges, cancellationToken); transaction.Complete(); } // get new caret position after formatting var newCaretPositionMarker = args.TextView.GetCaretPoint(args.SubjectBuffer); if (!newCaretPositionMarker.HasValue) { return; } var snapshotAfterFormatting = args.SubjectBuffer.CurrentSnapshot; var oldCaretPosition = caretPosition.Value.TranslateTo(snapshotAfterFormatting, PointTrackingMode.Negative); var newCaretPosition = newCaretPositionMarker.Value.TranslateTo(snapshotAfterFormatting, PointTrackingMode.Negative); if (oldCaretPosition.Position == newCaretPosition.Position) { return; } // caret has moved to wrong position, move it back to correct position args.TextView.TryMoveCaretToAndEnsureVisible(oldCaretPosition); }