I have a tagger (subclass of ITagger) and I'm trying to call GetClassificationSpans so I can use the classifications to find comments to format using tags. This worked in Visual Studio 2013, but now when running it in Visual Studio 2015, GetClassificationSpans always returns an empty list - even when I've examined the span in the debugger and it is definitely passing a span with a comment in it.
Does anyone know what could have changed in 2015 in regards to calling GetClassificationSpans?
BTW: I'm getting the classifier by importing the IClassifierAggregatorService in my tagger provider (subclass of ITaggerProvider) and passing it along to the constructor of the tagger:
[import]
IClassifierAggregatorService aggregator;
Then I use the following call in the tagger on the aggregator that I got from the provider:
IList<ClassificationSpan> lstClassifiers = aggregator.GetClassifier(span.Snapshot.TextBuffer).GetClassificationSpans(span);
And, as I said, the lstClassifiers list is always empty. The exact same code ran find in VS2013. I can't seem to find anything on the net that mentions any changes in VS2015 that may be causing this.
Thanks,
Well. After trying different things, it looks like it was several problems:
Hope that helps anyone that runs into the same issue.
So in general, the ITagger API doesn't mandate that a tagger returns the "real" information. Instead, it is an API that returns "whatever information you had at that point". If the buffers that are giving you trouble are C# or VB buffers, it's because in VS2015 we moved everything in Roslyn to be asynchronous, and so a call to GetClassificationSpans/GetTags might not return anything until we've recomputed the data. There's a new API, IAccurateTagger, that exists to request that taggers give "real" data, although that's not something you want to be running in text buffer changes since you'll kill performance.
If you are trying to find comments in VS2015 and the files that are tripping you up are C# or VB buffers, you're best off calling Roslyn APIs which give you the direct syntax tree data that you need. If it's a different type of buffer, you're at least better off calling IAccurateTagger, but try doing that as carefully as you can because of performance ramifications.
(Also, if you're trying to build an extension which auto-formats as you type, using the classification taggers will give you other headaches. There were bugs in VS2013 you'll have to work around where C# would give stale tags if you called it during a tags changed.)
I ran into the same problem, though in a different context. From my googling, it looks like they've changed the classifiers so that they're lazily initialized... and I guess
GetClassificationSpans()
won't forceably initialize them. MSFT still considers this a bug, so you might want to up-vote the issue on VS Connect.A potential workaround (as suggested by MSFT) is to switch to using
TagAggregator
instead ofIClassifier
. So instead of:You can instead write something like this:
This returns a list of
IMappingTagSpan<IClassificationTag>
instead of a list ofClassificationSpan
, so the way you'll work with them is slightly different. But the underlying data appears to be mostly the same---i.e., you can get a classification and span for each lexical element. There are some subtle differences (see the description on VS Connect), but the results were good enough for my application.