Commits

aarondandy committed 18d330e

fixes so that changes in the options page apply (nearly) immediately

  • Participants
  • Parent commits 3e0b1f6

Comments (0)

Files changed (8)

File src/YouCantSpell.Core/SpellCheckerPointer.cs

+using System;
+using System.Collections.Generic;
+
+namespace YouCantSpell
+{
+	public class SpellCheckerPointer : ISpellChecker, IDisposable
+	{
+
+		private ISpellChecker _core;
+		private readonly bool _performDispose;
+
+		public SpellCheckerPointer(ISpellChecker core) : this(core, true) {}
+
+		public SpellCheckerPointer(ISpellChecker core, bool performDispose){
+			if(null == core)
+				throw new ArgumentNullException("core");
+			_core = core;
+			_performDispose = performDispose;
+		}
+
+		public void Replace(ISpellChecker newCore){
+			if(null == newCore)
+				throw new ArgumentNullException();
+
+			var oldCore = _core;
+			_core = newCore;
+
+			DisposeIfRequired(oldCore);
+		}
+
+		private void DisposeIfRequired(ISpellChecker checker){
+			if (!_performDispose)
+				return;
+			var disposable = checker as IDisposable;
+			if(null != disposable)
+				disposable.Dispose();
+		}
+
+		public void Add(string word) {
+			_core.Add(word);
+		}
+
+		public void Add(IEnumerable<string> words) {
+			_core.Add(words);
+		}
+
+		public bool Check(string word) {
+			return _core.Check(word);
+		}
+
+		public string[] GetRecommendations(string word){
+			return _core.GetRecommendations(word);
+		}
+
+		public void Dispose(){
+			Dispose(true);
+			GC.SuppressFinalize(this);
+		}
+
+		protected virtual void Dispose(bool disposing){
+			DisposeIfRequired(_core);
+		}
+
+		~SpellCheckerPointer(){
+			Dispose(false);
+		}
+
+	}
+}

File src/YouCantSpell.Core/YouCantSpell.Core.csproj

     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="SpellChecker.cs" />
     <Compile Include="SpellCheckerCollection.cs" />
+    <Compile Include="SpellCheckerPointer.cs" />
     <Compile Include="TextSubString.cs" />
     <Compile Include="Utility\StringUtil.cs" />
     <Compile Include="TextCaseClassification.cs" />

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

 					continue;
 
 				// Finally we check the spelling of the word.
-				if(SpellCheckResources.Primary.Check(word))
+				if(SpellCheckResources.SpellChecker.Check(word))
 					continue;
 
 				// If we got this far we need to offer spelling suggestions.
 				if(null == wordPart || IsIgnored(wordPart.Value) || localIgnoredWords.Contains(wordPart.Value))
 					continue;
 
-				if(SpellCheckResources.Primary.Check(wordPart.Value))
+				if(SpellCheckResources.SpellChecker.Check(wordPart.Value))
 					continue;
 
 				var identifierLeftTrim = namePart.Offset + wordPart.Index;
 						localValidPartRange,
 						wordPart.Value,
 						word => FormatSuggestions(
-								Shell.Instance.GetComponent<ShellSpellCheckResources>().Primary.GetRecommendations(word),
+								Shell.Instance.GetComponent<ShellSpellCheckResources>().SpellChecker.GetRecommendations(word),
 								wordPosition,
 								parsedNameParts.Count,
 								namingRule,

File src/YouCantSpell.ReSharper.Shared/PrimaryOptionsControl.Designer.cs

 			this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
 			this.buttonOpenDictFolder = new System.Windows.Forms.Button();
 			this.buttonRefreshDictList = new System.Windows.Forms.Button();
+			this.panel1 = new System.Windows.Forms.Panel();
 			this.labelPutYourDictInThatFolder = new System.Windows.Forms.Label();
-			this.linkLabelKnownIssue = new System.Windows.Forms.LinkLabel();
+			this.linkLabelOooNew = new System.Windows.Forms.LinkLabel();
+			this.linkLabelOooOld = new System.Windows.Forms.LinkLabel();
+			this.label1 = new System.Windows.Forms.Label();
 			this.tableLayoutPanelUserWords.SuspendLayout();
 			this.groupBoxUserDictionary.SuspendLayout();
 			this.groupBoxIgnoredWords.SuspendLayout();
 			this.tabPageDict.SuspendLayout();
 			((System.ComponentModel.ISupportInitialize)(this.dataGridViewDictList)).BeginInit();
 			this.tableLayoutPanel1.SuspendLayout();
+			this.panel1.SuspendLayout();
 			this.SuspendLayout();
 			// 
 			// tableLayoutPanelUserWords
 			this.tableLayoutPanelUserWords.RowCount = 2;
 			this.tableLayoutPanelUserWords.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
 			this.tableLayoutPanelUserWords.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 30F));
