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

Commenter - 一个帮助您注释代码的 CodeRush 插件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.62/5 (12投票s)

2004年12月8日

CPOL

16分钟阅读

viewsIcon

182379

downloadIcon

1383

编写一个CodeRush插件Commenter将帮助您注释代码,并使其更容易地浏览您的代码。

目录

引言

CommenterCodeRush 的一个插件,CodeRush 是 Visual Studio 的一个插件(支持 Visual Studio 2002、2003、2005 和 2008)。基本上,Commenter 会帮助您注释代码,使其更容易浏览您的代码。目前 Commenter 只支持 C#,但 C++ 也可能工作(但可能需要一些额外的测试)。如果有人请求,可能会添加对 VB.NET 的支持,但不知道 VB 用户是否会喜欢这样的功能。项目文件使用 Visual Studio 2003,但您也可以将其转换为 Visual Studio 2005 或 Visual Studio 2002,一切都应该正常工作。(注意:自 v1.8 起,所有文件都适用于 Visual Studio 2008。)

本文仍基于 CR_Commenter 版本 1.0,自 2004 年以来 CR_Commenter 已更新 9 次,目前版本为 1.9(2008-11-27)。有关更新的功能列表和更多截图,请查看 这篇博客文章

请务必将启动程序更改为正确的devenv.exe(用于测试)。

注意:我与 CodeRush 的开发者没有任何关系,我只是喜欢他们的工具,并认为用它编写 Visual Studio 插件更容易。

我还会介绍如何编写和使用 CodeRush 插件,似乎网上没有相关的教程。Commenter 也可以作为一个原生的 Visual Studio 插件实现,但这会更难(解析等),并且任何使用我插件的人都应该使用 CodeRush 来提高他们的开发速度。

让我们来看一些实际的代码,以及使用 Commenter 时的样子

Commenter - 功能

如上图所示,Commenter 支持多项功能。只有当您按下“}”来结束代码块时,Commenter 才会执行其工作,唯一的例外是当您双击一个自动生成的注释时,您的光标将跳转到类或方法。

下面列出了各项功能

  • 可自定义的头注释:您编辑的每个源文件中,文件顶部都会添加一个可自定义的头。这个功能的优点是,每次修改文件时都会更新,所以您可以随时轻松地看到代码的创建时间和最后修改时间。
  • 如果请求,Commenter 会在您的所有 using 指令周围添加一个Using 指令区域,就像 Visual Studio 2005 创建新类时那样。它还会删除区域代码和指令之间的任何不必要的空行。
  • Commenter 可以自动将类、方法等的普通注释转换为XML 注释,这会很有用。它还允许您只编写普通注释(这显然比编写摘要块更快),然后只需在函数末尾按下 } 即可自动转换(然后添加参数等内容)。
  • 如果您没有为 `public` 函数或类提供任何注释,但可能需要XML 注释(例如,用于使用 FxCop 检查代码),则会自动为您生成一个 XML 注释。当然,您应该修改此注释或根据需要添加文本。仅仅有一个 XML 注释通常会激励您在那里编写一些注释。
  • 对我来说最重要的功能是自动注释的代码块,以便找出哪个代码块属于哪个。即使在只有 20 行代码的小示例中,我们已经有了 5 层缩进,但只看代码的底部,谁知道哪个属于哪个。我在非常大的源代码文件中测试过 Commenter,代码量达数千行,即使 CodeRush 解析存在一些错误,它也工作得很好。我使用这个注释技术已经好几年了,并且已经说服了其他一些程序员也这样做,但是如果你很懒(所有的程序员都很懒),你就不想写所有的注释。现在一切都将自动完成,没有理由再抱怨了。这个功能也是最复杂的,因为注释必须以智能的方式生成,这里有很多事情要做:纠正解析错误,收集参数,限制为 80 个字符和 3 个参数,以及对不同类型的代码块(if、for each 方法、类等)进行大量特殊处理。
  • 作为一项附加功能,您还可以单击自动生成的注释以跳转到相应的类或函数,有时这比在方法下拉列表中选择方法更有用、更快。

打开 DevExpress -> Options 页面时,您可以选择 Commenter options 页面并配置 Commenter,并使用您喜欢的任意多功能。options 页面看起来像这样

创建 CodeRush 插件

首先,您需要安装 CodeRush。您可以免费使用试用版,没有限制(除了启动时可能会出现一些提示框),然后开始为其编写插件。但您应该支持 DevExpress 的员工,购买他们的产品。

