Click here to Skip to main content
Click here to Skip to main content

Code Spelling Checker Extension for Visual Studio 2010 (VSX)

, 7 Apr 2010
Rate this:
Please Sign up or sign in to vote.
Building a spelling checker for source code as an extension for Visual Studio 2010

Introduction

I am convinced that the quality of an application depends on the use of proper spelling and grammar. It might be argued that this is nitpicking and that productivity is far more important. While this is important, one must bear in mind that any line of code will be read more often than it was written.

Good programs should not contain language errors due to the diligence of the programmers. Written code needs to be correct at all levels, starting with the design, the correctness and consistency in the names used down to the periods in the comments.

Not everyone has English as his first language, including myself and there are number of people with certain disabilities, e.g. dyslexia who also might have trouble reading or writing proper English. It is not to say that these people could not write a good application. The point I'm trying to make is that the written code should convey the intention of the writer.

To facilitate this, I thought it would be interesting to write a spelling checker extension for Visual Studio 2010 with the following features:

  • Check the spelling of the words in (XML) comments
  • Check the spelling of names on declaration using the MS.NET naming convention
  • Check the spelling of the words in string literals
  • Mark misspelled words with red squiggly lines
  • Provide a list of suggestions for a misspelled word
  • A misspelled word can be added to the custom words dictionary
  • The custom words dictionary is maintained inside the source tree. This has the benefit of source control and synchronizing it across a team, in case of teamwork.

First Step: Getting a Red Squiggle Under a Bit of Text

This turned out to be surprisingly easy. Start off with using a project template in order to get familiarized with some of the basic attributes in the MEF (Managed extension framework).

Visual Studio 2010 has a mechanism called tagging in which subscribers can add metadata to bits of the text file. The important concepts are:

  • Span, which in essence are coordinates (starting point + length) within the text
  • ITagger, which tells the IDE where to place the tags
  • ITag, which tells the IDE what to render (The IErrorTag is rendered as the red squiggle)
  • TagSpan, the combination of a Tag and a Span, a.k.a. where and what

The interface ITagger<IErrorTag> has one method called GetTags, which accepts a span collection and must return an enumeration of TagSpan objects. The provided span collection marks areas of interest to the IDE. This might be because the user has changed or otherwise triggered changes in the view and as such need retagging.

The following example code shows an implementation of this method which puts a squiggle under each “A”. These squiggles also display “C” as the accompanying tooltip.

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")
                );
            }
        }
    }
}

Second Step: Getting a Context Like Menu Tagged (a.k.a. Smart Tag) to a Bit of Text.

Again this turned out to be surprisingly easy. This is achieved by utilizing the same ITagger interface but this time with the SmartTag class as the type argument. SmartTag is the place holder for actions (grouped in sets). The user is hinted by a small blue rectangle of its presence. When the user places the mouse over the rectangle, it will show a dropdown list with the provided actions.

The ISmartTagAction interface has 2 important members:

  • DisplayText property, which is shown to the user in the dropdown list
  • Invoke method, which provides the actual implementation

Third Step: Check the Spelling

I remembered that one of the features of WPF is spellchecking and decided to investigate whether this would suffice. Although in WPF 4.0 support for custom words dictionaries has been added, it has been limited to English, French, German and Spanish. This wasn’t a problem as the Microsoft .NET naming guidelines state that identifiers should be declared in English.

However, the actual implementation was hidden (marked as internal), which I could either hack using reflection or using an actual WPF textbox underneath the covers. Tip: When you use the WPF textbox, the spellchecker disabled itself when the user uses a different input locale from the previously mentioned languages (+dialects). You can override this user setting to a specific language using an attached property “xml:lang” and an ISO 3166 code, e.g. “en-us” or “en-gb”.

I struggled with both strategies for a while, and eventually came to the conclusion that both were lacking what I was looking for... So I decided to look for alternatives and came across “Hunspell”, an open source spellchecking library, currently used by open office, Firefox, and others. It comes with a very large number of dictionaries and has thesaurus, hyphen and grammar functionality as well.

Unfortunately it is not exposed as com, so no standard PInvoke. Using some old school kernel32.dll trickery, we can load the library and unload it. But the real magic is that GetProcAddress combined with the Marshal.GetDelegateForFunctionPointer allows you to create a delegate which calls into the library. (For more details, check out the Hunspell namespace.)

Fourth Step: Getting the Bits to Check the Spelling Of

