Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Commenter - A CodeRush Plugin which Helps you to Comment your Code

0.00/5 (No votes)
29 Nov 2008 3  
Writing a CodeRush plugin commenter will help you to comment your code and make it easier to navigate through your code.

Contents

Introduction

Commenter is a plugin for CodeRush, which is an addin for Visual Studio (Visual Studio 2002, 2003, 2005 and 2008 are supported). Basically Commenter will help you to comment your code and make it easier to navigate through your code. Currently Commenter supports only C#, but C++ might work too (but may need some additional testing). Support for VB.NET might be added if requested, don't know if VB guys would like such a feature. The project files use Visual Studio 2003, but you can convert them to Visual Studio 2005 or Visual Studio 2002 as well and everything should work fine too. (Note: Since v1.8 all files are for Visual Studio 2008.)

This article is still based on the CR_Commenter version 1.0, since 2004 CR_Commenter was updated 9 times already and is in version 1.9 right now (2008-11-27). For an updated feature list and many more screenshots, check out this blog entry!

Just be sure to change the start-program to the correct devenv.exe too (for testing).

Note: I have nothing to do with the Developers of CodeRush, I just like their tool and think it's easier to write Visual Studio plugins with it.

I will also cover how to write and use a CodeRush plugin, it seems like there is no tutorial on the net for this. The Commenter could also be implemented as a native Visual Studio plugin, but this would be much harder (parsing, etc.), also anyone using my plugin should also useCodeRush to improve his development speed.

Let's take a look at some actual code and how it would look when using Commenter:

Commenter - Features

As you can see in the image above, there are several features supported in Commenter. The Commenter will only do its work when you press '}' to end a code block, the only exception is when you double-click on an auto-generated comment, then your cursor will jump to the class or method.

The features are listed below:

  • Customable header comment: In each source file you edit, a customable header will be added at the top of the file. The cool thing about this is, it gets updated every time when you modify a file, so you can always very easily see when the code was created and when it was modified the last time.
  • If requested, the Commenter will put a Using directives region around all your using directives, like Visual Studio 2005 does when creating new classes. It will also remove any unnecessary empty lines between the region code and the directives.
  • The commenter can convert normal comment of classes, methods, etc. to XML comments automatically, this can come in handy. It also allows you just to write normal comments (which is obviously faster than writing a summary block) and then just press } at the end of the function to convert it automatically (and then add parameters, etc. stuff).
  • In case you don't have any comments for a public function or class, but may need XML comments (e.g. for checking your code with FxCop), an XML comment will be generated for you. You should of course modify this comment or add text to it when required. Just having an XML comment will motivate you most times to write some comments there anyway.
  • The most important feature for me is the auto-commented code blocks to find out which code block belongs to what. Even in the small example with only 20 lines, we already got 5 indentations and who knows which belongs to what when seeing only the bottom part of this code. I tested the commenter on very large source files with a couple of thousand lines of code and it works nice, even if the CodeRush parsing has some errors. I used the commenting technique for a couple of years and have convinced some other coders to do this as well, but if you are lazy (and all programmers are), you don't want to write all those comments. Now everything will be done automatically, no reason to complain anymore. This feature was also the most complex one, because the comment has to be generated in a smart way, there are a lot of things going on here: correcting parsing errors, collecting parameters, limitation to 80 chars and 3 parameters and a lot of special handling for different kinds of code blocks (if, for each methods, classes, etc.).
  • As a bonus feature, you can also click on a auto generated comment to jump to the appropriate class or function, sometimes this is more useful and faster than selecting the method in the method dropdown list.

When opening the DevExpress -> Options page, you can select the Commenter options page and configurate the Commenter and use as many features as you like. The options page looks like this:

Creating the CodeRush Plugin

First of all, you need to have CodeRush installed, you can use the trial version without any limitations (except some nag box at startup I think) and start writing plugins for that. But you should support the guys at DevExpress for their work and buy the product.

It's also good to make yourself comfortable with CodeRush, the available plugins and how everything works before you start programming a plugin, also read the help!

