Skip to content

Commit

Permalink
SplitString
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Sep 22, 2022
1 parent 9a52171 commit 94af9d0
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,61 +92,50 @@ public bool ExecuteCommandWorker(ReturnKeyCommandArgs args)
}
}

IndentationOptions? lazyOptions = null;
var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
if (document == null)
{
return false;
}

var parsedDocument = ParsedDocument.CreateSynchronously(document, CancellationToken.None);
var options = subjectBuffer.GetIndentationOptions(_editorOptionsService, parsedDocument.LanguageServices, explicitFormat: false);

// We now go through the verified string literals and split each of them.
// The list of spans is traversed in reverse order so we do not have to
// deal with updating later caret positions to account for the added space
// from splitting at earlier caret positions.
foreach (var span in spans.Reverse())
{
if (!SplitString(textView, subjectBuffer, span.Start.Position, ref lazyOptions, CancellationToken.None))
using var transaction = CaretPreservingEditTransaction.TryCreate(
CSharpEditorResources.Split_string, textView, _undoHistoryRegistry, _editorOperationsFactoryService);

var splitter = StringSplitter.TryCreate(parsedDocument, span.Start.Position, options, CancellationToken.None);
if (splitter?.TrySplit(out var newRoot, out var newPosition) != true)
{
return false;
}
}

return true;
}

private bool SplitString(ITextView textView, ITextBuffer subjectBuffer, int position, ref IndentationOptions? lazyOptions, CancellationToken cancellationToken)
{
var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
if (document == null)
{
return false;
}

lazyOptions ??= subjectBuffer.GetIndentationOptions(_editorOptionsService, document.Project.Services, explicitFormat: false);
// apply the change:
var newDocument = parsedDocument.WithChangedRoot(newRoot!, CancellationToken.None);
subjectBuffer.ApplyChanges(newDocument.GetChanges(parsedDocument));
parsedDocument = newDocument;

using var transaction = CaretPreservingEditTransaction.TryCreate(
CSharpEditorResources.Split_string, textView, _undoHistoryRegistry, _editorOperationsFactoryService);
// move caret:
var snapshotPoint = new SnapshotPoint(
subjectBuffer.CurrentSnapshot, newPosition);
var newCaretPoint = textView.BufferGraph.MapUpToBuffer(
snapshotPoint, PointTrackingMode.Negative, PositionAffinity.Predecessor,
textView.TextBuffer);

var parsedDocument = ParsedDocument.CreateSynchronously(document, CancellationToken.None);
var splitter = StringSplitter.TryCreate(parsedDocument, position, lazyOptions.Value, cancellationToken);
if (splitter?.TrySplit(out var newRoot, out var newPosition) != true)
{
return false;
}

// apply the change:
var newDocument = document.WithSyntaxRoot(newRoot!);
var workspace = newDocument.Project.Solution.Workspace;
workspace.TryApplyChanges(newDocument.Project.Solution);

// move caret:
var snapshotPoint = new SnapshotPoint(
subjectBuffer.CurrentSnapshot, newPosition);
var newCaretPoint = textView.BufferGraph.MapUpToBuffer(
snapshotPoint, PointTrackingMode.Negative, PositionAffinity.Predecessor,
textView.TextBuffer);
if (newCaretPoint != null)
{
textView.Caret.MoveTo(newCaretPoint.Value);
}

if (newCaretPoint != null)
{
textView.Caret.MoveTo(newCaretPoint.Value);
transaction?.Complete();
}

transaction?.Complete();
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using static System.Net.Mime.MediaTypeNames;
using static Humanizer.In;

namespace Microsoft.CodeAnalysis;

Expand Down Expand Up @@ -55,4 +60,27 @@ public ParsedDocument WithChangedRoot(SyntaxNode root, CancellationToken cancell
var text = root.SyntaxTree.GetText(cancellationToken);
return new ParsedDocument(Id, text, root, HostLanguageServices);
}

/// <summary>
/// Equivalent semantics to <see cref="Document.GetTextChangesAsync(Document, CancellationToken)"/>
/// </summary>
public IEnumerable<TextChange> GetChanges(in ParsedDocument oldDocument)
{
Contract.ThrowIfFalse(Id == oldDocument.Id);

if (Text == oldDocument.Text || SyntaxTree == oldDocument.SyntaxTree)
{
return SpecializedCollections.EmptyEnumerable<TextChange>();
}

var textChanges = Text.GetTextChanges(oldDocument.Text);

// if changes are significant (not the whole document being replaced) then use these changes
if (textChanges.Count > 1 || textChanges.Count == 1 && textChanges[0].Span != new TextSpan(0, oldDocument.Text.Length))
{
return textChanges;
}

return SyntaxTree.GetChanges(oldDocument.SyntaxTree);
}
}

0 comments on commit 94af9d0

Please sign in to comment.