Skip to content

Commit aa8efc1

Browse files
Remove more blocking waits
1 parent 2051ab9 commit aa8efc1

File tree

2 files changed

+51
-65
lines changed

2 files changed

+51
-65
lines changed

src/VisualStudio/Core/Def/Implementation/AbstractVsTextViewFilter.cs

Lines changed: 44 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -35,106 +35,96 @@ internal abstract class AbstractVsTextViewFilter(
3535
IComponentModel componentModel) : AbstractOleCommandTarget(wpfTextView, componentModel), IVsTextViewFilter
3636
{
3737
int IVsTextViewFilter.GetDataTipText(TextSpan[] pSpan, out string pbstrText)
38+
{
39+
(pbstrText, var result) = this.ThreadingContext.JoinableTaskFactory.Run(() => GetDataTipTextAsync(pSpan));
40+
return result;
41+
}
42+
43+
private async Task<(string pbstrText, int result)> GetDataTipTextAsync(TextSpan[] pSpan)
3844
{
3945
try
4046
{
4147
if (pSpan == null || pSpan.Length != 1)
42-
{
43-
pbstrText = null;
44-
return VSConstants.E_INVALIDARG;
45-
}
48+
return (null, VSConstants.E_INVALIDARG);
4649

47-
return GetDataTipTextImpl(pSpan, out pbstrText);
50+
return await GetDataTipTextImplAsync(pSpan).ConfigureAwait(true);
4851
}
4952
catch (Exception e) when (FatalError.ReportAndCatch(e) && false)
5053
{
5154
throw ExceptionUtilities.Unreachable();
5255
}
5356
}
5457

55-
protected virtual int GetDataTipTextImpl(TextSpan[] pSpan, out string pbstrText)
58+
protected virtual async Task<(string pbstrText, int result)> GetDataTipTextImplAsync(TextSpan[] pSpan)
5659
{
5760
var subjectBuffer = WpfTextView.GetBufferContainingCaret();
5861
if (subjectBuffer == null)
59-
{
60-
pbstrText = null;
61-
return VSConstants.E_FAIL;
62-
}
62+
return (null, VSConstants.E_FAIL);
6363

64-
return GetDataTipTextImpl(subjectBuffer, pSpan, out pbstrText);
64+
return await GetDataTipTextImplAsync(subjectBuffer, pSpan).ConfigureAwait(true);
6565
}
6666

67-
protected int GetDataTipTextImpl(ITextBuffer subjectBuffer, TextSpan[] pSpan, out string pbstrText)
67+
protected async Task<(string pbstrText, int result)> GetDataTipTextImplAsync(ITextBuffer subjectBuffer, TextSpan[] pSpan)
6868
{
69-
pbstrText = null;
70-
7169
var vsBuffer = EditorAdaptersFactory.GetBufferAdapter(subjectBuffer);
7270

7371
// TODO: broken in REPL
7472
if (vsBuffer == null)
75-
{
76-
return VSConstants.E_FAIL;
77-
}
73+
return (null, VSConstants.E_FAIL);
7874

7975
using (Logger.LogBlock(FunctionId.Debugging_VsLanguageDebugInfo_GetDataTipText, CancellationToken.None))
8076
{
81-
pbstrText = null;
8277
if (pSpan == null || pSpan.Length != 1)
83-
{
84-
return VSConstants.E_INVALIDARG;
85-
}
78+
return (null, VSConstants.E_INVALIDARG);
8679

8780
var result = VSConstants.E_FAIL;
88-
string pbstrTextInternal = null;
81+
string pbstrText = null;
8982

9083
var uiThreadOperationExecutor = ComponentModel.GetService<IUIThreadOperationExecutor>();
91-
uiThreadOperationExecutor.Execute(
84+
using var context = uiThreadOperationExecutor.BeginExecute(
9285
title: ServicesVSResources.Debugger,
9386
defaultDescription: ServicesVSResources.Getting_DataTip_text,
9487
allowCancellation: true,
95-
showProgress: false,
96-
action: context =>
97-
{
98-
IServiceProvider serviceProvider = ComponentModel.GetService<SVsServiceProvider>();
99-
var debugger = (IVsDebugger)serviceProvider.GetService(typeof(SVsShellDebugger));
100-
var debugMode = new DBGMODE[1];
88+
showProgress: false);
10189

102-
var cancellationToken = context.UserCancellationToken;
103-
if (ErrorHandler.Succeeded(debugger.GetMode(debugMode)) && debugMode[0] != DBGMODE.DBGMODE_Design)
104-
{
105-
var textSpan = pSpan[0];
90+
IServiceProvider serviceProvider = ComponentModel.GetService<SVsServiceProvider>();
91+
var debugger = (IVsDebugger)serviceProvider.GetService(typeof(SVsShellDebugger));
92+
var debugMode = new DBGMODE[1];
93+
94+
var cancellationToken = context.UserCancellationToken;
95+
if (ErrorHandler.Succeeded(debugger.GetMode(debugMode)) && debugMode[0] != DBGMODE.DBGMODE_Design)
96+
{
97+
var textSpan = pSpan[0];
10698

107-
var textSnapshot = subjectBuffer.CurrentSnapshot;
108-
var document = textSnapshot.GetOpenDocumentInCurrentContextWithChanges();
99+
var textSnapshot = subjectBuffer.CurrentSnapshot;
100+
var document = textSnapshot.GetOpenDocumentInCurrentContextWithChanges();
109101

110-
if (document != null)
102+
if (document != null)
103+
{
104+
var languageDebugInfo = document.Project.Services.GetService<ILanguageDebugInfoService>();
105+
if (languageDebugInfo != null)
111106
{
112-
var languageDebugInfo = document.Project.Services.GetService<ILanguageDebugInfoService>();
113-
if (languageDebugInfo != null)
107+
var spanOpt = textSnapshot.TryGetSpan(textSpan);
108+
if (spanOpt.HasValue)
114109
{
115-
var spanOpt = textSnapshot.TryGetSpan(textSpan);
116-
if (spanOpt.HasValue)
110+
// 'kind' is an lsp-only concept, so we don't want/need to include it here (especially
111+
// as it can be expensive to compute, and we don't want to block the UI thread).
112+
var dataTipInfo = await languageDebugInfo.GetDataTipInfoAsync(
113+
document, spanOpt.Value.Start, includeKind: false, cancellationToken).ConfigureAwait(true);
114+
if (!dataTipInfo.IsDefault)
117115
{
118-
// 'kind' is an lsp-only concept, so we don't want/need to include it here (especially
119-
// as it can be expensive to compute, and we don't want to block the UI thread).
120-
var dataTipInfo = languageDebugInfo.GetDataTipInfoAsync(
121-
document, spanOpt.Value.Start, includeKind: false, cancellationToken).WaitAndGetResult(cancellationToken);
122-
if (!dataTipInfo.IsDefault)
123-
{
124-
var resultSpan = dataTipInfo.Span.ToSnapshotSpan(textSnapshot);
125-
var textOpt = dataTipInfo.Text;
116+
var resultSpan = dataTipInfo.Span.ToSnapshotSpan(textSnapshot);
117+
var textOpt = dataTipInfo.Text;
126118

127-
pSpan[0] = resultSpan.ToVsTextSpan();
128-
result = debugger.GetDataTipValue((IVsTextLines)vsBuffer, pSpan, textOpt, out pbstrTextInternal);
129-
}
119+
pSpan[0] = resultSpan.ToVsTextSpan();
120+
result = debugger.GetDataTipValue((IVsTextLines)vsBuffer, pSpan, textOpt, out pbstrText);
130121
}
131122
}
132123
}
133124
}
134-
});
125+
}
135126

136-
pbstrText = pbstrTextInternal;
137-
return result;
127+
return (pbstrText, result);
138128
}
139129
}
140130

src/VisualStudio/Core/Def/Venus/VenusCommandFilter.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
using System.Diagnostics;
88
using System.Linq;
9+
using System.Threading.Tasks;
910
using Microsoft.VisualStudio.ComponentModelHost;
1011
using Microsoft.VisualStudio.Editor;
1112
using Microsoft.VisualStudio.LanguageServices.Implementation.Extensions;
@@ -43,14 +44,13 @@ public VenusCommandFilter(
4344
protected override ITextBuffer GetSubjectBufferContainingCaret()
4445
=> _subjectBuffer;
4546

46-
protected override int GetDataTipTextImpl(TextSpan[] pSpan, out string pbstrText)
47+
protected override async Task<(string pbstrText, int result)> GetDataTipTextImplAsync(TextSpan[] pSpan)
4748
{
4849
var textViewModel = WpfTextView.TextViewModel;
4950
if (textViewModel == null)
5051
{
5152
Debug.Assert(WpfTextView.IsClosed);
52-
pbstrText = null;
53-
return VSConstants.E_FAIL;
53+
return (null, VSConstants.E_FAIL);
5454
}
5555

5656
// We need to map the TextSpan from the DataBuffer to our subject buffer.
@@ -72,7 +72,7 @@ protected override int GetDataTipTextImpl(TextSpan[] pSpan, out string pbstrText
7272
// Next, we'll check to see if there is actually a DataTip for this candidate.
7373
// If there is, we'll map this span back to the DataBuffer and return it.
7474
var subjectBufferSpanData = new TextSpan[] { candidateSpan.ToVsTextSpan() };
75-
var hr = GetDataTipTextImpl(_subjectBuffer, subjectBufferSpanData, out pbstrText);
75+
var (pbstrText, hr) = await GetDataTipTextImplAsync(_subjectBuffer, subjectBufferSpanData).ConfigureAwait(true);
7676
if (ErrorHandler.Succeeded(hr))
7777
{
7878
var subjectSpan = _subjectBuffer.CurrentSnapshot.GetSpan(subjectBufferSpanData[0]);
@@ -85,18 +85,14 @@ protected override int GetDataTipTextImpl(TextSpan[] pSpan, out string pbstrText
8585
.SingleOrDefault(x => x.IntersectsWith(span));
8686

8787
if (surfaceSpan == default)
88-
{
89-
pbstrText = null;
90-
return VSConstants.E_FAIL;
91-
}
88+
return (null, VSConstants.E_FAIL);
9289

9390
// pSpan is an in/out parameter
9491
pSpan[0] = surfaceSpan.ToVsTextSpan();
95-
return hr;
92+
return (pbstrText, hr);
9693
}
9794
}
9895

99-
pbstrText = null;
100-
return VSConstants.E_FAIL;
96+
return (null, VSConstants.E_FAIL);
10197
}
10298
}

0 commit comments

Comments
 (0)