From ea81a363fa68b75615ad1d35795a310371300bb0 Mon Sep 17 00:00:00 2001 From: Firas al-Khalil Date: Tue, 8 Apr 2025 13:15:31 +0200 Subject: [PATCH 1/2] fix(build): generate file name with prefix and extension on build Then copy that file to its destination. PR: https://github.com/stackmystack/tsdl/pull/22 --- src/parser.rs | 55 +++++++++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 3abe729..730b3d4 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -157,14 +157,7 @@ impl Language { } async fn build(&self, dir: &Path, ext: &str) -> Result<()> { - let effective_name = dir - .file_name() - .map(|n| { - n.to_string_lossy() - .strip_prefix("tree-sitter-") - .map_or_else(|| n.to_string_lossy().to_string(), str::to_string) - }) - .unwrap(); + let effective_name = self.parser_name_and_ext(dir, ext); self.build_script .as_ref() .map_or_else( @@ -174,7 +167,7 @@ impl Language { if ext == WASM_EXTENSION { cmd.arg("--wasm"); } - cmd.args(["--output", &format!("{effective_name}.{ext}")]); + cmd.args(["--output", &effective_name]); cmd }, |script| Command::from_str(script), @@ -243,9 +236,11 @@ impl Language { async fn do_copy(&self, dir: &Path, ext: &str) -> Result<()> { let dll = self.find_dll_files(dir, ext).await?; - let name = Self::extract_parser_name(&dll, ext); - let prefix = &self.prefix; - let dst = self.out_dir.clone().join(format!("{prefix}{name}.{ext}")); + let name = self.parser_name_and_ext(dir, ext); + let dst = self.out_dir.clone().join(name); + println!(); + println!("cp {} {}", dll.display(), dst.display()); + println!(); fs::copy(&dll, &dst) .await .with_context(|| format!("cp {} {}", &dll.display(), dst.display())) @@ -287,6 +282,19 @@ impl Language { .and(Ok(())) } + fn parser_name_and_ext(&self, dir: &Path, ext: &str) -> String { + let effective_name = dir + .file_name() + .map(|n| { + n.to_string_lossy() + .strip_prefix("tree-sitter-") + .map_or_else(|| n.to_string_lossy().to_string(), str::to_string) + }) + .unwrap(); + let prefix = &self.prefix; + format!("{prefix}{effective_name}.{ext}") + } + async fn find_dll_files(&self, dir: &Path, ext: &str) -> Result { let mut files = fs::read_dir(&dir).await.unwrap(); let mut dlls = Vec::with_capacity(1); @@ -309,29 +317,6 @@ impl Language { } } - fn extract_parser_name(dll_path: &Path, ext: &str) -> String { - let mut name = dll_path - .file_name() - .and_then(|n| n.to_str()) - .map(String::from) - .unwrap(); - if name == format!("parser.{ext}") { - name = dll_path - .parent() - .and_then(|p| p.file_name()) - .and_then(|n| n.to_str()) - .map(String::from) - .unwrap(); - } - if name.starts_with("libtree-sitter-") { - name = name.trim_start_matches("libtree-sitter-").to_string(); - } - if name.ends_with(&format!(".{ext}")) { - name = name.trim_end_matches(&format!(".{ext}")).to_string(); - } - name - } - fn create_copy_error(&self, dir: &Path, message: String) -> error::Step { error::Step { name: self.name.clone(), From 6552949a2351d022434d543f2df3ad7ff9adede9 Mon Sep 17 00:00:00 2001 From: Firas al-Khalil Date: Tue, 8 Apr 2025 13:45:20 +0200 Subject: [PATCH 2/2] fix(build): copy exact files, or best match when possible Since we're generating the exact file as `prefix + name + ext` in the build dir, we rely on that name to copy to output dir. If that name is not present, because the user defined a user script like make mostly (like in typescript), then take the first match and work with that. PR: https://github.com/stackmystack/tsdl/pull/22 --- src/parser.rs | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 730b3d4..bd39b67 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -295,25 +295,42 @@ impl Language { format!("{prefix}{effective_name}.{ext}") } + // Since we're generating the exact file as `prefix + name + ext` in the + // build dir, we rely on that name to copy to output dir. + + // If that name is not present, because the user defined a user script like + // make mostly (like in typescript), then take the first match and work + // with that. async fn find_dll_files(&self, dir: &Path, ext: &str) -> Result { + let effective_name = self.parser_name_and_ext(dir, ext); let mut files = fs::read_dir(&dir).await.unwrap(); - let mut dlls = Vec::with_capacity(1); + let mut exact_match = None; + let mut all_dlls = Vec::with_capacity(1); while let Ok(Some(entry)) = files.next_entry().await { let file_name = entry.file_name(); let name = file_name.as_os_str().to_str().unwrap(); - if entry.file_type().await.unwrap().is_file() && name.ends_with(&format!(".{ext}")) { - dlls.push(dir.join(name)); + if entry.file_type().await.unwrap().is_file() { + if name == effective_name { + exact_match = Some(dir.join(name)); + break; + } else if name.ends_with(&format!(".{ext}")) { + all_dlls.push(dir.join(name)); + } } } // Error handling for no DLLs or too many DLLs - match dlls.len() { - 0 => Err(self - .create_copy_error(dir, format!("Couldn't find any {ext} file")) - .into()), - n if n > 1 => Err(self - .create_copy_error(dir, format!("Found many {ext} files: {dlls:?}")) - .into()), - _ => Ok(dlls[0].clone()), + if let Some(exact) = exact_match { + Ok(exact.clone()) + } else { + match all_dlls.len() { + 0 => Err(self + .create_copy_error(dir, format!("Couldn't find any {ext} file")) + .into()), + 1 => Ok(all_dlls[0].clone()), + _ => Err(self + .create_copy_error(dir, format!("Found many {ext} files: {all_dlls:?}.")) + .into()), + } } }