-			this.tableLayoutPanelUserWords.Size = new System.Drawing.Size(604, 444);
+			this.tableLayoutPanelUserWords.Size = new System.Drawing.Size(604, 467);
 			this.tableLayoutPanelUserWords.TabIndex = 0;
 			// 
 			// groupBoxUserDictionary
 			this.groupBoxUserDictionary.Dock = System.Windows.Forms.DockStyle.Fill;
 			this.groupBoxUserDictionary.Location = new System.Drawing.Point(3, 3);
 			this.groupBoxUserDictionary.Name = "groupBoxUserDictionary";
-			this.groupBoxUserDictionary.Size = new System.Drawing.Size(296, 408);
+			this.groupBoxUserDictionary.Size = new System.Drawing.Size(296, 431);
 			this.groupBoxUserDictionary.TabIndex = 0;
 			this.groupBoxUserDictionary.TabStop = false;
 			this.groupBoxUserDictionary.Text = "User Dictionary";
 			this.stringListBoxUserDictionary.Dock = System.Windows.Forms.DockStyle.Fill;
 			this.stringListBoxUserDictionary.Location = new System.Drawing.Point(3, 16);
 			this.stringListBoxUserDictionary.Name = "stringListBoxUserDictionary";
-			this.stringListBoxUserDictionary.Size = new System.Drawing.Size(290, 389);
+			this.stringListBoxUserDictionary.Size = new System.Drawing.Size(290, 412);
 			this.stringListBoxUserDictionary.TabIndex = 0;
 			// 
 			// groupBoxIgnoredWords
 			this.groupBoxIgnoredWords.Dock = System.Windows.Forms.DockStyle.Fill;
 			this.groupBoxIgnoredWords.Location = new System.Drawing.Point(305, 3);
 			this.groupBoxIgnoredWords.Name = "groupBoxIgnoredWords";
-			this.groupBoxIgnoredWords.Size = new System.Drawing.Size(296, 408);
+			this.groupBoxIgnoredWords.Size = new System.Drawing.Size(296, 431);
 			this.groupBoxIgnoredWords.TabIndex = 1;
 			this.groupBoxIgnoredWords.TabStop = false;
 			this.groupBoxIgnoredWords.Text = "Ignored Words";
 			this.stringListBoxIgnoredWords.Dock = System.Windows.Forms.DockStyle.Fill;
 			this.stringListBoxIgnoredWords.Location = new System.Drawing.Point(3, 16);
 			this.stringListBoxIgnoredWords.Name = "stringListBoxIgnoredWords";
-			this.stringListBoxIgnoredWords.Size = new System.Drawing.Size(290, 389);
+			this.stringListBoxIgnoredWords.Size = new System.Drawing.Size(290, 412);
 			this.stringListBoxIgnoredWords.TabIndex = 0;
 			// 
 			// tabControlOptions
 			this.tabControlOptions.Controls.Add(this.tabPageUserWords);
 			this.tabControlOptions.Controls.Add(this.tabPageDict);
 			this.tabControlOptions.Dock = System.Windows.Forms.DockStyle.Fill;
-			this.tabControlOptions.Location = new System.Drawing.Point(0, 23);
+			this.tabControlOptions.Location = new System.Drawing.Point(0, 0);
 			this.tabControlOptions.Name = "tabControlOptions";
 			this.tabControlOptions.SelectedIndex = 0;
-			this.tabControlOptions.Size = new System.Drawing.Size(618, 476);
+			this.tabControlOptions.Size = new System.Drawing.Size(618, 499);
 			this.tabControlOptions.TabIndex = 1;
 			// 
 			// tabPageUserWords
 			this.tabPageUserWords.Location = new System.Drawing.Point(4, 22);
 			this.tabPageUserWords.Name = "tabPageUserWords";
 			this.tabPageUserWords.Padding = new System.Windows.Forms.Padding(3);