在开始编写插件之前,最好让自己熟悉 CodeRush、可用的插件以及一切的工作方式,还要阅读帮助文档!

好的,第一步是启动 Visual Studio,然后从菜单中选择DevExpress -> New plugin。现在选择您的语言(C#/VB.NET),输入项目名称,然后单击几次 Next(查看您是否想做一些其他选择,例如为您的插件包含一个选项页面)。我将我的项目命名为 `CR_Test`,CR_ 是所有插件 DLL 文件的默认名称前缀,CodeRush 会自动将插件重命名为 `Test`,源文件为 *TestPlugIn.cs*(项目仍命名为 `CR_Test`)。

好的,现在我们有了 *TestPlugIn.cs*。在设计视图中单击属性,然后选择事件(黄色闪电图标,如果您不知道的话)。现在您会看到很多标准的 Visual Studio 插件事件和 CodeRush 事件。起初,很难找出哪个事件适合您的项目。CodeRush 中还有大量的类和函数,这使得一开始很难开始做任何事情(因为您不知道从哪里开始)。以下是您可能需要的一些重要 CodeRush 类的快速概述:

  • 检查传递给您的事件的 `EventArgs` 中有哪些参数。例如 `TextView`、按下的字符、文档、当前选择等。
  • CodeRush.TextDocument,您可以使用它获取用户正在处理的当前源文件(如果 `EventArgs` 已经提供了文档实例,则不需要)。
    // The text document we are currently working on
    
    TextDocument document = (TextDocument)
        CodeRush.Documents.ActiveTextDocument;

    别忘了检查文档是否有效,也许当前没有选中文档,那么我们就无法继续。如果您不确定所有内容是否都已正确解析(也许有些内容已更改),只需调用 `document.ParseIfTextChanged();`

  • CodeRush.Selection(如果您获得了活动文档,请使用 `document.Selection`)包含有关当前选定代码的信息,您最可能感兴趣的是当前光标位置。
      int currentLine = document.Selection.ActivePoint.Line,
          currentLineOffset = document.Selection.ActivePoint.LineCharOffset;
  • 当前代码段可以通过 `CodeRush.Source.Active` 访问,还有许多其他 Active- 属性(当前类、命名空间、方法等),所有节点都相互连接(我们有父节点、子节点和详细节点)。
    • 可以通过 `.Nodes` 访问子节点,通过 `.DetailNodes` 访问详细节点(例如,用于参数或条件),父节点可以在 `.Parent` 找到。
      // Get active section (don't forget to check if its valid!)
      
      LanguageElement activeSection = CodeRush.Source.Active;
      LanguageElement activeNamespace = CodeRush.Source.ActiveNamespace;
      // Get type (class, method, if, while, namespace, etc.)
      
      LanguageElementType sectionType = activeSection.ElementType;
    • `LanguageElement` 只包含元素的通用属性,但如果您有一个 `if` 条件块、一个 `while` 代码块、一个方法、一个命名空间等,您可能希望访问更具体的派生类。例如,我们需要 `DelimiterCapableBlock` 来检查代码块。
      // First check if activeSection is a sub class 
      
      //of DelimterCapableBlock
      
      if (activeSection.GetType().IsSubclassOf(
          typeof(DelimiterCapableBlock)))
      {
          DelimiterCapableBlock codeBlock = 
                (DelimiterCapableBlock)activeSection;
          // Check out some properties
      
          bool isCodeBlock = codeBlock.HasDelimitedBlock;
      } // if (activeSection.GetType)
  • CodeRush.TextView 可能由 `EventArgs` 提供,它将帮助您浏览当前可见的源代码,并允许您跳转或选择任何内容。
  • 一些内容也隐藏在子类中,例如,如果您需要当前文档的文件名,只需使用 `document.FileNode.PathSegment`;如果您需要 `TextView` 的当前行,请使用 `ea.TextView.Caret.LineText`;当您尝试解决问题时,您需要自己找出这些内容。有时,如果找不到某个功能,自己实现它可能更容易,它可能不存在,或者不符合您的要求。

Commenter 使用我的一些辅助类来简化事情

  • CodeRushHelper:提供 Commenter 所需的一些功能,用于递归获取节的名称或按元素名称查找代码块。
  • Log:辅助类,用于将信息文本、错误和异常记录到文本文件中,有时调试复杂问题比仅仅记录正在发生的事情然后查看日志中的内容更困难。它还有助于分析代码并检查哪些部分运行缓慢或需要优化。
  • StringHelper:一个丰富的类,提供了许多额外的功能,用于比较、检查、编写和处理文本字符串。

编写代码

好了,废话不多说,让我们写一些实际的代码。我只会向您展示 Commenter 的一小部分(因为它对于本教程来说太复杂了,请阅读 Commenter 的源代码以了解更多关于它的工作原理)。我们将尝试添加一个简单的注释,说明代码块的类型。这意味着我们将把这样的代码块转换为...

if (money > 1000)
{
    money *= 2;
}

... 如下所示

if (money > 1000)
{
    money *= 2;
} // if

首先,我们添加一个 `Event` 来捕获是否按下了“}”。使用 **TestPlugIn 设计视图 -> Properties -> Events**,创建一个 `EditorCharacterTyped` 事件,然后粘贴此代码(其中一些内容上面已经解释过)。

