diff --git a/crates/proof/src/cs/mod.rs b/crates/proof/src/cs/mod.rs index 3531745f8..ef560be46 100644 --- a/crates/proof/src/cs/mod.rs +++ b/crates/proof/src/cs/mod.rs @@ -16,6 +16,11 @@ pub use suggest::suggest; /// The Czech dictionary: `None` until first use, then the installed one (or an empty one). static DICT: RwLock>> = RwLock::new(None); +/// Whether `DICT` holds a dictionary given with [`install_dictionary`] rather than one found on +/// disk: it has no file of its own to report from [`installed_path`], even if a matching file +/// happens to exist too. +static DICT_IN_MEMORY: RwLock = RwLock::new(false); + /// File names of a Czech Hunspell dictionary. const NAMES: &[&str] = &["cs_CZ", "cs-CZ", "cs"]; @@ -48,6 +53,7 @@ fn load_installed() -> AffixDict { pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = AffixDict::from_hunspell(aff, dic, &[])?; *DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d)); + *DICT_IN_MEMORY.write().unwrap_or_else(|e| e.into_inner()) = true; Ok(()) } @@ -55,12 +61,17 @@ pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { /// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed). pub fn reload_dictionary() { *DICT.write().unwrap_or_else(|e| e.into_inner()) = None; + *DICT_IN_MEMORY.write().unwrap_or_else(|e| e.into_inner()) = false; } /// The `.dic` file of the installed Czech dictionary, searching the dictionaries folder and /// the system locations now (File › Options › Proofing shows it, #3226); `None` when there is -/// none. A dictionary given with [`install_dictionary`] has no file and isn't reported. +/// none. A dictionary given with [`install_dictionary`] has no file and isn't reported, even if a +/// matching file also happens to exist. pub fn installed_path() -> Option { + if *DICT_IN_MEMORY.read().unwrap_or_else(|e| e.into_inner()) { + return None; + } crate::hunspell::find(NAMES).map(|(_, dic)| dic) } diff --git a/crates/proof/src/lib.rs b/crates/proof/src/lib.rs index d69ca336a..cdcd1b086 100644 --- a/crates/proof/src/lib.rs +++ b/crates/proof/src/lib.rs @@ -955,12 +955,12 @@ mod tests { ); // #3226: Russian and Czech were missing from installed_dictionaries() entirely (no // installed_path() in either module), so neither ever showed up in File › Options › - // Proofing, installed or not. - assert_eq!( - found[5..7], - [(ProofLang::Ru, Some(dir.join("ru_RU.dic"))), (ProofLang::Cs, Some(dir.join("cs_CZ.dic")))], - "Russian and Czech are reported too, between Turkish and Indonesian" - ); + // Proofing, installed or not. Their languages, not their exact path, is what belongs + // here: unlike the four above, installed_path() for Russian and Czech also reflects + // whether install_dictionary() gave one directly (#3252 review), which ru's and cs's own + // test modules do, concurrently, in tests of their own — asserting an exact path here + // would race them for no reason this test needs to care about. + assert_eq!(found[5..7].iter().map(|(lang, _)| *lang).collect::>(), [ProofLang::Ru, ProofLang::Cs], "{found:?}"); assert!(is_correct_in("chrząszcz", ProofLang::Pl) && !is_correct_in("chrzonszcz", ProofLang::Pl)); assert!(is_correct_in("дом", ProofLang::Ru) && !is_correct_in("дум", ProofLang::Ru)); } diff --git a/crates/proof/src/ru/mod.rs b/crates/proof/src/ru/mod.rs index ffd09f7ef..caba4f8aa 100644 --- a/crates/proof/src/ru/mod.rs +++ b/crates/proof/src/ru/mod.rs @@ -37,6 +37,11 @@ pub use suggest::suggest; /// The Russian dictionary: `None` until first use, then the installed one (or an empty one). static DICT: RwLock>> = RwLock::new(None); +/// Whether `DICT` holds a dictionary given with [`install_dictionary`] rather than one found on +/// disk: it has no file of its own to report from [`installed_path`], even if a matching file +/// happens to exist too. +static DICT_IN_MEMORY: RwLock = RwLock::new(false); + /// File names of a Russian Hunspell dictionary. const NAMES: &[&str] = &["ru_RU", "ru-RU", "ru"]; @@ -69,6 +74,7 @@ fn load_installed() -> AffixDict { pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = AffixDict::from_hunspell(aff, dic, &[])?; *DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d)); + *DICT_IN_MEMORY.write().unwrap_or_else(|e| e.into_inner()) = true; Ok(()) } @@ -76,12 +82,17 @@ pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { /// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed). pub fn reload_dictionary() { *DICT.write().unwrap_or_else(|e| e.into_inner()) = None; + *DICT_IN_MEMORY.write().unwrap_or_else(|e| e.into_inner()) = false; } /// The `.dic` file of the installed Russian dictionary, searching the dictionaries folder and /// the system locations now (File › Options › Proofing shows it, #3226); `None` when there is -/// none. A dictionary given with [`install_dictionary`] has no file and isn't reported. +/// none. A dictionary given with [`install_dictionary`] has no file and isn't reported, even if a +/// matching file also happens to exist. pub fn installed_path() -> Option { + if *DICT_IN_MEMORY.read().unwrap_or_else(|e| e.into_inner()) { + return None; + } crate::hunspell::find(NAMES).map(|(_, dic)| dic) }