22
33using System ;
44using System . Collections . Generic ;
5- using System . Linq ;
65using System . Threading ;
76using System . Threading . Tasks ;
87using Microsoft . CodeAnalysis . Classification ;
98using Microsoft . CodeAnalysis . Editor . Shared . Extensions ;
109using Microsoft . CodeAnalysis . Editor . Shared . Tagging ;
1110using Microsoft . CodeAnalysis . Editor . Shared . Threading ;
1211using Microsoft . CodeAnalysis . Editor . Shared . Utilities ;
13- using Microsoft . CodeAnalysis . Host ;
14- using Microsoft . CodeAnalysis . Host . Mef ;
1512using Microsoft . CodeAnalysis . Internal . Log ;
13+ using Microsoft . CodeAnalysis . Shared . Extensions ;
1614using Microsoft . CodeAnalysis . Shared . TestHooks ;
1715using Microsoft . CodeAnalysis . Text ;
1816using Microsoft . CodeAnalysis . Text . Shared . Extensions ;
1917using Microsoft . VisualStudio . Text ;
20- using Microsoft . VisualStudio . Text . Editor ;
2118using Microsoft . VisualStudio . Text . Tagging ;
2219using Roslyn . Utilities ;
2320
@@ -59,23 +56,13 @@ internal partial class TagComputer
5956 private ITextSnapshot _lastParsedSnapshot ;
6057 private Document _lastParsedDocument ;
6158
62- private bool _isClassificationOnlyWorkspace ;
6359 private Workspace _workspace ;
6460 private CancellationTokenSource _reportChangeCancellationSource ;
6561
6662 private readonly IAsynchronousOperationListener _listener ;
6763 private readonly IForegroundNotificationService _notificationService ;
6864 private readonly ClassificationTypeMap _typeMap ;
6965 private readonly SyntacticClassificationTaggerProvider _taggerProvider ;
70- private readonly IEditorClassificationService _editorClassificationService ;
71- private readonly IViewSupportsClassificationService _viewSupportsClassificationServiceOpt ;
72- private readonly ITextBufferAssociatedViewService _associatedViewService ;
73-
74- private readonly string _languageName ;
75-
76- // Not all buffers with a matching content type should be tagged, but determining this
77- // can be expensive.
78- private bool ? _cachedTaggableStatus ;
7966
8067 private int _taggerReferenceCount ;
8168
@@ -84,21 +71,13 @@ public TagComputer(
8471 IForegroundNotificationService notificationService ,
8572 IAsynchronousOperationListener asyncListener ,
8673 ClassificationTypeMap typeMap ,
87- SyntacticClassificationTaggerProvider taggerProvider ,
88- IViewSupportsClassificationService viewSupportsClassificationServiceOpt ,
89- ITextBufferAssociatedViewService associatedViewService ,
90- IEditorClassificationService editorClassificationService ,
91- string languageName )
74+ SyntacticClassificationTaggerProvider taggerProvider )
9275 {
9376 _subjectBuffer = subjectBuffer ;
9477 _notificationService = notificationService ;
9578 _listener = asyncListener ;
9679 _typeMap = typeMap ;
9780 _taggerProvider = taggerProvider ;
98- _viewSupportsClassificationServiceOpt = viewSupportsClassificationServiceOpt ;
99- _associatedViewService = associatedViewService ;
100- _editorClassificationService = editorClassificationService ;
101- _languageName = languageName ;
10281
10382 _workQueue = new AsynchronousSerialWorkQueue ( asyncListener ) ;
10483 _reportChangeCancellationSource = new CancellationTokenSource ( ) ;
@@ -108,7 +87,10 @@ public TagComputer(
10887 _workspaceRegistration = Workspace . GetWorkspaceRegistration ( subjectBuffer . AsTextContainer ( ) ) ;
10988 _workspaceRegistration . WorkspaceChanged += OnWorkspaceRegistrationChanged ;
11089
111- ConnectToWorkspace ( _workspaceRegistration . Workspace ) ;
90+ if ( _workspaceRegistration . Workspace != null )
91+ {
92+ ConnectToWorkspace ( _workspaceRegistration . Workspace ) ;
93+ }
11294 }
11395
11496 private void OnWorkspaceRegistrationChanged ( object sender , EventArgs e )
@@ -153,92 +135,47 @@ private void ConnectToWorkspace(Workspace workspace)
153135 ResetLastParsedDocument ( ) ;
154136
155137 _workspace = workspace ;
138+ _workspace . WorkspaceChanged += this . OnWorkspaceChanged ;
139+ _workspace . DocumentOpened += this . OnDocumentOpened ;
140+ _workspace . DocumentActiveContextChanged += this . OnDocumentActiveContextChanged ;
156141
157- if ( _workspace != null )
158- {
159- _isClassificationOnlyWorkspace = false ;
160- _workspace . WorkspaceChanged += this . OnWorkspaceChanged ;
161- _workspace . DocumentOpened += this . OnDocumentOpened ;
162- _workspace . DocumentActiveContextChanged += this . OnDocumentActiveContextChanged ;
163-
164- var textContainer = _subjectBuffer . AsTextContainer ( ) ;
142+ var textContainer = _subjectBuffer . AsTextContainer ( ) ;
165143
166- var documentId = _workspace . GetDocumentIdInCurrentContext ( textContainer ) ;
167- if ( documentId != null )
168- {
169- var document = workspace . CurrentSolution . GetDocument ( documentId ) ;
170- if ( document != null )
171- {
172- EnqueueParseSnapshotTask ( document ) ;
173- return ;
174- }
175- }
176- }
177- else
144+ var documentId = _workspace . GetDocumentIdInCurrentContext ( textContainer ) ;
145+ if ( documentId != null )
178146 {
179- // This buffer isn't being tracked by any workspace. In Visual Studio, this
180- // can happen if it is not in the Running Document Table. We'll try to do
181- // basic syntax classification based on the initial state of the snapshot.
182- // Changes to the buffer are not observed, but initial tags will track forward.
183-
184- _isClassificationOnlyWorkspace = true ;
185- if ( _languageName != null )
147+ var document = workspace . CurrentSolution . GetDocument ( documentId ) ;
148+ if ( document != null )
186149 {
187- _workspace = new AdhocWorkspace ( ) ;
188- var solution = _workspace . CreateSolution ( SolutionId . CreateNewId ( ) ) ;
189- var project = solution . AddProject ( name : string . Empty , assemblyName : string . Empty , language : _languageName ) ;
190-
191- var parsedSnapshot = _subjectBuffer . CurrentSnapshot ;
192- var document = project . AddDocument ( name : string . Empty , text : _subjectBuffer . CurrentSnapshot . AsText ( ) ) ;
193-
194- EnqueueParseSnapshotTask ( document , parsedSnapshot ) ;
195- return ;
150+ EnqueueParseSnapshotTask ( document ) ;
196151 }
197152 }
198153 }
199154
200155 public void DisconnectFromWorkspace ( )
201156 {
202- if ( _isClassificationOnlyWorkspace )
203- {
204- _workspace . Dispose ( ) ;
205- _workspace = null ;
206- _isClassificationOnlyWorkspace = false ;
207- }
208- else if ( _workspace != null )
157+ if ( _workspace != null )
209158 {
210159 _workspace . WorkspaceChanged -= this . OnWorkspaceChanged ;
211160 _workspace . DocumentOpened -= this . OnDocumentOpened ;
212161 _workspace . DocumentActiveContextChanged -= this . OnDocumentActiveContextChanged ;
213162
214163 _workspace = null ;
215- }
216164
217- ResetLastParsedDocument ( ) ;
165+ ResetLastParsedDocument ( ) ;
166+ }
218167 }
219168
220169 private void EnqueueParseSnapshotTask ( Document newDocument )
221170 {
222- Contract . Assert ( ! _isClassificationOnlyWorkspace , "classification-only workspaces must provide the corresponding snapshot" ) ;
223-
224- _workQueue . EnqueueBackgroundTask (
225- c => this . EnqueueParseSnapshotWorkerAsync ( newDocument , c ) ,
226- GetType ( ) + ".EnqueueParseSnapshotTask.1" ,
227- CancellationToken . None ) ;
228- }
229-
230- private void EnqueueParseSnapshotTask ( Document newDocument , ITextSnapshot snapshot )
231- {
232- _workQueue . EnqueueBackgroundTask (
233- c => this . EnqueueParseSnapshotWorkerAsync ( newDocument , snapshot , c ) ,
234- GetType ( ) + ".EnqueueParseSnapshotTask.1" ,
235- CancellationToken . None ) ;
171+ if ( newDocument != null )
172+ {
173+ _workQueue . EnqueueBackgroundTask ( c => this . EnqueueParseSnapshotWorkerAsync ( newDocument , c ) , GetType ( ) + ".EnqueueParseSnapshotTask.1" , CancellationToken . None ) ;
174+ }
236175 }
237176
238177 private async Task EnqueueParseSnapshotWorkerAsync ( Document document , CancellationToken cancellationToken )
239178 {
240- Contract . Assert ( ! _isClassificationOnlyWorkspace , "classification-only workspaces must provide the corresponding snapshot" ) ;
241-
242179 // we will enqueue new one soon, cancel pending refresh right away
243180 _reportChangeCancellationSource . Cancel ( ) ;
244181
@@ -252,14 +189,8 @@ private async Task EnqueueParseSnapshotWorkerAsync(Document document, Cancellati
252189 return ;
253190 }
254191
255- await EnqueueParseSnapshotWorkerAsync ( document , snapshot , cancellationToken ) . ConfigureAwait ( false ) ;
256- }
257-
258- private async Task EnqueueParseSnapshotWorkerAsync ( Document document , ITextSnapshot snapshot , CancellationToken cancellationToken )
259- {
260192 // preemptively parse file in background so that when we are called from tagger from UI thread, we have tree ready.
261193 var syntaxTree = await document . GetSyntaxTreeAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
262-
263194 lock ( _gate )
264195 {
265196 _lastParsedSnapshot = snapshot ;
@@ -302,37 +233,26 @@ public IEnumerable<ITagSpan<IClassificationTag>> GetTags(NormalizedSnapshotSpanC
302233 {
303234 using ( Logger . LogBlock ( FunctionId . Tagger_SyntacticClassification_TagComputer_GetTags , CancellationToken . None ) )
304235 {
305- if ( ! _cachedTaggableStatus . HasValue )
236+ if ( spans . Count > 0 && _workspace != null )
306237 {
307- if ( ! _isClassificationOnlyWorkspace )
308- {
309- _cachedTaggableStatus = true ;
310- }
311- else
238+ var firstSpan = spans [ 0 ] ;
239+ var languageServices = _workspace . Services . GetLanguageServices ( firstSpan . Snapshot . ContentType ) ;
240+ if ( languageServices != null )
312241 {
313- var wpfTextViews = _associatedViewService . GetAssociatedTextViews ( _subjectBuffer ) ;
314- if ( wpfTextViews . Any ( ) )
315- {
316- _cachedTaggableStatus = _viewSupportsClassificationServiceOpt ? . CanClassifyViews ( wpfTextViews . Cast < ITextView > ( ) ) ?? true ;
317- }
318- }
319- }
242+ var classificationService = languageServices . GetService < IEditorClassificationService > ( ) ;
320243
321- if ( _cachedTaggableStatus == false )
322- {
323- return SpecializedCollections . EmptyEnumerable < ITagSpan < IClassificationTag > > ( ) ;
324- }
244+ if ( classificationService != null )
245+ {
246+ var classifiedSpans = ClassificationUtilities . GetOrCreateClassifiedSpanList ( ) ;
325247
326- if ( spans . Count > 0 )
327- {
328- var classifiedSpans = ClassificationUtilities . GetOrCreateClassifiedSpanList ( ) ;
248+ foreach ( var span in spans )
249+ {
250+ AddClassifiedSpans ( classificationService , span , classifiedSpans ) ;
251+ }
329252
330- foreach ( var span in spans )
331- {
332- AddClassifiedSpans ( _editorClassificationService , span , classifiedSpans ) ;
253+ return ClassificationUtilities . ConvertAndReturnList ( _typeMap , spans [ 0 ] . Snapshot , classifiedSpans ) ;
254+ }
333255 }
334-
335- return ClassificationUtilities . ConvertAndReturnList ( _typeMap , spans [ 0 ] . Snapshot , classifiedSpans ) ;
336256 }
337257
338258 return SpecializedCollections . EmptyEnumerable < ITagSpan < IClassificationTag > > ( ) ;
0 commit comments