-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Catch and report when we are unable to make an invisible editor #78236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cfbec58
451f8ac
5b1a64d
8d1b410
318c5ff
50cc532
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
| using System.Diagnostics.CodeAnalysis; | ||
| using System.IO; | ||
| using System.Linq; | ||
| using System.Runtime.InteropServices; | ||
| using System.Text; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
@@ -112,6 +113,12 @@ internal abstract partial class VisualStudioWorkspaceImpl : VisualStudioWorkspac | |
| private readonly IAsynchronousOperationListener _workspaceListener; | ||
| private bool _isExternalErrorDiagnosticUpdateSourceSubscribedToSolutionBuildEvents; | ||
|
|
||
| /// <summary> | ||
| /// Only read/written on hte UI thread. | ||
| /// </summary> | ||
| private bool _isShowingDocumentChangeErrorInfoBar = false; | ||
| private bool _ignoreDocumentTextChangeErrors; | ||
|
|
||
| public VisualStudioWorkspaceImpl(ExportProvider exportProvider, IAsyncServiceProvider asyncServiceProvider) | ||
| : base(VisualStudioMefHostServices.Create(exportProvider)) | ||
| { | ||
|
|
@@ -1192,29 +1199,81 @@ protected override void ApplyAnalyzerConfigDocumentTextChanged(DocumentId docume | |
|
|
||
| private void ApplyTextDocumentChange(DocumentId documentId, SourceText newText) | ||
| { | ||
| var containedDocument = ContainedDocument.TryGetContainedDocument(documentId); | ||
| this._threadingContext.ThrowIfNotOnUIThread(); | ||
|
|
||
| if (containedDocument != null) | ||
| { | ||
| containedDocument.UpdateText(newText); | ||
| } | ||
| else | ||
| CodeAnalysis.TextDocument? document = null; | ||
|
|
||
| try | ||
| { | ||
| if (IsDocumentOpen(documentId)) | ||
| { | ||
| var textBuffer = this.CurrentSolution.GetTextDocument(documentId)!.GetTextSynchronously(CancellationToken.None).Container.TryGetTextBuffer(); | ||
| document = this.CurrentSolution.GetRequiredTextDocument(documentId); | ||
|
|
||
| if (textBuffer != null) | ||
| var containedDocument = ContainedDocument.TryGetContainedDocument(documentId); | ||
| if (containedDocument != null) | ||
| { | ||
| containedDocument.UpdateText(newText); | ||
| } | ||
| else | ||
| { | ||
| if (IsDocumentOpen(documentId)) | ||
| { | ||
| TextEditApplication.UpdateText(newText, textBuffer, EditOptions.DefaultMinimalChange); | ||
| return; | ||
| var textBuffer = document.GetTextSynchronously(CancellationToken.None).Container.TryGetTextBuffer(); | ||
| if (textBuffer != null) | ||
| { | ||
| TextEditApplication.UpdateText(newText, textBuffer, EditOptions.DefaultMinimalChange); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // The document wasn't open in a normal way, so invisible editor time | ||
| using var invisibleEditor = OpenInvisibleEditor(documentId); | ||
| TextEditApplication.UpdateText(newText, invisibleEditor.TextBuffer, EditOptions.None); | ||
| // The document wasn't open in a normal way, so invisible editor time | ||
| using var invisibleEditor = OpenInvisibleEditor(documentId); | ||
| TextEditApplication.UpdateText(newText, invisibleEditor.TextBuffer, EditOptions.None); | ||
| } | ||
| } | ||
| catch (Exception ex) when (FatalError.ReportAndCatch(ex)) | ||
| { | ||
| ReportErrorChangingDocumentText(ex); | ||
| return; | ||
| } | ||
|
|
||
| void ReportErrorChangingDocumentText(Exception exception) | ||
| { | ||
| // Don't spam the info bar. If the user already has a message up, leave it at that. Also, | ||
| // if they've asked to not be notified about future doc change issue, respect that flag. | ||
| if (_ignoreDocumentTextChangeErrors || _isShowingDocumentChangeErrorInfoBar) | ||
| return; | ||
|
|
||
| var documentName = document?.Name ?? documentId.ToString(); | ||
|
|
||
| var errorReportingService = this.Services.GetRequiredService<IErrorReportingService>(); | ||
| errorReportingService.ShowGlobalErrorInfo( | ||
| message: string.Format(ServicesVSResources.Error_encountered_updating_0, documentName), | ||
| TelemetryFeatureName.Workspace, | ||
| exception, | ||
| // 'Show stack trace' will not dismiss the info bar. | ||
| new(WorkspacesResources.Show_Stack_Trace, InfoBarUI.UIKind.HyperLink, | ||
| () => errorReportingService.ShowDetailedErrorInfo(exception), closeAfterAction: false), | ||
| // 'Ignore' just closes the info bar, but allows future errors to show up. | ||
| new(ServicesVSResources.Ignore, InfoBarUI.UIKind.Button, GetDefaultDismissAction()), | ||
| // 'Ignore (including future errors) closes the info bar, but also sets the flag so the user gets no more messages | ||
| // in the current session. | ||
| new(ServicesVSResources.Ignore_including_future_errors, InfoBarUI.UIKind.Button, GetDefaultDismissAction( | ||
| () => _ignoreDocumentTextChangeErrors = true)), | ||
| // Close button is the same as 'ignore'. It closes the info bar, but allows future errors to show up. | ||
| new(string.Empty, InfoBarUI.UIKind.Close, GetDefaultDismissAction())); | ||
|
|
||
| // Mark that we're showing the info bar at this point. | ||
| _isShowingDocumentChangeErrorInfoBar = true; | ||
| } | ||
|
|
||
| Action GetDefaultDismissAction(Action? additionalAction = null) | ||
| => () => | ||
| { | ||
| additionalAction?.Invoke(); | ||
|
|
||
| // All info bar actions (except for 'show stack trace') dismiss the info bar, putting us back in the | ||
| // "we're not showing the user anything" state. | ||
| _isShowingDocumentChangeErrorInfoBar = false; | ||
|
Comment on lines
+1273
to
+1275
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Too bad there's not a generic way for us just to pass a handler for "any way this goes away".... :-/ |
||
| }; | ||
| } | ||
|
|
||
| protected override void ApplyDocumentInfoChanged(DocumentId documentId, DocumentInfo updatedInfo) | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.