Use correct working directory for non-workspace proc-macro execution

This commit is contained in:
Mehul Arora 2025-02-12 14:43:25 -05:00
parent d10388096e
commit 3a31741627
15 changed files with 159 additions and 31 deletions

View file

@ -296,6 +296,9 @@ pub struct CrateData {
pub dependencies: Vec<Dependency>,
pub origin: CrateOrigin,
pub is_proc_macro: bool,
/// The working directory to run proc-macros in. This is the workspace root of the cargo workspace
/// for workspace members, the crate manifest dir otherwise.
pub proc_macro_cwd: Option<AbsPathBuf>,
}
#[derive(Default, Clone, PartialEq, Eq)]
@ -360,8 +363,9 @@ impl CrateGraph {
cfg_options: Arc<CfgOptions>,
potential_cfg_options: Option<Arc<CfgOptions>>,
mut env: Env,
is_proc_macro: bool,
origin: CrateOrigin,
is_proc_macro: bool,
proc_macro_cwd: Option<AbsPathBuf>,
) -> CrateId {
env.entries.shrink_to_fit();
let data = CrateData {
@ -375,6 +379,7 @@ impl CrateGraph {
dependencies: Vec::new(),
origin,
is_proc_macro,
proc_macro_cwd,
};
self.arena.alloc(data)
}
@ -698,8 +703,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
let crate2 = graph.add_crate_root(
FileId::from_raw(2u32),
@ -709,8 +715,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
let crate3 = graph.add_crate_root(
FileId::from_raw(3u32),
@ -720,8 +727,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
@ -745,8 +753,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
let crate2 = graph.add_crate_root(
FileId::from_raw(2u32),
@ -756,8 +765,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
@ -778,8 +788,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
let crate2 = graph.add_crate_root(
FileId::from_raw(2u32),
@ -789,8 +800,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
let crate3 = graph.add_crate_root(
FileId::from_raw(3u32),
@ -800,8 +812,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
@ -822,8 +835,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
let crate2 = graph.add_crate_root(
FileId::from_raw(2u32),
@ -833,8 +847,9 @@ mod tests {
Default::default(),
Default::default(),
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
assert!(graph
.add_dep(

View file

@ -10,7 +10,7 @@ use rustc_hash::FxHashMap;
use span::EditionedFileId;
use syntax::{ast, Parse, SourceFile, SyntaxError};
use triomphe::Arc;
use vfs::{AbsPathBuf, FileId};
use vfs::FileId;
pub use crate::{
change::FileChange,
@ -85,8 +85,6 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
/// Crate related data shared by the whole workspace.
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct CrateWorkspaceData {
/// The working directory to run proc-macros in. This is usually the workspace root of cargo workspaces.
pub proc_macro_cwd: Option<AbsPathBuf>,
// FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
pub data_layout: TargetLayoutLoadResult,
/// Toolchain version used to compile the crate.

View file

@ -238,6 +238,9 @@ impl CustomProcMacroExpander {
let krate_graph = db.crate_graph();
// Proc macros have access to the environment variables of the invoking crate.
let env = &krate_graph[calling_crate].env;
let current_dir =
krate_graph[calling_crate].proc_macro_cwd.as_deref().map(ToString::to_string);
match proc_macro.expander.expand(
tt,
attr_arg,
@ -245,10 +248,7 @@ impl CustomProcMacroExpander {
def_site,
call_site,
mixed_site,
db.crate_workspace_data()[&calling_crate]
.proc_macro_cwd
.as_ref()
.map(ToString::to_string),
current_dir,
) {
Ok(t) => ExpandResult::ok(t),
Err(err) => match err {

View file

@ -252,14 +252,14 @@ impl Analysis {
Arc::new(cfg_options),
None,
Env::default(),
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
change.change_file(file_id, Some(text));
let ws_data = crate_graph
.iter()
.zip(iter::repeat(Arc::new(CrateWorkspaceData {
proc_macro_cwd: None,
data_layout: Err("fixture has no layout".into()),
toolchain: None,
})))

View file

@ -68,6 +68,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
dependencies,
origin,
is_proc_macro,
proc_macro_cwd,
} = &crate_graph[crate_id];
format_to!(
buf,
@ -85,6 +86,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
format_to!(buf, " Env: {:?}\n", env);
format_to!(buf, " Origin: {:?}\n", origin);
format_to!(buf, " Is a proc macro crate: {}\n", is_proc_macro);
format_to!(buf, " Proc macro cwd: {:?}\n", proc_macro_cwd);
let deps = dependencies
.iter()
.map(|dep| format!("{}={}", dep.name, dep.crate_id.into_raw()))

View file

@ -456,7 +456,6 @@ fn load_crate_graph(
let ws_data = crate_graph
.iter()
.zip(iter::repeat(From::from(CrateWorkspaceData {
proc_macro_cwd: None,
data_layout: target_layout.clone(),
toolchain: toolchain.clone(),
})))

View file

@ -164,6 +164,7 @@ impl ProjectJson {
is_proc_macro: crate_data.is_proc_macro,
repository: crate_data.repository,
build,
proc_macro_cwd: crate_data.proc_macro_cwd.map(absolutize_on_base),
}
})
.collect(),
@ -240,6 +241,8 @@ pub struct Crate {
pub(crate) include: Vec<AbsPathBuf>,
pub(crate) exclude: Vec<AbsPathBuf>,
pub(crate) is_proc_macro: bool,
/// The working directory to run proc-macros in. This is usually the workspace root of cargo workspaces.
pub(crate) proc_macro_cwd: Option<AbsPathBuf>,
pub(crate) repository: Option<String>,
pub build: Option<Build>,
}
@ -362,6 +365,8 @@ struct CrateData {
repository: Option<String>,
#[serde(default)]
build: Option<BuildData>,
#[serde(default)]
proc_macro_cwd: Option<Utf8PathBuf>,
}
mod cfg_ {

View file

@ -958,6 +958,7 @@ fn project_json_to_crate_graph(
is_proc_macro,
repository,
is_workspace_member,
proc_macro_cwd,
..
},
file_id,
@ -1005,7 +1006,6 @@ fn project_json_to_crate_graph(
Arc::new(cfg_options),
None,
env,
*is_proc_macro,
if let Some(name) = display_name.clone() {
CrateOrigin::Local {
repo: repository.clone(),
@ -1014,6 +1014,8 @@ fn project_json_to_crate_graph(
} else {
CrateOrigin::Local { repo: None, name: None }
},
*is_proc_macro,
proc_macro_cwd.clone(),
);
debug!(
?crate_graph_crate_id,
@ -1283,11 +1285,12 @@ fn detached_file_to_crate_graph(
cfg_options.clone(),
None,
Env::default(),
false,
CrateOrigin::Local {
repo: None,
name: display_name.map(|n| n.canonical_name().to_owned()),
},
false,
None,
);
public_deps.add_to_crate_graph(&mut crate_graph, detached_file_crate);
@ -1448,8 +1451,13 @@ fn add_target_crate_root(
Arc::new(cfg_options),
potential_cfg_options.map(Arc::new),
env,
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
origin,
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
Some(if pkg.is_member {
cargo.workspace_root().to_path_buf()
} else {
pkg.manifest.parent().to_path_buf()
}),
);
if let TargetKind::Lib { is_proc_macro: true } = kind {
let proc_macro = match build_data {
@ -1587,8 +1595,9 @@ fn sysroot_to_crate_graph(
cfg_options.clone(),
None,
Env::default(),
false,
CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)),
false,
None,
);
Some((krate, crate_id))
})

View file

@ -61,6 +61,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
1: CrateData {
root_file_id: FileId(
@ -132,6 +137,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
2: CrateData {
root_file_id: FileId(
@ -203,6 +213,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
3: CrateData {
root_file_id: FileId(
@ -274,6 +289,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
4: CrateData {
root_file_id: FileId(
@ -341,5 +361,10 @@
name: "libc",
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
),
},
}

View file

@ -61,6 +61,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
1: CrateData {
root_file_id: FileId(
@ -132,6 +137,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
2: CrateData {
root_file_id: FileId(
@ -203,6 +213,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
3: CrateData {
root_file_id: FileId(
@ -274,6 +289,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
4: CrateData {
root_file_id: FileId(
@ -341,5 +361,10 @@
name: "libc",
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
),
},
}

View file

@ -60,6 +60,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
1: CrateData {
root_file_id: FileId(
@ -130,6 +135,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
2: CrateData {
root_file_id: FileId(
@ -200,6 +210,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
3: CrateData {
root_file_id: FileId(
@ -270,6 +285,11 @@
),
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$hello-world",
),
),
},
4: CrateData {
root_file_id: FileId(
@ -337,5 +357,10 @@
name: "libc",
},
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
),
},
}

View file

@ -38,6 +38,7 @@
Alloc,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
1: CrateData {
root_file_id: FileId(
@ -69,6 +70,7 @@
Core,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
2: CrateData {
root_file_id: FileId(
@ -100,6 +102,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
3: CrateData {
root_file_id: FileId(
@ -131,6 +134,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
4: CrateData {
root_file_id: FileId(
@ -179,6 +183,7 @@
ProcMacro,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
5: CrateData {
root_file_id: FileId(
@ -210,6 +215,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
6: CrateData {
root_file_id: FileId(
@ -306,6 +312,7 @@
Std,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
7: CrateData {
root_file_id: FileId(
@ -337,6 +344,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
8: CrateData {
root_file_id: FileId(
@ -368,6 +376,7 @@
Test,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
9: CrateData {
root_file_id: FileId(
@ -399,6 +408,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
10: CrateData {
root_file_id: FileId(
@ -477,6 +487,7 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
},
11: CrateData {
root_file_id: FileId(
@ -555,5 +566,6 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
},
}

View file

@ -38,6 +38,7 @@
Alloc,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
1: CrateData {
root_file_id: FileId(
@ -69,6 +70,7 @@
Core,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
2: CrateData {
root_file_id: FileId(
@ -100,6 +102,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
3: CrateData {
root_file_id: FileId(
@ -131,6 +134,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
4: CrateData {
root_file_id: FileId(
@ -179,6 +183,7 @@
ProcMacro,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
5: CrateData {
root_file_id: FileId(
@ -210,6 +215,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
6: CrateData {
root_file_id: FileId(
@ -306,6 +312,7 @@
Std,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
7: CrateData {
root_file_id: FileId(
@ -337,6 +344,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
8: CrateData {
root_file_id: FileId(
@ -368,6 +376,7 @@
Test,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
9: CrateData {
root_file_id: FileId(
@ -399,6 +408,7 @@
Other,
),
is_proc_macro: false,
proc_macro_cwd: None,
},
10: CrateData {
root_file_id: FileId(
@ -474,5 +484,6 @@
),
},
is_proc_macro: false,
proc_macro_cwd: None,
},
}

View file

@ -885,7 +885,6 @@ pub fn ws_to_crate_graph(
ws_data.extend(mapping.values().copied().zip(iter::repeat(Arc::new(CrateWorkspaceData {
toolchain: toolchain.clone(),
data_layout: target_layout.clone(),
proc_macro_cwd: Some(ws.workspace_root().to_owned()),
}))));
proc_macro_paths.push(crate_proc_macros);
}

View file

@ -211,8 +211,9 @@ impl ChangeFixture {
From::from(meta.cfg.clone()),
Some(From::from(meta.cfg)),
meta.env,
false,
origin,
false,
None,
);
let prev = crates.insert(crate_name.clone(), crate_id);
assert!(prev.is_none(), "multiple crates with same name: {crate_name}");
@ -249,8 +250,9 @@ impl ChangeFixture {
From::from(default_cfg.clone()),
Some(From::from(default_cfg)),
default_env,
false,
CrateOrigin::Local { repo: None, name: None },
false,
None,
);
} else {
for (from, to, prelude) in crate_deps {
@ -286,8 +288,9 @@ impl ChangeFixture {
String::from("__ra_is_test_fixture"),
String::from("__ra_is_test_fixture"),
)]),
false,
CrateOrigin::Lang(LangCrateOrigin::Core),
false,
None,
);
for krate in all_crates {
@ -333,8 +336,9 @@ impl ChangeFixture {
String::from("__ra_is_test_fixture"),
String::from("__ra_is_test_fixture"),
)]),
true,
CrateOrigin::Local { repo: None, name: None },
true,
None,
);
proc_macros.insert(proc_macros_crate, Ok(proc_macro));
@ -362,7 +366,6 @@ impl ChangeFixture {
crate_graph
.iter()
.zip(iter::repeat(From::from(CrateWorkspaceData {
proc_macro_cwd: None,
data_layout: target_data_layout,
toolchain,
})))