/// <summary> /// format given snapshot and apply text changes to buffer /// </summary> public static void FormatAndApplyToBuffer( this ITextBuffer textBuffer, TextSpan span, EditorOptionsService editorOptionsService, CancellationToken cancellationToken) { var document = textBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } var documentSyntax = ParsedDocument.CreateSynchronously(document, cancellationToken); var rules = FormattingRuleUtilities.GetFormattingRules(documentSyntax, document.Project.LanguageServices, span, additionalRules: null); var formatter = document.GetRequiredLanguageService <ISyntaxFormattingService>(); var options = textBuffer.GetSyntaxFormattingOptions(editorOptionsService, document.Project.LanguageServices, explicitFormat: false); var result = formatter.GetFormattingResult(documentSyntax.Root, SpecializedCollections.SingletonEnumerable(span), options, rules, cancellationToken); var changes = result.GetTextChanges(cancellationToken); using (Logger.LogBlock(FunctionId.Formatting_ApplyResultToBuffer, cancellationToken)) { textBuffer.ApplyChanges(changes); } }
private void Format(ITextView textView, ITextBuffer textBuffer, Document document, TextSpan?selectionOpt, CancellationToken cancellationToken) { var formattingService = document.GetRequiredLanguageService <IFormattingInteractionService>(); using (Logger.LogBlock(FunctionId.CommandHandler_FormatCommand, KeyValueLogMessage.Create(LogType.UserAction, m => m["Span"] = selectionOpt?.Length ?? -1), cancellationToken)) using (var transaction = CreateEditTransaction(textView, EditorFeaturesResources.Formatting)) { // Note: C# always completes synchronously, TypeScript is async var changes = formattingService.GetFormattingChangesAsync(document, textBuffer, selectionOpt, cancellationToken).WaitAndGetResult(cancellationToken); if (changes.IsEmpty) { return; } if (selectionOpt.HasValue) { var ruleFactory = document.Project.Solution.Workspace.Services.GetRequiredService <IHostDependentFormattingRuleFactoryService>(); changes = ruleFactory.FilterFormattedChanges(document.Id, selectionOpt.Value, changes).ToImmutableArray(); } if (!changes.IsEmpty) { using (Logger.LogBlock(FunctionId.Formatting_ApplyResultToBuffer, cancellationToken)) { textBuffer.ApplyChanges(changes); } } transaction.Complete(); } }
private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextBuffer buffer, int indentationLine, char ch, bool useTabs) { var document = buffer.CurrentSnapshot.GetRelatedDocumentsWithChanges().First(); var documentSyntax = await ParsedDocument.CreateAsync(document, CancellationToken.None); var line = documentSyntax.Text.Lines[indentationLine]; var index = line.ToString().LastIndexOf(ch); Assert.InRange(index, 0, int.MaxValue); // get token var position = line.Start + index; var token = documentSyntax.Root.FindToken(position); var formattingRuleProvider = workspace.Services.GetService <IHostDependentFormattingRuleFactoryService>(); var rules = ImmutableArray.Create(formattingRuleProvider.CreateRule(documentSyntax, position)).AddRange(Formatter.GetDefaultFormattingRules(document)); var options = new IndentationOptions( new CSharpSyntaxFormattingOptions { Common = new SyntaxFormattingOptions.CommonOptions() { LineFormatting = new LineFormattingOptions { UseTabs = useTabs } } }); var formatter = new CSharpSmartTokenFormatter(options, rules, (CompilationUnitSyntax)documentSyntax.Root, documentSyntax.Text); var changes = formatter.FormatToken(token, CancellationToken.None); buffer.ApplyChanges(changes); }
private void ApplyEdits(Document document, ITextView textView, ITextBuffer subjectBuffer, string title, CommentSelectionResult edits, CancellationToken cancellationToken) { var originalSnapshot = subjectBuffer.CurrentSnapshot; // Apply the text changes. using (var transaction = new CaretPreservingEditTransaction(title, textView, _undoHistoryRegistry, _editorOperationsFactoryService)) { subjectBuffer.ApplyChanges(edits.TextChanges); transaction.Complete(); } if (edits.TrackingSpans.Any()) { // Create tracking spans to track the text changes. var trackingSpans = edits.TrackingSpans .SelectAsArray(textSpan => (originalSpan: textSpan, trackingSpan: CreateTrackingSpan(edits.ResultOperation, originalSnapshot, textSpan.TrackingTextSpan))); // Convert the tracking spans into snapshot spans for formatting and selection. var trackingSnapshotSpans = trackingSpans.Select(s => CreateSnapshotSpan(subjectBuffer.CurrentSnapshot, s.trackingSpan, s.originalSpan)); if (edits.ResultOperation == Operation.Uncomment && document.SupportsSyntaxTree) { // Format the document only during uncomment operations. Use second transaction so it can be undone. using var transaction = new CaretPreservingEditTransaction(title, textView, _undoHistoryRegistry, _editorOperationsFactoryService); var newText = subjectBuffer.CurrentSnapshot.AsText(); var oldSyntaxTree = document.GetSyntaxTreeSynchronously(cancellationToken); var newRoot = oldSyntaxTree.WithChangedText(newText).GetRoot(cancellationToken); var formattingOptions = subjectBuffer.GetSyntaxFormattingOptions(_editorOptionsService, document.Project.LanguageServices, explicitFormat: false); var formattingSpans = trackingSnapshotSpans.Select(change => CommonFormattingHelpers.GetFormattingSpan(newRoot, change.Span.ToTextSpan())); var formattedChanges = Formatter.GetFormattedTextChanges(newRoot, formattingSpans, document.Project.Solution.Services, formattingOptions, rules: null, cancellationToken); subjectBuffer.ApplyChanges(formattedChanges); transaction.Complete(); } // Set the multi selection after edits have been applied. textView.SetMultiSelection(trackingSnapshotSpans); } }