Commits

aarondandy committed 3902bc8

assorted cleanup, refactoring, fixes and optimization

  • Participants
  • Parent commits 672a948

Comments (0)

Files changed (16)

File src/YouCantSpell.Core/CachedSpellChecker.cs

 using System.Collections.Generic;
 using System.Linq;
 using System.Collections.ObjectModel;
+using System.Threading;
 
 namespace YouCantSpell
 {
 			public readonly ReadOnlyCollection<string> Suggestions;
 		}
 
-		private readonly object _sync = new object();
+		//private readonly object _cacheLock = new object();
 		private ISpellChecker _core;
 		private readonly bool _ownsCore;
 		private readonly Dictionary<string, CachedSpellCheckData> _cache;
 		private readonly int _cacheMax = 1024; // must be larger than 0
+		private readonly ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
 
 		/// <summary>
 		/// Wraps another spell checker to provide caching and synchronization.
 
 		/// <inheritdoc/>
 		public void Add(string word) {
-			lock(_sync) {
+			_cacheLock.EnterWriteLock();
+			try {
 				_core.Add(word);
 				_cache.Clear(); // NOTE: when a new item is added the caches must be cleared as it will affect the suggestions
 			}
+			finally {
+				_cacheLock.ExitWriteLock();
+			}
 		}
 
 		/// <inheritdoc/>
 		public void Add(IEnumerable<string> words) {
-			lock(_sync) {
+			_cacheLock.EnterWriteLock();
+			try {
 				_core.Add(words);
 				_cache.Clear();  // NOTE: when a new item is added the caches must be cleared as it will affect the suggestions
 			}
+			finally {
+				_cacheLock.ExitWriteLock();
+			}
 		}
 
 		/// <inheritdoc/>
 			return JustCheckCore(word).WordFound;
 		}
 
-		private CachedSpellCheckData JustCheckCore(string word) {
-			lock (_sync) {
+		private CachedSpellCheckData JustCheckCore(string word)
+		{
+			_cacheLock.EnterUpgradeableReadLock();
+			try {
 				CachedSpellCheckData result;
 				if (_cache.TryGetValue(word, out result))
 					return result;
 
-				while (_cache.Count >= _cacheMax)
-					_cache.Remove(_cache.Keys.First());
+				_cacheLock.EnterWriteLock();
+				try {
+					while (_cache.Count >= _cacheMax)
+						_cache.Remove(_cache.Keys.First());
 
-				_cache[word] = result = new CachedSpellCheckData(_core.Check(word));
+					_cache[word] = result = new CachedSpellCheckData(_core.Check(word));
+				}
+				finally {
+					_cacheLock.ExitWriteLock();
+				}
 				return result;
 			}
+			finally {
+				_cacheLock.ExitUpgradeableReadLock();
+			}
 		}
 
 		/// <inheritdoc/>
 		}
 
 		private CachedSpellCheckData GetRecommendationsCore(string word) {
-			lock(_sync) {
+			_cacheLock.EnterUpgradeableReadLock();
+			try {
 				CachedSpellCheckData result;
-				if (_cache.TryGetValue(word, out result))
-				{
-					if (result.Suggestions != null)
+				bool? wordFound = null;
+				if(_cache.TryGetValue(word, out result)) {
+					if(result.Suggestions != null)
 						return result;
 
-					_cache[word] = result = new CachedSpellCheckData(result.WordFound, _core.GetRecommendations(word));
-					return result;
+					wordFound = result.WordFound;
 				}
 
-				while(_cache.Count >= _cacheMax)
-					_cache.Remove(_cache.Keys.First()); // TODO: this could be a lot better
+				_cacheLock.EnterWriteLock();
+				try
+				{
+					if (!wordFound.HasValue)
+						wordFound = _core.Check(word);
 
-				_cache[word] = result = new CachedSpellCheckData(_core.Check(word), _core.GetRecommendations(word));
+					while (_cache.Count >= _cacheMax)
+						_cache.Remove(_cache.Keys.First()); // TODO: this could be a lot better
+
+					_cache[word] = result = new CachedSpellCheckData(wordFound.Value, _core.GetRecommendations(word));
+				}
+				finally {
+					_cacheLock.ExitWriteLock();
+				}
 				return result;
 			}
+			finally {
+				_cacheLock.ExitUpgradeableReadLock();
+			}
 		}
 
 		protected virtual void Dispose(bool includeManagedResources) {

File src/YouCantSpell.Core/SpellChecker.cs

 
 		/// <inheritdoc/>
 		public void Add(string word) {
-			_core.Add(word);
+			if(!_core.Add(word)) {
+				_core.Add(word.ToUpper());
+				_core.Add(word.ToLower());
+			}
 		}
 
 		/// <inheritdoc/>

File src/YouCantSpell.ReSharper.Shared/CSharp/CSharpFreeTextSpellingHighlightFinder.cs

-using System;
-using System.Collections.Generic;
-using System.Linq;
-using JetBrains.DocumentModel;
-using JetBrains.ReSharper.Daemon;
-using JetBrains.ReSharper.Psi.Caches;
-using JetBrains.ReSharper.Psi.Tree;
-using JetBrains.Util;
-using YouCantSpell.CStyle;
-using YouCantSpell.Utility;
-
-namespace YouCantSpell.ReSharper.CSharp
-{
-	/// <summary>
-	/// Locates and created spelling error highlightings in free form text nodes such as comments or string literals.
-	/// </summary>
-	[Obsolete]
-	public class CSharpFreeTextSpellingHighlightFinder
-	{
-
-		private readonly ShellSpellCheckResources _shellSpellCheckResources;
-		private readonly IDocument _document;
-		private readonly HashSet<string> _localIdentifierNames;
-		private readonly IDeclarationsCache _declarationsCache;
-
-		/// <summary>
-		/// Creates a free text processor for the given document and shellSpellCheckResources with the provided ignored words and known declarations.
-		/// </summary>
-		/// <param name="shellSpellCheckResources">The shellSpellCheckResources that is executing this search.</param>
-		/// <param name="document">The document that is being searched.</param>
-		/// <param name="localIdentifierNames">The local identifier names that should be ignored.</param>
-		/// <param name="declarationsCache">The known declarations that can be ignored.</param>
-		public CSharpFreeTextSpellingHighlightFinder(
-			ShellSpellCheckResources shellSpellCheckResources,
-			IDocument document,
-			HashSet<string> localIdentifierNames,
-			IDeclarationsCache declarationsCache
-		) {
-			_shellSpellCheckResources = shellSpellCheckResources;
-			_document = document;
-			_localIdentifierNames = localIdentifierNames;
-			_declarationsCache = declarationsCache;
-		}
-
-		private bool WordIsIgnored(string word)
-		{
-			return CSharpUtil.IsKeyword(word)
-				|| _shellSpellCheckResources.IsIgnoredInsensitive(word)
-				|| _localIdentifierNames.Contains(word)
-				|| _declarationsCache.GetElementsByShortName(word).NotNullAndHasAny()
-				|| _localIdentifierNames.Contains(word + "Attribute")
-				|| _declarationsCache.GetElementsByShortName(word + "Attribute").NotNullAndHasAny()
-				|| CStyleFreeTextParser.LooksLikeCodeWord(word);
-		}
-
-		/// <summary>
-		/// Locates spelling errors within a free form XML text string.
-		/// </summary>
-		/// <param name="node">The PSI node that is being processed.</param>
-		/// <param name="text">The text string within the node that is to be processed.</param>
-		/// <param name="textRange">The location within the document of the text.</param>
-		/// <returns>Spelling error highlights that have been identified.</returns>
-		public IEnumerable<HighlightingInfo> FindXmlTextHighlightings(
-			ITreeNode node,
-			string text,
-			DocumentRange textRange
-		) {
-			var parser = new CStyleFreeTextParser();
-			var xmlTextParts = parser.ParseXmlTextParts(new TextSubString(text));
-			var wordParts = xmlTextParts.SelectMany(parser.ParseSentenceWordsForSpellCheck);
-			foreach(var wordPart in wordParts)
-			{
-				var word = wordPart.SubText;
-
-				// Make sure that the word is not to be ignored for any reason.
-				if(WordIsIgnored(word)) continue;
-
-				// Finally we check the spelling of the word.
-				if (_shellSpellCheckResources.Primary.Check(word)) continue;
-
-				// If we got this far we need to offer spelling suggestions.
-				var wordPartDocumentOffset = textRange.TextRange.StartOffset + wordPart.Offset;
-				var wordRange = new DocumentRange(_document,new TextRange(wordPartDocumentOffset, wordPartDocumentOffset + word.Length));
-				var highlight = new CSharpSpellingErrorHighlighting(
-					node,
-					wordRange,
-					word,
-					null
-				);
-				yield return new HighlightingInfo(wordRange, highlight);
-			}
-
-		}
-		
-
-
-	}
-}

File src/YouCantSpell.ReSharper.Shared/CStyleSpellCheckDaemonStageProcessBase.cs

 	{
 
 		private const int MinWordSize = 2;
-		private const int MaxSuggestions = 10;
 
 		/// <summary>
 		/// Force the casing of the first character in a string to the desired case.
 			}
 		}
 
+		private struct ParseKey : IEquatable<ParseKey>
+		{
+			public readonly NamingRule NamingRule;
+			public readonly string Text;
+
+			public ParseKey(string text, NamingRule namingRule) {
+				Text = text;
+				NamingRule = namingRule;
+			}
+
+			public override bool Equals(object obj) {
+				return obj is ParseKey && Equals((ParseKey)obj);
+			}
+
+			public bool Equals(ParseKey other) {
+				return String.Equals(Text, other.Text) && NamingRule.Equals(other.NamingRule);
+			}
+
+			public override int GetHashCode() {
+				return Text.GetHashCode() ^ -NamingRule.GetHashCode();
+			}
+		}
+
+		private readonly Dictionary<ParseKey, Name> _nameParseCache = new Dictionary<ParseKey, Name>();
+		private readonly ReaderWriterLockSlim _nameParseCacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
+
 		protected CStyleSpellCheckDaemonStageProcessBase(
 			IDaemonProcess process,
 			IContextBoundSettingsStore settingsStore,
 
 		public PsiLanguageType LanguageType { get; private set; }
 
-		public abstract void Execute(Action<DaemonStageResult> commiter);
-
-		private struct ParseKey : IEquatable<ParseKey>
-		{
-			public readonly NamingRule NamingRule;
-			public readonly string Text;
-
-			public ParseKey(string text, NamingRule namingRule) {
-				Text = text;
-				NamingRule = namingRule;
-			}
-
-			public override bool Equals(object obj) {
-				return obj is ParseKey && Equals((ParseKey) obj);
-			}
-
-			public bool Equals(ParseKey other) {
-				return String.Equals(Text, other.Text) && NamingRule.Equals(other.NamingRule);
-			}
-
-			public override int GetHashCode() {
-				return Text.GetHashCode() ^ -NamingRule.GetHashCode();
-			}
-		}
-
-		private readonly Dictionary<ParseKey, Name> _nameParseCache = new Dictionary<ParseKey,Name>();
-		private readonly ReaderWriterLockSlim _nameParseCacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
+		public abstract void Execute(Action<DaemonStageResult> committer);
 
 		private Name ParseName(string name, NamingRule namingRule) {
 			Name result;
 		}
 
 		protected DocumentRange? FindTrueDocumentRange(TreeTextRange range) {
-			var validPartRanges = CodeFile.GetIntersectingRanges(range)
-					.Where(x => x.Document == Document)
-					.ToList();
-			if(validPartRanges.Count != 1)
-				return null;
-			return validPartRanges[0];
+			return CodeFile.GetIntersectingRanges(range)
+				.SingleOrDefault(x => x.Document == PsiSourceFile.Document);
 		}
 
 		protected IEnumerable<TextSubString> ParseNameParts(string nameText) {
 		protected string RemovePrefixAndSuffix(IIdentifier identifier) {
 			var name = ParseName(identifier);
 			var nameParts = name.InnerElements.ToList();
-			if(nameParts.Count > 0 && nameParts[0].IsSeparator)
-				nameParts.RemoveAt(0);
-			if(nameParts.Count > 0 && nameParts[nameParts.Count - 1].IsSeparator)
-				nameParts.RemoveAt(nameParts.Count - 1);
-			return String.Concat(nameParts.Select(x => x.Text));
+			int startIndex = (nameParts.Count > 0 && nameParts[0].IsSeparator)
+				? 1
+				: 0;
+			int endIndex = (nameParts.Count > 0 && nameParts[nameParts.Count - 1].IsSeparator)
+				? nameParts.Count - 1
+				: nameParts.Count;
+
+			if (startIndex >= endIndex) return String.Empty;
+
+			if (startIndex == 0 && endIndex == nameParts.Count)
+				return identifier.Name;
+
+			var builder = new StringBuilder();
+			for(int i = startIndex; i < endIndex; i++)
+				builder.Append(nameParts[i].Text);
+			return builder.ToString();
 		}
 
 		protected virtual IEnumerable<HighlightingInfo> FindFreeTextHighlightings(ITreeNode node, string text, DocumentRange textRange, HashSet<string> localIdentifierNames, IDeclarationsCache declarationsCache) {
+			var highlights = new List<HighlightingInfo>(0);
+			if(IsIgnored(text))
+				return highlights;
+
 			var parser = new CStyleFreeTextParser();
 			var xmlTextParts = parser.ParseXmlTextParts(new TextSubString(text));
 			var wordParts = xmlTextParts.SelectMany(parser.ParseSentenceWordsForSpellCheck);
 					Document,
 					new TextRange(wordPartDocumentOffset, wordPartDocumentOffset + word.Length)
 				);
-				yield return new HighlightingInfo(wordRange, CreateErrorHighlighting(node,wordRange,word,null));
+				highlights.Add(new HighlightingInfo(wordRange, CreateErrorHighlighting(node,wordRange,word,null)));
 			}
+			return highlights;
 		}
 
 		protected IEnumerable<HighlightingInfo> FindHighlightings(IComment comment, HashSet<string> localIdentifierNames, IDeclarationsCache declarationsCache) {
 		private string MassageProposedSuggestion(string newSuggestion, bool literalIsOk, int position, NamingRule namingRule) {
 			// after rendering the suggestion as an identifier name we need to parse it again to remove some stuff
 			// just in case anything funny like a prefix or @ was added we need to get rid of that (unless @ is OK)
-			var reparsedNamed = NamingManager.Parsing.Parse(newSuggestion, NamingRule.Default, NamingPolicyProvider);
-			if (reparsedNamed.NamePrefix.Text.Length > 0 && (!literalIsOk || reparsedNamed.NamePrefix.Text != "@")) {
+			var reParsedNamed = NamingManager.Parsing.Parse(newSuggestion, NamingRule.Default, NamingPolicyProvider);
+			if (reParsedNamed.NamePrefix.Text.Length > 0 && (!literalIsOk || reParsedNamed.NamePrefix.Text != "@")) {
 				// we need to pull the prefix off except for one special situation, with literals, if that is a prefix
-				newSuggestion = newSuggestion.Substring(reparsedNamed.NamePrefix.Text.Length);
+				newSuggestion = newSuggestion.Substring(reParsedNamed.NamePrefix.Text.Length);
 			}
 			if (!literalIsOk && newSuggestion.Length > 1 && newSuggestion.StartsWith("@"))
 				newSuggestion = newSuggestion.Substring(1); // if the @ prefix is not OK we need to get rid of that
 							//.Select(x => FormatSuggestion(x, wordPosition, namingRule, parsedNameParts.Count, textClassification))
 							.Where(x => !String.IsNullOrEmpty(x) && word != x)
 							.Distinct()
-							.Take(MaxSuggestions)
+							.Take(ReSharperUtil.MaxSuggestions)
 							.ToArray()
 					)
 				));

File src/YouCantSpell.ReSharper.Shared/Html/HtmlFreeTextSpellingHighlightFinder.cs

-using System;
-using System.Collections.Generic;
-using JetBrains.DocumentModel;
-using JetBrains.ReSharper.Daemon;
-using JetBrains.Util;
-using YouCantSpell.CStyle;
-using JetBrains.ReSharper.Psi.Tree;
-
-namespace YouCantSpell.ReSharper.Html
-{
-	public class HtmlFreeTextSpellingHighlightFinder
-	{
-		private const int MinWordSize = 2;
-
-		private readonly ShellSpellCheckResources _shellSpellCheckResources;
-		private readonly IDocument _document;
-		
-		public HtmlFreeTextSpellingHighlightFinder(
-			ShellSpellCheckResources shellSpellCheckResources,
-			IDocument document
-		) {
-			_shellSpellCheckResources = shellSpellCheckResources;
-			_document = document;
-		}
-
-		private bool WordIsIgnored(string word) {
-			return String.IsNullOrEmpty(word)
-				|| word.Length < MinWordSize
-				|| _shellSpellCheckResources.IsIgnoredInsensitive(word)
-				|| CStyleFreeTextParser.LooksLikeCodeWord(word);
-		}
-
-		public IEnumerable<HighlightingInfo> FindWordHighlightings(
-			ITreeNode node,
-			string text,
-			DocumentRange textRange
-		) {
-			var parser = new CStyleFreeTextParser();
-			var wordParts = parser.ParseSentenceWordsForSpellCheck(new TextSubString(text));
-			foreach(var wordPart in wordParts) {
-				var word = wordPart.SubText;
-
-				// Make sure that the word is not to be ignored for any reason.
-				if (WordIsIgnored(word)) continue;
-
-				// Finally we check the spelling of the word.
-				if (_shellSpellCheckResources.Primary.Check(word)) continue;
-
-				// If we got this far we need to offer spelling suggestions.
-				var wordPartDocumentOffset = textRange.TextRange.StartOffset + wordPart.Offset;
-				var wordRange = new DocumentRange(_document, new TextRange(wordPartDocumentOffset, wordPartDocumentOffset + word.Length));
-				var highlight = new HtmlSpellingErrorHighlighting(
-					node,
-					wordRange,
-					word,
-					null
-				);
-				yield return new HighlightingInfo(wordRange, highlight);
-			}
-		}
-
-	}
-}

File src/YouCantSpell.ReSharper.Shared/Html/HtmlSpellCheckDaemonStageProcess.cs

 using System;
 using System.Collections.Generic;
-using System.Linq;
 using JetBrains.DocumentModel;
 using JetBrains.ReSharper.Daemon;
 using JetBrains.ReSharper.Psi;
 using JetBrains.ReSharper.Psi.Html.Impl.Tree;
 using JetBrains.ReSharper.Psi.Html.Tree;
 using JetBrains.ReSharper.Psi.Tree;
-using JetBrains.Application;
 
 namespace YouCantSpell.ReSharper.Html
 {
-	public class HtmlSpellCheckDaemonStageProcess : IDaemonStageProcess
+	public class HtmlSpellCheckDaemonStageProcess : TagMarkupSpellCheckDaemonStageProcessBase<IHtmlFile>
 	{
 
-		private readonly IDaemonProcess _daemonProcess;
-		private readonly ShellSpellCheckResources _spellCheckResources;
-		private readonly IPsiSourceFile _sourceFile;
-		private readonly IHtmlFile _htmlFile;
-		private readonly HtmlFreeTextSpellingHighlightFinder _freeTextSpellingHighlightFinder;
-
-		public HtmlSpellCheckDaemonStageProcess(IDaemonProcess daemonProcess, IHtmlFile htmlFile) {
-			if (null == daemonProcess) throw new ArgumentNullException("daemonProcess");
-			if (null == htmlFile) throw new ArgumentNullException("htmlFile");
-
-			_daemonProcess = daemonProcess;
-			_htmlFile = htmlFile;
-			_spellCheckResources = Shell.Instance.GetComponent<ShellSpellCheckResources>();
-			_sourceFile = daemonProcess.SourceFile;
-			_freeTextSpellingHighlightFinder = new HtmlFreeTextSpellingHighlightFinder(
-				_spellCheckResources, _sourceFile.Document);
-		}
-
-		public IDaemonProcess DaemonProcess {
-			get { return _daemonProcess; }
-		}
-
-		private DocumentRange? FindTrueDocumentRange(TreeTextRange range) {
-			return _htmlFile.GetIntersectingRanges(range)
-				.SingleOrDefault(x => x.Document == _sourceFile.Document);
-		}
-
-		private IEnumerable<HighlightingInfo> FindWordHighlightings(ITreeNode node)
-		{
-			var validRange = FindTrueDocumentRange(node.GetTreeTextRange());
-			if (!validRange.HasValue) return Enumerable.Empty<HighlightingInfo>();
-
-			return _freeTextSpellingHighlightFinder
-				.FindWordHighlightings(node, node.GetText(), validRange.Value);
-		}
+		public HtmlSpellCheckDaemonStageProcess(IDaemonProcess daemonProcess, IHtmlFile htmlFile)
+			:base(daemonProcess, htmlFile) { }
 
 		private IEnumerable<HighlightingInfo> FindHighlightings(HtmlTag node) {
 			var results = new List<HighlightingInfo>(0);
 				var validRange = FindTrueDocumentRange(valueElement.GetUnquotedTreeTextRange());
 				if (!validRange.HasValue) continue;
 
-				results.AddRange(_freeTextSpellingHighlightFinder
-					.FindWordHighlightings(valueElement,valueElement.UnquotedValue,validRange.Value));
+				results.AddRange(FindWordHighlightings(valueElement,valueElement.UnquotedValue,validRange.Value));
 			}
 			return results;
 		}
 
-		public void Execute(Action<DaemonStageResult> committer) {
-			var textNodeTypes = _htmlFile.TokenTypes.TEXT;
+		protected override SpellingErrorHighlightingBase CreateHighlighting(ITreeNode node, DocumentRange errorRange, string wordInError, Func<string, string[]> getSuggestions) {
+			return new HtmlSpellingErrorHighlighting(node, errorRange, wordInError, null);
+		}
+
+		public override void Execute(Action<DaemonStageResult> committer) {
+			var textNodeTypes = CodeFile.TokenTypes.TEXT;
 			var highlightings = new List<HighlightingInfo>(0);
 
-			_htmlFile.ProcessChildren<HtmlTag>(node =>
+			CodeFile.ProcessChildren<HtmlTag>(node =>
 				highlightings.AddRange(FindHighlightings(node))
 			);
 
-			_htmlFile.ProcessChildren<TreeElement>(node => {
+			CodeFile.ProcessChildren<TreeElement>(node => {
 				if(textNodeTypes.Equals(node.NodeType))
 					highlightings.AddRange(FindWordHighlightings(node));
 			});

File src/YouCantSpell.ReSharper.Shared/JavaScript/JavaScriptFreeTextSpellingHighlightFinder.cs

-using System;
-using System.Collections.Generic;
-using System.Linq;
-using JetBrains.DocumentModel;
-using JetBrains.ReSharper.Daemon;
-using JetBrains.ReSharper.Psi.Caches;
-using JetBrains.ReSharper.Psi.Tree;
-using JetBrains.Util;
-using YouCantSpell.CStyle;
-using YouCantSpell.Utility;
-
-namespace YouCantSpell.ReSharper.JavaScript
-{
-	[Obsolete]
-	public class JavaScriptFreeTextSpellingHighlightFinder
-	{
-
-		private readonly ShellSpellCheckResources _shellSpellCheckResources;
-		private readonly IDocument _document;
-		private readonly HashSet<string> _localIdentifierNames;
-		private readonly IDeclarationsCache _declarationsCache;
-
-		/// <summary>
-		/// Creates a free text processor for the given document and shellSpellCheckResources with the provided ignored words and known declarations.
-		/// </summary>
-		/// <param name="shellSpellCheckResources">The shellSpellCheckResources that is executing this search.</param>
-		/// <param name="document">The document that is being searched.</param>
-		/// <param name="localIdentifierNames">The local identifier names that should be ignored.</param>
-		/// <param name="declarationsCache">The known declarations that can be ignored.</param>
-		public JavaScriptFreeTextSpellingHighlightFinder(
-			ShellSpellCheckResources shellSpellCheckResources,
-			IDocument document,
-			HashSet<string> localIdentifierNames,
-			IDeclarationsCache declarationsCache
-		) {
-			_shellSpellCheckResources = shellSpellCheckResources;
-			_document = document;
-			_localIdentifierNames = localIdentifierNames;
-			_declarationsCache = declarationsCache;
-		}
-
-		private bool WordIsIgnored(string word) {
-			return CStyleFreeTextParser.LooksLikeCodeWord(word)
-				|| JavaScriptUtil.IsKeyword(word)
-				|| _shellSpellCheckResources.IsIgnoredInsensitive(word)
-				|| _localIdentifierNames.Contains(word)
-				|| _declarationsCache.GetElementsByShortName(word).NotNullAndHasAny();
-		}
-
-		/// <summary>
-		/// Locates spelling errors within a free form XML text string.
-		/// </summary>
-		/// <param name="node">The PSI node that is being processed.</param>
-		/// <param name="text">The text string within the node that is to be processed.</param>
-		/// <param name="textRange">The location within the document of the text.</param>
-		/// <returns>Spelling error highlights that have been identified.</returns>
-		public IEnumerable<HighlightingInfo> FindXmlTextHighlightings(
-			ITreeNode node,
-			string text,
-			DocumentRange textRange
-		) {
-			var parser = new CStyleFreeTextParser();
-			var xmlTextParts = parser.ParseXmlTextParts(new TextSubString(text));
-			var wordParts = xmlTextParts.SelectMany(parser.ParseSentenceWordsForSpellCheck);
-			foreach(var wordPart in wordParts) {
-				var word = wordPart.SubText;
-
-				// Make sure that the word is not to be ignored for any reason.
-				if(WordIsIgnored(word))
-					continue;
-
-				// Finally we check the spelling of the word.
-				if(_shellSpellCheckResources.Primary.Check(word))
-					continue;
-
-				// If we got this far we need to offer spelling suggestions.
-				var wordPartDocumentOffset = textRange.TextRange.StartOffset + wordPart.Offset;
-				var wordRange = new DocumentRange(
-					_document,
-					new TextRange(wordPartDocumentOffset, wordPartDocumentOffset + word.Length)
-				);
-				var highlight = new JavaScriptSpellingErrorHighlighting(
-					node,
-					wordRange,
-					word,
-					null
-				);
-				yield return new HighlightingInfo(wordRange, highlight);
-			}
-
-		}
-
-	}
-}

File src/YouCantSpell.ReSharper.Shared/ReSharperUtil.cs

 	public static class ReSharperUtil
 	{
 
+		internal static readonly int MaxSuggestions = 13;
+
 		/// <summary>
 		/// Locates resharper in-code configuration comments.
 		/// </summary>

File src/YouCantSpell.ReSharper.Shared/SpellingQuickFixBase.cs

 		where THighlighting : SpellingErrorHighlightingBase
 		where TSpellingFixBulbItem : SpellingFixBulbItemBase<THighlighting>
 	{
+
 		/// <summary>
 		/// The bound highlighting.
 		/// </summary>
 		JetBrains.ReSharper.Intentions.Extensibility.IBulbAction
 #endif
 					>(CreateSpellingFix)
+					.Take(ReSharperUtil.MaxSuggestions)
 					.ToList();
 				
 				// append on the option parameters

File src/YouCantSpell.ReSharper.Shared/TagMarkupSpellCheckDaemonStageProcessBase.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using JetBrains.Application;
+using JetBrains.DocumentModel;
+using JetBrains.ReSharper.Daemon;
+using JetBrains.ReSharper.Psi;
+using JetBrains.ReSharper.Psi.Tree;
+using JetBrains.Util;
+using YouCantSpell.CStyle;
+
+namespace YouCantSpell.ReSharper
+{
+	public abstract class TagMarkupSpellCheckDaemonStageProcessBase<TCodeFile>
+		: IDaemonStageProcess
+		where TCodeFile : class, IFile
+	{
+
+		private const int MinWordSize = 2;
+
+		protected TagMarkupSpellCheckDaemonStageProcessBase(IDaemonProcess daemonProcess, TCodeFile codeFile)
+		{
+			if(null == daemonProcess) throw new ArgumentNullException("daemonProcess");
+			if(null == codeFile) throw new ArgumentNullException("codeFile");
+			DaemonProcess = daemonProcess;
+			CodeFile = codeFile;
+
+			SpellCheckResources = Shell.Instance.GetComponent<ShellSpellCheckResources>();
+			PsiSourceFile = daemonProcess.SourceFile;
+			Document = daemonProcess.Document;
+		}
+
+		public IDaemonProcess DaemonProcess { get; private set; }
+
+		public TCodeFile CodeFile { get; private set; }
+
+		public ShellSpellCheckResources SpellCheckResources { get; private set; }
+
+		public IPsiSourceFile PsiSourceFile { get; private set; }
+
+		public IDocument Document { get; private set; }
+
+		protected DocumentRange? FindTrueDocumentRange(TreeTextRange range) {
+			return CodeFile.GetIntersectingRanges(range)
+				.SingleOrDefault(x => x.Document == PsiSourceFile.Document);
+		}
+
+		protected bool WordIsIgnored(string word) {
+			return String.IsNullOrEmpty(word)
+				|| word.Length < MinWordSize
+				|| SpellCheckResources.IsIgnoredInsensitive(word)
+				|| CStyleFreeTextParser.LooksLikeCodeWord(word);
+		}
+
+		protected IEnumerable<HighlightingInfo> FindWordHighlightings(ITreeNode node) {
+			var validRange = FindTrueDocumentRange(node.GetTreeTextRange());
+			if(!validRange.HasValue) return Enumerable.Empty<HighlightingInfo>();
+
+			return FindWordHighlightings(node, node.GetText(), validRange.Value);
+		}
+
+		protected IEnumerable<HighlightingInfo> FindWordHighlightings(ITreeNode node, string text, DocumentRange textRange) {
+			var highlights = new List<HighlightingInfo>(0);
+			if(WordIsIgnored(text))
+				return highlights;
+
+			var parser = new CStyleFreeTextParser();
+			var wordParts = parser.ParseSentenceWordsForSpellCheck(new TextSubString(text));
+			foreach(var wordPart in wordParts) {
+				var word = wordPart.SubText;
+
+				// Make sure that the word is not to be ignored for any reason.
+				if(WordIsIgnored(word)) continue;
+
+				// Finally we check the spelling of the word.
+				if(SpellCheckResources.Primary.Check(word)) continue;
+
+				// If we got this far we need to offer spelling suggestions.
+				var wordPartDocumentOffset = textRange.TextRange.StartOffset + wordPart.Offset;
+				var wordRange = new DocumentRange(Document, new TextRange(wordPartDocumentOffset, wordPartDocumentOffset + word.Length));
+				var highlight = CreateHighlighting(node, wordRange, word, null);
+				highlights.Add(new HighlightingInfo(wordRange, highlight));
+			}
+			return highlights;
+		}
+
+		public abstract void Execute(Action<DaemonStageResult> committer);
+
+		protected abstract SpellingErrorHighlightingBase CreateHighlighting(ITreeNode node, DocumentRange errorRange, string wordInError, Func<string, string[]> getSuggestions);
+
+	}
+}

File src/YouCantSpell.ReSharper.Shared/Xml/XmlFreeTextSpellingHighlightFinder.cs

-using System;
-using System.Collections.Generic;
-using JetBrains.DocumentModel;
-using JetBrains.ReSharper.Daemon;
-using JetBrains.ReSharper.Psi.Tree;
-using JetBrains.Util;
-using YouCantSpell.CStyle;
-
-namespace YouCantSpell.ReSharper.Xml
-{
-	public class XmlFreeTextSpellingHighlightFinder
-	{
-		private const int MinWordSize = 2;
-
-		private readonly ShellSpellCheckResources _shellSpellCheckResources;
-		private readonly IDocument _document;
-
-		public XmlFreeTextSpellingHighlightFinder(
-			ShellSpellCheckResources shellSpellCheckResources,
-			IDocument document
-		) {
-			_shellSpellCheckResources = shellSpellCheckResources;
-			_document = document;
-		}
-
-		private bool WordIsIgnored(string word) {
-			return String.IsNullOrEmpty(word)
-				|| word.Length < MinWordSize
-				|| _shellSpellCheckResources.IsIgnoredInsensitive(word)
-				|| CStyleFreeTextParser.LooksLikeCodeWord(word);
-		}
-
-		public IEnumerable<HighlightingInfo> FindWordHighlightings(
-			ITreeNode node,
-			string text,
-			DocumentRange textRange
-		) {
-			var highlights = new List<HighlightingInfo>(0);
-			var parser = new CStyleFreeTextParser();
-			var wordParts = parser.ParseSentenceWordsForSpellCheck(new TextSubString(text));
-			foreach(var wordPart in wordParts) {
-				var word = wordPart.SubText;
-
-				// Make sure that the word is not to be ignored for any reason.
-				if (WordIsIgnored(word)) continue;
-
-				// Finally we check the spelling of the word.
-				if (_shellSpellCheckResources.Primary.Check(word)) continue;
-
-				// If we got this far we need to offer spelling suggestions.
-				var wordPartDocumentOffset = textRange.TextRange.StartOffset + wordPart.Offset;
-				var wordRange = new DocumentRange(_document, new TextRange(wordPartDocumentOffset, wordPartDocumentOffset + word.Length));
-				var highlight = new XmlSpellingErrorHighlighting(
-					node,
-					wordRange,
-					word,
-					null
-				);
-				highlights.Add(new HighlightingInfo(wordRange, highlight));
-			}
-			return highlights;
-		}
-
-	}
-}

File src/YouCantSpell.ReSharper.Shared/Xml/XmlSpellCheckDaemonStageProcess.cs

 using System;
 using System.Collections.Generic;
 using System.Linq;
-using JetBrains.Application;
 using JetBrains.DocumentModel;
 using JetBrains.ReSharper.Daemon;
 using JetBrains.ReSharper.Psi;
 
 namespace YouCantSpell.ReSharper.Xml
 {
-	public class XmlSpellCheckDaemonStageProcess : IDaemonStageProcess
+	public class XmlSpellCheckDaemonStageProcess : TagMarkupSpellCheckDaemonStageProcessBase<IXmlFile>
 	{
 
-		private readonly IDaemonProcess _daemonProcess;
-		private readonly ShellSpellCheckResources _spellCheckResources;
-		private readonly IXmlFile _xmlFile;
-		private readonly IPsiSourceFile _sourceFile;
-		private readonly XmlFreeTextSpellingHighlightFinder _freeTextSpellingHighlightFinder;
-
-		public XmlSpellCheckDaemonStageProcess(IDaemonProcess daemonProcess, IXmlFile xmlFile) {
-			if (null == daemonProcess) throw new ArgumentNullException("daemonProcess");
-			if (null == xmlFile) throw new ArgumentNullException("xmlFile");
-
-			_daemonProcess = daemonProcess;
-			_xmlFile = xmlFile;
-			_spellCheckResources = Shell.Instance.GetComponent<ShellSpellCheckResources>();
-			_sourceFile = daemonProcess.SourceFile;
-			_freeTextSpellingHighlightFinder = new XmlFreeTextSpellingHighlightFinder(
-				_spellCheckResources, _sourceFile.Document);
-		}
-
-		public IDaemonProcess DaemonProcess {
-			get { return _daemonProcess; }
-		}
-
-		private DocumentRange? FindTrueDocumentRange(TreeTextRange range) {
-			return _xmlFile.GetIntersectingRanges(range)
-				.SingleOrDefault(x => x.Document == _sourceFile.Document);
-		}
-
-		private IEnumerable<HighlightingInfo> FindWordHighlightings(ITreeNode node) {
-			var validRange = FindTrueDocumentRange(node.GetTreeTextRange());
-			if (!validRange.HasValue) return Enumerable.Empty<HighlightingInfo>();
-
-			return _freeTextSpellingHighlightFinder.FindWordHighlightings(node, node.GetText(), validRange.Value);
-		}
+		public XmlSpellCheckDaemonStageProcess(IDaemonProcess daemonProcess, IXmlFile xmlFile)
+			: base(daemonProcess, xmlFile) { }
 
 		private IEnumerable<HighlightingInfo> FindWordHighlightings(XmlValueToken node) {
 			var absoluteUnquotedRange = node.GetTreeTextRange();
-			absoluteUnquotedRange = new TreeTextRange(
+
+			var validRange = FindTrueDocumentRange(new TreeTextRange(
 				absoluteUnquotedRange.StartOffset + node.UnquotedValueRange.StartOffset,
 				node.UnquotedValueRange.Length
-			);
-			var validRange = FindTrueDocumentRange(absoluteUnquotedRange);
+			));
 			if (!validRange.HasValue) return Enumerable.Empty<HighlightingInfo>();
 
-			return _freeTextSpellingHighlightFinder.FindWordHighlightings(
-				node,
-				node.UnquotedValue,
-				validRange.Value
-			);
+			return FindWordHighlightings(node, node.UnquotedValue, validRange.Value);
 		}
 
-		public void Execute(Action<DaemonStageResult> committer) {
+		protected override SpellingErrorHighlightingBase CreateHighlighting(ITreeNode node, DocumentRange errorRange, string wordInError, Func<string, string[]> getSuggestions) {
+			return new XmlSpellingErrorHighlighting(node, errorRange, wordInError, getSuggestions);
+		}
+
+		public override void Execute(Action<DaemonStageResult> committer) {
 			var highlightings = new List<HighlightingInfo>(0);
 
-			_xmlFile.ProcessChildren<XmlFloatingTextToken>(node => {
+			CodeFile.ProcessChildren<XmlFloatingTextToken>(node => {
 				if(!node.IsIdentifier() && !node.IsWhitespaceToken())
 					highlightings.AddRange(FindWordHighlightings(node));
 			});
 
-			_xmlFile.ProcessChildren<XmlValueToken>(node => highlightings.AddRange(FindWordHighlightings(node)));
+			CodeFile.ProcessChildren<XmlValueToken>(node => highlightings.AddRange(FindWordHighlightings(node)));
 
-			_xmlFile.ProcessChildren<XmlToken>(node => {
+			CodeFile.ProcessChildren<XmlToken>(node => {
 				if (node.XmlTokenTypes.COMMENT_BODY.Equals(node.NodeType))
 					highlightings.AddRange(FindWordHighlightings(node));
 			});

File src/YouCantSpell.ReSharper.v61.Net35/YouCantSpell.ReSharper.v61.Net35.csproj

     <Reference Include="WindowsBase" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\CSharp\CSharpFreeTextSpellingHighlightFinder.cs">
-      <Link>CSharp\CSharpFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\CSharp\CSharpSpellCheckDaemonStageProcess.cs">
       <Link>CSharp\CSharpSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\CStyleSpellCheckDaemonStageProcessBase.cs">
       <Link>CStyleSpellCheckDaemonStageProcessBase.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlFreeTextSpellingHighlightFinder.cs">
-      <Link>Html\HtmlFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlSpellCheckDaemonStageProcess.cs">
       <Link>Html\HtmlSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlSpellingQuickFix.cs">
       <Link>Html\HtmlSpellingQuickFix.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\JavaScript\JavaScriptFreeTextSpellingHighlightFinder.cs">
-      <Link>JavaScript\JavaScriptFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\JavaScript\JavaScriptSpellCheckDaemonStageProcess.cs">
       <Link>JavaScript\JavaScriptSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\SpellingQuickFixBase.cs">
       <Link>SpellingQuickFixBase.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\Xml\XmlFreeTextSpellingHighlightFinder.cs">
-      <Link>Xml\XmlFreeTextSpellingHighlightFinder.cs</Link>
+    <Compile Include="..\YouCantSpell.ReSharper.Shared\TagMarkupSpellCheckDaemonStageProcessBase.cs">
+      <Link>TagMarkupSpellCheckDaemonStageProcessBase.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Xml\XmlSpellCheckDaemonStageProcess.cs">
       <Link>Xml\XmlSpellCheckDaemonStageProcess.cs</Link>

File src/YouCantSpell.ReSharper.v61/YouCantSpell.ReSharper.v61.csproj

     <Reference Include="WindowsBase" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\CSharp\CSharpFreeTextSpellingHighlightFinder.cs">
-      <Link>CSharp\CSharpFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\CSharp\CSharpSpellCheckDaemonStageProcess.cs">
       <Link>CSharp\CSharpSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\CStyleSpellCheckDaemonStageProcessBase.cs">
       <Link>CStyleSpellCheckDaemonStageProcessBase.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlFreeTextSpellingHighlightFinder.cs">
-      <Link>Html\HtmlFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlSpellCheckDaemonStageProcess.cs">
       <Link>Html\HtmlSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlSpellingQuickFix.cs">
       <Link>Html\HtmlSpellingQuickFix.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\JavaScript\JavaScriptFreeTextSpellingHighlightFinder.cs">
-      <Link>JavaScript\JavaScriptFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\JavaScript\JavaScriptSpellCheckDaemonStageProcess.cs">
       <Link>JavaScript\JavaScriptSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\SpellingQuickFixBase.cs">
       <Link>SpellingQuickFixBase.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\Xml\XmlFreeTextSpellingHighlightFinder.cs">
-      <Link>Xml\XmlFreeTextSpellingHighlightFinder.cs</Link>
+    <Compile Include="..\YouCantSpell.ReSharper.Shared\TagMarkupSpellCheckDaemonStageProcessBase.cs">
+      <Link>TagMarkupSpellCheckDaemonStageProcessBase.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Xml\XmlSpellCheckDaemonStageProcess.cs">
       <Link>Xml\XmlSpellCheckDaemonStageProcess.cs</Link>

File src/YouCantSpell.ReSharper.v70.Net35/YouCantSpell.ReSharper.v70.Net35.csproj

     <None Include="packages.config" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\CSharp\CSharpFreeTextSpellingHighlightFinder.cs">
-      <Link>CSharp\CSharpFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\CSharp\CSharpSpellCheckDaemonStageProcess.cs">
       <Link>CSharp\CSharpSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\CStyleSpellCheckDaemonStageProcessBase.cs">
       <Link>CStyleSpellCheckDaemonStageProcessBase.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlFreeTextSpellingHighlightFinder.cs">
-      <Link>Html\HtmlFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlSpellCheckDaemonStageProcess.cs">
       <Link>Html\HtmlSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlSpellingQuickFix.cs">
       <Link>Html\HtmlSpellingQuickFix.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\JavaScript\JavaScriptFreeTextSpellingHighlightFinder.cs">
-      <Link>JavaScript\JavaScriptFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\JavaScript\JavaScriptSpellCheckDaemonStageProcess.cs">
       <Link>JavaScript\JavaScriptSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\SpellingQuickFixBase.cs">
       <Link>SpellingQuickFixBase.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\Xml\XmlFreeTextSpellingHighlightFinder.cs">
-      <Link>Xml\XmlFreeTextSpellingHighlightFinder.cs</Link>
+    <Compile Include="..\YouCantSpell.ReSharper.Shared\TagMarkupSpellCheckDaemonStageProcessBase.cs">
+      <Link>TagMarkupSpellCheckDaemonStageProcessBase.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Xml\XmlSpellCheckDaemonStageProcess.cs">
       <Link>Xml\XmlSpellCheckDaemonStageProcess.cs</Link>

File src/YouCantSpell.ReSharper.v70/YouCantSpell.ReSharper.v70.csproj

     <Reference Include="WindowsBase" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\CSharp\CSharpFreeTextSpellingHighlightFinder.cs">
-      <Link>CSharp\CSharpFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\CSharp\CSharpSpellCheckDaemonStageProcess.cs">
       <Link>CSharp\CSharpSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\CStyleSpellCheckDaemonStageProcessBase.cs">
       <Link>CStyleSpellCheckDaemonStageProcessBase.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlFreeTextSpellingHighlightFinder.cs">
-      <Link>Html\HtmlFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlSpellCheckDaemonStageProcess.cs">
       <Link>Html\HtmlSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Html\HtmlSpellingQuickFix.cs">
       <Link>Html\HtmlSpellingQuickFix.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\JavaScript\JavaScriptFreeTextSpellingHighlightFinder.cs">
-      <Link>JavaScript\JavaScriptFreeTextSpellingHighlightFinder.cs</Link>
-    </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\JavaScript\JavaScriptSpellCheckDaemonStageProcess.cs">
       <Link>JavaScript\JavaScriptSpellCheckDaemonStageProcess.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\SpellingQuickFixBase.cs">
       <Link>SpellingQuickFixBase.cs</Link>
     </Compile>
-    <Compile Include="..\YouCantSpell.ReSharper.Shared\Xml\XmlFreeTextSpellingHighlightFinder.cs">
-      <Link>Xml\XmlFreeTextSpellingHighlightFinder.cs</Link>
+    <Compile Include="..\YouCantSpell.ReSharper.Shared\TagMarkupSpellCheckDaemonStageProcessBase.cs">
+      <Link>TagMarkupSpellCheckDaemonStageProcessBase.cs</Link>
     </Compile>
     <Compile Include="..\YouCantSpell.ReSharper.Shared\Xml\XmlSpellCheckDaemonStageProcess.cs">
       <Link>Xml\XmlSpellCheckDaemonStageProcess.cs</Link>