Commits

derigel  committed 30778d8

Handle online removing word from user dictionaries

  • Participants
  • Parent commits ee74648
  • Branches resharper8

Comments (0)

Files changed (8)

File ReSpeller/SpellEngine/Dictionaries/FileDictionaryStorage.cs

+using System;
 using System.Collections.Generic;
 using System.IO;
 using JetBrains.Util;
       string[] lines = File.ReadAllLines(myFileName);
       return lines;
     }
+
+    public event Action ContentChanged;
   }
 }

File ReSpeller/SpellEngine/Dictionaries/HunspellDictionaryFactory.cs

 using JetBrains.Application.Settings;
+using JetBrains.DataFlow;
 
 namespace ReSpeller.SpellEngine.Dictionaries
 {
   public class HunspellDictionaryFactory : IDictionaryFactory
   {
-    private readonly IContextBoundSettingsStore myStore;
+    private readonly Lifetime myLifetime;
+    private readonly IContextBoundSettingsStoreLive myStore;
 
-    public HunspellDictionaryFactory(IContextBoundSettingsStore store)
+    public HunspellDictionaryFactory(Lifetime lifetime, IContextBoundSettingsStoreLive store)
     {
+      myLifetime = lifetime;
       myStore = store;
     }
 
     public IUserInternalDictionary CreateDictionary(string language)
     {
-      var storage = new SettingsDictionaryStorage(myStore, language);
+      var storage = new SettingsDictionaryStorage(myLifetime, myStore, language);
       var hunspellEngine = HunspellEngine.CreateForLanguage(Constants.MainDictDir, language);
       return new UserInternalDictionary(hunspellEngine, language, storage, storage);
     }

File ReSpeller/SpellEngine/Dictionaries/HunspellEngine.cs

+using System;
 using System.Collections.Generic;
 using System.IO;
 using NHunspell;
       }
     }
 
-    public void Dispose()
+    public void Remove(string word)
+    {
+      myHunspell.Remove(word);
+    }
+
+    void IDisposable.Dispose()
     {
       if (myHunspell != null && !myHunspell.IsDisposed)
         myHunspell.Dispose();

File ReSpeller/SpellEngine/Dictionaries/IDictionaryEngine.cs

     List<string> Suggest(string word);
     void Add(string word);
     void AddRange(IEnumerable<string> words);
+    void Remove(string word);
   }
 }

File ReSpeller/SpellEngine/Dictionaries/IDictionaryStorage.cs

-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 
 namespace ReSpeller.SpellEngine.Dictionaries
 {
   {
     void AddWord(string word);
     IEnumerable<string> GetContent();
+
+    event Action ContentChanged;
   }
 }

File ReSpeller/SpellEngine/Dictionaries/SettingsDictionaryStorage.cs

-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using JetBrains.Application.Settings;
 using JetBrains.Application.Settings.Store;
+using JetBrains.DataFlow;
 using ReSpeller.Settings;
 
 namespace ReSpeller.SpellEngine.Dictionaries
     private readonly string myLanguage;
     private readonly OneToSetSettingAccessor<UserDictionariesSettings, string, string> mySettingsAccessor;
 
-    public SettingsDictionaryStorage(IContextBoundSettingsStore contextBoundSettingsStore, string language)
+    public SettingsDictionaryStorage(Lifetime lifetime, IContextBoundSettingsStoreLive contextBoundSettingsStore, string language)
     {
       myLanguage = language;
       mySettingsAccessor = OneToSetSettingAccessor<UserDictionariesSettings, string, string>.Create(contextBoundSettingsStore, settings => settings.Words);
+      contextBoundSettingsStore.AdviseChange(lifetime,
+        contextBoundSettingsStore.Schema.GetIndexedEntry<UserDictionariesSettings, string, bool>(settings => settings.Words),
+        ContentChanged);
     }
 
     public void AddWord(string word)
     {
       return mySettingsAccessor.GetValues(myLanguage);
     }
+
+    public event Action ContentChanged = delegate { };
   }
 }

File ReSpeller/SpellEngine/Dictionaries/UserInternalDictionary.cs

 using System;
 using System.Collections.Generic;
+using System.Linq;
+using JetBrains.Util;
 
 namespace ReSpeller.SpellEngine.Dictionaries
 {
     private readonly string myLanguage;
     private readonly IDictionaryStorage myUserStorage;
     private readonly IDictionaryStorage myInternalStorage;
-
+    private readonly HashSet<string> myWordsStorageHash = new HashSet<string>();
 
     public UserInternalDictionary(IDictionaryEngine engine, string language, IDictionaryStorage userStorage, IDictionaryStorage internalStorage)
     {
       myLanguage = language;
       myUserStorage = userStorage;
       myInternalStorage = internalStorage;
-      myEngine.AddRange(myUserStorage.GetContent());
-      myEngine.AddRange(myInternalStorage.GetContent());
+      myWordsStorageHash.AddRange(myUserStorage.GetContent());
+      myWordsStorageHash.AddRange(myInternalStorage.GetContent());
+      myEngine.AddRange(myWordsStorageHash);
+      myUserStorage.ContentChanged += UserStorageContentChanged;
+      myInternalStorage.ContentChanged += UserStorageContentChanged;
+    }
+
+    private void UserStorageContentChanged()
+    {
+      lock (myWordsStorageHash)
+      {
+        var newContent = myUserStorage.GetContent()
+          .Concat(myInternalStorage.GetContent())
+          .ToHashSet();
+        foreach (var oldWord in myWordsStorageHash.Except(newContent).ToList())
+        {
+          myEngine.Remove(oldWord);
+          myWordsStorageHash.Remove(oldWord);
+        }
+        
+        foreach (var word in newContent)
+        {
+          if (myWordsStorageHash.Add(word))
+            myEngine.Add(word);
+        }
+      }
     }
 
     void IDisposable.Dispose()
     {
+      myInternalStorage.ContentChanged -= UserStorageContentChanged;
+      myUserStorage.ContentChanged -= UserStorageContentChanged;
       myEngine.Dispose();
     }
 

File ReSpeller/SpellEngine/SpellChecker.cs

   [ShellComponent(ProgramConfigurations.ALL & ~ProgramConfigurations.TEST)]
   public sealed class SpellChecker : IDisposable, ISpellChecker, ISingleLanguageWordStorage
   {
-    private readonly IContextBoundSettingsStore myStore;
+    private readonly IContextBoundSettingsStoreLive myStore;
     private const string CurrentLanguage = "en_us";
 
     private readonly IUserInternalDictionary myDictionary;
     public SpellChecker(Lifetime lifetime, ISettingsStore store)
     {
       myStore = store.BindToContextLive(lifetime, ContextRange.ApplicationWide);
-      var factory = new HunspellDictionaryFactory(myStore);
+      var factory = new HunspellDictionaryFactory(lifetime, myStore);
       myDictionary = factory.CreateDictionary(CurrentLanguage);
       myWordChecker = new ConfigurableWordChecker(new List<ILanguageDictionary> {myDictionary});
       myWordSuggester = new SingleDictionarySuggestor(myDictionary);