diff --git a/src/EditorFeatures/Core/Implementation/Preview/PreviewFactoryService.cs b/src/EditorFeatures/Core/Implementation/Preview/PreviewFactoryService.cs index e4542501f4d0bb1e44817254addcdc3ca5a727f4..deca042b4a72f5af188b5b3b5a24b273605b369f 100644 --- a/src/EditorFeatures/Core/Implementation/Preview/PreviewFactoryService.cs +++ b/src/EditorFeatures/Core/Implementation/Preview/PreviewFactoryService.cs @@ -553,8 +553,10 @@ private ITextBuffer CreateNewPlainTextBuffer(TextDocument document, Cancellation document.GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken).ToString(), contentType); } - private async Task CreateNewDifferenceViewerAsync(PreviewWorkspace leftWorkspace, PreviewWorkspace rightWorkspace, - IProjectionBuffer originalBuffer, IProjectionBuffer changedBuffer, double zoomLevel, CancellationToken cancellationToken) + private async Task CreateNewDifferenceViewerAsync( + PreviewWorkspace leftWorkspace, PreviewWorkspace rightWorkspace, + IProjectionBuffer originalBuffer, IProjectionBuffer changedBuffer, + double zoomLevel, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -564,24 +566,27 @@ private ITextBuffer CreateNewPlainTextBuffer(TextDocument document, Cancellation Contract.ThrowIfTrue((leftWorkspace == null) && (rightWorkspace == null)); var diffBuffer = _differenceBufferService.CreateDifferenceBuffer( - originalBuffer, changedBuffer, - new StringDifferenceOptions(), disableEditing: true); + originalBuffer, changedBuffer, + new StringDifferenceOptions(), disableEditing: true); var diffViewer = _differenceViewerService.CreateDifferenceView(diffBuffer, _previewRoleSet); diffViewer.Closed += (s, e) => { - if (leftWorkspace != null) - { - leftWorkspace.Dispose(); - leftWorkspace = null; - } - - if (rightWorkspace != null) - { - rightWorkspace.Dispose(); - rightWorkspace = null; - } + // Workaround Editor bug. The editor has an issue where they sometimes crash when + // trying to apply changes to projection buffer. So, when the user actually invokes + // a SuggestedAction we may then edit a text buffer, which the editor will then + // try to propagate through the projections we have here over that buffer. To ensure + // that that doesn't happen, we clear out the projections first so that this crash + // won't happen. + originalBuffer.DeleteSpans(0, originalBuffer.CurrentSnapshot.SpanCount); + changedBuffer.DeleteSpans(0, changedBuffer.CurrentSnapshot.SpanCount); + + leftWorkspace?.Dispose(); + leftWorkspace = null; + + rightWorkspace?.Dispose(); + rightWorkspace = null; }; const string DiffOverviewMarginName = "deltadifferenceViewerOverview"; @@ -615,15 +620,8 @@ private ITextBuffer CreateNewPlainTextBuffer(TextDocument document, Cancellation // We use ConfigureAwait(true) to stay on the UI thread. await diffViewer.SizeToFitAsync().ConfigureAwait(true); - if (leftWorkspace != null) - { - leftWorkspace.EnableDiagnostic(); - } - - if (rightWorkspace != null) - { - rightWorkspace.EnableDiagnostic(); - } + leftWorkspace?.EnableDiagnostic(); + rightWorkspace?.EnableDiagnostic(); return new DifferenceViewerPreview(diffViewer); }