(template: &ProgramTemplate, issues: &mut Vec<ProgramTemplateIssue>)
| 164 | } |
| 165 | |
| 166 | fn validate_program_template(template: &ProgramTemplate, issues: &mut Vec<ProgramTemplateIssue>) { |
| 167 | if template.name.trim().is_empty() { |
| 168 | issues.push(ProgramTemplateIssue::new( |
| 169 | "empty_name", |
| 170 | "name", |
| 171 | "program template name is required", |
| 172 | )); |
| 173 | } else if !is_program_identifier(&template.name) { |
| 174 | issues.push(ProgramTemplateIssue::new( |
| 175 | "invalid_name", |
| 176 | "name", |
| 177 | "program template name must contain only ASCII letters, numbers, '_' or '-'", |
| 178 | )); |
| 179 | } |
| 180 | |
| 181 | if template.description.trim().is_empty() { |
| 182 | issues.push(ProgramTemplateIssue::new( |
| 183 | "empty_description", |
| 184 | "description", |
| 185 | "program template description is required", |
| 186 | )); |
| 187 | } |
| 188 | |
| 189 | let mut parameter_names = HashSet::new(); |
| 190 | for (index, parameter) in template.parameters.iter().enumerate() { |
| 191 | let path = format!("parameters[{index}].name"); |
| 192 | if parameter.name.trim().is_empty() { |
| 193 | issues.push(ProgramTemplateIssue::new( |
| 194 | "empty_parameter_name", |
| 195 | path, |
| 196 | "program parameter name is required", |
| 197 | )); |
| 198 | } else if !is_program_identifier(¶meter.name) { |
| 199 | issues.push(ProgramTemplateIssue::new( |
| 200 | "invalid_parameter_name", |
| 201 | path, |
| 202 | "program parameter name must contain only ASCII letters, numbers, '_' or '-'", |
| 203 | )); |
| 204 | } else if !parameter_names.insert(parameter.name.clone()) { |
| 205 | issues.push(ProgramTemplateIssue::new( |
| 206 | "duplicate_parameter", |
| 207 | path, |
| 208 | format!("duplicate program parameter '{}'", parameter.name), |
| 209 | )); |
| 210 | } |
| 211 | |
| 212 | if parameter.required && parameter.default.is_some() { |
| 213 | issues.push(ProgramTemplateIssue::new( |
| 214 | "required_parameter_with_default", |
| 215 | format!("parameters[{index}].default"), |
| 216 | "required program parameters must not define defaults", |
| 217 | )); |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | if template.steps.is_empty() { |
| 222 | issues.push(ProgramTemplateIssue::new( |
| 223 | "empty_steps", |
no test coverage detected