diff --git a/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralCommandHandler.cs b/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralCommandHandler.cs
index 23403b2c9398e..583c3a9f2e59a 100644
--- a/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralCommandHandler.cs
+++ b/src/EditorFeatures/CSharp/SplitStringLiteral/SplitStringLiteralCommandHandler.cs
@@ -92,7 +92,14 @@ 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
@@ -100,53 +107,35 @@ public bool ExecuteCommandWorker(ReturnKeyCommandArgs args)
// 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;
}
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/ParsedDocument.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/ParsedDocument.cs
index 61a3336f9b59e..c72048048d0c5 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/ParsedDocument.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Utilities/ParsedDocument.cs
@@ -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;
@@ -55,4 +60,27 @@ public ParsedDocument WithChangedRoot(SyntaxNode root, CancellationToken cancell
var text = root.SyntaxTree.GetText(cancellationToken);
return new ParsedDocument(Id, text, root, HostLanguageServices);
}
+
+ ///
+ /// Equivalent semantics to
+ ///
+ public IEnumerable GetChanges(in ParsedDocument oldDocument)
+ {
+ Contract.ThrowIfFalse(Id == oldDocument.Id);
+
+ if (Text == oldDocument.Text || SyntaxTree == oldDocument.SyntaxTree)
+ {
+ return SpecializedCollections.EmptyEnumerable();
+ }
+
+ 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);
+ }
}