use crate::ir::Span;
use crate::ir::WidgetKind;
use crate::parser::error::{ParseError, ParseErrorKind};
use std::collections::HashMap;
const DEPRECATED_ATTRIBUTES: &[(&str, &str, &str)] = &[
("path", "src", "image,svg"),
("active", "toggled", "toggler"),
("is_toggled", "toggled", "toggler"),
("secure", "password", "text_input"),
];
pub fn validate_attributes(
widget_kind: &WidgetKind,
attributes: &HashMap<String, crate::ir::AttributeValue>,
span: Span,
) -> Result<(), ParseError> {
for (old_name, new_name, applicable_widgets) in DEPRECATED_ATTRIBUTES {
if attributes.contains_key(*old_name) {
let widget_name = widget_kind.to_string();
if applicable_widgets
.split(',')
.any(|w| w == widget_name.as_str())
{
return Err(ParseError {
kind: ParseErrorKind::DeprecatedAttribute,
message: format!(
"Attribute '{}' is deprecated for {} widgets",
old_name, widget_name
),
span,
suggestion: Some(format!("Use '{}' instead: {}=\"...\"", new_name, new_name)),
});
}
}
}
Ok(())
}
pub fn normalize_attributes(
widget_kind: &WidgetKind,
attributes: &mut HashMap<String, crate::ir::AttributeValue>,
) -> Vec<(String, String)> {
let mut warnings = Vec::new();
let widget_name = widget_kind.to_string();
for (old_name, new_name, applicable_widgets) in DEPRECATED_ATTRIBUTES {
if attributes.contains_key(*old_name) {
if applicable_widgets
.split(',')
.any(|w| w == widget_name.as_str())
{
if let Some(value) = attributes.remove(*old_name) {
attributes.insert(new_name.to_string(), value);
warnings.push((old_name.to_string(), new_name.to_string()));
}
}
}
}
warnings
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ir::AttributeValue;
#[test]
fn test_normalize_image_path_to_src() {
let mut attributes = HashMap::new();
attributes.insert(
"path".to_string(),
AttributeValue::Static("icon.png".to_string()),
);
let warnings = normalize_attributes(&WidgetKind::Image, &mut attributes);
assert_eq!(warnings.len(), 1);
assert_eq!(warnings[0], ("path".to_string(), "src".to_string()));
assert!(attributes.contains_key("src"));
assert!(!attributes.contains_key("path"));
}
#[test]
fn test_normalize_toggler_active_to_toggled() {
let mut attributes = HashMap::new();
attributes.insert(
"active".to_string(),
AttributeValue::Static("true".to_string()),
);
let warnings = normalize_attributes(&WidgetKind::Toggler, &mut attributes);
assert_eq!(warnings.len(), 1);
assert_eq!(warnings[0], ("active".to_string(), "toggled".to_string()));
assert!(attributes.contains_key("toggled"));
assert!(!attributes.contains_key("active"));
}
#[test]
fn test_normalize_textinput_secure_to_password() {
let mut attributes = HashMap::new();
attributes.insert(
"secure".to_string(),
AttributeValue::Static("true".to_string()),
);
let warnings = normalize_attributes(&WidgetKind::TextInput, &mut attributes);
assert_eq!(warnings.len(), 1);
assert_eq!(warnings[0], ("secure".to_string(), "password".to_string()));
assert!(attributes.contains_key("password"));
assert!(!attributes.contains_key("secure"));
}
#[test]
fn test_normalize_no_change_for_standard_attributes() {
let mut attributes = HashMap::new();
attributes.insert(
"src".to_string(),
AttributeValue::Static("icon.png".to_string()),
);
let warnings = normalize_attributes(&WidgetKind::Image, &mut attributes);
assert_eq!(warnings.len(), 0);
assert!(attributes.contains_key("src"));
}
#[test]
fn test_normalize_ignores_deprecated_on_wrong_widget() {
let mut attributes = HashMap::new();
attributes.insert(
"path".to_string(),
AttributeValue::Static("some_path".to_string()),
);
let warnings = normalize_attributes(&WidgetKind::Button, &mut attributes);
assert_eq!(warnings.len(), 0);
assert!(attributes.contains_key("path")); }
}