private IEnumerable <ISuggestedAction> GetLightBulbActions(ILightBulbBroker broker, IWpfTextView view) { if (!broker.IsLightBulbSessionActive(view)) { var bufferType = view.TextBuffer.ContentType.DisplayName; throw new Exception(string.Format("No light bulb session in View! Buffer content type={0}", bufferType)); } var activeSession = broker.GetSession(view); if (activeSession == null || !activeSession.IsExpanded) { var bufferType = view.TextBuffer.ContentType.DisplayName; throw new InvalidOperationException(string.Format("No expanded light bulb session found after View.ShowSmartTag. Buffer content type={0}", bufferType)); } IEnumerable <SuggestedActionSet> actionSets; if (activeSession.TryGetSuggestedActionSets(out actionSets) != QuerySuggestedActionCompletionStatus.Completed) { actionSets = Array.Empty <SuggestedActionSet>(); } return(SelectActions(actionSets)); }
public static async Task <bool> WaitForLightBulbSessionAsync(ILightBulbBroker broker, IWpfTextView view, CancellationToken cancellationToken) { var startTime = DateTimeOffset.Now; var active = await Helper.RetryAsync(async cancellationToken => { if (broker.IsLightBulbSessionActive(view)) { return(true); } if (cancellationToken.IsCancellationRequested) { throw new InvalidOperationException("Expected a light bulb session to appear."); } // checking whether there is any suggested action is async up to editor layer and our waiter doesn't track up to that point. // so here, we have no other way than sleep (with timeout) to see LB is available. await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); return(broker.IsLightBulbSessionActive(view)); }, TimeSpan.FromMilliseconds(1), cancellationToken); if (!active) { return(false); } await WaitForItemsAsync(broker, view, cancellationToken); return(true); }
private static IssueLocationActionsSource CreateTestSubject(ITagAggregator <ISelectedIssueLocationTag> selectedIssueLocationsTagAggregator, ITagAggregator <IIssueLocationTag> issueLocationsTagAggregator, IIssueSelectionService selectionService = null, ILightBulbBroker lightBulbBroker = null, ITextView textView = null) { textView = textView ?? CreateWpfTextView(); var vsUiShell = Mock.Of <IVsUIShell>(); var bufferTagAggregatorFactoryService = new Mock <IBufferTagAggregatorFactoryService>(); bufferTagAggregatorFactoryService .Setup(x => x.CreateTagAggregator <ISelectedIssueLocationTag>(textView.TextBuffer)) .Returns(selectedIssueLocationsTagAggregator); bufferTagAggregatorFactoryService .Setup(x => x.CreateTagAggregator <IIssueLocationTag>(textView.TextBuffer)) .Returns(issueLocationsTagAggregator); var analysisIssueSelectionServiceMock = new Mock <IIssueSelectionService>(); analysisIssueSelectionServiceMock.Setup(x => x.SelectedIssue).Returns(Mock.Of <IAnalysisIssueVisualization>()); selectionService ??= analysisIssueSelectionServiceMock.Object; lightBulbBroker ??= Mock.Of <ILightBulbBroker>(); return(new IssueLocationActionsSource(lightBulbBroker, vsUiShell, bufferTagAggregatorFactoryService.Object, textView, selectionService)); }
public static Task <bool> WaitForLightBulbSessionAsync( ILightBulbBroker broker, IWpfTextView view ) { var startTime = DateTimeOffset.Now; return(Helper.RetryAsync( async() => { if (broker.IsLightBulbSessionActive(view)) { return true; } if (DateTimeOffset.Now > startTime + Helper.HangMitigatingTimeout) { throw new InvalidOperationException( "Expected a light bulb session to appear." ); } // checking whether there is any suggested action is async up to editor layer and our waiter doesn't track up to that point. // so here, we have no other way than sleep (with timeout) to see LB is available. await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(true); return broker.IsLightBulbSessionActive(view); }, TimeSpan.Zero )); }
internal KeyFilterFactory( ICompletionBroker completionBroker, ISignatureHelpBroker signatureHelpBroker, ILightBulbBroker smartTagBroker, IAsyncQuickInfoBroker quickInfoBroker) { _helperFactory = new DisplayWindowHelper(completionBroker, signatureHelpBroker, smartTagBroker, quickInfoBroker); }
public Dev14KeyProcessor(IWpfTextView wpfTextView, ILightBulbBroker lightBulbBroker, ISuggestedActionCategoryRegistryService suggestedActionCategoryRegistryService, ISmartTagBroker smartTagBroker, IPeekBroker peekBroker) { this.wpfTextView = wpfTextView; this.lightBulbBroker = lightBulbBroker; this.suggestedActionCategoryRegistryService = suggestedActionCategoryRegistryService; this.smartTagBroker = smartTagBroker; this.peekBroker = peekBroker; AddShortcuts(); }
public IssueLocationActionsSourceProvider([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider, IBufferTagAggregatorFactoryService bufferTagAggregatorFactoryService, IIssueSelectionService selectionService, ILightBulbBroker lightBulbBroker) { this.bufferTagAggregatorFactoryService = bufferTagAggregatorFactoryService; this.selectionService = selectionService; this.lightBulbBroker = lightBulbBroker; vsUiShell = serviceProvider.GetService(typeof(SVsUIShell)) as IVsUIShell; }
private DisplayWindowHelper( ITextView view, ICompletionBroker completionBroker, ISignatureHelpBroker signatureHelpBroker, ILightBulbBroker smartTagBroker, IAsyncQuickInfoBroker quickInfoBroker) : this(completionBroker, signatureHelpBroker, smartTagBroker, quickInfoBroker) { TextView = view; }
internal DisplayWindowHelper( ICompletionBroker completionBroker, ISignatureHelpBroker signatureHelpBroker, ILightBulbBroker smartTagBroker, IAsyncQuickInfoBroker quickInfoBroker) { _completionBroker = completionBroker; _signatureHelpBroker = signatureHelpBroker; _smartTagBroker = smartTagBroker; _quickInfoBroker = quickInfoBroker; }
public LightBulbItemsSourceProvider( JoinableTaskContext joinableTaskContext, SVsServiceProvider serviceProvider, ILightBulbBroker lightBulbBroker, IVsEditorAdaptersFactoryService adaptersFactoryService, ISuggestedActionCategoryRegistryService2 categoryRegistryService) { this.joinableTaskContext = joinableTaskContext; this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); this.lightBulbBroker = lightBulbBroker ?? throw new ArgumentNullException(nameof(lightBulbBroker)); this.adaptersFactoryService = adaptersFactoryService ?? throw new ArgumentNullException(nameof(adaptersFactoryService)); this.categoryRegistryService = categoryRegistryService ?? throw new ArgumentNullException(nameof(categoryRegistryService)); }
public static bool WaitForLightBulbSession(ILightBulbBroker broker, Microsoft.VisualStudio.Text.Editor.IWpfTextView view) => Helper.Retry(() => { if (broker.IsLightBulbSessionActive(view)) { return(true); } // checking whether there is any suggested action is async up to editor layer and our waiter doesnt track up to that point. // so here, we have no other way than sleep (with timeout) to see LB is available. HostWaitHelper.PumpingWait(Task.Delay(TimeSpan.FromSeconds(1))); return(broker.IsLightBulbSessionActive(view)); }, TimeSpan.FromSeconds(0));
public ILightBulbSession GetLightBulbSession() { ILightBulbBroker broker = EditorShell.Current.ExportProvider.GetExportedValue <ILightBulbBroker>(); var session = broker.GetSession(EditorWindow.CoreEditor.View); int retries = 0; while (session == null && retries < 10) { this.DoIdle(1000); session = broker.GetSession(EditorWindow.CoreEditor.View); retries++; } return(session); }
public static bool WaitForLightBulbSession(ILightBulbBroker broker, Microsoft.VisualStudio.Text.Editor.IWpfTextView view) { return Helper.Retry<bool>(() => { if (broker.IsLightBulbSessionActive(view)) { return true; } // checking whether there is any suggested action is async up to editor layer and our waiter doesnt track up to that point. // so here, we have no other way than sleep (with timeout) to see LB is available. HostWaitHelper.PumpingWait(Task.Delay(TimeSpan.FromSeconds(1))); return broker.IsLightBulbSessionActive(view); }, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(20)); }
public IssueLocationActionsSource(ILightBulbBroker lightBulbBroker, IVsUIShell vsUiShell, IBufferTagAggregatorFactoryService bufferTagAggregatorFactoryService, ITextView textView, IIssueSelectionService selectionService) { this.lightBulbBroker = lightBulbBroker; this.vsUiShell = vsUiShell; this.textView = textView; this.selectionService = selectionService; issueLocationsTagAggregator = bufferTagAggregatorFactoryService.CreateTagAggregator <IIssueLocationTag>(textView.TextBuffer); issueLocationsTagAggregator.TagsChanged += TagAggregator_TagsChanged; selectedIssueLocationsTagAggregator = bufferTagAggregatorFactoryService.CreateTagAggregator <ISelectedIssueLocationTag>(textView.TextBuffer); selectedIssueLocationsTagAggregator.TagsChanged += TagAggregator_TagsChanged; }
public static async Task <bool> WaitForLightBulbSessionAsync(ILightBulbBroker broker, IWpfTextView view, CancellationToken cancellationToken) { var startTime = DateTimeOffset.Now; var active = await Helper.RetryAsync(async cancellationToken => { if (broker.IsLightBulbSessionActive(view)) { return(true); } if (cancellationToken.IsCancellationRequested) { throw new InvalidOperationException("Expected a light bulb session to appear."); } if (broker.IsLightBulbSessionActive(view)) { var session = broker.GetSession(view); var hasSuggestedActions = await broker.HasSuggestedActionsAsync(session.ActionCategories, view, cancellationToken); return(hasSuggestedActions); } return(false); }, TimeSpan.FromMilliseconds(1), cancellationToken); if (!active) { return(false); } await WaitForItemsAsync(broker, view, cancellationToken); return(true); }
private static async Task <IEnumerable <SuggestedActionSet>?> TryWaitForItemsAsync(TestServices testServices, ILightBulbBroker broker, IWpfTextView view, CancellationToken cancellationToken) { var activeSession = broker.GetSession(view); if (activeSession == null) { var bufferType = view.TextBuffer.ContentType.DisplayName; throw new InvalidOperationException($"No expanded light bulb session found after View.ShowSmartTag. Buffer content type={bufferType}"); } var asyncSession = (IAsyncLightBulbSession)activeSession; var tcs = new TaskCompletionSource <List <SuggestedActionSet> >(); EventHandler <SuggestedActionsUpdatedArgs>?handler = null; handler = (s, e) => { // ignore these. we care about when the lightbulb items are all completed. if (e.Status == QuerySuggestedActionCompletionStatus.InProgress) { return; } if (e.Status == QuerySuggestedActionCompletionStatus.Completed) { tcs.SetResult(e.ActionSets.ToList()); } else { tcs.SetException(new InvalidOperationException($"Light bulb transitioned to non-complete state: {e.Status}")); } asyncSession.SuggestedActionsUpdated -= handler; }; asyncSession.SuggestedActionsUpdated += handler; asyncSession.Dismissed += (_, _) => tcs.TrySetCanceled(new CancellationToken(true)); if (asyncSession.IsDismissed) { tcs.TrySetCanceled(new CancellationToken(true)); } // Calling PopulateWithData ensures the underlying session will call SuggestedActionsUpdated at least once // with the latest data computed. This is needed so that if the lightbulb computation is already complete // that we hear about the results. asyncSession.PopulateWithData(overrideRequestedActionCategories: null, operationContext: null); try { return(await tcs.Task.WithCancellation(cancellationToken)); } catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested) { if (Version.Parse("17.1.31928.29") >= await testServices.Shell.GetVersionAsync(cancellationToken)) { // Unexpected cancellation can occur when the editor dismisses the light bulb without request return(null); } throw; } }
public static async Task <IEnumerable <SuggestedActionSet> > WaitForItemsAsync(TestServices testServices, ILightBulbBroker broker, IWpfTextView view, CancellationToken cancellationToken) { while (true) { var items = await TryWaitForItemsAsync(testServices, broker, view, cancellationToken); if (items is not null) { return(items); } // The session was dismissed unexpectedly. The editor might show it again. await testServices.Editor.WaitForEditorOperationsAsync(cancellationToken); } }
public static async Task <bool> WaitForLightBulbSessionAsync(TestServices testServices, ILightBulbBroker broker, IWpfTextView view, CancellationToken cancellationToken) { await testServices.Editor.WaitForEditorOperationsAsync(cancellationToken); var active = broker.IsLightBulbSessionActive(view); if (!active) { return(false); } await WaitForItemsAsync(testServices, broker, view, cancellationToken); return(true); }
private ClassifiedToken[] GetLightbulbPreviewClassifications( string menuText, ILightBulbBroker broker, IWpfTextView view, IViewClassifierAggregatorService viewClassifierAggregator, IEditorPrimitivesFactoryService editorPrimitives) { LightBulbHelper.WaitForLightBulbSession(broker, view); var bufferType = view.TextBuffer.ContentType.DisplayName; if (!broker.IsLightBulbSessionActive(view)) { throw new Exception(string.Format("No Active Smart Tags in View! Buffer content type={0}", bufferType)); } var activeSession = broker.GetSession(view); if (activeSession == null || !activeSession.IsExpanded) { throw new InvalidOperationException(string.Format("No expanded light bulb session found after View.ShowSmartTag. Buffer content type={0}", bufferType)); } if (!string.IsNullOrEmpty(menuText)) { IEnumerable <SuggestedActionSet> actionSets; if (activeSession.TryGetSuggestedActionSets(out actionSets) != QuerySuggestedActionCompletionStatus.Completed) { actionSets = Array.Empty <SuggestedActionSet>(); } var set = actionSets.SelectMany(s => s.Actions).FirstOrDefault(a => a.DisplayText == menuText); if (set == null) { throw new InvalidOperationException( string.Format("ISuggestionAction {0} not found. Buffer content type={1}", menuText, bufferType)); } IWpfTextView preview = null; object pane = HostWaitHelper.PumpingWaitResult(set.GetPreviewAsync(CancellationToken.None)); if (pane is System.Windows.Controls.UserControl) { var container = ((System.Windows.Controls.UserControl)pane).FindName("PreviewDockPanel") as DockPanel; var host = FindDescendants <UIElement>(container).OfType <IWpfTextViewHost>().LastOrDefault(); preview = (host == null) ? null : host.TextView; } if (preview == null) { throw new InvalidOperationException(string.Format("Could not find light bulb preview. Buffer content type={0}", bufferType)); } activeSession.Collapse(); var classifier = viewClassifierAggregator.GetClassifier(preview); var classifiedSpans = classifier.GetClassificationSpans(new SnapshotSpan(preview.TextBuffer.CurrentSnapshot, 0, preview.TextBuffer.CurrentSnapshot.Length)); return(classifiedSpans.Select(x => new ClassifiedToken(x.Span.GetText().ToString(), x.ClassificationType.Classification)).ToArray()); } activeSession.Collapse(); return(Array.Empty <ClassifiedToken>()); }
public static async Task <IEnumerable <SuggestedActionSet> > WaitForItemsAsync(ILightBulbBroker broker, IWpfTextView view, CancellationToken cancellationToken) { var activeSession = broker.GetSession(view); if (activeSession is null) { var bufferType = view.TextBuffer.ContentType.DisplayName; throw new InvalidOperationException($"No expanded light bulb session found after View.ShowSmartTag. Buffer content type={bufferType}"); } var asyncSession = (IAsyncLightBulbSession)activeSession; var tcs = new TaskCompletionSource <List <SuggestedActionSet> >(); void Handler(object s, SuggestedActionsUpdatedArgs e) { // ignore these. we care about when the lightbulb items are all completed. if (e.Status == QuerySuggestedActionCompletionStatus.InProgress) { return; } if (e.Status == QuerySuggestedActionCompletionStatus.Completed || e.Status == QuerySuggestedActionCompletionStatus.CompletedWithoutData) { tcs.SetResult(e.ActionSets.ToList()); } else { tcs.SetException(new InvalidOperationException($"Light bulb transitioned to non-complete state: {e.Status}")); } asyncSession.SuggestedActionsUpdated -= Handler; } asyncSession.SuggestedActionsUpdated += Handler; asyncSession.Dismissed += (_, _) => tcs.TrySetCanceled(new CancellationToken(true)); if (asyncSession.IsDismissed) { tcs.TrySetCanceled(new CancellationToken(true)); } // Calling PopulateWithData ensures the underlying session will call SuggestedActionsUpdated at least once // with the latest data computed. This is needed so that if the lightbulb computation is already complete // that we hear about the results. asyncSession.PopulateWithData(overrideRequestedActionCategories: null, operationContext: null); return(await tcs.Task.WithCancellation(cancellationToken)); }
public static async Task <IEnumerable <SuggestedActionSet> > WaitForItemsAsync(ILightBulbBroker broker, IWpfTextView view) { using var cancellationTokenSource = new CancellationTokenSource(Helper.HangMitigatingTimeout); var editor = Editor_InProc.Create(); while (true) { var items = await TryWaitForItemsAsync(broker, view, cancellationTokenSource.Token); if (items is not null) { return(items); } // The session was dismissed unexpectedly. The editor might show it again. editor.WaitForEditorOperations(Helper.HangMitigatingTimeout); } }
public static async Task <IEnumerable <SuggestedActionSet> > WaitForItemsAsync(ILightBulbBroker broker, IWpfTextView view) { var activeSession = broker.GetSession(view); if (activeSession == null) { var bufferType = view.TextBuffer.ContentType.DisplayName; throw new InvalidOperationException($"No expanded light bulb session found after View.ShowSmartTag. Buffer content type={bufferType}"); } var asyncSession = (IAsyncLightBulbSession)activeSession; var tcs = new TaskCompletionSource <List <SuggestedActionSet> >(); EventHandler <SuggestedActionsUpdatedArgs>?handler = null; handler = (s, e) => { // ignore these. we care about when the lightbulb items are all completed. if (e.Status == QuerySuggestedActionCompletionStatus.InProgress) { return; } if (e.Status == QuerySuggestedActionCompletionStatus.Completed) { tcs.SetResult(e.ActionSets.ToList()); } else { tcs.SetException(new InvalidOperationException($"Light bulb transitioned to non-complete state: {e.Status}")); } asyncSession.SuggestedActionsUpdated -= handler; }; asyncSession.SuggestedActionsUpdated += handler; // Calling PopulateWithData ensures the underlying session will call SuggestedActionsUpdated at least once // with the latest data computed. This is needed so that if the lightbulb computation is already complete // that we hear about the results. asyncSession.PopulateWithData(overrideRequestedActionCategories: null, operationContext: null); return(await tcs.Task.WithTimeout(Helper.HangMitigatingTimeout).ConfigureAwait(false)); }