Ok, first step it to start Visual Studio and select DevExpress -> New plugin from the menu. Now select your language (C#/VB.NET), enter the name of the project and click a couple of times next (see if you want to make some other choices like including an options page for your plugin). I called my project CR_Test, CR_ is the default name prefix for all plugin DLL files, CodeRush will automatically rename the plugin to Test and the source file to TestPlugIn.cs (the project is still named CR_Test):

Ok, now we got a TestPlugIn.cs, click on properties in design view and select events (the yellow flash icon, in case you don't know). Now you see a lot of standard Visual Studio plugin events and CodeRush events. At first it won't be easy to find out which event is the correct one for your project. There is also an incredible mass of classes and functions in CodeRush, which makes it very hard to start doing anything at first (because you don't know where to start). Here is a quick overview about some important CodeRush classes, you might need:

  • Check out what parameters are in the EventArgs passed to you from the event. e.g. TextView, pressed character, the document, the current selection, etc.
  • CodeRush.TextDocument, you can get the current source file the user is working on with (you won't need that if EventArgs gives you the document instance already):
    // The text document we are currently working on
    
    TextDocument document = (TextDocument)
        CodeRush.Documents.ActiveTextDocument;

    Don't forget to check if document is valid now, maybe there is currently no active file selected, then we can't proceed. When you are not sure everything is parsed correctly (maybe something was changed), just call document.ParseIfTextChanged();

  • CodeRush.Selection (if you get an active document, use document.Selection) contains information about the currently selected code, most likely you will be interested in the current cursor position:
      int currentLine = document.Selection.ActivePoint.Line,
          currentLineOffset = document.Selection.ActivePoint.LineCharOffset;
  • The current code section can be accessed via CodeRush.Source.Active, there are also a lot of other Active- properties (current class, namespace, method, etc.) and all nodes are connected to each other (we got a parent, children and detail nodes):
    • child nodes can be accessed with .Nodes, detail nodes (e.g. for parameters or conditions) can be accessed with .DetailNodes and the parent can be found at .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 contains only the common properties of elements, but if you got an if condition block, a while code block, a method, the namespace, etc., you might want to access the more specified derived classes. For example, we need DelimiterCapableBlock to check code blocks:
      // 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 may be provided by EventArgs, it will help you to navigate through the currently visible source code and allows you to jump around or select anything.
  • There are also a lot of things hidden in some sub class, like when you need the filename of the current document just use document.FileNode.PathSegment or when you need the current line from TextView use ea.TextView.Caret.LineText, you will have to find out this stuff by yourself when trying to solve your problems. Sometimes it may be easier to implement functionality yourself, if you can't find it, it may not exist or it does not match your requirements.

The Commenter uses some of my helper classes to simplify things:

  • CodeRushHelper: Provides some functionality required by Commenter to get names of sections recursively or find code blocks by the element name.
  • Log: Helper class to log info text, errors and exceptions to a text file, sometimes debugging complex problems is harder than just log what's happening and then see in the log what's going on. It's also useful to profile code and check out which parts are slow or need optimizations.
  • StringHelper: A rich class providing a lot of extra functionality for comparing, checking, writing and handling text strings.

Writing Some Code

Okay, enough bubbling around, let's write some actual code. I will only show you a very small part of Commenter (because it would be too complex for this tutorial, read the Commenter source code to find out more about how it works). We will try to add a simple comment with the type of the code block. This means we will convert a code block like this...

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

... to the following:

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

First of all, we add an Event to catch if '}' was pressed. Use TestPlugIn designer view -> Properties -> Events and create a EditorCharacterTyped event and paste this code (some of it was already explained above):

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)

This event is called whenever the user presses any key in the Visual Studio editor. When this key was '}' and we got a valid source code document, we will get the document, the current line and offset, the activeCodeBlock and its element type. Then this code will try to modify the current line and add the " // "+type comment to it.

When you try it out, you will see that the commenting works, but we don't get the correct code block name. It will be always the parent or nextcode block, this is because the cursor is outside the codeblock when pressing '}' and the next or parent code block is returned when calling CodeRush.Source.Active. To fix this, we have to move the cursor to the beginning of the current line (insert this before activeCodeBlock):

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

Now it works, but the cursor is at the wrong position, so we have to fix that again at the end of the function with:

document.Selection.MoveToLineAndOffset(
    currentLine,
    currentLineOffset);

Note: When finished testing CR_Test.dll, you have to close Visual Studio and remove CR_Test.dll from the DevExpress\CodeRush\1.1\Bin\Plugins directory! You will have to do the same thing every time you want to edit your plugin solution. If the *.dll, is not removed, the solution is not able to copy and execute the new version of the plugin. Now from here on, try out other Events and add your own plugin ideas, you can do a lot more with CodeRush, like adding new tool windows in Visual Studio. Check out the sourcecode of Commenter to find out how it works and learn more about writing a CodeRush plugin.

Conclusion

That's it for this tutorial. I hope this gave you some insight on the Commenter plugin. If you find any bugs, have suggestions or want some additional features or support for another language, please leave a comment below. Feel free to use the Commenter, the program and sourcecode are completely free.

History

Articles and more detail about each version can be found on my blog!

  • Initial version : 2004-12-08 (v1.0)
    • Initial version supports commenting, adding header block and basic XML generation.
    • Wrote this article.
  • First Update : 2004-12-12 (v1.1)
    • Lots of smaller improvements (more generated comments, click on auto generated comments to jump to function, etc.), very stable now!
  • Second Update : 2004-12-17 (v1.2)
    • New version 2004-12-17 with some minor bug fixes
  • Third Update : 2005-04-04 (v1.3)
    • Several new features and some bug fixes, see the TODO.txt file for details.
    • Now supports newest CodeRush version, auto XML comments work now for non-public methods too and will produce better comments.
    • Also added better support for non C# files like *.fx, *.cpp, *.h, etc. If CodeRush does not parse them, Commenter will do it and still generate nice comments and the header section!
  • Fourth Update : 2005-10-04 (v1.4)
    • Added a bunch of keywords to translate abbreviations to full names.
    • Fixed: No more XML generation of namespace sections or in methods.
    • Fixed: All sections are updated, the first one is not skipped anymore.
    • Fixed: Using directives section for multilines.
    • New: Support for autogenerated region blocks for big methods.
  • Fifth Update : 2005-12-28 (v1.5)
    • First version for Visual Studio 2005 and using .NET 2.0 now for supporting generics and anonymous delegates.
    • Fixed again: No XML generation inside of methods (recent CodeRush version changed its behaviour somehow).
    • Fixed: If using defines in the using statements the surrounding region is now generated properly.
    • Fixed: Constructing more useful comments for if and for, more intelligent block reconstruction and naming.
    • New: Hotkey for generating XML: Ctrl+1
    • New: Added version information and update button in options screen.
  • Sixth Update : 2006-06-08 (v1.6)
    • Added add namespace feature to support C# 3.0 (CTP May) in Visual Studio 2005.
    • Added action hint effects for commenting, regions and namespace adding.
    • Improved options screen a little, added more hotkeys and help.
    • More hotkeys available, Ctrl+1, Ctrl+2, Ctrl+3, Ctrl+F9, Ctrl+.
  • v1.7 Update: 2006-08-05 (v1.7)
    • Fixed couple of bugs (long comment lines got cut of, fixed autogenerating header when user modified it a lot)
    • Generating comments will no longer expand any collapsed regions, at whichever file position we are.
    • Parameter comment generating now always works, no matter if you add or remove parameters. This is a quite useful feature, even refactoring parameters is supported (moving, removing, adding stuff).
    • Autosorting feature for using directives, also fixed couple of using issues.
    • Better support for Ctrl+., more intelligent checks for sub types in namespaces and for uncompiled assemblies.
    • Autosorting of all variables, properties, constructors and methods if you want to autogenerate some nice regions for all these types. This feature allows you to import external code and let it fit your coding style (ok, at least my coding style) much more easily.
  • v1.8 Update: 2008-04-27 (v1.8)
    • Fixed many smaller issues that have been collected over the last 2 years
    • Fixed '}' inside string or comment, even if CodeRush has not processed the whole file yet (double checking now). E.g. the following string will not longer produce any comments:
      SQL = String.Format("UPDATE GC SET Status = {0} WHERE ID = {1}", Msg, ID);
    • Supporting to generate regions again, but split up function names, also suppress CodeRush region generation with Ctrl+3, Ctrl+R (also suppressing Visual Studio hotkeys now). Better support for auto generated region blocks for big methods, just press Ctrl+3 to generate region (let CR_Commenter choose the name automatically, allow editing after pressing Ctrl+3).
    • Fixed #if DEBUG in Using directives (caused trouble, was removed)
    • Also added code to always remove #if DEBUG and #endif, especially at the beginning and end of the Using directives region.
    • Fixed double line #using Using directives issue when using directives got mixed up.
    • Fixed long line commenter generation, will now still work, but no longer cut off any of your code. If you have long code lines (>100 letters), you can still generate comments for them and the Commenter will not longer cut anything off (you are responsible for formatting the code).
    • Fixed auto-collapsing of regions, especially when closing blocks in methods, the method should not auto-collapse!
    • Checked support with other languages (which are at least similar to C#) like Lua, Python, etc.
    • In Python/Lua, etc. we had to disable } comment generation and also use other comments (# for python, -- for lua) when using Ctrl+1 for header generation.
    • Test all other hotkeys and make sure they do not affect the code badly in CodeRush unsupported languages (Note: VB is still not supported since it is very different from C# code).
    • Supports now any unit test framework, actually does not care anymore what you use, only the unit test generation code will add Xunit, but you can easily change that code if you want to.
    • Options are now available directly into Editor tree of the CodeRush options!
    • Refactored all classes, added about 4 new classes and removed 1 unused class. The source code is now much easier to read, to follow and to change.
    • Remove commented out code, cleaned up the source code a lot.
    • And finally applied the commenter to the commenter source code :)
  • v1.9 Update: 2008-11-14 (v1.9)
    • Major update with many feature requests now finally implemented.
      New features:
      • All features can now be enabled or disabled and you can set your own hotkey for them
      • Completely new options screen, simplified and unified settings, less chaotic look
      • Added cool new per-project and per-solution header comments
      • New shortcut Ctrl+6 to just update the header
      • Added lower limit for block size to reduce comments for small blocks (also works recursive)
      • Added new features and hotkey logic, everything is now easier to customize
      • Easier visibility if plugin is installed and working (more visual events, better options screen)
      • Fixed generating comments for new files (messes up the using directives region), seems to be related to generating header comments
      • Improve line length count for removing comments (good new standard: 5 lines)
      • Fixed several problems in Format-Strings or SQL code
      • Added whole method identifier from the accessibility keyword to the closing parenthesis for region directives
      • Improved the CodeRush-autogenerated regions (Ctrl+3), make sure comments are not messed up
      • New default: Do not generate XML parameter comments (mostly not used for better documentation anyway, adding them yourself for more details is more comfortable)
      • Added C++ "pragma region - #pragma endregion" support (thanks for testing to Enrico)
      • C++: include includes into using directives region
      • C++: Fixed header comment (project name could not be found)
      • C++: Do not use XML comments, just leave normal comments!
      • Fixed wrongly generated regions outside of our plugin
      • C++: Fixed #includes region, do not modify include lines
      • Fixed region generation when CodeRush generates region before us!
      • Fixed header in case some other header comment is used
      • Added multiline header comment support for // /* */ -- and # to support all kinds of languages and comment formats
      • Also force generate comments on properties (methods work, also test constructors)
      • C++ allow Ctrl+4 and Ctrl+5 for C++ region collapsing (using Visual Studio's Edit.ToggleOutliningExpansion and Edit.ToggleAllOutlining as fallbacks)
      • Tested with CodeRush versions 2 and 3
      • New shortcut for updating the header (F6)
      • Lower limit for block size (recursion)
      • Tested long lines {} again (now works better inside methods)
      • Allow SQL statements with {} in them
      • Allow only to update when Ctrl+1 is pressed
      • Include method parameters for region names (optional)
      • Much better support for C++, a lot of extra testing
      • C++ feature for regions (#pragma region) with Ctrl+R
      • Improved language support for Python (IronPython) and Lua (LuaInterface)
      • Also supporting UnrealScript (very similar to C++)
      • Per-project headers (saved in project file)
      • Most recent changes in the header comment, also merging any old headers with the new header (or skip generation if not compatible).
      • New obfuscate file feature with Ctrl+8 to cut any comments, empty lines, mainly to reduce file size! Supported languages: C#, C++, Python, Lua

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here