为什么这个画装饰品两次? (Visual Studio扩展)

时间:2016-01-10 07:26:27

标签: c# .net visual-studio visual-studio-extensions

我正在创建一个扩展程序,围绕某些令牌绘制装饰,并提出下面的代码。只要代码在一行上,它就可以正常工作。只要我添加一个新行,就会在每次按键或滚动(LayoutChanged事件)时在现有装饰品上重复绘制装饰品。

我可能做错了什么?另外,我在下面提出了自己的代码,因此可能存在根本性的错误。

private void CreateVisuals(ITextViewLine line)
{
    var textViewLines = _wpfTextView.TextViewLines;
    var text = line.Snapshot.GetText();
    //var text = textViewLines.FormattedSpan.Snapshot.GetText();
    var todoRegex = new Regex(@"\/\/\s*TODO\b");
    var match = todoRegex.Match(text);
    while (match.Success)
    {
        var matchStart = match.Index;
        var span = new SnapshotSpan(_wpfTextView.TextSnapshot, Span.FromBounds(matchStart, matchStart + match.Length));
        DrawAdornment(textViewLines, span);
        match = match.NextMatch();
    }
}

1 个答案:

答案 0 :(得分:1)

因此,如果您在LayoutChanged期间添加装饰品,则只需为正在布局的文本添加装饰品。您可以从TextViewLayoutChangedEventArgs.NewOrReformattedLines获取正在中继的行列表。如果您通过VSSDK模板创建新的文本装饰,您将看到如何完成。

只要编辑器需要布局某些行,就会引发LayoutChanged事件,但并不总是要排列所有行。例如,在滚动时,它只需要计算滚动到视图中的行的布局。如果插入/删除行,则不必向上或向下移动其他行。

(与您的问题无关,但仍然很重要:调用ITextSnapshot.GetText()的速度非常慢。如果您打开了一个多兆字节的文件,这将需要我们分配一个非常慢的字符串。实践中,GetText()应该只用于调试。如果您正在寻找TODO注释,并且您可以将其限制为Visual Studio 2015中的C#或VB代码,那么您真的应该查看Roslyn,它可以让您访问语法树信息。)