为什么在修改本地数据时收益不起作用?

时间:2019-06-12 14:59:56

标签: c# visual-studio-extensions

我正在编写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指令上)。

我有什么想念的吗?使用收益回报时是否禁止修改本地数据?是否存在一些隐藏的并发问题?感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我终于发现我没有正确扫描NormalizedSnapshotSpanCollection跨度给出的行。我错误地在Type中重复了每个跨度的所有行。实际上,我需要获取与给定跨度关联的行号,现在它可以工作了:

  • 我在分析的每一行上都适当地获得了边距字形。
  • 在具有边距字形的行之前添加新行时,我再也没有重复了。

因此我的解决方法是:

foreach (ITextSnapshotLine textSnapshotLine in textSnapshot.Lines)