ralph/template/variables/
validate.rs1use std::collections::HashSet;
21
22use regex::Regex;
23
24use crate::contracts::Task;
25
26use super::context::{TemplateValidation, TemplateWarning};
27
28const KNOWN_VARIABLES: &[&str] = &["target", "module", "file", "branch"];
30
31pub(super) fn extract_variables(input: &str) -> HashSet<String> {
35 let mut variables = HashSet::new();
36 let re = match Regex::new(r"\{\{(\w+)\}\}") {
40 Ok(re) => re,
41 Err(_) => return variables, };
43
44 for cap in re.captures_iter(input) {
45 if let Some(matched) = cap.get(1) {
46 variables.insert(matched.as_str().to_string());
47 }
48 }
49 variables
50}
51
52pub(super) fn uses_branch_variable(input: &str) -> bool {
54 input.contains("{{branch}}")
55}
56
57pub fn validate_task_template(task: &Task) -> TemplateValidation {
63 let mut validation = TemplateValidation::default();
64 let mut all_variables: HashSet<String> = HashSet::new();
65
66 let fields = [
68 ("title", task.title.clone()),
69 ("request", task.request.clone().unwrap_or_default()),
70 ];
71
72 for (field_name, value) in &fields {
73 if uses_branch_variable(value) {
74 validation.uses_branch = true;
75 }
76 let vars = extract_variables(value);
77 for var in &vars {
78 if !KNOWN_VARIABLES.contains(&var.as_str()) {
79 validation.warnings.push(TemplateWarning::UnknownVariable {
80 name: var.clone(),
81 field: Some(field_name.to_string()),
82 });
83 }
84 all_variables.insert(var.clone());
85 }
86 }
87
88 let array_fields: [(&str, &[String]); 5] = [
90 ("tags", &task.tags),
91 ("scope", &task.scope),
92 ("evidence", &task.evidence),
93 ("plan", &task.plan),
94 ("notes", &task.notes),
95 ];
96
97 for (field_name, values) in &array_fields {
98 for value in *values {
99 if uses_branch_variable(value) {
100 validation.uses_branch = true;
101 }
102 let vars = extract_variables(value);
103 for var in &vars {
104 if !KNOWN_VARIABLES.contains(&var.as_str()) {
105 validation.warnings.push(TemplateWarning::UnknownVariable {
106 name: var.clone(),
107 field: Some(field_name.to_string()),
108 });
109 }
110 all_variables.insert(var.clone());
111 }
112 }
113 }
114
115 validation
116}