Skip to content

Commit c9b9d75

Browse files
authored
refactor: replace String with PathBuf for path handling (#146)
Convert string fields to `PathBuf` for improved type safety and optimize path handling throughout the codebase. This includes changing `Gemset.gem_home` and `Bundler.working_dir` from `String` to `PathBuf`, enhancing path operations in the debug adapter and HERB language server, updating all calling code to efficiently use `PathBuf::from()`, and removing unnecessary string conversions and clones.
1 parent 9fe7077 commit c9b9d75

File tree

5 files changed

+32
-24
lines changed

5 files changed

+32
-24
lines changed

src/bundler.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::command_executor::CommandExecutor;
2-
use std::path::Path;
2+
use std::path::PathBuf;
33

44
/// A simple wrapper around the `bundle` command.
55
pub struct Bundler {
6-
pub working_dir: String,
6+
pub working_dir: PathBuf,
77
command_executor: Box<dyn CommandExecutor>,
88
}
99

@@ -13,7 +13,7 @@ impl Bundler {
1313
/// # Arguments
1414
/// * `working_dir` - The working directory where `bundle` commands should be executed.
1515
/// * `command_executor` - An executor for `bundle` commands.
16-
pub fn new(working_dir: String, command_executor: Box<dyn CommandExecutor>) -> Self {
16+
pub fn new(working_dir: PathBuf, command_executor: Box<dyn CommandExecutor>) -> Self {
1717
Bundler {
1818
working_dir,
1919
command_executor,
@@ -43,7 +43,7 @@ impl Bundler {
4343
args: &[&str],
4444
envs: &[(&str, &str)],
4545
) -> Result<String, String> {
46-
let bundle_gemfile_path = Path::new(&self.working_dir).join("Gemfile");
46+
let bundle_gemfile_path = self.working_dir.join("Gemfile");
4747
let bundle_gemfile = bundle_gemfile_path
4848
.to_str()
4949
.ok_or_else(|| "Invalid path to Gemfile".to_string())?;

src/gemset.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use crate::command_executor::CommandExecutor;
22
use regex::Regex;
3+
use std::path::PathBuf;
34

45
/// A simple wrapper around the `gem` command.
56
pub struct Gemset {
6-
pub gem_home: String,
7+
pub gem_home: PathBuf,
78
command_executor: Box<dyn CommandExecutor>,
89
}
910

1011
impl Gemset {
11-
pub fn new(gem_home: String, command_executor: Box<dyn CommandExecutor>) -> Self {
12+
pub fn new(gem_home: PathBuf, command_executor: Box<dyn CommandExecutor>) -> Self {
1213
Self {
1314
gem_home,
1415
command_executor,
@@ -17,9 +18,7 @@ impl Gemset {
1718

1819
/// Returns the full path to a gem binary executable.
1920
pub fn gem_bin_path(&self, bin_name: &str) -> Result<String, String> {
20-
let path = std::path::Path::new(&self.gem_home)
21-
.join("bin")
22-
.join(bin_name);
21+
let path = self.gem_home.join("bin").join(bin_name);
2322

2423
path.to_str()
2524
.map(ToString::to_string)
@@ -29,7 +28,7 @@ impl Gemset {
2928
pub fn gem_path_env(&self) -> Vec<(String, String)> {
3029
vec![(
3130
"GEM_PATH".to_string(),
32-
format!("{}:$GEM_PATH", self.gem_home),
31+
format!("{}:$GEM_PATH", self.gem_home.display()),
3332
)]
3433
}
3534

@@ -97,7 +96,11 @@ impl Gemset {
9796
.chain(std::iter::once("--norc"))
9897
.chain(args.iter().copied())
9998
.collect();
100-
let command_envs = &[("GEM_HOME", self.gem_home.as_str())];
99+
let gem_home_str = self
100+
.gem_home
101+
.to_str()
102+
.ok_or("Failed to convert gem_home path to string")?;
103+
let command_envs = &[("GEM_HOME", gem_home_str)];
101104

102105
self.command_executor
103106
.execute("gem", &full_args, command_envs)
@@ -200,13 +203,13 @@ mod tests {
200203
const TEST_GEM_HOME: &str = "/test/gem_home";
201204

202205
fn create_gemset(mock_executor: MockGemCommandExecutor) -> Gemset {
203-
Gemset::new(TEST_GEM_HOME.to_string(), Box::new(mock_executor))
206+
Gemset::new(TEST_GEM_HOME.into(), Box::new(mock_executor))
204207
}
205208

206209
#[test]
207210
fn test_gem_bin_path() {
208211
let gemset = Gemset::new(
209-
TEST_GEM_HOME.to_string(),
212+
TEST_GEM_HOME.into(),
210213
Box::new(MockGemCommandExecutor::new()),
211214
);
212215
let path = gemset.gem_bin_path("ruby-lsp").unwrap();
@@ -216,7 +219,7 @@ mod tests {
216219
#[test]
217220
fn test_gem_path_env() {
218221
let gemset = Gemset::new(
219-
TEST_GEM_HOME.to_string(),
222+
TEST_GEM_HOME.into(),
220223
Box::new(MockGemCommandExecutor::new()),
221224
);
222225
let env = gemset.gem_path_env();

src/language_servers/herb.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl Herb {
4141
.unwrap()
4242
.join(&server_path)
4343
.to_string_lossy()
44-
.to_string(),
44+
.into_owned(),
4545
"--stdio".to_string(),
4646
],
4747
env: Default::default(),

src/language_servers/language_server.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use std::collections::HashMap;
33

44
use crate::{bundler::Bundler, command_executor::RealCommandExecutor, gemset::Gemset};
5+
use std::path::PathBuf;
56
use zed_extension_api::{self as zed};
67

78
#[derive(Clone, Debug)]
@@ -164,7 +165,10 @@ pub trait LanguageServer {
164165
return self.try_find_on_path_or_extension_gemset(language_server_id, worktree);
165166
}
166167

167-
let bundler = Bundler::new(worktree.root_path(), Box::new(RealCommandExecutor));
168+
let bundler = Bundler::new(
169+
PathBuf::from(worktree.root_path()),
170+
Box::new(RealCommandExecutor),
171+
);
168172
let shell_env = worktree.shell_env();
169173
let env_vars: Vec<(&str, &str)> = shell_env
170174
.iter()
@@ -218,7 +222,7 @@ pub trait LanguageServer {
218222
.to_string_lossy()
219223
.to_string();
220224

221-
let gemset = Gemset::new(gem_home.clone(), Box::new(RealCommandExecutor));
225+
let gemset = Gemset::new(PathBuf::from(&gem_home), Box::new(RealCommandExecutor));
222226

223227
zed::set_language_server_installation_status(
224228
language_server_id,

src/ruby.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod command_executor;
33
mod gemset;
44
mod language_servers;
55

6-
use std::{collections::HashMap, path::Path};
6+
use std::{collections::HashMap, path::PathBuf};
77

88
use bundler::Bundler;
99
use command_executor::RealCommandExecutor;
@@ -133,14 +133,17 @@ impl zed::Extension for RubyExtension {
133133
.map(|(key, value)| (key.as_str(), value.as_str()))
134134
.collect();
135135

136-
let mut rdbg_path = Path::new(&adapter_name)
136+
let mut rdbg_path = PathBuf::from(&adapter_name)
137137
.join("rdbg")
138138
.to_string_lossy()
139139
.into_owned();
140140
let mut use_bundler = false;
141141

142142
if worktree.which(&rdbg_path).is_none() {
143-
let bundler = Bundler::new(worktree.root_path(), Box::new(RealCommandExecutor));
143+
let bundler = Bundler::new(
144+
PathBuf::from(worktree.root_path()),
145+
Box::new(RealCommandExecutor),
146+
);
144147
match bundler.installed_gem_version("debug", &env_vars) {
145148
Ok(_version) => {
146149
rdbg_path = worktree
@@ -150,10 +153,8 @@ impl zed::Extension for RubyExtension {
150153
}
151154
Err(_e) => {
152155
let gem_home = std::env::current_dir()
153-
.map_err(|e| format!("Failed to get extension directory: {e}"))?
154-
.to_string_lossy()
155-
.to_string();
156-
let gemset = Gemset::new(gem_home.clone(), Box::new(RealCommandExecutor));
156+
.map_err(|e| format!("Failed to get extension directory: {e}"))?;
157+
let gemset = Gemset::new(gem_home, Box::new(RealCommandExecutor));
157158

158159
match gemset.install_gem("debug") {
159160
Ok(_) => rdbg_path = gemset.gem_bin_path("rdbg")?,

0 commit comments

Comments
 (0)