private void TestPlugIn_EditorCharacterTyped(
    EditorCharacterTypedEventArgs ea)
{
    // Only check if '}' was pressed

    if (ea.Character == '}' &&
        CodeRush.Source.ActiveFileNode != null &&
        CodeRush.Source.ActiveFileNode.Document != null)
    {
        // The text document we are currently working on

        TextDocument document = (TextDocument)
            CodeRush.Documents.ActiveTextDocument;

        int currentLine = document.Selection.ActivePoint.Line,
            currentLineOffset = document.Selection.ActivePoint.LineCharOffset;
        // Get active code block

        LanguageElement activeCodeBlock = CodeRush.Source.Active;
        if (activeCodeBlock == null)
            // Can't continue if code block is not valid.

            return;
            
        // Get code block type (class, method, if, while, namespace, etc.)

        LanguageElementType codeBlockType = activeCodeBlock.ElementType;

        string lineText = ea.TextView.Caret.LineText;
        // Continue only if line ends with '}', don't overwrite

        // already existing comment

        if (lineText.EndsWith("}"))
        {
            lineText = lineText.TrimEnd() + " // " +
                codeBlockType.ToString().ToLower();
            // And write it to source file

            document.SetText(
                currentLine, 1,
                currentLine, currentLineOffset,
                lineText);
        } // if (lineText.EndsWith)

    } // if (ea.Character)

} // TestPlugIn_EditorCharacterTyped(ea)

当用户在 Visual Studio 编辑器中按下任何键时,都会调用此事件。如果此键是“}”,并且我们有一个有效的源代码文档,我们将获取文档、当前行和偏移量、`activeCodeBlock` 及其元素类型。然后此代码将尝试修改当前行并向其添加“ // ”+type 注释。

当您尝试时,您会发现注释有效,但我们没有得到正确的代码块名称。它总是父代码块或下一个代码块,因为当按下“}”时,光标位于代码块外部,并且在调用 `CodeRush.Source.Active` 时返回的是下一个或父代码块。为了解决这个问题,我们必须将光标移动到当前行的开头(在 `activeCodeBlock` 之前插入此代码)。

document.Selection.StartOfLine(
    EnvDTE.vsStartOfLineOptions.vsStartOfLineOptionsFirstText);

现在可以了,但光标位置不正确,所以我们必须在函数末尾再次修复它:

document.Selection.MoveToLineAndOffset(
    currentLine,
    currentLineOffset);

注意:完成测试 *CR_Test.dll* 后,您必须关闭 Visual Studio 并从 *DevExpress\CodeRush\1.1\Bin\Plugins* 目录中删除 *CR_Test.dll*!每次要编辑插件解决方案时,都必须执行相同的操作。如果未删除 `*.dll`,则解决方案将无法复制和执行新版本的插件。现在从这里开始,尝试其他事件并添加您自己的插件创意,您可以使用 CodeRush 做更多的事情,例如在 Visual Studio 中添加新的工具窗口。查看 Commenter 的源代码,了解它是如何工作的,并进一步了解如何编写 CodeRush 插件。

结论

本教程到此结束。我希望这能让您对 Commenter 插件有所了解。如果您发现任何错误、有建议或想要额外的功能或对另一种语言的支持,请在下方留言。请随意使用 **Commenter**,该程序和源代码完全免费。

历史

