【问题标题】:Visual Studio 2010 SDK -- How to place an adornment next to XML comment groups?Visual Studio 2010 SDK -- 如何在 XML 注释组旁边放置一个装饰?
【发布时间】:2014-08-13 15:30:09
【问题描述】:

我很难找到如何执行此操作,而且 Visual Studio SDK 参考也不是很有帮助。

我正在尝试弄清楚如何获得NormalizedSnapshotSpanCollection 的 XML cmets。我想在它们旁边放一个图标...我不想在每行旁边放一个图标,而只希望在每组的第一行旁边...

///<summary>SomeXML Comment</summary>   [ICON]
///<remarks>some remarks</remarks>
public void Foo()
{
    ///Some false XML comment line that does not get an icon.
}

【问题讨论】:

  • 很遗憾,我想我不能给你一个完整的答案,但是我可以指出你至少需要了解 IAdornmentLayer 的方向(这就是你在看法)。视图本身是一种 IWpfTextView。这是在屏幕上绘制实际图标的部分。找出我无法帮助您的确切位置,因为我不知道如何发现 xml 注释块的右上角,更不用说专门位于方法/字段/属性/类/等上方的位置了。
  • 为什么需要 NormalizedSnapshotSpanCollection?你知道你可以从 IWpfTextView 获取当前编辑器缓冲区的所有行,并使用简单的正则表达式找到所有匹配 ///whatever 行然后添加一个图标,(在你的装饰层),在你想要在那条线上的坐标?
  • 不,我不知道。我刚刚看到一个使用 NormalizedSnapshotSpancollection 的示例,所以我认为我需要它......基本上,任何能给我我需要的坐标而不会误报的东西,所以我可以在需要的地方放一个图标。

标签: c# visual-studio-2010 xml-comments visual-studio-sdk adornment


【解决方案1】:

这是我能得到的,我认为它与您需要的非常相似。如果您有任何疑问,我将更新此内容并提供更多详细信息。

我从 VS 2010 SDK 网站的 this sample 开始。它已经非常接近您的需要,但还需要几个步骤。


下载C#版本,解压到文件夹,编译。要运行它并进行测试,您需要转到 Project > Properties > Debug

您需要选择“启动外部程序”选项并设置您的 VS 2010 应用程序的路径,例如 C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe

在命令行参数集中:/rootsuffix Exp

现在您应该可以运行它了,在打开的 VS 中创建一些示例项目,如果您在任何地方键入一个六位数的数字,例如 00AA00,它将显示为一个具有相应颜色的矩形。关闭调试 VS 实例。


现在让我们编辑一些代码。在ColorAdornmentTagger.cs 中评论定义#define HIDING_TEXT。这将在文本旁边显示装饰,而不是代替它。

在同一个文件中,您需要找到SnapshotSpan adornmentSpan 的初始化位置并将行更改为:

SnapshotSpan adornmentSpan = new SnapshotSpan(colorTagSpans[0].End, 0);

这会将装饰放置在文本跨度之后,而不是之前。


ColorTagger.cs。更改构造函数中的正则表达式,使构造函数现在看起来像

    internal ColorTagger(ITextBuffer buffer)
        : base(
        buffer, 
        new[] { new Regex(@"/// <summary>.*", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) }
        )
    {
    }

这将设置正则表达式以识别方法注释行。

这个类中的其他方法我们不会用到,你可以评论它们或者返回一些随机的颜色。


在“ColorAdornment.cs”中。这是装饰 WPF 控件本身。首先将基类从Button 更改为ContentControl。将类的构造函数改为

    internal ColorAdornment(ColorTag colorTag)
    {
        BitmapImage image = new BitmapImage(); 
        using (FileStream stream = File.OpenRead("c:\\temp\\sologo.png")) 
        { 
            image.BeginInit(); 
            image.StreamSource = stream; 
            image.CacheOption = BitmapCacheOption.OnLoad; 
            image.EndInit(); 
        }

        this.Content = new Image() { Margin = new Thickness(20,0,0,0), Width = 100, Height = 30, Source = image };
    }

您可以将图片路径更改为您需要的图片路径。我刚刚从 Wikipedia 下载了 SO 徽标并放入了我的临时文件夹。

编译并运行。您应该能够在调试 VS 实例中的 cmets 旁边看到 SO 徽标。


一些额外的说明。

首先,通过这种方式,您只需得到一个工作原型,您应该重命名类并根据需要清理代码。

其次,当我调试它时,我的调试 VS 不时冻结。我认为这可能与IntraTextAdornmentTagger.cs中的锁有关

如果你也看到卡顿,尝试用这种方式更新下面的方法:

    protected void InvalidateSpans(IList<SnapshotSpan> spans)
    {
        if (spans.Count == 0)
            return;
        bool wasEmpty = false;
        lock (this.invalidatedSpans)
        {
            wasEmpty = this.invalidatedSpans.Count == 0;
            this.invalidatedSpans.AddRange(spans);
        }

        if (wasEmpty)
            this.view.VisualElement.Dispatcher.BeginInvoke(new Action(AsyncUpdate));
    }

和这样的AsyncUpdate:

    private void AsyncUpdate()
    {
        // Store the snapshot that we're now current with and send an event
        // for the text that has changed.
        if (this.snapshot != this.view.TextBuffer.CurrentSnapshot)
        {
            this.snapshot = this.view.TextBuffer.CurrentSnapshot;

            Dictionary<SnapshotSpan, TAdornment> translatedAdornmentCache = new Dictionary<SnapshotSpan, TAdornment>();

            foreach (var keyValuePair in this.adornmentCache)
                translatedAdornmentCache.Add(keyValuePair.Key.TranslateTo(this.snapshot, SpanTrackingMode.EdgeExclusive), keyValuePair.Value);

            this.adornmentCache = translatedAdornmentCache;
        }

        List<SnapshotSpan> spansCopy;
        lock (this.invalidatedSpans)
        {
            spansCopy = this.invalidatedSpans.ToList();
            this.invalidatedSpans.Clear();
        }

        List<SnapshotSpan> translatedSpans = spansCopy.Select(s => s.TranslateTo(this.snapshot, SpanTrackingMode.EdgeInclusive)).ToList();

        if (translatedSpans.Count == 0)
            return;

        var start = translatedSpans.Select(span => span.Start).Min();
        var end = translatedSpans.Select(span => span.End).Max();

        RaiseTagsChanged(new SnapshotSpan(start, end));
    }

【讨论】:

  • 嗯,这绝对是一个很好的起点。我希望有某种算法来检测注释块是否位于有效类、枚举、结构、属性、字段、方法等之上,但这个算法与我现在想得到的一样接近。它依赖/// &lt;summary&gt;*这一事实存在一些漏洞,因为我可以将其放在其他地方并得到误报(我知道这样做没有意义)。无论哪种方式,全 +200 以提供很多帮助。
  • 另外,为什么我需要 /rootsuffix Exp 参数来调用 devenv.exe?
  • @michael:谢谢! /rootsuffix Exp 是为了保护您的实验中的默认 VS msdn.microsoft.com/en-us/library/bb166560(v=VS.80).aspx
  • @michael:关于误报,您是对的(尽管在其他任何地方都不太可能看到该字符串),您可以尝试通过匹配类名、枚举、字段来提出更好的正则表达式,或者这样...另一个选择是探索SDK文档,我认为有一种方法可以使用编辑器的知识,了解文本的哪个部分属于程序中的哪个类型。也许有一种方法可以检测字段或类的注释在哪里......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-02
  • 1970-01-01
  • 2011-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多