Я пишу расширение Visual Studio и в настоящее время добавляю глифы полей в редактор.Я начал с пошагового примера из документации MS: https://docs.microsoft.com/en-us/visualstudio/extensibility/walkthrough-creating-a-margin-glyph?view=vs-2017.
Моя логика немного отличается от примера, так как я не анализирую содержимое файла, заданное параметром spans: я уже получаюнабор результатов с местоположениями дефектов из процесса анализа ранее.И обоснование состоит в том, чтобы просто сгенерировать тег, если и только если он еще не отображен.
Действительно, я хочу избежать ложного отображения нового глифа, если пользователь добавляет новую строку на строку передсуществующий флаг.Пример: если в строке 42 есть глиф, а курсор находится в строке 41, и пользователь вводит новую строку, то в строке 42 создается новый глиф (потому что метод GetTags вызывается снова), а предыдущий глиф перемещается в строку43.
Мой код:
internal class MyDefectTagger : ITagger<MyDefectTag>
{
private IClassifier m_classifier;
private ITextBuffer m_buffer;
internal MyDefectTagger(IClassifier classifier, ITextBuffer buffer)
{
m_classifier = classifier;
m_buffer = buffer;
}
IEnumerable<ITagSpan<MyDefectTag>>
ITagger<MyDefectTag>.GetTags(NormalizedSnapshotSpanCollection spans)
{
var filename = GetFileName(m_buffer);
if (MyModel.Instance == null ||
MyModel.Instance.defectsLocation == null ||
!MyModel.Instance.defectsLocation.ContainsKey(filename))
{
yield break;
}
foreach (SnapshotSpan span in spans)
{
ITextSnapshot textSnapshot = span.Snapshot;
foreach (ITextSnapshotLine textSnapshotLine in textSnapshot.Lines)
{
var line = textSnapshotLine.LineNumber + 1; // Lines start at 1 in VS Editor
if (MyModel.Instance.defectsLocation[filename].ContainsKey(line) &&
!MyModel.Instance.defectsLocation[filename][line].rendered)
{
MyModel.Instance.defectsLocation[filename][line].rendered = true; // YIELD WORKS IF THIS LINE IS COMMENTED OUT
yield return new TagSpan<MyDefectTag>(new SnapshotSpan(textSnapshotLine.Start, 0), new MyDefectTag());
}
}
}
}
}
public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
private string GetFileName(ITextBuffer buffer)
{
buffer.Properties.TryGetProperty(typeof(ITextDocument), out ITextDocument document);
return document?.FilePath;
}
}
Странно то, что yield возвращается нормально, когда строка "rendered = true" закомментирована (хотя я получаю ложные новые глифы).В то время как выходы, кажется, заблокированы, когда строка render = true запущена (в то время как отладчик все еще выполняет команду yield).
Что-то пропущено?Запрещено ли изменять локальные данные при использовании yield return?Есть ли какая-то скрытая проблема параллелизма?Спасибо за вашу помощь!