Skip to content

Commit 610ecc9

Browse files
bors[bot]matklad
andauthored
Merge #9620
9620: internal: don't depend on cwd r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 0fb1c27 + 8d8c26e commit 610ecc9

File tree

27 files changed

+178
-105
lines changed

27 files changed

+178
-105
lines changed

Cargo.lock

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/flycheck/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ jod-thread = "0.1.1"
1818

1919
toolchain = { path = "../toolchain", version = "0.0.0" }
2020
stdx = { path = "../stdx", version = "0.0.0" }
21+
paths = { path = "../paths", version = "0.0.0" }

crates/flycheck/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
use std::{
66
fmt,
77
io::{self, BufRead, BufReader},
8-
path::PathBuf,
98
process::{self, Command, Stdio},
109
time::Duration,
1110
};
1211

1312
use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
13+
use paths::AbsPathBuf;
1414
use serde::Deserialize;
1515
use stdx::JodChild;
1616

@@ -63,7 +63,7 @@ impl FlycheckHandle {
6363
id: usize,
6464
sender: Box<dyn Fn(Message) + Send>,
6565
config: FlycheckConfig,
66-
workspace_root: PathBuf,
66+
workspace_root: AbsPathBuf,
6767
) -> FlycheckHandle {
6868
let actor = FlycheckActor::new(id, sender, config, workspace_root);
6969
let (sender, receiver) = unbounded::<Restart>();
@@ -82,7 +82,7 @@ impl FlycheckHandle {
8282

8383
pub enum Message {
8484
/// Request adding a diagnostic with fixes included to a file
85-
AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic },
85+
AddDiagnostic { workspace_root: AbsPathBuf, diagnostic: Diagnostic },
8686

8787
/// Request check progress notification to client
8888
Progress {
@@ -121,7 +121,7 @@ struct FlycheckActor {
121121
id: usize,
122122
sender: Box<dyn Fn(Message) + Send>,
123123
config: FlycheckConfig,
124-
workspace_root: PathBuf,
124+
workspace_root: AbsPathBuf,
125125
/// WatchThread exists to wrap around the communication needed to be able to
126126
/// run `cargo check` without blocking. Currently the Rust standard library
127127
/// doesn't provide a way to read sub-process output without blocking, so we
@@ -140,7 +140,7 @@ impl FlycheckActor {
140140
id: usize,
141141
sender: Box<dyn Fn(Message) + Send>,
142142
config: FlycheckConfig,
143-
workspace_root: PathBuf,
143+
workspace_root: AbsPathBuf,
144144
) -> FlycheckActor {
145145
FlycheckActor { id, sender, config, workspace_root, cargo_handle: None }
146146
}
@@ -220,7 +220,7 @@ impl FlycheckActor {
220220
cmd.arg(command);
221221
cmd.current_dir(&self.workspace_root);
222222
cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
223-
.arg(self.workspace_root.join("Cargo.toml"));
223+
.arg(self.workspace_root.join("Cargo.toml").as_os_str());
224224

225225
if let Some(target) = target_triple {
226226
cmd.args(&["--target", target.as_str()]);

crates/paths/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ edition = "2018"
77

88
[lib]
99
doctest = false
10+
11+
[dependencies]
12+
serde = "1"

crates/paths/src/lib.rs

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::{
44
borrow::Borrow,
55
convert::{TryFrom, TryInto},
6+
ffi::OsStr,
67
ops,
78
path::{Component, Path, PathBuf},
89
};
@@ -65,6 +66,27 @@ impl PartialEq<AbsPath> for AbsPathBuf {
6566
}
6667
}
6768

69+
impl serde::Serialize for AbsPathBuf {
70+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
71+
where
72+
S: serde::Serializer,
73+
{
74+
self.0.serialize(serializer)
75+
}
76+
}
77+
78+
impl<'de> serde::Deserialize<'de> for AbsPathBuf {
79+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
80+
where
81+
D: serde::Deserializer<'de>,
82+
{
83+
let path = PathBuf::deserialize(deserializer)?;
84+
AbsPathBuf::try_from(path).map_err(|path| {
85+
serde::de::Error::custom(format!("expected absolute path, got {}", path.display()))
86+
})
87+
}
88+
}
89+
6890
impl AbsPathBuf {
6991
/// Wrap the given absolute path in `AbsPathBuf`
7092
///
@@ -97,13 +119,6 @@ impl AbsPathBuf {
97119
#[repr(transparent)]
98120
pub struct AbsPath(Path);
99121

100-
impl ops::Deref for AbsPath {
101-
type Target = Path;
102-
fn deref(&self) -> &Path {
103-
&self.0
104-
}
105-
}
106-
107122
impl AsRef<Path> for AbsPath {
108123
fn as_ref(&self) -> &Path {
109124
&self.0
@@ -168,6 +183,43 @@ impl AbsPath {
168183
pub fn strip_prefix(&self, base: &AbsPath) -> Option<&RelPath> {
169184
self.0.strip_prefix(base).ok().map(RelPath::new_unchecked)
170185
}
186+
pub fn starts_with(&self, base: &AbsPath) -> bool {
187+
self.0.starts_with(&base.0)
188+
}
189+
pub fn ends_with(&self, suffix: &RelPath) -> bool {
190+
self.0.starts_with(&suffix.0)
191+
}
192+
193+
// region:delegate-methods
194+
195+
// Note that we deliberately don't implement `Deref<Target = Path>` here.
196+
//
197+
// The problem with `Path` is that it directly exposes convenience IO-ing
198+
// methods. For example, `Path::exists` delegates to `fs::metadata`.
199+
//
200+
// For `AbsPath`, we want to make sure that this is a POD type, and that all
201+
// IO goes via `fs`. That way, it becomes easier to mock IO when we need it.
202+
203+
pub fn file_name(&self) -> Option<&OsStr> {
204+
self.0.file_name()
205+
}
206+
pub fn extension(&self) -> Option<&OsStr> {
207+
self.0.extension()
208+
}
209+
pub fn file_stem(&self) -> Option<&OsStr> {
210+
self.0.file_stem()
211+
}
212+
pub fn as_os_str(&self) -> &OsStr {
213+
self.0.as_os_str()
214+
}
215+
pub fn display(&self) -> std::path::Display<'_> {
216+
self.0.display()
217+
}
218+
#[deprecated(note = "use std::fs::metadata().is_ok() instead")]
219+
pub fn exists(&self) -> bool {
220+
self.0.exists()
221+
}
222+
// endregion:delegate-methods
171223
}
172224

173225
/// Wrapper around a relative [`PathBuf`].
@@ -224,13 +276,6 @@ impl RelPathBuf {
224276
#[repr(transparent)]
225277
pub struct RelPath(Path);
226278

227-
impl ops::Deref for RelPath {
228-
type Target = Path;
229-
fn deref(&self) -> &Path {
230-
&self.0
231-
}
232-
}
233-
234279
impl AsRef<Path> for RelPath {
235280
fn as_ref(&self) -> &Path {
236281
&self.0

crates/proc_macro_api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ memmap2 = "0.3.0"
1818
object = { version = "0.25.3", default-features = false, features = ["std", "read_core", "elf", "macho", "pe"] }
1919
snap = "1.0"
2020

21+
paths = { path = "../paths", version = "0.0.0" }
2122
tt = { path = "../tt", version = "0.0.0" }
2223
base_db = { path = "../base_db", version = "0.0.0" }
2324
stdx = { path = "../stdx", version = "0.0.0" }

crates/proc_macro_api/src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ mod rpc;
1111
mod version;
1212

1313
use base_db::{Env, ProcMacro};
14+
use paths::{AbsPath, AbsPathBuf};
1415
use std::{
1516
ffi::OsStr,
1617
io,
17-
path::{Path, PathBuf},
1818
sync::{Arc, Mutex},
1919
};
2020

@@ -28,7 +28,7 @@ pub use version::{read_dylib_info, RustCInfo};
2828
#[derive(Debug, Clone)]
2929
struct ProcMacroProcessExpander {
3030
process: Arc<Mutex<ProcMacroProcessSrv>>,
31-
dylib_path: PathBuf,
31+
dylib_path: AbsPathBuf,
3232
name: SmolStr,
3333
}
3434

@@ -79,25 +79,25 @@ pub struct ProcMacroClient {
7979
impl ProcMacroClient {
8080
/// Spawns an external process as the proc macro server and returns a client connected to it.
8181
pub fn extern_process(
82-
process_path: PathBuf,
82+
process_path: AbsPathBuf,
8383
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
8484
) -> io::Result<ProcMacroClient> {
8585
let process = ProcMacroProcessSrv::run(process_path, args)?;
8686
Ok(ProcMacroClient { process: Arc::new(Mutex::new(process)) })
8787
}
8888

89-
pub fn by_dylib_path(&self, dylib_path: &Path) -> Vec<ProcMacro> {
89+
pub fn by_dylib_path(&self, dylib_path: &AbsPath) -> Vec<ProcMacro> {
9090
let _p = profile::span("ProcMacroClient::by_dylib_path");
9191
match version::read_dylib_info(dylib_path) {
9292
Ok(info) => {
9393
if info.version.0 < 1 || info.version.1 < 47 {
94-
eprintln!("proc-macro {} built by {:#?} is not supported by Rust Analyzer, please update your rust version.", dylib_path.to_string_lossy(), info);
94+
eprintln!("proc-macro {} built by {:#?} is not supported by Rust Analyzer, please update your rust version.", dylib_path.display(), info);
9595
}
9696
}
9797
Err(err) => {
9898
eprintln!(
9999
"proc-macro {} failed to find the given version. Reason: {}",
100-
dylib_path.to_string_lossy(),
100+
dylib_path.display(),
101101
err
102102
);
103103
}
@@ -128,7 +128,7 @@ impl ProcMacroClient {
128128
let expander = Arc::new(ProcMacroProcessExpander {
129129
process: self.process.clone(),
130130
name: name.clone(),
131-
dylib_path: dylib_path.into(),
131+
dylib_path: dylib_path.to_path_buf(),
132132
});
133133

134134
ProcMacro { name, kind, expander }

crates/proc_macro_api/src/process.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use std::{
44
convert::{TryFrom, TryInto},
55
ffi::{OsStr, OsString},
66
io::{self, BufRead, BufReader, Write},
7-
path::{Path, PathBuf},
87
process::{Child, ChildStdin, ChildStdout, Command, Stdio},
98
};
109

10+
use paths::{AbsPath, AbsPathBuf};
1111
use stdx::JodChild;
1212

1313
use crate::{
@@ -24,7 +24,7 @@ pub(crate) struct ProcMacroProcessSrv {
2424

2525
impl ProcMacroProcessSrv {
2626
pub(crate) fn run(
27-
process_path: PathBuf,
27+
process_path: AbsPathBuf,
2828
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
2929
) -> io::Result<ProcMacroProcessSrv> {
3030
let mut process = Process::run(process_path, args)?;
@@ -37,7 +37,7 @@ impl ProcMacroProcessSrv {
3737

3838
pub(crate) fn find_proc_macros(
3939
&mut self,
40-
dylib_path: &Path,
40+
dylib_path: &AbsPath,
4141
) -> Result<Vec<(String, ProcMacroKind)>, tt::ExpansionError> {
4242
let task = ListMacrosTask { lib: dylib_path.to_path_buf() };
4343

@@ -84,7 +84,7 @@ struct Process {
8484

8585
impl Process {
8686
fn run(
87-
path: PathBuf,
87+
path: AbsPathBuf,
8888
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
8989
) -> io::Result<Process> {
9090
let args: Vec<OsString> = args.into_iter().map(|s| s.as_ref().into()).collect();
@@ -101,8 +101,11 @@ impl Process {
101101
}
102102
}
103103

104-
fn mk_child(path: &Path, args: impl IntoIterator<Item = impl AsRef<OsStr>>) -> io::Result<Child> {
105-
Command::new(&path)
104+
fn mk_child(
105+
path: &AbsPath,
106+
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
107+
) -> io::Result<Child> {
108+
Command::new(path.as_os_str())
106109
.args(args)
107110
.stdin(Stdio::piped())
108111
.stdout(Stdio::piped())

crates/proc_macro_api/src/rpc.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
//! to be much easier, we deliberately duplicate `tt` structs with `#[serde(with = "XXDef")]`
77
//! for separation of code responsibility.
88
9-
use std::path::PathBuf;
10-
9+
use paths::AbsPathBuf;
1110
use serde::{Deserialize, Serialize};
1211
use tt::{
1312
Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, SmolStr, Spacing, Subtree, TokenId,
@@ -16,7 +15,7 @@ use tt::{
1615

1716
#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
1817
pub struct ListMacrosTask {
19-
pub lib: PathBuf,
18+
pub lib: AbsPathBuf,
2019
}
2120

2221
#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
@@ -50,7 +49,7 @@ pub struct ExpansionTask {
5049
#[serde(with = "opt_subtree_def")]
5150
pub attributes: Option<Subtree>,
5251

53-
pub lib: PathBuf,
52+
pub lib: AbsPathBuf,
5453

5554
/// Environment variables to set during macro expansion.
5655
pub env: Vec<(String, String)>,
@@ -272,7 +271,7 @@ mod tests {
272271
macro_body: tt.clone(),
273272
macro_name: Default::default(),
274273
attributes: None,
275-
lib: Default::default(),
274+
lib: AbsPathBuf::assert(std::env::current_dir().unwrap()),
276275
env: Default::default(),
277276
};
278277

0 commit comments

Comments
 (0)