diff --git a/crates/core/src/binding.rs b/crates/core/src/binding.rs index 5dfcc5b90..a8c165ec6 100644 --- a/crates/core/src/binding.rs +++ b/crates/core/src/binding.rs @@ -8,6 +8,7 @@ use marzano_language::target_language::TargetLanguage; use marzano_util::analysis_logs::{AnalysisLogBuilder, AnalysisLogs}; use marzano_util::position::{Position, Range}; use std::ops::Range as StdRange; +use std::path::Path; use std::{borrow::Cow, collections::HashMap, fmt::Display}; use tree_sitter::Node; @@ -53,7 +54,7 @@ pub enum Binding<'a> { // used by slices that don't correspond to a node // currently only comment content. String(&'a str, Range), - FileName(&'a str), + FileName(&'a Path), Node(&'a str, Node<'a>), // tree-sitter lists ("multiple" fields of nodes) do not have a unique identity // so we represent them by the parent node and a field id @@ -446,7 +447,7 @@ impl<'a> Binding<'a> { Binding::String(s, r) => Ok(Cow::Owned( s[r.start_byte as usize..r.end_byte as usize].into(), )), - Binding::FileName(s) => Ok(Cow::Owned(s.to_string())), + Binding::FileName(s) => Ok(Cow::Owned(s.to_string_lossy().into())), Binding::List(source, _parent_node, _field_id) => { if let Some(pos) = self.position() { let range = CodeRange::new(pos.start_byte, pos.end_byte, source); @@ -475,7 +476,7 @@ impl<'a> Binding<'a> { Binding::Empty(_, _, _) => "".to_string(), Binding::Node(source, node) => node_text(source, node).to_string(), Binding::String(s, r) => s[r.start_byte as usize..r.end_byte as usize].into(), - Binding::FileName(s) => s.to_string(), + Binding::FileName(s) => s.to_string_lossy().into(), Binding::List(source, _, _) => { if let Some(pos) = self.position() { source[pos.start_byte as usize..pos.end_byte as usize].to_string() @@ -499,9 +500,18 @@ impl<'a> Binding<'a> { Binding::Node(source, _) => Some(source), Binding::String(source, _) => Some(source), Binding::List(source, _, _) => Some(source), - // maybe should be none? - Binding::FileName(source) => Some(source), - Binding::ConstantRef(_) => None, + Binding::FileName(..) | Binding::ConstantRef(..) => None, + } + } + + pub fn as_filename(&self) -> Option<&Path> { + match self { + Binding::FileName(path) => Some(path), + Binding::Empty(..) + | Binding::Node(..) + | Binding::String(..) + | Binding::List(..) + | Binding::ConstantRef(..) => None, } } diff --git a/crates/core/src/equivalence.rs b/crates/core/src/equivalence.rs index c26176db0..5b74bd4d6 100644 --- a/crates/core/src/equivalence.rs +++ b/crates/core/src/equivalence.rs @@ -61,7 +61,7 @@ pub fn are_bindings_equivalent(binding1: &Binding, binding2: &Binding) -> bool { Binding::String(s1, range) => { s1[range.start_byte as usize..range.end_byte as usize] == binding2.text() } - Binding::FileName(s1) => *s1 == binding2.text(), + Binding::FileName(s1) => binding2.as_filename().map_or(false, |s2| *s1 == s2), } } diff --git a/crates/core/src/pattern.rs b/crates/core/src/pattern.rs index a92fee099..6090649df 100644 --- a/crates/core/src/pattern.rs +++ b/crates/core/src/pattern.rs @@ -215,8 +215,8 @@ impl MatchRanges { #[derive(Debug, Clone)] pub struct FileOwner { - absolute_path: String, - name: String, + absolute_path: PathBuf, + name: PathBuf, // todo wrap in Rc>> // so that we can lazily parse tree: Tree, @@ -227,15 +227,16 @@ pub struct FileOwner { impl FileOwner { pub(crate) fn new( - name: String, + name: impl Into, source: String, matches: Option, new: bool, language: &impl Language, logs: &mut AnalysisLogs, ) -> Result { - let tree = language.parse_file(&name, &source, logs, new)?; - let absolute_path = absolutize(&name)?; + let name = name.into(); + let tree = language.parse_file(name.to_string_lossy().as_ref(), &source, logs, new)?; + let absolute_path = PathBuf::from(absolutize(name.to_string_lossy().as_ref())?); Ok(FileOwner { name, absolute_path, @@ -768,7 +769,7 @@ impl Debug for FileOwners { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0 .iter() - .try_fold((), |_, file| writeln!(f, "{}", file.name)) + .try_fold((), |_, file| writeln!(f, "{}", file.name.display())) } } diff --git a/crates/core/src/pattern/api.rs b/crates/core/src/pattern/api.rs index 40f156a29..10457d30f 100644 --- a/crates/core/src/pattern/api.rs +++ b/crates/core/src/pattern/api.rs @@ -101,7 +101,7 @@ impl MatchResult { let file = file.last().unwrap(); if file.new { return Ok(Some(MatchResult::CreateFile(CreateFile::file_to_create( - &file.name, + file.name.to_string_lossy().as_ref(), &file.source, )))); } else if let Some(ranges) = &file.matches.borrow().input_matches { @@ -111,7 +111,7 @@ impl MatchResult { return Ok(Some(MatchResult::Match(Match::file_to_match( ranges, &file.source, - &file.name, + file.name.to_string_lossy().as_ref(), &file.tree, language, )))); @@ -358,7 +358,7 @@ impl Rewrite { Match::file_to_match( ranges, &initial.source, - &initial.name, + initial.name.to_string_lossy().as_ref(), &initial.tree, language, ) @@ -366,7 +366,7 @@ impl Rewrite { bail!("cannot have rewrite without matches") }; let rewritten = EntireFile::file_to_entire_file( - &rewrite.name, + rewrite.name.to_string_lossy().as_ref(), &rewrite.source, rewrite.matches.borrow().byte_ranges.as_ref(), ); diff --git a/crates/core/src/pattern/step.rs b/crates/core/src/pattern/step.rs index 6fc09b5a5..644f8add5 100644 --- a/crates/core/src/pattern/step.rs +++ b/crates/core/src/pattern/step.rs @@ -1,5 +1,5 @@ use marzano_util::position::Range; -use std::collections::BTreeMap; +use std::{collections::BTreeMap, path::PathBuf}; use super::{ auto_wrap::wrap_pattern_in_before_and_after_each_file, @@ -11,7 +11,6 @@ use super::{ FileOwner, }; use crate::{ - binding::Constant, context::Context, orphan::{get_orphaned_ranges, remove_orphaned_ranges}, pattern::{InputRanges, MatchRanges}, @@ -232,10 +231,9 @@ impl Matcher for Step { let file = state.files.get_file(file_ptr); let mut match_log = file.matches.borrow_mut(); - let filename_string = &file.name; + let filename_path = &file.name; - // todo shouldn't have to wrap new_filename in const - let mut new_filename: Constant = Constant::String(filename_string.to_owned()); + let mut new_filename = filename_path.clone(); let src = &file.source; @@ -247,7 +245,8 @@ impl Matcher for Step { .effects .iter() .find(|e| { - e.binding.source() == Some(src) || e.binding.source() == Some(filename_string) + e.binding.source() == Some(src) + || e.binding.as_filename() == Some(filename_path) }) .cloned() .is_some() @@ -276,7 +275,7 @@ impl Matcher for Step { let ranges = MatchRanges::new(new_ranges.into_iter().map(|r| r.into()).collect()); let owned_file = FileOwner::new( - new_filename.to_string(), + new_filename, new_src, Some(ranges), true, @@ -296,7 +295,12 @@ impl Matcher for Step { { for f in new_files_vector { if let ResolvedPattern::File(file) = f { - let name = file.name(&state.files).text(&state.files).unwrap().into(); + let name: PathBuf = file + .name(&state.files) + .text(&state.files) + .unwrap() + .as_ref() + .into(); let body = file.body(&state.files).text(&state.files).unwrap().into(); let owned_file = FileOwner::new(name, body, None, true, context.language(), logs)?; diff --git a/crates/core/src/text_unparser.rs b/crates/core/src/text_unparser.rs index fa725c042..b9429cf1f 100644 --- a/crates/core/src/text_unparser.rs +++ b/crates/core/src/text_unparser.rs @@ -1,5 +1,4 @@ -use crate::binding::{linearize_binding, Binding, Constant}; - +use crate::binding::{linearize_binding, Binding}; use crate::pattern::resolved_pattern::CodeRange; use crate::pattern::state::FileRegistry; use crate::pattern::Effect; @@ -10,6 +9,7 @@ use marzano_language::target_language::TargetLanguage; use marzano_util::analysis_logs::AnalysisLogs; use std::collections::HashMap; use std::ops::Range; +use std::path::{Path, PathBuf}; /** * Applies the given effects to the given code, using the bindings to resolve metavariables in the snippets. @@ -22,8 +22,8 @@ pub(crate) fn apply_effects<'a>( code: &'a str, effects: Vector>, files: &FileRegistry<'a>, - the_filename: &str, - new_filename: &mut Constant, + the_filename: &Path, + new_filename: &mut PathBuf, language: &TargetLanguage, current_name: Option<&str>, logs: &mut AnalysisLogs, @@ -60,7 +60,7 @@ pub(crate) fn apply_effects<'a>( false, logs, )?; - *new_filename = Constant::String(snippet.to_string()); + *new_filename = PathBuf::from(snippet.to_string()); } } }