codegen/app/
identifiers.rs1use anyhow::bail;
2use wowlab_fs::path::Path;
3use wowlab_manifest_schema::ItemManifestEntry;
4
5use super::{generation::LoadedSpec, ownership::validate_owned_path};
6use crate::helpers::to_snake;
7
8pub(super) fn validate_rust_identifier(identifier: &str, context: &str) -> anyhow::Result<()> {
9 if syn::parse_str::<syn::Ident>(identifier).is_ok() {
10 Ok(())
11 } else {
12 bail!("{context} generates invalid Rust identifier `{identifier}`")
13 }
14}
15
16pub(super) fn validate_module_component(component: &str, context: &str) -> anyhow::Result<()> {
17 validate_owned_path(Path::new(component))?;
18
19 validate_rust_identifier(component, context)
20}
21
22pub(super) fn validate_named_identifiers<'a>(
23 names: impl Iterator<Item = &'a String>,
24 section: &str,
25 path: &Path,
26) -> anyhow::Result<()> {
27 for name in names {
28 validate_rust_identifier(name, &format!("{} [{section}.{name}]", path.display()))?;
29 }
30
31 Ok(())
32}
33
34pub(super) fn validate_spec_identifiers(spec: &LoadedSpec) -> anyhow::Result<()> {
35 let path = &spec.path;
36
37 validate_module_component(&spec.mod_name, &format!("spec manifest {}", path.display()))?;
38 validate_named_identifiers(spec.manifest.spells.keys(), "spells", path)?;
39 validate_named_identifiers(spec.manifest.auras.keys(), "auras", path)?;
40 validate_named_identifiers(spec.manifest.talents.keys(), "talents", path)?;
41 validate_named_identifiers(spec.manifest.set_bonuses.keys(), "set_bonuses", path)?;
42 validate_named_identifiers(spec.manifest.effects.keys(), "effects", path)?;
43
44 for name in spec.manifest.reported_spells.keys() {
45 validate_rust_identifier(
46 &name.to_uppercase(),
47 &format!("{} [reported_spells.{name}]", path.display()),
48 )?;
49 }
50
51 for (tree_name, tree) in &spec.manifest.hero_talents {
52 validate_rust_identifier(
53 &tree_name.to_uppercase(),
54 &format!("{} [hero_talents.{tree_name}]", path.display()),
55 )?;
56 validate_named_identifiers(
57 tree.spells.keys(),
58 &format!("hero_talents.{tree_name}.spells"),
59 path,
60 )?;
61 validate_named_identifiers(
62 tree.auras.keys(),
63 &format!("hero_talents.{tree_name}.auras"),
64 path,
65 )?;
66 }
67
68 if let Some(metric_keys) = &spec.manifest.metric_keys {
69 validate_rust_identifier(
70 &metric_keys.module_name,
71 &format!("{} [metric_keys.module_name]", path.display()),
72 )?;
73
74 for key in &metric_keys.keys {
75 validate_rust_identifier(key, &format!("{} [metric_keys.keys]", path.display()))?;
76 }
77 }
78
79 Ok(())
80}
81
82pub(super) fn validate_item_identifiers(
83 key: &str,
84 item: &ItemManifestEntry,
85 path: &Path,
86) -> anyhow::Result<()> {
87 validate_module_component(&to_snake(key), &format!("{} [items.{key}]", path.display()))?;
88 validate_named_identifiers(item.spells.keys(), &format!("items.{key}.spells"), path)?;
89 validate_named_identifiers(item.auras.keys(), &format!("items.{key}.auras"), path)?;
90
91 validate_named_identifiers(item.effects.keys(), &format!("items.{key}.effects"), path)
92}