diff --git a/crates/core/src/pattern/accumulate.rs b/crates/core/src/pattern/accumulate.rs index 850fced8b..a4a590faa 100644 --- a/crates/core/src/pattern/accumulate.rs +++ b/crates/core/src/pattern/accumulate.rs @@ -16,7 +16,6 @@ use super::{ }; use super::{Effect, EffectKind}; use crate::context::Context; -use crate::smart_insert::normalize_insert; use tree_sitter::Node; #[derive(Debug, Clone)] @@ -203,7 +202,7 @@ impl Matcher for Accumulate { .iter() .map(|b| { let is_first = !state.effects.iter().any(|e| e.binding == *b); - normalize_insert(b, &mut replacement, is_first, context.language())?; + replacement.normalize_insert(b, is_first, context.language())?; Ok(Effect { binding: b.clone(), pattern: replacement.clone(), diff --git a/crates/core/src/pattern/resolved_pattern.rs b/crates/core/src/pattern/resolved_pattern.rs index fa9e05955..d42c5ad1f 100644 --- a/crates/core/src/pattern/resolved_pattern.rs +++ b/crates/core/src/pattern/resolved_pattern.rs @@ -13,7 +13,6 @@ use crate::{ binding::{Binding, Constant}, context::Context, pattern::{container::PatternOrResolved, patterns::Name}, - smart_insert::normalize_insert, }; use anyhow::{anyhow, bail, Result}; use im::{vector, Vector}; @@ -374,7 +373,7 @@ impl<'a> ResolvedPattern<'a> { .iter() .map(|b| { let is_first = !effects.iter().any(|e| e.binding == *b); - normalize_insert(b, &mut with, is_first, language)?; + with.normalize_insert(b, is_first, language)?; Ok(Effect { binding: b.clone(), pattern: with.clone(), @@ -977,6 +976,26 @@ impl<'a> ResolvedPattern<'a> { ResolvedPattern::Constant(constant) => Ok(constant.to_string().into()), } } + + pub(crate) fn normalize_insert( + &mut self, + binding: &Binding<'a>, + is_first: bool, + language: &TargetLanguage, + ) -> Result<()> { + let ResolvedPattern::Snippets(ref mut snippets) = self else { + return Ok(()); + }; + let Some(ResolvedSnippet::Text(text)) = snippets.front() else { + return Ok(()); + }; + if let Some(padding) = binding.get_insertion_padding(&text, is_first, language) { + if padding.chars().next() != binding.text().chars().last() { + snippets.push_front(ResolvedSnippet::Text(padding.into())); + } + } + Ok(()) + } } pub(crate) fn pattern_to_binding<'a>( diff --git a/crates/core/src/smart_insert.rs b/crates/core/src/smart_insert.rs index bf9d462f0..22f3d859f 100644 --- a/crates/core/src/smart_insert.rs +++ b/crates/core/src/smart_insert.rs @@ -1,69 +1,53 @@ -use crate::{ - binding::Binding, - pattern::resolved_pattern::{ResolvedPattern, ResolvedSnippet}, -}; -use anyhow::Result; +use crate::binding::Binding; use itertools::Itertools; use marzano_language::{language::Language, target_language::TargetLanguage}; use tree_sitter::Node; -pub(crate) fn normalize_insert<'a>( - binding: &Binding<'a>, - with: &mut ResolvedPattern<'a>, - is_first: bool, - language: &TargetLanguage, -) -> Result<()> { - let ResolvedPattern::Snippets(ref mut snippets) = with else { - return Ok(()); - }; - let Some(ResolvedSnippet::Text(text)) = snippets.front() else { - return Ok(()); - }; - let insert_padding = match binding { - Binding::List(src, node, field_id) => { - let mut cursor = node.walk(); - let children = node - .children_by_field_id(*field_id, &mut cursor) - .collect_vec(); - if children.is_empty() { - return Ok(()); - } - calculate_padding(src, &children, text, is_first, language).or_else(|| { - if children.len() == 1 { - let child = children.first().unwrap(); - let child_text = child.utf8_text(src.as_bytes()).ok()?; - if child.end_position().row() > child.start_position().row() - && !child_text.ends_with('\n') - && !text.starts_with('\n') - { - return Some("\n".to_string()); +impl<'a> Binding<'a> { + /// Returns the padding to use for inserting the given text. + pub(crate) fn get_insertion_padding( + &self, + text: &str, + is_first: bool, + language: &TargetLanguage, + ) -> Option { + match self { + Self::List(src, node, field_id) => { + let mut cursor = node.walk(); + let children = node + .children_by_field_id(*field_id, &mut cursor) + .collect_vec(); + if children.is_empty() { + return None; + } + calculate_padding(src, &children, text, is_first, language).or_else(|| { + if children.len() == 1 { + let child = children.first().unwrap(); + let child_text = child.utf8_text(src.as_bytes()).ok()?; + if child.end_position().row() > child.start_position().row() + && !child_text.ends_with('\n') + && !text.starts_with('\n') + { + return Some("\n".to_string()); + } } + None + }) + } + Self::Node(src, node) => { + let node_text = node.utf8_text(src.as_bytes()).ok()?; + if language.is_statement(node.kind_id()) + && !node_text.ends_with('\n') + && !text.starts_with('\n') + { + Some("\n".to_string()) + } else { + None } - None - }) - } - Binding::Node(src, node) => { - let node_text = node.utf8_text(src.as_bytes())?; - if language.is_statement(node.kind_id()) - && !node_text.ends_with('\n') - && !text.starts_with('\n') - { - Some("\n".to_string()) - } else { - None } - } - Binding::String(..) - | Binding::FileName(_) - | Binding::Empty(..) - | Binding::ConstantRef(_) => None, - }; - if let Some(padding) = insert_padding { - if padding.chars().next() != binding.text().chars().last() { - snippets.push_front(ResolvedSnippet::Text(padding.into())); + Self::String(..) | Self::FileName(_) | Self::Empty(..) | Self::ConstantRef(_) => None, } } - Ok(()) } fn calculate_padding(