-			this.tabPageUserWords.Size = new System.Drawing.Size(610, 450);
+			this.tabPageUserWords.Size = new System.Drawing.Size(610, 473);
 			this.tabPageUserWords.TabIndex = 0;
 			this.tabPageUserWords.Text = "User Words";
 			this.tabPageUserWords.UseVisualStyleBackColor = true;
 			this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
 			this.tableLayoutPanel1.Controls.Add(this.buttonOpenDictFolder, 0, 0);
 			this.tableLayoutPanel1.Controls.Add(this.buttonRefreshDictList, 2, 0);
-			this.tableLayoutPanel1.Controls.Add(this.labelPutYourDictInThatFolder, 1, 0);
+			this.tableLayoutPanel1.Controls.Add(this.panel1, 1, 0);
 			this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Bottom;
 			this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 339);
 			this.tableLayoutPanel1.Name = "tableLayoutPanel1";
 			this.buttonRefreshDictList.UseVisualStyleBackColor = true;
 			this.buttonRefreshDictList.Click += new System.EventHandler(this.buttonRefreshDictList_Click);
 			// 
+			// panel1
+			// 
+			this.panel1.Controls.Add(this.labelPutYourDictInThatFolder);
+			this.panel1.Controls.Add(this.linkLabelOooNew);
+			this.panel1.Controls.Add(this.linkLabelOooOld);
+			this.panel1.Controls.Add(this.label1);
+			this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+			this.panel1.Location = new System.Drawing.Point(201, 0);
+			this.panel1.Margin = new System.Windows.Forms.Padding(0);
+			this.panel1.Name = "panel1";
+			this.panel1.Padding = new System.Windows.Forms.Padding(3);
+			this.panel1.Size = new System.Drawing.Size(201, 131);
+			this.panel1.TabIndex = 2;
+			// 
 			// labelPutYourDictInThatFolder
 			// 
 			this.labelPutYourDictInThatFolder.Dock = System.Windows.Forms.DockStyle.Fill;
-			this.labelPutYourDictInThatFolder.Location = new System.Drawing.Point(204, 0);
+			this.labelPutYourDictInThatFolder.Location = new System.Drawing.Point(3, 3);
 			this.labelPutYourDictInThatFolder.Name = "labelPutYourDictInThatFolder";
-			this.labelPutYourDictInThatFolder.Size = new System.Drawing.Size(195, 131);
+			this.labelPutYourDictInThatFolder.Padding = new System.Windows.Forms.Padding(0, 0, 0, 13);
+			this.labelPutYourDictInThatFolder.Size = new System.Drawing.Size(195, 84);
 			this.labelPutYourDictInThatFolder.TabIndex = 2;
-			this.labelPutYourDictInThatFolder.Text = "2) Place your dictionaries in that folder.\r\n*.dic and *.aff\r\nNOTE: Names must mat" +
-    "ch!";
-			this.labelPutYourDictInThatFolder.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+			this.labelPutYourDictInThatFolder.Text = "2) Place your dictionaries in that folder.\r\nBe sure to include both files:\r\n<name" +
+    ">.dic and <name>.aff";
+			this.labelPutYourDictInThatFolder.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
 			// 
-			// linkLabelKnownIssue
+			// linkLabelOooNew
 			// 
