YouCantSpell / 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>
	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(
				yield return new HighlightingInfo(wordRange, highlight);


Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.