GetClassificationSpans в Visual Studio 2015 ничего не возвращает

У меня есть тегер (подкласс ITagger), и я пытаюсь вызвать GetClassificationSpans, чтобы я мог использовать классификации, чтобы найти комментарии для форматирования с использованием тегов. Это работало в Visual Studio 2013, но теперь, когда он запускается в Visual Studio 2015, GetClassificationSpans всегда возвращает пустой список - даже когда я исследовал диапазон в отладчике, и он определенно передает диапазон с комментарием в нем.

Кто-нибудь знает, что могло измениться в 2015 году в отношении вызова GetClassificationSpans?

Кстати, я получаю классификатор, импортировав IClassifierAggregatorService в мой поставщик тегеров (подкласс ITaggerProvider) и передав его в конструктор тегера:

[import]
IClassifierAggregatorService aggregator;

Затем я использую следующий вызов в тегере на агрегаторе, который я получил от провайдера:

IList<ClassificationSpan> lstClassifiers = aggregator.GetClassifier(span.Snapshot.TextBuffer).GetClassificationSpans(span);

И, как я уже сказал, список lstClassifiers всегда пуст. Точно такой же код побежал найти в VS2013. Кажется, я не могу найти в сети ничего, что упоминало бы о каких-либо изменениях в VS2015, которые могут быть причиной этого.

Спасибо,

3 ответа

Я столкнулся с той же проблемой, хотя и в другом контексте. Из моего поиска в Google, похоже, они изменили классификаторы, так что они лениво инициализируются... и я думаю, GetClassificationSpans() не будет принудительно инициализировать их. MSFT по-прежнему считает, что это ошибка, поэтому вы можете проголосовать за эту проблему в VS Connect.

Потенциальный обходной путь (как предлагает MSFT) состоит в том, чтобы перейти к использованию TagAggregator вместо IClassifier, Так что вместо:

var service = container.GetService<IClassifierAggregatorService>();
var classifier = service.GetClassifier(textView.TextBuffer);
var spans = classifier.GetClassificationSpans(new SnapshotSpan(...));

Вместо этого вы можете написать что-то вроде этого:

var service = container.GetService<IViewTagAggregatorFactoryService>();
var aggregator = service.CreateTagAggregator<IClassificationTag>(textView);
var tags = aggregator.GetTags(new SnapshotSpan(...)));

Это возвращает список IMappingTagSpan<IClassificationTag> вместо списка ClassificationSpanТаким образом, способ работы с ними немного отличается. Но базовые данные, по-видимому, в основном одинаковы, т. Е. Вы можете получить классификацию и диапазон для каждого лексического элемента. Есть некоторые тонкие различия (см. Описание на VS Connect), но результаты были достаточно хороши для моего приложения.

Что ж. После попытки разных вещей, похоже, было несколько проблем:

  1. Порядок выполнения должен был измениться, чтобы классификации не казались настроенными до того места, где я ранее вызывал GetClassificationSpans. (В конструкторе tagger уровня буфера [а не в tagger уровня представления].) Теперь я вызываю GetCLassificationSpans только во время обработки BufferChanged/LayoutChanged. (Единственная проблема, с которой я столкнулся сейчас, заключается в том, что у меня не появляется событие BufferChanged при открытии файла. Надеюсь, это не должно быть слишком сложно, чтобы обойти это.)
  2. Кажется, это будет работать лучше, если я использую ссылку на буфер, переданную в провайдер, устанавливаю там ссылку на IClassifier и передаю ее моему тегеру вместо агрегатора (и поэтому я перестал использовать ссылку на буфер в диапазоне снимков),
  3. Я получаю гораздо лучшие результаты, обновляя свои ссылки на v14 DLL SDK из ссылок v12, которые я использовал ранее.

Надеюсь, что это помогает любому, кто сталкивается с той же проблемой.

В общем, API ITagger не требует, чтобы теггер возвращал "реальную" информацию. Вместо этого это API, который возвращает "любую информацию, которую вы имели на тот момент". Если буферы, которые доставляют вам проблемы, это буферы C# или VB, это потому, что в VS2015 мы перевели все в Roslyn на асинхронный, и поэтому вызов GetClassificationSpans/GetTags может ничего не возвращать, пока мы не пересчитаем данные. Существует новый API, IAccurateTagger, который существует, чтобы запрашивать, чтобы тэгеры выдавали "реальные" данные, хотя это не то, что вы хотите запускать в изменениях текстового буфера, так как вы снизите производительность.

Если вы пытаетесь найти комментарии в VS2015, и файлы, которые вызывают вас, являются буферами C# или VB, лучше всего вызывать API-интерфейсы Roslyn, которые предоставляют вам необходимые данные дерева прямого синтаксиса. Если это другой тип буфера, вам, по крайней мере, лучше вызвать IAccurateTagger, но постарайтесь делать это как можно осторожнее из-за снижения производительности.

(Кроме того, если вы пытаетесь создать расширение, которое автоматически форматирует при вводе, использование тегов классификации доставит вам другие головные боли. В VS2013 были ошибки, вам придется работать, где C# будет выдавать устаревшие теги, если вы назвал его во время изменения тегов.)

Другие вопросы по тегам