65.9K
CodeProject 正在变化。 阅读更多。
Home

Visual Studio 2010 的代码拼写检查器扩展 (VSX)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.98/5 (41投票s)

2010年4月1日

CPOL

6分钟阅读

viewsIcon

115955

downloadIcon

2418

构建一个源代码拼写检查器,作为 Visual Studio 2010 的扩展

引言

我坚信应用程序的质量取决于是否使用了正确的拼写和语法。有人可能会争辩说这是吹毛求疵,并且效率比这更重要。虽然效率很重要,但必须记住,任何一行代码被阅读的次数都比编写它的次数多。

好的程序由于程序员的疏忽不应包含语言错误。编写的代码需要在各个级别上都是正确的,从设计、名称的正确性和一致性,一直到注释中的标点符号。

并非每个人都以英语为母语,包括我自己,而且还有一些有特定障碍的人,例如阅读或书写标准英语有困难的阅读障碍者。这并不是说这些人不能编写出好的应用程序。我想说的是,编写的代码应该传达作者的意图。

为了实现这一点,我认为编写一个 Visual Studio 2010 的拼写检查扩展会很有趣,它具有以下功能:

  • 检查(XML)注释中的单词拼写
  • 使用 MS.NET 命名约定检查声明中的名称拼写
  • 检查字符串字面量中的单词拼写
  • 用红色波浪线标记拼写错误的单词
  • 为拼写错误的单词提供建议列表
  • 拼写错误的单词可以添加到自定义词典中
  • 自定义词典保存在源代码树中。这样可以方便地进行源代码控制,并在团队合作的情况下在团队之间同步。

第一步:在文本上添加红色波浪线

事实证明这非常容易。首先使用项目模板来熟悉 MEF (Managed Extension Framework) 的一些基本属性。

Visual Studio 2010 有一个称为“标记”的机制,订阅者可以在其中向文本块添加元数据。重要的概念包括:

  • Span,本质上是文本内的坐标(起始点 + 长度)
  • ITagger,它告诉 IDE 在哪里放置标记
  • ITag,它告诉 IDE 渲染什么(IErrorTag 被渲染为红色波浪线)
  • TagSpanTagSpan 的组合,即“在哪里”和“什么”

interface ITagger<IErrorTag> 有一个名为 GetTags 的方法,该方法接受一个 span 集合,并必须返回一个 TagSpan 对象枚举。提供的 span 集合标记了 IDE 感兴趣的区域。这可能是因为用户已更改或以其他方式触发了视图中的更改,因此需要重新标记。

下面的示例代码展示了此方法的实现,该方法在每个“A”下添加一个波浪线。这些波浪线还将“C”显示为伴随的工具提示。

public IEnumerable<ITagSpan<IErrorTag>> GetTags (NormalizedSnapshotSpanCollection spans)
{
    foreach (var span in spans)
    {
        var text = span.Snapshot.GetText (span);
        for (int i = 0; i < text.Length; i++)
        {
            if (text[i] == 'A')
            {
                yield return new TagSpan<ErrorTag>
                (
                    new SnapshotSpan
                    (
                        span.Snapshot,
                        span.Start + i,
                        1
                    ),
                    new ErrorTag ("B", "C")
                );
            }
        }
    }
}

第二步:为文本块添加上下文菜单标记(也称为智能标签)

这同样非常容易。通过使用相同的 ITagger 接口来实现,这次使用 SmartTag 类作为类型参数。SmartTag 是动作(分组在集合中)的占位符。用户会通过一个小的蓝色矩形提示其存在。当用户将鼠标悬停在矩形上时,它会显示一个包含可用动作的下拉列表。

ISmartTagAction 接口有两个重要成员:

  • DisplayText 属性,显示在下拉列表中的用户
  • Invoke 方法,提供实际实现

第三步:检查拼写

我记得 WPF 的一个功能就是拼写检查,于是决定研究一下这是否足够。尽管在 WPF 4.0 中增加了对自定义词典的支持,但仅限于英语、法语、德语和西班牙语。这不是问题,因为 Microsoft .NET 命名指南规定标识符应以英语声明。

然而,实际实现被隐藏了(标记为内部),我可以通过反射来 hack 它,或者在底层使用实际的 WPF 文本框。**提示**:当您使用 WPF 文本框时,如果用户使用的输入语言区域与前面提到的语言(+方言)不同,拼写检查器会自动禁用。您可以使用附加属性“xml:lang”和 ISO 3166 代码,例如“en-us”或“en-gb”,将此用户设置覆盖为特定语言。

我在这两种策略上都挣扎了一段时间,最终得出结论,它们都缺乏我所寻找的东西……因此,我决定寻找替代方案,并偶然发现了“Hunspell”,这是一个开源的拼写检查库,目前被 Open Office、Firefox 等使用。它附带了大量的词典,并且还具有同义词、连字符和语法功能。

不幸的是,它没有作为 COM 暴露,所以无法进行标准的 PInvoke。使用一些老式的 *kernel32.dll* 技巧,我们可以加载和卸载该库。但真正的魔法在于 GetProcAddress 结合 Marshal.GetDelegateForFunctionPointer 允许您创建一个可以调用该库的委托。(更多详细信息,请查看 Hunspell 命名空间。)

第四步:获取需要检查拼写的代码片段

Roman Golovin 和 Noah Richards 创建的拼写检查器使用了一种有趣的技术。这个拼写检查器是/将是 VS SDK 的一部分,并使用一个称为分类器的服务。语言服务使用此机制根据文本的上下文和通用含义对其进行分类。我猜测这被用于语法着色过程。

不幸的是,它在声明名称与使用名称之间没有提供任何细节。因此,我决定自己构建 C# 扫描器和简单的解析器(因为这是我选择的语言)。尽管扫描器和词法标记已完成,但解析器的目的是仅正确识别所有不同类型的名称声明。

屏幕截图

从这个截图可以看出,“misspellled”(有 3 个 L)和 Namespace 都被标记了。它还显示了命名空间、别名和委托(带参数和默认值)的声明。

SpellSharp1.jpg

通过将鼠标悬停在智能标签指示器(蓝色矩形)上,下拉菜单将变得可见。

SpellSharp2.jpg

添加到自定义词典的第一个单词会导致 CustomWords.txt 文件被添加到解决方案的“Solution items”标准文件夹中。

SpellSharp3.jpg

带属性和注释的枚举

SpellSharp4.jpg

带各种成员的接口

SpellSharp5.jpg

带各种成员的类

SpellSharp6.jpg

已知bug

  • 未处理 C# 预编译器指令(已修复)

未来版本

  • 包含单元测试
  • 添加 MSBuild 任务
  • 添加一个 VS 命令,用于扫描解决方案中的所有文件,类似于查找/替换方法
  • 添加 (T) SQL 语言支持
  • 添加 VB.NET 语言支持
  • 添加 F# 语言支持
  • 使用托管拼写检查器,也许自己写一个玩
  • 建议或错误?
© . All rights reserved.