diff --git a/leptos_hot_reload/src/diff.rs b/leptos_hot_reload/src/diff.rs index 408995695..347ee188e 100644 --- a/leptos_hot_reload/src/diff.rs +++ b/leptos_hot_reload/src/diff.rs @@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize}; struct OldChildren(IndexMap>); impl LNode { + #[must_use] pub fn diff(&self, other: &LNode) -> Vec { let mut old_children = OldChildren::default(); self.add_old_children(vec![], &mut old_children); @@ -196,7 +197,7 @@ impl LNode { if replace { match &new_value { LAttributeValue::Boolean => { - Some((name.to_owned(), "".to_string())) + Some((name.to_owned(), String::new())) } LAttributeValue::Static(s) => { Some((name.to_owned(), s.to_owned())) @@ -213,13 +214,13 @@ impl LNode { }); let removals = old.iter().filter_map(|(name, _)| { - if !new.iter().any(|(new_name, _)| new_name == name) { + if new.iter().any(|(new_name, _)| new_name == name) { + None + } else { Some(Patch { path: path.to_owned(), action: PatchAction::RemoveAttribute(name.to_owned()), }) - } else { - None } }); @@ -259,7 +260,6 @@ impl LNode { let new = new.get(a); match (old, new) { - (None, None) => {} (None, Some(new)) => patches.push(Patch { path: path.to_owned(), action: PatchAction::InsertChild { @@ -271,11 +271,10 @@ impl LNode { path: path.to_owned(), action: PatchAction::RemoveChild { at: a }, }), - (Some(old), Some(new)) => { - if old != new { - break; - } + (Some(old), Some(new)) if old != new => { + break; } + _ => {} } a += 1; @@ -287,7 +286,6 @@ impl LNode { let new = new.get(b); match (old, new) { - (None, None) => {} (None, Some(new)) => patches.push(Patch { path: path.to_owned(), action: PatchAction::InsertChildAfter { @@ -299,18 +297,16 @@ impl LNode { path: path.to_owned(), action: PatchAction::RemoveChild { at: b }, }), - (Some(old), Some(new)) => { - if old != new { - break; - } + (Some(old), Some(new)) if old != new => { + break; } + _ => {} } if b == 0 { break; - } else { - b -= 1; } + b -= 1; } // diffing in middle diff --git a/leptos_hot_reload/src/lib.rs b/leptos_hot_reload/src/lib.rs index 79ed1565f..48f0707ff 100644 --- a/leptos_hot_reload/src/lib.rs +++ b/leptos_hot_reload/src/lib.rs @@ -33,10 +33,14 @@ pub struct ViewMacros { } impl ViewMacros { + #[must_use] pub fn new() -> Self { Self::default() } + /// # Errors + /// + /// Will return `Err` if the path is not UTF-8 path or the contents of the file cannot be parsed. pub fn update_from_paths>(&self, paths: &[T]) -> Result<()> { let mut views = HashMap::new(); @@ -59,6 +63,9 @@ impl ViewMacros { Ok(()) } + /// # Errors + /// + /// Will return `Err` if the contents of the file cannot be parsed. pub fn parse_file(path: &Utf8PathBuf) -> Result> { let mut file = File::open(path)?; let mut content = String::new(); @@ -76,11 +83,14 @@ impl ViewMacros { let rsx = rstml::parse2(tokens.collect::())?; let template = LNode::parse_view(rsx)?; - views.push(MacroInvocation { id, template }) + views.push(MacroInvocation { id, template }); } Ok(views) } + /// # Errors + /// + /// Will return `Err` if the contents of the file cannot be parsed. pub fn patch(&self, path: &Utf8PathBuf) -> Result> { let new_views = Self::parse_file(path)?; let mut lock = self.views.write(); @@ -125,7 +135,7 @@ impl std::fmt::Debug for MacroInvocation { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("MacroInvocation") .field("id", &self.id) - .finish() + .finish_non_exhaustive() } } @@ -136,7 +146,7 @@ pub struct ViewMacroVisitor<'a> { impl<'ast> Visit<'ast> for ViewMacroVisitor<'ast> { fn visit_macro(&mut self, node: &'ast Macro) { - let ident = node.path.get_ident().map(|n| n.to_string()); + let ident = node.path.get_ident().map(ToString::to_string); if ident == Some("view".to_string()) { self.views.push(node); } diff --git a/leptos_hot_reload/src/node.rs b/leptos_hot_reload/src/node.rs index f50d7d0c1..78dd09429 100644 --- a/leptos_hot_reload/src/node.rs +++ b/leptos_hot_reload/src/node.rs @@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize}; // `syn` types are `!Send` so we can't store them as we might like. // This is only used to diff view macros for hot reloading so it's very minimal // and ignores many of the data types. +#[allow(clippy::module_name_repetitions)] #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum LNode { Fragment(Vec), @@ -38,18 +39,26 @@ pub enum LAttributeValue { } impl LNode { + /// # Errors + /// + /// Will return `Err` if parsing the view fails. pub fn parse_view(nodes: Vec) -> Result { let mut out = Vec::new(); for node in nodes { LNode::parse_node(node, &mut out)?; } if out.len() == 1 { - Ok(out.pop().unwrap()) + out.pop().ok_or_else(|| { + unreachable!("The last element should not be None.") + }) } else { Ok(LNode::Fragment(out)) } } + /// # Errors + /// + /// Will return `Err` if parsing the node fails. pub fn parse_node(node: Node, views: &mut Vec) -> Result<()> { match node { Node::Fragment(frag) => { @@ -61,9 +70,9 @@ impl LNode { views.push(LNode::Text(text.value_string())); } Node::Block(block) => { - let code = block.into_token_stream(); - let code = code.to_string(); - views.push(LNode::DynChild(code)); + views.push(LNode::DynChild( + block.into_token_stream().to_string(), + )); } Node::Element(el) => { if is_component_node(&el) { @@ -83,7 +92,7 @@ impl LNode { attr.key.to_string(), format!("{:#?}", attr.value()), )), - _ => None, + NodeAttribute::Block(_) => None, }) .collect(), children, @@ -151,8 +160,9 @@ impl LNode { LAttributeValue::Static(value) => { Some(format!("{name}=\"{value}\" ")) } - LAttributeValue::Dynamic => None, - LAttributeValue::Noop => None, + LAttributeValue::Dynamic | LAttributeValue::Noop => { + None + } }) .collect::(); diff --git a/leptos_hot_reload/src/parsing.rs b/leptos_hot_reload/src/parsing.rs index 84626848a..697b0d538 100644 --- a/leptos_hot_reload/src/parsing.rs +++ b/leptos_hot_reload/src/parsing.rs @@ -1,6 +1,5 @@ use rstml::node::{NodeElement, NodeName}; -/// /// Converts `syn::Block` to simple expression /// /// For example: @@ -14,6 +13,7 @@ use rstml::node::{NodeElement, NodeName}; /// // variable /// {path::x} /// ``` +#[must_use] pub fn block_to_primitive_expression(block: &syn::Block) -> Option<&syn::Expr> { // its empty block, or block with multi lines if block.stmts.len() != 1 { @@ -29,6 +29,7 @@ pub fn block_to_primitive_expression(block: &syn::Block) -> Option<&syn::Expr> { /// /// This function doesn't convert literal wrapped inside block /// like: `{"string"}`. +#[must_use] pub fn value_to_string(value: &syn::Expr) -> Option { match &value { syn::Expr::Lit(lit) => match &lit.lit { @@ -42,6 +43,10 @@ pub fn value_to_string(value: &syn::Expr) -> Option { } } +/// # Panics +/// +/// Will panic if the last element does not exist in the path. +#[must_use] pub fn is_component_tag_name(name: &NodeName) -> bool { match name { NodeName::Path(path) => { @@ -55,11 +60,11 @@ pub fn is_component_tag_name(name: &NodeName) -> bool { .to_string() .starts_with(|c: char| c.is_ascii_uppercase()) } - NodeName::Block(_) => false, - NodeName::Punctuated(_) => false, + NodeName::Block(_) | NodeName::Punctuated(_) => false, } } +#[must_use] pub fn is_component_node(node: &NodeElement) -> bool { is_component_tag_name(node.name()) }