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, которые могут быть причиной этого.

Спасибо,


person alexand256    schedule 07.11.2015    source источник


Ответы (3)


Я столкнулся с той же проблемой, хотя и в другом контексте. Судя по моим гуглениям, они изменили классификаторы, так что они лениво инициализируются... и я думаю, что 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), но результаты оказались достаточно хорошими для моего приложения.

person ijprest    schedule 05.01.2016

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

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

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

person alexand256    schedule 07.11.2015
comment
Переход между версиями SDK DLL не должен был иметь никакого эффекта — вы по-прежнему вызываете один и тот же код, когда фактически работаете в Visual Studio. - person Jason Malinowski; 10.11.2015

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

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

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

person Jason Malinowski    schedule 10.11.2015