示例#1
0
        /// <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);
            }
        }
示例#2
0
        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();
                }
        }
示例#3
0
        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);
            }
        }