-			this.linkLabelKnownIssue.Dock = System.Windows.Forms.DockStyle.Top;
-			this.linkLabelKnownIssue.Location = new System.Drawing.Point(0, 0);
-			this.linkLabelKnownIssue.Name = "linkLabelKnownIssue";
-			this.linkLabelKnownIssue.Size = new System.Drawing.Size(618, 23);
-			this.linkLabelKnownIssue.TabIndex = 2;
-			this.linkLabelKnownIssue.TabStop = true;
-			this.linkLabelKnownIssue.Text = "NOTE: After saving your changes you must restart Visual Studio for them to take e" +
-    "ffect... Sorry!";
-			this.linkLabelKnownIssue.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
-			this.linkLabelKnownIssue.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelKnownIssue_LinkClicked);
+			this.linkLabelOooNew.Cursor = System.Windows.Forms.Cursors.Hand;
+			this.linkLabelOooNew.Dock = System.Windows.Forms.DockStyle.Bottom;
+			this.linkLabelOooNew.Location = new System.Drawing.Point(3, 87);
+			this.linkLabelOooNew.Margin = new System.Windows.Forms.Padding(3);
+			this.linkLabelOooNew.Name = "linkLabelOooNew";
+			this.linkLabelOooNew.Size = new System.Drawing.Size(195, 13);
+			this.linkLabelOooNew.TabIndex = 3;
+			this.linkLabelOooNew.TabStop = true;
+			this.linkLabelOooNew.Text = "new Open Office dictionaries";
+			this.linkLabelOooNew.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+			this.linkLabelOooNew.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelOooNew_LinkClicked);
+			// 
+			// linkLabelOooOld
+			// 
+			this.linkLabelOooOld.Cursor = System.Windows.Forms.Cursors.Hand;
+			this.linkLabelOooOld.Dock = System.Windows.Forms.DockStyle.Bottom;
+			this.linkLabelOooOld.Location = new System.Drawing.Point(3, 100);
+			this.linkLabelOooOld.Margin = new System.Windows.Forms.Padding(3);
+			this.linkLabelOooOld.Name = "linkLabelOooOld";
+			this.linkLabelOooOld.Size = new System.Drawing.Size(195, 13);
+			this.linkLabelOooOld.TabIndex = 4;
+			this.linkLabelOooOld.TabStop = true;
+			this.linkLabelOooOld.Text = "old Open Office dictionaries";
+			this.linkLabelOooOld.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+			this.linkLabelOooOld.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelOooOld_LinkClicked);
+			// 
+			// label1
+			// 
+			this.label1.Cursor = System.Windows.Forms.Cursors.Hand;
+			this.label1.Dock = System.Windows.Forms.DockStyle.Bottom;
+			this.label1.Location = new System.Drawing.Point(3, 113);
+			this.label1.Margin = new System.Windows.Forms.Padding(3);
+			this.label1.Name = "label1";
+			this.label1.Size = new System.Drawing.Size(195, 15);
+			this.label1.TabIndex = 5;
+			this.label1.Text = "Use 7-Zip to extract dictionaries.";
+			this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+			this.label1.Click += new System.EventHandler(this.label1_Click);
 			// 
 			// PrimaryOptionsControl
 			// 
 			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
 			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
 			this.Controls.Add(this.tabControlOptions);
-			this.Controls.Add(this.linkLabelKnownIssue);
 			this.Name = "PrimaryOptionsControl";
 			this.Size = new System.Drawing.Size(618, 499);
 			this.Load += new System.EventHandler(this.PrimaryOptionsControl_Load);
 			this.tabPageDict.ResumeLayout(false);
 			((System.ComponentModel.ISupportInitialize)(this.dataGridViewDictList)).EndInit();
 			this.tableLayoutPanel1.ResumeLayout(false);
+			this.panel1.ResumeLayout(false);
 			this.ResumeLayout(false);
 
 		}
 		private System.Windows.Forms.DataGridViewTextBoxColumn DictNameColumn;
 		private System.Windows.Forms.DataGridViewCheckBoxColumn ForSpellCheckColumn;
 		private System.Windows.Forms.DataGridViewCheckBoxColumn ForIgnoreColumn;
-		private System.Windows.Forms.LinkLabel linkLabelKnownIssue;
+		private System.Windows.Forms.Panel panel1;
+		private System.Windows.Forms.LinkLabel linkLabelOooNew;
+		private System.Windows.Forms.LinkLabel linkLabelOooOld;
+		private System.Windows.Forms.Label label1;
 
 	}
 }

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

 using System.IO;
 using System.Linq;
 using System.Linq.Expressions;
-using System.Resources;
 using System.Windows.Forms;
 using JetBrains.Annotations;
 using JetBrains.Application;
 	/// The spell check options pane that is displayed in the ReSharper options UI.
 	/// </summary>
 #if RSHARP6
-	[OptionsPage(Pid, "SpellColumn Check Settings", "YouCantSpell.ReSharper.resources.SpellCheckOptionsIcon.png", ParentId = EnvironmentPage.Pid, Sequence = 100)]
+	[OptionsPage(Pid, "You Can't Spell Settings", "YouCantSpell.ReSharper.resources.SpellCheckOptionsIcon.png", ParentId = EnvironmentPage.Pid, Sequence = 100)]
 #else
