public Task <Document> FormatAsync(Document document, ImmutableArray <TextSpan> changes, CancellationToken cancellationToken) { var root = document.GetSyntaxRootSynchronously(cancellationToken); var formattingSpans = changes.Select(s => CommonFormattingHelpers.GetFormattingSpan(root, s)); return(Formatter.FormatAsync(document, formattingSpans, cancellationToken: cancellationToken)); }
private void AdjustIndentationForSpan( Document document, ITextEdit edit, TextSpan visibleSpan, IFormattingRule baseIndentationRule, OptionSet options) { var root = document.GetSyntaxRootAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); using (var rulePool = SharedPools.Default <List <IFormattingRule> >().GetPooledObject()) using (var spanPool = SharedPools.Default <List <TextSpan> >().GetPooledObject()) { var venusFormattingRules = rulePool.Object; var visibleSpans = spanPool.Object; venusFormattingRules.Add(baseIndentationRule); venusFormattingRules.Add(ContainedDocumentPreserveFormattingRule.Instance); var formattingRules = venusFormattingRules.Concat(Formatter.GetDefaultFormattingRules(document)); var workspace = document.Project.Solution.Workspace; var changes = Formatter.GetFormattedTextChanges( root, new TextSpan[] { CommonFormattingHelpers.GetFormattingSpan(root, visibleSpan) }, workspace, options, formattingRules, CancellationToken.None); visibleSpans.Add(visibleSpan); var newChanges = FilterTextChanges(document.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None), visibleSpans, changes.ToReadOnlyCollection()).Where(t => visibleSpan.Contains(t.Span)); foreach (var change in newChanges) { edit.Replace(change.Span.ToSpan(), change.NewText); } } }
public void FormatSpan(SnapshotSpan span) { // Formatting a snippet isn't cancellable. var cancellationToken = CancellationToken.None; // At this point, the $selection$ token has been replaced with the selected text and // declarations have been replaced with their default text. We need to format the // inserted snippet text while carefully handling $end$ position (where the caret goes // after Return is pressed). The IExpansionSession keeps a tracking point for this // position but we do the tracking ourselves to properly deal with virtual space. To // ensure the end location is correct, we take three extra steps: // 1. Insert an empty comment ("/**/" or "'") at the current $end$ position (prior // to formatting), and keep a tracking span for the comment. // 2. After formatting the new snippet text, find and delete the empty multiline // comment (via the tracking span) and notify the IExpansionSession of the new // $end$ location. If the line then contains only whitespace (due to the formatter // putting the empty comment on its own line), then delete the white space and // remember the indentation depth for that line. // 3. When the snippet is finally completed (via Return), and PositionCaretForEditing() // is called, check to see if the end location was on a line containing only white // space in the previous step. If so, and if that line is still empty, then position // the caret in virtual space. // This technique ensures that a snippet like "if($condition$) { $end$ }" will end up // as: // if ($condition$) // { // $end$ // } if (!TryGetSubjectBufferSpan(span, out var snippetSpan)) { return; } // Insert empty comment and track end position var snippetTrackingSpan = snippetSpan.CreateTrackingSpan(SpanTrackingMode.EdgeInclusive); var fullSnippetSpan = ExpansionSession.GetSnippetSpan(); var isFullSnippetFormat = fullSnippetSpan == span; var endPositionTrackingSpan = isFullSnippetFormat ? InsertEmptyCommentAndGetEndPositionTrackingSpan() : null; var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(SubjectBuffer.CurrentSnapshot, snippetTrackingSpan.GetSpan(SubjectBuffer.CurrentSnapshot)); SubjectBuffer.CurrentSnapshot.FormatAndApplyToBuffer(formattingSpan, CancellationToken.None); if (isFullSnippetFormat) { CleanUpEndLocation(endPositionTrackingSpan); // Unfortunately, this is the only place we can safely add references and imports // specified in the snippet xml. In OnBeforeInsertion we have no guarantee that the // snippet xml will be available, and changing the buffer during OnAfterInsertion can // cause the underlying tracking spans to get out of sync. var currentStartPosition = snippetTrackingSpan.GetStartPoint(SubjectBuffer.CurrentSnapshot).Position; AddReferencesAndImports( ExpansionSession, currentStartPosition, cancellationToken); SetNewEndPosition(endPositionTrackingSpan); } }
public async Task <ImmutableArray <TextChange> > GetFormattingChangesOnPasteAsync( Document document, TextSpan textSpan, DocumentOptionSet?documentOptions, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, textSpan); var service = document.GetRequiredLanguageService <ISyntaxFormattingService>(); var rules = new List <AbstractFormattingRule>() { new PasteFormattingRule() }; rules.AddRange(service.GetDefaultFormattingRules()); if (documentOptions == null) { var inferredIndentationService = document.Project.Solution.Workspace.Services.GetRequiredService <IInferredIndentationService>(); documentOptions = await inferredIndentationService.GetDocumentOptionsWithInferredIndentationAsync(document, explicitFormat : false, cancellationToken : cancellationToken).ConfigureAwait(false); } var formattingOptions = SyntaxFormattingOptions.Create(documentOptions, document.Project.Solution.Workspace.Services, document.Project.Language); var result = service.GetFormattingResult(root, SpecializedCollections.SingletonEnumerable(formattingSpan), formattingOptions, rules, cancellationToken); return(result.GetTextChanges(cancellationToken).ToImmutableArray()); }
protected static async Task <LSP.TextEdit[]?> GetTextEditsAsync( RequestContext context, LSP.FormattingOptions options, IGlobalOptionService globalOptions, CancellationToken cancellationToken, LSP.Range?range = null) { var document = context.Document; if (document == null) { return(null); } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var rangeSpan = (range != null) ? ProtocolConversions.RangeToTextSpan(range, text) : new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, rangeSpan); // We should use the options passed in by LSP instead of the document's options. var formattingOptions = await ProtocolConversions.GetFormattingOptionsAsync(options, document, globalOptions, cancellationToken).ConfigureAwait(false); var services = document.Project.Solution.Services; var textChanges = Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), services, formattingOptions, rules: null, cancellationToken); var edits = new ArrayBuilder <LSP.TextEdit>(); edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text))); return(edits.ToArrayAndFree()); }
public Document Format(Document document, IEnumerable <TextSpan> changes, CancellationToken cancellationToken) { var root = document.GetSyntaxRootSynchronously(cancellationToken); var formattingSpans = changes.Select(s => CommonFormattingHelpers.GetFormattingSpan(root, s)); return(Formatter.FormatAsync(document, formattingSpans, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken)); }
public async Task <IList <TextChange> > GetFormattingChangesAsync(Document document, TextSpan?textSpan, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = textSpan.HasValue ? textSpan.Value : new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); return(Formatter.GetFormattedTextChanges(root, new TextSpan[] { formattingSpan }, document.Project.Solution.Workspace, cancellationToken: cancellationToken)); }
public Document Format(Document document, IEnumerable <TextSpan> changes, CancellationToken cancellationToken) { var snapshot = document.GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken).FindCorrespondingEditorTextSnapshot(); var root = document.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); var formattingSpans = changes.Select(s => s.ToSnapshotSpan(snapshot)) .Select(s => CommonFormattingHelpers.GetFormattingSpan(root, s.Span.ToTextSpan())); return(Formatter.FormatAsync(document, formattingSpans, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken)); }
public async Task<IList<TextChange>> GetFormattingChangesAsync(Document document, TextSpan? textSpan, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var span = textSpan ?? new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); return Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), document.Project.Solution.Workspace, options, cancellationToken); }
public async Task <IList <TextChange> > GetFormattingChangesAsync(Document document, TextSpan?textSpan, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = textSpan ?? new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); var options = await document.GetDocumentOptionsWithInferredIndentationAsync(explicitFormat : true, indentationManagerService : _indentationManagerService, cancellationToken : cancellationToken).ConfigureAwait(false); return(Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), document.Project.Solution.Workspace, options, cancellationToken)); }
public Task <ImmutableArray <TextChange> > GetFormattingChangesAsync( Document document, ITextBuffer textBuffer, TextSpan?textSpan, CancellationToken cancellationToken) { var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken); var options = textBuffer.GetSyntaxFormattingOptions(_editorOptionsService, parsedDocument.LanguageServices, explicitFormat: true); var span = textSpan ?? new TextSpan(0, parsedDocument.Root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(parsedDocument.Root, span); return(Task.FromResult(Formatter.GetFormattedTextChanges(parsedDocument.Root, SpecializedCollections.SingletonEnumerable(formattingSpan), document.Project.Solution.Services, options, cancellationToken).ToImmutableArray())); }
public async Task <ImmutableArray <TextChange> > GetFormattingChangesAsync( Document document, TextSpan?textSpan, CancellationToken cancellationToken) { var options = await _indentationManager.GetInferredFormattingOptionsAsync(document, explicitFormat : true, cancellationToken).ConfigureAwait(false); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = textSpan ?? new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); var services = document.Project.Solution.Workspace.Services; return(Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), services, options, cancellationToken).ToImmutableArray()); }
public async Task<IList<TextChange>> GetFormattingChangesOnPasteAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, textSpan); var service = document.GetLanguageService<ISyntaxFormattingService>(); if (service == null) { return SpecializedCollections.EmptyList<TextChange>(); } var rules = new List<IFormattingRule>() { new PasteFormattingRule() }; rules.AddRange(service.GetDefaultFormattingRules()); return Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), document.Project.Solution.Workspace, options, rules, cancellationToken); }
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); } }
public async Task <ImmutableArray <TextChange> > GetFormattingChangesAsync( Document document, TextSpan?textSpan, DocumentOptionSet?documentOptions, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = textSpan ?? new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); if (documentOptions == null) { var inferredIndentationService = document.Project.Solution.Workspace.Services.GetRequiredService <IInferredIndentationService>(); documentOptions = await inferredIndentationService.GetDocumentOptionsWithInferredIndentationAsync(document, explicitFormat : true, cancellationToken : cancellationToken).ConfigureAwait(false); } var services = document.Project.Solution.Workspace.Services; var formattingOptions = SyntaxFormattingOptions.Create(documentOptions, services, document.Project.Language); return(Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), services, formattingOptions, cancellationToken).ToImmutableArray()); }