有关每个版本的文章和更多详细信息,可在我的博客上找到

  • 初始版本:2004-12-08(**v1.0**)
    • 初始版本支持注释、添加头块和基本 XML 生成。
    • 撰写了本文。
  • 首次更新:2004-12-12(**v1.1**)
    • 许多小的改进(更多生成的注释、单击自动生成的注释跳转到函数等),现在非常稳定!
  • 第二次更新:2004-12-17(**v1.2**)
    • 新版本 2004-12-17,包含一些小的错误修复。
  • 第三次更新:2005-04-04(**v1.3**)
    • 几项新功能和一些错误修复,有关详细信息,请参阅 *TODO.txt* 文件。
    • 现在支持最新的 CodeRush 版本,非 `public` 方法的自动 XML 注释现在也能工作,并且会生成更好的注释。
    • 还增加了对非 C# 文件(如 *.fx、*.cpp、*.h 等)的更好支持。如果 CodeRush 无法解析它们,Commenter 将会解析,并仍然生成漂亮的注释和头部分!
  • 第四次更新:2005-10-04(**v1.4**)
    • 添加了一批关键字,用于将缩写转换为完整名称。
    • 修复:不再为命名空间节或方法中的 XML 生成。
    • 修复:所有节都已更新,第一个节不再被跳过。
    • 修复:多行使用的指令节。
    • 新增:支持大型方法的自动生成区域块。
  • 第五次更新:2005-12-28(**v1.5**)
    • 第一个版本支持 Visual Studio 2005,并使用 .NET 2.0 来支持泛型和匿名委托。
    • 再次修复:方法内不再生成 XML(最近的 CodeRush 版本不知何故改变了行为)。
    • 修复:如果在 using 语句中使用 define,则周围的区域现在已正确生成。
    • 修复:为 `if` 和 `for` 构建更有用的注释,更智能的代码块重构和命名。
    • 新增:生成 XML 的快捷键:Ctrl+1
    • 新增:在选项屏幕中添加了版本信息和更新按钮。
  • 第六次更新:2006-06-08(**v1.6**)
    • 添加了添加命名空间的功能,以支持 Visual Studio 2005 中的 C# 3.0 (CTP May)。
    • 为注释、区域和命名空间添加添加操作提示效果。
    • 略微改进了选项屏幕,添加了更多快捷键和帮助。
    • 更多可用快捷键:Ctrl+1、Ctrl+2、Ctrl+3、Ctrl+F9、Ctrl+。
  • v1.7 更新:2006-08-05(**v1.7**)
    • 修复了几个错误(长注释行被截断,修复了用户大量修改后的自动生成头注释)
    • 生成注释将不再扩展任何折叠的区域,无论我们在哪个文件位置。
    • 参数注释生成现在始终有效,无论您添加或删除参数。这是一个非常实用的功能,甚至支持参数重构(移动、删除、添加等)。
    • using 指令的自动排序功能,并修复了几个 using 问题。
    • 更好地支持 Ctrl+。,对命名空间中的子类型和未编译的程序集进行更智能的检查。
    • 所有变量、属性、构造函数和方法的自动排序功能,如果您想为所有这些类型自动生成一些漂亮的区域。此功能允许您导入外部代码,并使其更轻松地适应您的编码风格(好吧,至少是我的编码风格)。
  • v1.8 更新:2008-04-27(**v1.8**)
    • 修复了过去两年中收集到的许多小问题。
    • 修复了 `string` 或注释中的“}”,即使 CodeRush 尚未处理整个文件(现在会双重检查)。例如,下面的 `string` 不会再产生任何注释。
      SQL = String.Format("UPDATE GC SET Status = {0} WHERE ID = {1}", Msg, ID);
    • 再次支持生成区域,但拆分了函数名称,还使用 Ctrl+3、Ctrl+R 抑制 CodeRush 区域生成(现在也抑制 Visual Studio 快捷键)。更好地支持大型方法的自动生成区域块,只需按 Ctrl+3 即可生成区域(让 `CR_Commenter` 自动选择名称,按下 Ctrl+3 后允许编辑)。
    • 修复了 `Using` 指令中的 `#if` DEBUG(造成了麻烦,已删除)。
    • 还添加了代码以始终删除 `#if` DEBUG 和 `#endif`,特别是在 `Using` 指令区域的开头和结尾。
    • 修复了当 using 指令混淆时出现的双行 `#using` Using 指令问题。
    • 修复了长行注释生成,现在仍然有效,但不再截断您的任何代码。如果您有长代码行(>100 个字母),您仍然可以为它们生成注释,Commenter 不会再截断任何内容(您负责格式化代码)。
    • 修复了区域的自动折叠,特别是在方法中关闭块时,方法不应该自动折叠!
    • 检查了对其他(至少与 C# 相似的)语言的支持,如 Lua、Python 等。
    • 在 Python/Lua 等语言中,我们必须禁用 } 注释生成,并在使用 Ctrl+1 进行头注释生成时使用其他注释(# 用于 Python,-- 用于 Lua)。
    • 测试所有其他快捷键,并确保它们不会在 CodeRush 不支持的语言中对代码产生不良影响(注意:VB 仍然不支持,因为它与 C# 代码差异很大)。
    • 现在支持任何单元测试框架,实际上不再关心您使用什么,只有单元测试生成代码会添加 Xunit,但如果您愿意,可以轻松更改该代码。
    • 选项现在可以直接在 CodeRush 选项的 Editor 树中找到!
    • 重构了所有类,添加了大约 4 个新类,并删除了 1 个未使用的类。源代码现在更容易阅读、跟踪和更改。
    • 删除了注释掉的代码,对源代码进行了大量清理。
    • 最后,将 Commenter 应用于 Commenter 源代码 :)
  • v1.9 更新:2008-11-14(**v1.9**)
    • 主要更新,许多功能请求现已最终实现。
      新功能
      • 所有功能现在都可以启用或禁用,您可以为它们设置自己的快捷键。
      • 全新的选项屏幕,简化的统一设置,看起来不那么混乱。
      • 添加了很酷的新项目和解决方案级别的头注释。
      • 新快捷键 Ctrl+6 用于仅更新头注释。
      • 添加了块大小的下限,以减少小块的注释(也递归工作)。
      • 添加了新功能和快捷键逻辑,现在一切都更容易自定义。
      • 更容易看到插件是否已安装并正在工作(更多视觉事件,更好的选项屏幕)。
      • 修复了为新文件生成注释时的问题(扰乱了 using 指令区域),这似乎与生成头注释有关。
      • 改进了行长度计数以移除注释(好的新标准:5 行)。
      • 修复了 Format-Strings 或 SQL 代码中的几个问题。
      • 将整个方法标识符从可访问性关键字添加到区域指令的闭合括号。
      • 改进了 CodeRush 自动生成的区域(Ctrl+3),确保注释不会被弄乱。
      • 新默认:不生成 XML 参数注释(通常对更好的文档来说没什么用,自己添加更详细的内容更方便)。
      • 添加了 C++ “`pragma region - #pragma endregion`” 支持(感谢 Enrico 的测试)。
      • C++:将 include 包含到 using 指令区域。
      • C++:修复了头注释(找不到项目名称)。
      • C++:不使用 XML 注释,只保留普通注释!
      • 修复了我们插件外部错误生成的区域。
      • C++:修复了 `#includes` 区域,不修改 include 行。
      • 修复了当 CodeRush 先生成区域时的区域生成问题!
      • 修复了在存在其他头注释时的头注释。
      • 添加了多行头注释支持 // /* */ -- 和 #,以支持所有类型的语言和注释格式。
      • 还强制对属性生成注释(方法可以,构造函数也测试过)。
      • C++ 允许使用 Ctrl+4 和 Ctrl+5 进行 C++ 区域折叠(作为备用使用 Visual Studio 的 `Edit.ToggleOutliningExpansion` 和 `Edit.ToggleAllOutlining`)。
      • 与 CodeRush 版本 2 和 3 进行了测试。
      • 更新头注释的新快捷键(F6)。
      • 块大小下限(递归)。
      • 再次测试了长行 {}(现在在方法内部工作得更好)。
      • 允许 SQL 语句包含 {}。
      • 仅允许在按下 Ctrl+1 时更新。
      • 将方法参数包含到区域名称中(可选)。
      • 对 C++ 的支持大大提高,进行了大量额外的测试。
      • C++ 区域功能(#pragma region)使用 Ctrl+R。
      • 改进了 Python (IronPython) 和 Lua (LuaInterface) 的语言支持。
      • 还支持 UnrealScript(与 C++ 非常相似)。
      • 项目级别头注释(保存在项目文件中)。
      • 最近的头注释更改,还会将任何旧的头注释与新头注释合并(或者在不兼容时跳过生成)。
      • 新的混淆文件功能,使用 Ctrl+8 来移除任何注释、空行,主要是为了减小文件大小!支持的语言:C#、C++、Python、Lua。
© . All rights reserved.