我正在编写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;
}
}
奇怪的是,当注释掉“ rendered = true”行时,yield会正常返回(尽管我得到了错误的新字形)。当运行line rendering = true时,产量似乎被阻止了(调试器仍然踩在yield指令上)。
我有什么想念的吗?使用收益回报时是否禁止修改本地数据?是否存在一些隐藏的并发问题?感谢您的帮助!
答案 0 :(得分:0)
我终于发现我没有正确扫描NormalizedSnapshotSpanCollection跨度给出的行。我错误地在Type
中重复了每个跨度的所有行。实际上,我需要获取与给定跨度关联的行号,现在它可以工作了:
因此我的解决方法是:
foreach (ITextSnapshotLine textSnapshotLine in textSnapshot.Lines)