From 4a666018159075ec273518f0ca27932db6a58198 Mon Sep 17 00:00:00 2001 From: Richard Braakman Date: Thu, 20 Jul 2023 18:40:43 +0300 Subject: [PATCH] validate available scopes for some localizations --- src/ck3/data/decisions.rs | 4 ++++ src/ck3/data/traits.rs | 2 +- src/ck3/item.rs | 1 + src/context.rs | 4 ++++ src/data/gui.rs | 4 +++- src/data/localization.rs | 11 +++++------ src/datatype.rs | 4 +++- src/desc.rs | 11 ++++++----- src/everything.rs | 2 +- 9 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/ck3/data/decisions.rs b/src/ck3/data/decisions.rs index 1762b781..b7af42b5 100644 --- a/src/ck3/data/decisions.rs +++ b/src/ck3/data/decisions.rs @@ -62,20 +62,24 @@ impl DbKind for Decision { if !vd.field_validated_sc("selection_tooltip", &mut sc, validate_desc) { let loca = format!("{key}_tooltip"); data.verify_exists_implied(Item::Localization, &loca, key); + data.validate_localization_sc(&loca, &mut sc); } if !vd.field_validated_sc("title", &mut sc, validate_desc) { data.verify_exists(Item::Localization, key); + data.validate_localization_sc(key.as_str(), &mut sc); } if !vd.field_validated_sc("desc", &mut sc, validate_desc) { let loca = format!("{key}_desc"); data.verify_exists_implied(Item::Localization, &loca, key); + data.validate_localization_sc(&loca, &mut sc); } if !vd.field_validated_sc("confirm_text", &mut sc, validate_desc) { let loca = format!("{key}_confirm"); data.verify_exists_implied(Item::Localization, &loca, key); + data.validate_localization_sc(&loca, &mut sc); } vd.field_validated_block("is_shown", |b, data| { diff --git a/src/ck3/data/traits.rs b/src/ck3/data/traits.rs index 69b942fe..3f83201f 100644 --- a/src/ck3/data/traits.rs +++ b/src/ck3/data/traits.rs @@ -140,7 +140,7 @@ impl Trait { } if !vd.field_validated("icon", |bv, data| { - validate_desc_map(bv, data, &mut sc, |name, data| { + validate_desc_map(bv, data, &mut sc, |name, data, _| { if let Some(icon_path) = data.get_defined_string_warn(&self.key, "NGameIcons|TRAIT_ICON_PATH") { diff --git a/src/ck3/item.rs b/src/ck3/item.rs index 4027cc59..c04f18cf 100644 --- a/src/ck3/item.rs +++ b/src/ck3/item.rs @@ -449,6 +449,7 @@ impl Item { | Item::BuildingGfx | Item::ClothingGfx | Item::CoaGfx + | Item::MemoryCategory | Item::Sound | Item::UnitGfx => Confidence::Weak, Item::SpecialBuilding => Confidence::Reasonable, diff --git a/src/context.rs b/src/context.rs index b3069d5b..3a27ac86 100644 --- a/src/context.rs +++ b/src/context.rs @@ -109,6 +109,10 @@ impl ScopeContext { self.strict_scopes = strict; } + pub fn is_strict(&self) -> bool { + self.strict_scopes + } + pub fn set_no_warn(&mut self, no_warn: bool) { self.no_warn = no_warn; } diff --git a/src/data/gui.rs b/src/data/gui.rs index 9e799937..e2169de6 100644 --- a/src/data/gui.rs +++ b/src/data/gui.rs @@ -13,7 +13,9 @@ use crate::helpers::dup_error; use crate::item::Item; use crate::parse::localization::ValueParser; use crate::pdxfile::PdxFile; -use crate::report::{error, error_info, old_warn, warn, warn_info, ErrorKey}; +#[cfg(feature = "ck3")] +use crate::report::warn; +use crate::report::{error, error_info, old_warn, warn_info, ErrorKey}; use crate::scopes::Scopes; use crate::token::Token; diff --git a/src/data/localization.rs b/src/data/localization.rs index eb8d9401..04f0544f 100644 --- a/src/data/localization.rs +++ b/src/data/localization.rs @@ -274,7 +274,6 @@ impl Localization { } fn check_loca_code( - loca_key: &Token, value: &LocaValue, data: &Everything, sc: &mut ScopeContext, @@ -283,7 +282,7 @@ impl Localization { match value { LocaValue::Concat(v) => { for value in v { - Self::check_loca_code(loca_key, value, data, sc, lang); + Self::check_loca_code(value, data, sc, lang); } } // A reference to a game concept @@ -352,11 +351,11 @@ impl Localization { } } - pub fn validate_use(&self, key: &Token, data: &Everything, sc: &mut ScopeContext) { + pub fn validate_use(&self, key: &str, data: &Everything, sc: &mut ScopeContext) { for lang in &self.mod_langs { if let Some(hash) = self.locas.get(lang) { - if let Some(entry) = hash.get(key.as_str()) { - Self::check_loca_code(key, &entry.value, data, sc, lang); + if let Some(entry) = hash.get(key) { + Self::check_loca_code(&entry.value, data, sc, lang); } } } @@ -369,7 +368,7 @@ impl Localization { for entry in hash.values() { let mut sc = ScopeContext::new_unrooted(Scopes::all(), &entry.key); sc.set_strict_scopes(false); - Self::check_loca_code(&entry.key, &entry.value, data, &mut sc, lang); + Self::check_loca_code(&entry.value, data, &mut sc, lang); } } } diff --git a/src/datatype.rs b/src/datatype.rs index fb83bc5d..2260c2b1 100644 --- a/src/datatype.rs +++ b/src/datatype.rs @@ -50,6 +50,7 @@ pub enum CodeArg { } impl CodeChain { + #[cfg(feature = "ck3")] pub fn as_gameconcept(&self) -> Option<&Token> { if self.codes.len() == 1 && self.codes[0].arguments.is_empty() { Some(&self.codes[0].name) @@ -277,6 +278,7 @@ pub fn validate_datatypes( // In ck3, allow unadorned game concepts as long as they end with _i // (which means they are just the icon). This is a heuristic. + #[cfg(feature = "ck3")] if !found && code.name.as_str().ends_with("_i") && data.item_exists(Item::GameConcept, code.name.as_str()) @@ -336,7 +338,7 @@ pub fn validate_datatypes( // Unfortunately we don't have a complete list of those, so accept any lowercase id and // warn if it starts with uppercase. This is not a foolproof check though. // TODO: it's in theory possible to build a complete list of possible scope variable names - if code.name.as_str().chars().next().unwrap().is_uppercase() { + if sc.is_strict() || code.name.as_str().chars().next().unwrap().is_uppercase() { // TODO: If there is a Custom of the same name, suggest that let msg = format!("unknown datafunction {}", &code.name); if let Some(alternative) = diff --git a/src/desc.rs b/src/desc.rs index aad5f5e4..d0607a0c 100644 --- a/src/desc.rs +++ b/src/desc.rs @@ -13,7 +13,7 @@ fn validate_desc_map_block( block: &Block, data: &Everything, sc: &mut ScopeContext, - f: &impl Fn(&Token, &Everything), + f: &impl Fn(&Token, &Everything, &mut ScopeContext), ) { let mut vd = Validator::new(block, data); let mut seen_desc = false; @@ -34,7 +34,7 @@ fn validate_desc_map_block( match bv { BV::Value(token) => { if !token.as_str().contains(' ') { - f(token, data); + f(token, data, sc); } } BV::Block(block) => { @@ -75,12 +75,12 @@ pub fn validate_desc_map( bv: &BV, data: &Everything, sc: &mut ScopeContext, - f: impl Fn(&Token, &Everything), + f: impl Fn(&Token, &Everything, &mut ScopeContext), ) { match bv { BV::Value(t) => { if !t.as_str().contains(' ') { - f(t, data); + f(t, data, sc); } } BV::Block(b) => { @@ -90,7 +90,8 @@ pub fn validate_desc_map( } pub fn validate_desc(bv: &BV, data: &Everything, sc: &mut ScopeContext) { - validate_desc_map(bv, data, sc, |token, data| { + validate_desc_map(bv, data, sc, |token, data, sc| { data.verify_exists(Item::Localization, token); + data.validate_localization_sc(token.as_str(), sc); }); } diff --git a/src/everything.rs b/src/everything.rs index baae2bee..af1f91be 100644 --- a/src/everything.rs +++ b/src/everything.rs @@ -1000,7 +1000,7 @@ impl Everything { /// Validate the use of a localization within a specific `ScopeContext`. /// This allows validation of the named scopes used within the localization's datafunctions. - pub(crate) fn validate_localization_sc(&self, key: &Token, sc: &mut ScopeContext) { + pub(crate) fn validate_localization_sc(&self, key: &str, sc: &mut ScopeContext) { self.localization.validate_use(key, self, sc); }