使用 Visual Studio SDK 确定插入符是否在注释块中

Determine if the caret is in a comment block with Visual Studio SDK

场景


我只想在插入符号位于 Xml 注释块中时启用自定义菜单中的命令

''' ... If caret is here, in a Vb.Net Xml comment block.

/// ... If caret is here, in a C# Xml comment block.

然后,一个预期结果的伪代码:

C#:

private void CmdExample_BeforeQueryStatus(object sender, EventArgs e) {
    // Enable this command only if the caret is in a Xml comment block.
    ((OleMenuCommand)sender).Enabled = IsCaretInXmlComment?();
}

Vb:

Private Sub CmdExample_BeforeQueryStatus(ByVal sender As Object, ByVal e As EventArgs) _
Handles cmdExample.BeforeQueryStatus

    ' Enable this command only if the caret is in a Xml comment block.
    DirectCast(sender, OleMenuCommand).Enabled = IsCaretInXmlComment?()

End Sub

问题


只是,我怎么能做到呢?。在 Vb.Net 或 C# 中。

研究


我不确定该怎么做,所以我对 vsCMElement 枚举的值进行了反复试验,因为我看到了类似的东西 here,但是 CodeElement2.Kind 属性 总是抛出一个 NullReferenceException.

C#:

TextPoint tp = 
    ((TextSelection)MyDte.ActiveDocument.Selection).ActivePoint;

CodeElement2 ce = 
    MyDte.ActiveDocument.ProjectItem.FileCodeModel.
          CodeElementFromPoint(tp, vsCMElement.vsCMElementOther);

Vb:

Dim tp As TextPoint = 
    CType(MyDte.ActiveDocument.Selection, TextSelection).ActivePoint

Dim ce As CodeElement2 =
    MyDte.ActiveDocument.ProjectItem.FileCodeModel.
          CodeElementFromPoint(tp, vsCMElement.vsCMElementOther)

我也发现了这个question,但是没有说明性的代码示例我对此很迷茫。

如果您的目标是 Visual Studio 2015 年或更高版本,最好的方法是使用 Roslyn。有了它,您可以获得语法树,然后确定您是否在评论中。如果你看看我们对 IsEntirelyWithinSingleLineDocComment 的实现,你就会明白我们今天是如何做到的。如果您是 Roslyn 的新手,已经有一些现有的问题可以帮助您获得语法树。

如果您需要定位低于该版本的版本,那么自从 Roslyn 于 2012 年首次发布以来,您就有麻烦了。一种常见的方法是询问分类信息,以确定某些内容是否是注释.分类是驱动您在编辑器中看到的文本着色的因素。如果您的文件得到 ITextBuffer,那么您可以 MEF 导入 IClassifierAggregatorService 并请求分类,然后过滤到文档注释类型。 Noah Richard's original spell check sample 是如何做到这一点的一个很好的例子。