Source

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

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
{
	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(x => parser.ParseSentenceWordsForSpellCheck(x));
			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);
			}

		}

	}
}