77using System ;
88using System . Linq ;
99using System . Threading ;
10+ using System . Threading . Tasks ;
1011using Microsoft . CodeAnalysis . BraceMatching ;
1112using Microsoft . CodeAnalysis . Debugging ;
1213using Microsoft . CodeAnalysis . Editor ;
2930
3031namespace Microsoft . VisualStudio . LanguageServices . Implementation ;
3132
32- internal abstract class AbstractVsTextViewFilter : AbstractOleCommandTarget , IVsTextViewFilter
33+ internal abstract class AbstractVsTextViewFilter (
34+ IWpfTextView wpfTextView ,
35+ IComponentModel componentModel ) : AbstractOleCommandTarget ( wpfTextView , componentModel ) , IVsTextViewFilter
3336{
34- public AbstractVsTextViewFilter (
35- IWpfTextView wpfTextView ,
36- IComponentModel componentModel )
37- : base ( wpfTextView , componentModel )
37+ int IVsTextViewFilter . GetDataTipText ( TextSpan [ ] pSpan , out string pbstrText )
3838 {
39+ ( pbstrText , var result ) = this . ThreadingContext . JoinableTaskFactory . Run ( ( ) => GetDataTipTextAsync ( pSpan ) ) ;
40+ return result ;
3941 }
4042
41- int IVsTextViewFilter . GetDataTipText ( TextSpan [ ] pSpan , out string pbstrText )
43+ private async Task < ( string pbstrText , int result ) > GetDataTipTextAsync ( TextSpan [ ] pSpan )
4244 {
4345 try
4446 {
4547 if ( pSpan == null || pSpan . Length != 1 )
46- {
47- pbstrText = null ;
48- return VSConstants . E_INVALIDARG ;
49- }
48+ return ( null , VSConstants . E_INVALIDARG ) ;
5049
51- return GetDataTipTextImpl ( pSpan , out pbstrText ) ;
50+ return await GetDataTipTextImplAsync ( pSpan ) . ConfigureAwait ( true ) ;
5251 }
5352 catch ( Exception e ) when ( FatalError . ReportAndCatch ( e ) && false )
5453 {
5554 throw ExceptionUtilities . Unreachable ( ) ;
5655 }
5756 }
5857
59- protected virtual int GetDataTipTextImpl ( TextSpan [ ] pSpan , out string pbstrText )
58+ protected virtual async Task < ( string pbstrText , int result ) > GetDataTipTextImplAsync ( TextSpan [ ] pSpan )
6059 {
6160 var subjectBuffer = WpfTextView . GetBufferContainingCaret ( ) ;
6261 if ( subjectBuffer == null )
63- {
64- pbstrText = null ;
65- return VSConstants . E_FAIL ;
66- }
62+ return ( null , VSConstants . E_FAIL ) ;
6763
68- return GetDataTipTextImpl ( subjectBuffer , pSpan , out pbstrText ) ;
64+ return await GetDataTipTextImplAsync ( subjectBuffer , pSpan ) . ConfigureAwait ( true ) ;
6965 }
7066
71- protected int GetDataTipTextImpl ( ITextBuffer subjectBuffer , TextSpan [ ] pSpan , out string pbstrText )
67+ protected async Task < ( string pbstrText , int result ) > GetDataTipTextImplAsync ( ITextBuffer subjectBuffer , TextSpan [ ] pSpan )
7268 {
73- pbstrText = null ;
74-
7569 var vsBuffer = EditorAdaptersFactory . GetBufferAdapter ( subjectBuffer ) ;
7670
7771 // TODO: broken in REPL
7872 if ( vsBuffer == null )
79- {
80- return VSConstants . E_FAIL ;
81- }
73+ return ( null , VSConstants . E_FAIL ) ;
8274
8375 using ( Logger . LogBlock ( FunctionId . Debugging_VsLanguageDebugInfo_GetDataTipText , CancellationToken . None ) )
8476 {
85- pbstrText = null ;
8677 if ( pSpan == null || pSpan . Length != 1 )
87- {
88- return VSConstants . E_INVALIDARG ;
89- }
78+ return ( null , VSConstants . E_INVALIDARG ) ;
9079
9180 var result = VSConstants . E_FAIL ;
92- string pbstrTextInternal = null ;
81+ string pbstrText = null ;
9382
9483 var uiThreadOperationExecutor = ComponentModel . GetService < IUIThreadOperationExecutor > ( ) ;
95- uiThreadOperationExecutor . Execute (
84+ using var context = uiThreadOperationExecutor . BeginExecute (
9685 title : ServicesVSResources . Debugger ,
9786 defaultDescription : ServicesVSResources . Getting_DataTip_text ,
9887 allowCancellation : true ,
99- showProgress : false ,
100- action : context =>
101- {
102- IServiceProvider serviceProvider = ComponentModel . GetService < SVsServiceProvider > ( ) ;
103- var debugger = ( IVsDebugger ) serviceProvider . GetService ( typeof ( SVsShellDebugger ) ) ;
104- var debugMode = new DBGMODE [ 1 ] ;
88+ showProgress : false ) ;
10589
106- var cancellationToken = context . UserCancellationToken ;
107- if ( ErrorHandler . Succeeded ( debugger . GetMode ( debugMode ) ) && debugMode [ 0 ] != DBGMODE . DBGMODE_Design )
108- {
109- 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 ] ;
11098
111- var textSnapshot = subjectBuffer . CurrentSnapshot ;
112- var document = textSnapshot . GetOpenDocumentInCurrentContextWithChanges ( ) ;
99+ var textSnapshot = subjectBuffer . CurrentSnapshot ;
100+ var document = textSnapshot . GetOpenDocumentInCurrentContextWithChanges ( ) ;
113101
114- if ( document != null )
102+ if ( document != null )
103+ {
104+ var languageDebugInfo = document . Project . Services . GetService < ILanguageDebugInfoService > ( ) ;
105+ if ( languageDebugInfo != null )
115106 {
116- var languageDebugInfo = document . Project . Services . GetService < ILanguageDebugInfoService > ( ) ;
117- if ( languageDebugInfo != null )
107+ var spanOpt = textSnapshot . TryGetSpan ( textSpan ) ;
108+ if ( spanOpt . HasValue )
118109 {
119- var spanOpt = textSnapshot . TryGetSpan ( textSpan ) ;
120- 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 )
121115 {
122- // 'kind' is an lsp-only concept, so we don't want/need to include it here (especially
123- // as it can be expensive to compute, and we don't want to block the UI thread).
124- var dataTipInfo = languageDebugInfo . GetDataTipInfoAsync (
125- document , spanOpt . Value . Start , includeKind : false , cancellationToken ) . WaitAndGetResult ( cancellationToken ) ;
126- if ( ! dataTipInfo . IsDefault )
127- {
128- var resultSpan = dataTipInfo . Span . ToSnapshotSpan ( textSnapshot ) ;
129- var textOpt = dataTipInfo . Text ;
116+ var resultSpan = dataTipInfo . Span . ToSnapshotSpan ( textSnapshot ) ;
117+ var textOpt = dataTipInfo . Text ;
130118
131- pSpan [ 0 ] = resultSpan . ToVsTextSpan ( ) ;
132- result = debugger . GetDataTipValue ( ( IVsTextLines ) vsBuffer , pSpan , textOpt , out pbstrTextInternal ) ;
133- }
119+ pSpan [ 0 ] = resultSpan . ToVsTextSpan ( ) ;
120+ result = debugger . GetDataTipValue ( ( IVsTextLines ) vsBuffer , pSpan , textOpt , out pbstrText ) ;
134121 }
135122 }
136123 }
137124 }
138- } ) ;
125+ }
139126
140- pbstrText = pbstrTextInternal ;
141- return result ;
127+ return ( pbstrText , result ) ;
142128 }
143129 }
144130
145131 int IVsTextViewFilter . GetPairExtents ( int iLine , int iIndex , TextSpan [ ] pSpan )
146132 {
147- try
148- {
149- var result = VSConstants . S_OK ;
150- ComponentModel . GetService < IUIThreadOperationExecutor > ( ) . Execute (
151- "Intellisense" ,
152- defaultDescription : "" ,
153- allowCancellation : true ,
154- showProgress : false ,
155- action : c => result = GetPairExtentsWorker ( iLine , iIndex , pSpan , c . UserCancellationToken ) ) ;
156-
157- return result ;
158- }
159- catch ( Exception e ) when ( FatalError . ReportAndCatch ( e ) && false )
160- {
161- throw ExceptionUtilities . Unreachable ( ) ;
162- }
133+ return this . ThreadingContext . JoinableTaskFactory . Run ( ( ) => GetPairExtentsAsync ( iLine , iIndex , pSpan ) ) ;
163134 }
164135
165- private int GetPairExtentsWorker ( int iLine , int iIndex , TextSpan [ ] pSpan , CancellationToken cancellationToken )
136+ private async Task < int > GetPairExtentsAsync ( int iLine , int iIndex , TextSpan [ ] pSpan )
166137 {
138+ using var waitContext = ComponentModel . GetService < IUIThreadOperationExecutor > ( ) . BeginExecute (
139+ "Intellisense" ,
140+ defaultDescription : "" ,
141+ allowCancellation : true ,
142+ showProgress : false ) ;
143+
167144 var braceMatcher = ComponentModel . GetService < IBraceMatchingService > ( ) ;
168145 var globalOptions = ComponentModel . GetService < IGlobalOptionService > ( ) ;
169- return GetPairExtentsWorker (
146+
147+ return await GetPairExtentsAsync (
170148 WpfTextView ,
171149 braceMatcher ,
172150 globalOptions ,
173151 iLine ,
174152 iIndex ,
175153 pSpan ,
176154 ( VSConstants . VSStd2KCmdID ) this . CurrentlyExecutingCommand == VSConstants . VSStd2KCmdID . GOTOBRACE_EXT ,
177- cancellationToken ) ;
155+ waitContext . UserCancellationToken ) . ConfigureAwait ( true ) ;
178156 }
179157
180158 // Internal for testing purposes
181- internal static int GetPairExtentsWorker ( ITextView textView , IBraceMatchingService braceMatcher , IGlobalOptionService globalOptions , int iLine , int iIndex , TextSpan [ ] pSpan , bool extendSelection , CancellationToken cancellationToken )
159+ internal static async Task < int > GetPairExtentsAsync (
160+ ITextView textView ,
161+ IBraceMatchingService braceMatcher ,
162+ IGlobalOptionService globalOptions ,
163+ int iLine ,
164+ int iIndex ,
165+ TextSpan [ ] pSpan ,
166+ bool extendSelection ,
167+ CancellationToken cancellationToken )
182168 {
183169 pSpan [ 0 ] . iStartLine = pSpan [ 0 ] . iEndLine = iLine ;
184170 pSpan [ 0 ] . iStartIndex = pSpan [ 0 ] . iEndIndex = iIndex ;
@@ -202,7 +188,8 @@ internal static int GetPairExtentsWorker(ITextView textView, IBraceMatchingServi
202188 if ( document != null )
203189 {
204190 var options = globalOptions . GetBraceMatchingOptions ( document . Project . Language ) ;
205- var matchingSpan = braceMatcher . FindMatchingSpanAsync ( document , position , options , cancellationToken ) . WaitAndGetResult ( cancellationToken ) ;
191+ var matchingSpan = await braceMatcher . FindMatchingSpanAsync (
192+ document , position , options , cancellationToken ) . ConfigureAwait ( true ) ;
206193
207194 if ( matchingSpan . HasValue )
208195 {
@@ -236,7 +223,8 @@ internal static int GetPairExtentsWorker(ITextView textView, IBraceMatchingServi
236223 if ( extendSelection )
237224 {
238225 // case a.
239- var closingSpans = braceMatcher . FindMatchingSpanAsync ( document , matchingSpan . Value . Start , options , cancellationToken ) . WaitAndGetResult ( cancellationToken ) ;
226+ var closingSpans = await braceMatcher . FindMatchingSpanAsync (
227+ document , matchingSpan . Value . Start , options , cancellationToken ) . ConfigureAwait ( true ) ;
240228 var vsClosingSpans = textView . GetSpanInView ( closingSpans . Value . ToSnapshotSpan ( subjectBuffer . CurrentSnapshot ) ) . First ( ) . ToVsTextSpan ( ) ;
241229 pSpan [ 0 ] . iEndIndex = vsClosingSpans . iStartIndex ;
242230 }
@@ -255,7 +243,8 @@ internal static int GetPairExtentsWorker(ITextView textView, IBraceMatchingServi
255243 pSpan [ 0 ] . iEndIndex = vsTextSpan . iStartIndex ;
256244
257245 // case b.
258- var openingSpans = braceMatcher . FindMatchingSpanAsync ( document , matchingSpan . Value . End , options , cancellationToken ) . WaitAndGetResult ( cancellationToken ) ;
246+ var openingSpans = await braceMatcher . FindMatchingSpanAsync (
247+ document , matchingSpan . Value . End , options , cancellationToken ) . ConfigureAwait ( true ) ;
259248 var vsOpeningSpans = textView . GetSpanInView ( openingSpans . Value . ToSnapshotSpan ( subjectBuffer . CurrentSnapshot ) ) . First ( ) . ToVsTextSpan ( ) ;
260249 pSpan [ 0 ] . iStartIndex = vsOpeningSpans . iStartIndex ;
261250 }
0 commit comments