An interesting technique used by the spell checker created by Roman Golovin and Noah Richards. This spell checker is/will be part of the VS SDK and uses a service called the classifier. This mechanism is used by the language services to classify bits of text as to their contextual and generic meaning. My guess is that this is used by the syntax colorizing process.

Unfortunately, it did not provide any detail when a name was declared as opposed to used. So I decided to build my own C# scanner & simple parser (as this is my language of choice). Though the scanner and the lexical tokens are complete, the intention of the parser is only to correctly identify all different types of name declarations.

Screenshots

You can tell from this screenshot that the word “misspellled" (having 3 L’s) and Namespace have been marked. It also shows namespace, alias and delegate (with parameter and defaults) declarations.

SpellSharp1.jpg

By hovering over the smart tag indicator (blue rectangle), the drop down becomes visible.

SpellSharp2.jpg

The first word to be added to the custom words dictionary results in the file CustomWords.txt to be added to the solution in the standard folder “Solution items”.

SpellSharp3.jpg

An enumeration with attributes and comments:

SpellSharp4.jpg

An interface with various members:

SpellSharp5.jpg

A class with various members:

SpellSharp6.jpg

Known Bugs

  • No handling C# pre compiler directives (Fixed)

Future Versions

  • Including unit tests
  • Adding MS build task
  • Adding a VS command to scan all files in the solution akin to the find/replace method
  • Adding (T) SQL language support
  • Adding VB.NET language support
  • Adding F# language support
  • Using a managed spelling checker, maybe writing my own for fun
  • Suggestions or bugs?

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Digital-samurai

Netherlands Netherlands
No Biography provided

Comments and Discussions

 
QuestionInstallation PinmemberNMarouschek11-Apr-12 0:17 
GeneralMy vote of 1 Pinmemberittay ophir10-Sep-11 7:51 
QuestionIt works, I updated it to NHunspell, fixed the missing parts in the code Pinmemberfiechter16-Aug-11 1:00 
AnswerRe: It works, I updated it to NHunspell, fixed the missing parts in the code PinmemberForogar12-Jan-12 5:25 
QuestionHas anyone gotten this to work? PinmemberGamePlayHeaven4-Jan-11 22:40 
GeneralMy vote of 1 PinmemberStonie14-Sep-10 20:27 
GeneralCrashing VS Pinmemberscott lafoy9-Sep-10 5:41 
GeneralRe: Crashing VS PinmemberStonie14-Sep-10 20:26 
QuestionHunspell Missing? PinmemberStonie6-Sep-10 19:57 
GeneralVisual studio 2008 Pinmembersania112110-Aug-10 0:14 
GeneralKeyboard Support PinmemberChristopher Snyder15-Jul-10 3:41 
GeneralRe: Keyboard Support PinmentorGiorgi Dalakishvili3-Sep-11 7:27 
GeneralWin32Exception in DIGITALSAMURAI.SPELLSHARP.DLL Pinmemberacangialosi21-Jun-10 8:50 
GeneralRe: Win32Exception in DIGITALSAMURAI.SPELLSHARP.DLL PinmemberStonie14-Sep-10 20:31 
Question[Suggestion] Misspellings as compilation errors/warnings? Pinmembersomestrangename29-Apr-10 18:31 
AnswerRe: [Suggestion] Misspellings as compilation errors/warnings? PinmemberDigital-samurai2-May-10 2:47 
GeneralRe: [Suggestion] Misspellings as compilation errors/warnings? Pinmembersomestrangename2-May-10 4:50 
GeneralRe: [Suggestion] Misspellings as compilation errors/warnings? PinmemberDigital-samurai3-May-10 22:49 
GeneralRe: [Suggestion] Misspellings as compilation errors/warnings? Pinmembersomestrangename4-May-10 1:33 
GeneralRe: [Suggestion] Misspellings as compilation errors/warnings? Pinmembersomestrangename16-May-10 19:19 
GeneralVery cool PinmemberHardy Wang28-Apr-10 3:12 
GeneralRe: Very cool PinmemberDigital-samurai2-May-10 2:48 
GeneralNice PinmemberGaurav Dudeja India8-Apr-10 20:24 
GeneralRe: Nice PinmemberDigital-samurai2-May-10 2:48 
GeneralWhich version of VS2010 Pinmemberzhuqil7-Apr-10 15:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 8 Apr 2010
Article Copyright 2010 by Digital-samurai
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid