1. Nerzhul500
  2. Resharper Spell Checker

Source

Resharper Spell Checker / ReSpeller / Bulbs / TextRangeTypoReplaceBulbItem.cs

using System.Collections.Generic;
using JetBrains.Application;
using JetBrains.DocumentModel;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Bulbs;
using JetBrains.ReSharper.Feature.Services.LiveTemplates.Hotspots;
using JetBrains.ReSharper.Feature.Services.LiveTemplates.LiveTemplates;
using JetBrains.ReSharper.LiveTemplates;
using JetBrains.TextControl;
using JetBrains.Util;

namespace ReSpeller.Bulbs
{
  class TextRangeTypoReplaceBulbItem : IBulbItem
  {
    private DocumentRange myRange;
    private readonly Lazy<List<string>> mySuggestions;

    public TextRangeTypoReplaceBulbItem(DocumentRange range, Lazy<List<string>> suggestions)
    {
      myRange = range;
      mySuggestions = suggestions;
    }

    public void Execute(ISolution solution, ITextControl textControl)
    {
      if (!myRange.IsValid())
        return;
      var allWords = new List<string>();
      string text = myRange.GetText();
        List<string> suggests = mySuggestions.Value;
        if (!suggests.Contains(text))
        allWords.Add(text);
      allWords.AddRange(suggests);
      var templateField = new TemplateField("TEXT_RANGE_TYPO", new TextHotspotExpression(allWords), 0);
      var fieldInfo = new HotspotInfo(templateField, myRange.TextRange);
      textControl.Caret.MoveTo(fieldInfo.Ranges[0].StartOffset, CaretVisualPlacement.Generic);
      var liveTemplatesManager = Shell.Instance.GetComponent<LiveTemplatesManager>();
      HotspotSession hotspotSession = liveTemplatesManager.CreateHotspotSessionAtopExistingText(
        solution, 
        new TextRange(fieldInfo.Ranges[0].EndOffset + 1), 
        textControl, 
        LiveTemplatesManager.EscapeAction.LeaveTextAndCaret, fieldInfo);
      hotspotSession.Execute();
    }

    public string Text
    {
      get { return string.Format("Typo in \"{0}\". Replace with ...", myRange.GetText()); }
    }
  }
}