-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
196 additions
and
369 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
29 changes: 0 additions & 29 deletions
29
src/EditorFeatures/Core/Workspaces/EditorErrorReportingServiceFactory.cs
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...ef/Workspace/DetailedErrorInfoDialog.xaml → ...rorReporting/DetailedErrorInfoDialog.xaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
157 changes: 157 additions & 0 deletions
157
src/VisualStudio/Core/Def/ErrorReporting/VisualStudioInfoBar.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using Microsoft.CodeAnalysis.Editor.Shared.Utilities; | ||
using Microsoft.CodeAnalysis.Shared.TestHooks; | ||
using Microsoft.VisualStudio; | ||
using Microsoft.VisualStudio.Imaging; | ||
using Microsoft.VisualStudio.Shell; | ||
using Microsoft.VisualStudio.Shell.Interop; | ||
using Roslyn.Utilities; | ||
|
||
namespace Microsoft.CodeAnalysis.ErrorReporting | ||
{ | ||
internal sealed class VisualStudioInfoBar | ||
{ | ||
private readonly IThreadingContext _threadingContext; | ||
private readonly SVsServiceProvider _serviceProvider; | ||
private readonly IAsynchronousOperationListener _listener; | ||
|
||
/// <summary> | ||
/// Keep track of the messages that are currently being shown to the user. If we would | ||
/// show the same message again, block that from happening so we don't spam the user with | ||
/// the same message. When the info bar item is dismissed though, we then may show the | ||
/// same message in the future. This is important for user clarity as it's possible for | ||
/// a feature to fail for some reason, then work fine for a while, then fail again. We want | ||
/// the second failure message to be reported to ensure the user is not confused. | ||
/// | ||
/// Accessed on UI thread. | ||
/// </summary> | ||
private readonly HashSet<string> _currentlyShowingMessages = new(); | ||
|
||
public VisualStudioInfoBar( | ||
IThreadingContext threadingContext, | ||
SVsServiceProvider serviceProvider, | ||
IAsynchronousOperationListenerProvider listenerProvider) | ||
{ | ||
_threadingContext = threadingContext; | ||
_serviceProvider = serviceProvider; | ||
_listener = listenerProvider.GetListener(FeatureAttribute.InfoBar); | ||
} | ||
|
||
public void ShowInfoBar(string message, params InfoBarUI[] items) | ||
{ | ||
// We can be called from any thread since errors can occur anywhere, however we can only construct and InfoBar from the UI thread. | ||
_threadingContext.JoinableTaskFactory.RunAsync(async () => | ||
{ | ||
using var _ = _listener.BeginAsyncOperation(nameof(ShowInfoBar)); | ||
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(_threadingContext.DisposalToken); | ||
// If we're already shown this same message to the user, then do not bother showing it | ||
// to them again. It will just be noisy. | ||
if (!_currentlyShowingMessages.Contains(message) && | ||
_serviceProvider.GetService(typeof(SVsShell)) is IVsShell shell && | ||
ErrorHandler.Succeeded(shell.GetProperty((int)__VSSPROPID7.VSSPROPID_MainWindowInfoBarHost, out var globalInfoBar)) && | ||
globalInfoBar is IVsInfoBarHost infoBarHost && | ||
_serviceProvider.GetService(typeof(SVsInfoBarUIFactory)) is IVsInfoBarUIFactory factory) | ||
{ | ||
// create action item list | ||
var actionItems = new List<IVsInfoBarActionItem>(); | ||
foreach (var item in items) | ||
{ | ||
switch (item.Kind) | ||
{ | ||
case InfoBarUI.UIKind.Button: | ||
actionItems.Add(new InfoBarButton(item.Title)); | ||
break; | ||
case InfoBarUI.UIKind.HyperLink: | ||
actionItems.Add(new InfoBarHyperlink(item.Title)); | ||
break; | ||
case InfoBarUI.UIKind.Close: | ||
break; | ||
default: | ||
throw ExceptionUtilities.UnexpectedValue(item.Kind); | ||
} | ||
} | ||
var infoBarModel = new InfoBarModel( | ||
new[] { new InfoBarTextSpan(message) }, | ||
actionItems, | ||
KnownMonikers.StatusInformation, | ||
isCloseButtonVisible: true); | ||
var infoBarUI = factory.CreateInfoBar(infoBarModel); | ||
if (infoBarUI == null) | ||
return; | ||
uint? infoBarCookie = null; | ||
var eventSink = new InfoBarEvents(items, onClose: () => | ||
{ | ||
Contract.ThrowIfFalse(_threadingContext.JoinableTaskContext.IsOnMainThread); | ||
// Remove the message from the list that we're keeping track of. Future identical | ||
// messages can now be shown. | ||
_currentlyShowingMessages.Remove(message); | ||
// Run given onClose action if there is one. | ||
items.FirstOrDefault(i => i.Kind == InfoBarUI.UIKind.Close).Action?.Invoke(); | ||
if (infoBarCookie.HasValue) | ||
{ | ||
infoBarUI.Unadvise(infoBarCookie.Value); | ||
} | ||
}); | ||
infoBarUI.Advise(eventSink, out var cookie); | ||
infoBarCookie = cookie; | ||
infoBarHost.AddInfoBar(infoBarUI); | ||
_currentlyShowingMessages.Add(message); | ||
} | ||
}); | ||
} | ||
|
||
private sealed class InfoBarEvents : IVsInfoBarUIEvents | ||
{ | ||
private readonly InfoBarUI[] _items; | ||
private readonly Action _onClose; | ||
|
||
public InfoBarEvents(InfoBarUI[] items, Action onClose) | ||
{ | ||
Contract.ThrowIfNull(onClose); | ||
|
||
_items = items; | ||
_onClose = onClose; | ||
} | ||
|
||
public void OnActionItemClicked(IVsInfoBarUIElement infoBarUIElement, IVsInfoBarActionItem actionItem) | ||
{ | ||
var item = _items.FirstOrDefault(i => i.Title == actionItem.Text); | ||
if (item.IsDefault) | ||
{ | ||
return; | ||
} | ||
|
||
item.Action?.Invoke(); | ||
|
||
if (!item.CloseAfterAction) | ||
{ | ||
return; | ||
} | ||
|
||
infoBarUIElement.Close(); | ||
} | ||
|
||
public void OnClosed(IVsInfoBarUIElement infoBarUIElement) | ||
=> _onClose(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.