-	[OptionsPage(Pid, "SpellColumn Check Settings", typeof(UnnamedThemedIcons.SpellCheckOptionsIcon), ParentId = EnvironmentPage.Pid, Sequence = 100)]
+	[OptionsPage(Pid, "You Can't Spell Settings", typeof(UnnamedThemedIcons.SpellCheckOptionsIcon), ParentId = EnvironmentPage.Pid, Sequence = 100)]
 #endif
 	public partial class PrimaryOptionsControl : UserControl, IOptionsPage
 	{
 		/// <inheritdoc/>
 		public bool OnOk() {
 			// When the save button is clicked we should try to signal to the core spell check resources that things have changed.
-			if (_changesMade) {
-				var spellChecker = Shell.Instance.TryGetComponent<ShellSpellCheckResources>();
+			if (_changesMade){
+				var spellChecker = Shell.Instance.TryGetComponent<ShellSpellCheckResources>()
+					?? ShellSpellCheckResources.MostRecentInstance;
 				if (null != spellChecker)
-					spellChecker.FullReset();
+					spellChecker.FullReset(_settings);
 			}
 			return true;
 		}
 			var row = dataGridViewDictList.Rows[e.RowIndex];
 			var dictName = Convert.ToString(row.Cells[0].Value);
 
+			var isForSpellCheck = Convert.ToBoolean(row.Cells[1].Value);
+			var isForIgnore = Convert.ToBoolean(row.Cells[2].Value);
+
 			switch (e.ColumnIndex){
 			case 0: return;
 			case 1:{
-				var isForSpellCheck = Convert.ToBoolean(row.Cells[1].Value);
 				var currentForSepllCheck = new HashSet<string>(_settings.EnumEntryIndices<SpellCheckSettings, string, byte>(x => x.SpellCheckDictionaries));
 				if (isForSpellCheck && !currentForSepllCheck.Contains(dictName)) {
 					_settings.SetIndexedValue((SpellCheckSettings x) => x.SpellCheckDictionaries, dictName, default(byte));
+					_changesMade = true;
 				}
 				else if(!isForSpellCheck && currentForSepllCheck.Contains(dictName)) {
 					_settings.RemoveIndexedValue((SpellCheckSettings x) => x.SpellCheckDictionaries, dictName);
+					_changesMade = true;
 				}
+
+				if (isForSpellCheck && isForIgnore)
+					row.Cells[2].Value = false; // uncheck the ignore one
+
 				break;
 			}
 			case 2:{
-				var isForIgnore = Convert.ToBoolean(row.Cells[2].Value);
 				var currentForIgnore = new HashSet<string>(_settings.EnumEntryIndices<SpellCheckSettings, string, byte>(x => x.IgnoreDictionaries));
 				if (isForIgnore && !currentForIgnore.Contains(dictName)) {
 					_settings.SetIndexedValue((SpellCheckSettings x) => x.IgnoreDictionaries, dictName, default(byte));
+					_changesMade = true;
 				}
 				else if(!isForIgnore && currentForIgnore.Contains(dictName)) {
 					_settings.RemoveIndexedValue((SpellCheckSettings x) => x.IgnoreDictionaries, dictName);
+					_changesMade = true;
 				}
+
+				if (isForSpellCheck && isForIgnore)
+					row.Cells[1].Value = false; // uncheck the spell check one
+
 				break;
 			}
 			default: return;
 		private void PrimaryOptionsControl_Load(object sender, EventArgs e){
 		}
 
-		private void linkLabelKnownIssue_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
-			System.Diagnostics.Process.Start("http://bitbucket.org/aarondandy/youcantspell/issue/12/settings-changes-are-not-reflected-until");
+		private void linkLabelOooNew_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
+			System.Diagnostics.Process.Start("http://extensions.services.openoffice.org/dictionary");
+		}
+
+		private void linkLabelOooOld_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e){
+			System.Diagnostics.Process.Start("http://wiki.openoffice.org/wiki/Dictionaries");
+		}
+
+		private void label1_Click(object sender, EventArgs e){
+			System.Diagnostics.Process.Start("http://7-zip.org/");
 		}
 	}
 }

File src/YouCantSpell.ReSharper.Shared/PrimaryOptionsControl.resx

   <metadata name="ForIgnoreColumn.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
+  <metadata name="DictNameColumn.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="ForSpellCheckColumn.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="ForIgnoreColumn.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
 </root>

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

 using System.Collections.Generic;
 using System.Linq;
+using JetBrains.Annotations;
 using JetBrains.Application;
 using JetBrains.Application.Settings;
 using System;
 	public class ShellSpellCheckResources : IDisposable
 	{
 
+		private static WeakReference _mostRecentInstance;
+
+		/// <summary>
+		/// Returns the most recent spell check resources.
+		/// </summary>
+		/// <remarks>
+		/// I can't figure out how to get access to this instance from the options page
+		/// so this is a bit of a hack to access the most recent instance, which should
+		/// also be what I would expect to get from the ReSharper IoC stuff, if I knew
+		/// how to use it.
+		/// </remarks>
+		[Obsolete("This is a dirty filthy no good hack.")]
+		public static ShellSpellCheckResources MostRecentInstance{
+			get { return null == _mostRecentInstance ? null : (ShellSpellCheckResources) _mostRecentInstance.Target; }
+		}
+
 		public static string[] GetSpellingSuggestions(string word) {
-			var spellChecker = Shell.Instance.GetComponent<ShellSpellCheckResources>().Primary;
+			var spellChecker = Shell.Instance.GetComponent<ShellSpellCheckResources>().SpellChecker;
 			return spellChecker.GetRecommendations(word);
 		}
 
-		private CachedSpellChecker _primary;
+		private SpellCheckerPointer _spellChecker;
+		private readonly object _spellCheckerSync = new object();
+
 		private CachedSpellChecker _ignoreDictionaries;
 		private HashSet<string> _ignored;
 		private HashSet<string> _ignoredInsensitive;
 		private readonly object _ignoredSync = new object();
 
-		public ShellSpellCheckResources(ISettingsStore settingsStore)
+		public ShellSpellCheckResources([NotNull] ISettingsStore settingsStore)
+			: this(settingsStore.BindToContextTransient(ContextRange.Smart((lifetime, contexts) => contexts.Empty))) { }
+
+		public ShellSpellCheckResources([NotNull] IContextBoundSettingsStore boundSettings)
 		{
-			FullReset(settingsStore);
+			FullReset(boundSettings);
+			_mostRecentInstance = new WeakReference(this);
 		}
 
 		/// <summary>
 		/// Resets the spell check resources to their initial states and reloads the settings that are to be applied.
 		/// </summary>
-		/// <param name="settingsStore">Optional settings.</param>
+		/// <param name="boundSettings">Optional settings.</param>
 		/// <remarks>
 		/// If settings are not provided they will be retrieved automatically.
 		/// The settingsStore parameter is to be used to override the settings store that is used.
 		/// </remarks>
-		public void FullReset(ISettingsStore settingsStore = null)
+		public void FullReset(IContextBoundSettingsStore boundSettings = null)
 		{
-			settingsStore = settingsStore ?? Shell.Instance.GetComponent<ISettingsStore>();
-			var boundSettings = settingsStore.BindToContextTransient(ContextRange.Smart((lifetime, contexts) => contexts.Empty));
+			if (null == boundSettings){
+				var settingsStore = Shell.Instance.GetComponent<ISettingsStore>();
+				if (null == settingsStore)
+					return;
+
+				boundSettings = settingsStore.BindToContextTransient(ContextRange.Smart((lifetime, contexts) => contexts.Empty));
+			}
 
 			ResetSpellChecker(boundSettings);
 			ResetIgnoreLists(boundSettings);
 
 		private void ResetSpellChecker(IContextBoundSettingsStore boundSettings)
 		{
-			var oldSpellCheckCore = _primary;
 
 			var selectedSepllCheckers = new HashSet<string>(boundSettings.EnumEntryIndices<SpellCheckSettings, string, byte>(x => x.SpellCheckDictionaries));
 			// we sort the spell checkers so that just in case we don't have any set we can take the EN dictionaries first.
-			var availableSepllCheckers = SpellChecker.GetAllAvailableDictionaryNames().OrderByDescending(x =>{
+			var availableSepllCheckers = YouCantSpell.SpellChecker.GetAllAvailableDictionaryNames().OrderByDescending(x =>{
 				if (String.Equals(x, "EN_US", StringComparison.OrdinalIgnoreCase))
 					return 100;
 				if (x.StartsWith("EN", StringComparison.OrdinalIgnoreCase))
 			}
 
 			ISpellChecker newSpellCheckCore = new SpellCheckerCollection(activeSepllCheckers.Select(x => new SpellChecker(x)).Cast<ISpellChecker>());
+			newSpellCheckCore.Add(boundSettings.EnumEntryIndices<SpellCheckSettings, string, byte>(x => x.UserEntries));
+			newSpellCheckCore = new CachedSpellChecker(newSpellCheckCore, true);
 
-			newSpellCheckCore.Add(boundSettings.EnumEntryIndices<SpellCheckSettings, string, byte>(x => x.UserEntries));
-			_primary = new CachedSpellChecker(newSpellCheckCore, true);
+			lock (_spellCheckerSync){
+				if(null == _spellChecker)
+					_spellChecker = new SpellCheckerPointer(newSpellCheckCore, true);
+				else
+					_spellChecker.Replace(newSpellCheckCore);
+			}
 
-			if(null != oldSpellCheckCore)
-				oldSpellCheckCore.Dispose();
 		}
 
 		private void ResetIgnoreLists(IContextBoundSettingsStore boundSettings){
-			var oldIgnoreDictionaries = _ignoreDictionaries;
-
+			CachedSpellChecker oldIgnoreDictionaries;
 			var selectedIgnoreDictionaries = new HashSet<string>(boundSettings.EnumEntryIndices<SpellCheckSettings, string, byte>(x => x.IgnoreDictionaries));
-			var activeIgnoreDictionaries = SpellChecker.GetAllAvailableDictionaryNames().Where(selectedIgnoreDictionaries.Contains).ToList();
-
+			var activeIgnoreDictionaries = YouCantSpell.SpellChecker.GetAllAvailableDictionaryNames().Where(selectedIgnoreDictionaries.Contains).ToList();
 			ISpellChecker newIgnoreDictionaries = null;
-			if (activeIgnoreDictionaries.Count > 0){
+			if (activeIgnoreDictionaries.Count > 0) {
 				newIgnoreDictionaries = activeIgnoreDictionaries.Count == 1
 					? (ISpellChecker)new SpellChecker(activeIgnoreDictionaries[0])
 					: new SpellCheckerCollection(activeIgnoreDictionaries.Select(x => new SpellChecker(x)).Cast<ISpellChecker>());
 			}
 
-			var ignoreWords = boundSettings.EnumEntryIndices<SpellCheckSettings, string, byte>(x => x.IgnoreEntries).ToList();
-			lock(_ignoredSync)
-			{
-				_ignored = new HashSet<string>(ignoreWords);
-				_ignoredInsensitive = new HashSet<string>(ignoreWords, StringComparer.CurrentCultureIgnoreCase);
+			var ignoreWords = new HashSet<string>(boundSettings.EnumEntryIndices<SpellCheckSettings, string, byte>(x => x.IgnoreEntries));
+			var ignoreWordsInsensitive = new HashSet<string>(ignoreWords, StringComparer.CurrentCultureIgnoreCase);
+			lock (_ignoredSync) {
+				oldIgnoreDictionaries = _ignoreDictionaries;
+				_ignored = ignoreWords;
+				_ignoredInsensitive = ignoreWordsInsensitive;
 				_ignoreDictionaries = null == newIgnoreDictionaries ? null : new CachedSpellChecker(newIgnoreDictionaries, true);
 			}
 
 				oldIgnoreDictionaries.Dispose();
 		}
 
-		public ISpellChecker Primary { get { return _primary; } }
+		public ISpellChecker SpellChecker { get { return _spellChecker; } }
 
 		/// <summary>
 		/// Determines if the given word is ignored using case sensitive rules.
 		/// NOTE: this is a temporary addition to the dictionary. For a permanent additions you must add the word to the settings.
 		/// </remarks>
 		internal void NotifyNewUserDictionaryWord(string word) {
-			Primary.Add(word);
+			SpellChecker.Add(word);
 		}
 
 		/// <summary>
 
 		/// <inheritdoc/>
 		public void Dispose() {
-			if(null != _primary)
+			if(null != _spellChecker)
 			{
-				_primary.Dispose();
-				_primary = null;
+				_spellChecker.Dispose();
+				_spellChecker = null;
 			}
 		}
 

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

 				if(WordIsIgnored(word)) continue;
 
 				// Finally we check the spelling of the word.
-				if(SpellCheckResources.Primary.Check(word)) continue;
+				if(SpellCheckResources.SpellChecker.Check(word)) continue;
 
 				// If we got this far we need to offer spelling suggestions.
 				var wordPartDocumentOffset = textRange.TextRange.StartOffset + wordPart.Offset;