From 3a317416271c6b4ea765631196f198f1664ec44a Mon Sep 17 00:00:00 2001 From: Mehul Arora Date: Wed, 12 Feb 2025 14:43:25 -0500 Subject: [PATCH] Use correct working directory for non-workspace proc-macro execution --- crates/base-db/src/input.rs | 37 +++++++++++++------ crates/base-db/src/lib.rs | 4 +- crates/hir-expand/src/proc_macro.rs | 8 ++-- crates/ide/src/lib.rs | 4 +- crates/ide/src/status.rs | 2 + crates/load-cargo/src/lib.rs | 1 - crates/project-model/src/project_json.rs | 5 +++ crates/project-model/src/workspace.rs | 17 +++++++-- .../cargo_hello_world_project_model.txt | 25 +++++++++++++ ...project_model_with_selective_overrides.txt | 25 +++++++++++++ ..._project_model_with_wildcard_overrides.txt | 25 +++++++++++++ .../output/rust_project_cfg_groups.txt | 12 ++++++ ...rust_project_hello_world_project_model.txt | 11 ++++++ crates/rust-analyzer/src/reload.rs | 1 - crates/test-fixture/src/lib.rs | 13 ++++--- 15 files changed, 159 insertions(+), 31 deletions(-) diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index c2cea07190..bd08387b58 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -296,6 +296,9 @@ pub struct CrateData { pub dependencies: Vec, 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, } #[derive(Default, Clone, PartialEq, Eq)] @@ -360,8 +363,9 @@ impl CrateGraph { cfg_options: Arc, potential_cfg_options: Option>, mut env: Env, - is_proc_macro: bool, origin: CrateOrigin, + is_proc_macro: bool, + proc_macro_cwd: Option, ) -> 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( diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index c7e4168f6b..eed8c88683 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -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, // FIXME: Consider removing this, making HirDatabase::target_data_layout an input query pub data_layout: TargetLayoutLoadResult, /// Toolchain version used to compile the crate. diff --git a/crates/hir-expand/src/proc_macro.rs b/crates/hir-expand/src/proc_macro.rs index 07808fea85..3dc3dcd760 100644 --- a/crates/hir-expand/src/proc_macro.rs +++ b/crates/hir-expand/src/proc_macro.rs @@ -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 { diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index e942f5a6aa..27a1a510b4 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -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, }))) diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs index b0022cfac7..f8ecaa8fdf 100644 --- a/crates/ide/src/status.rs +++ b/crates/ide/src/status.rs @@ -68,6 +68,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option) -> 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) -> 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())) diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index 67ee9d1119..76f1a7f48b 100644 --- a/crates/load-cargo/src/lib.rs +++ b/crates/load-cargo/src/lib.rs @@ -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(), }))) diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs index feee40a1fc..2f9612e3a4 100644 --- a/crates/project-model/src/project_json.rs +++ b/crates/project-model/src/project_json.rs @@ -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, pub(crate) exclude: Vec, 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, pub(crate) repository: Option, pub build: Option, } @@ -362,6 +365,8 @@ struct CrateData { repository: Option, #[serde(default)] build: Option, + #[serde(default)] + proc_macro_cwd: Option, } mod cfg_ { diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index f5d46daa80..16b5bb11af 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -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)) }) diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt index 880e90c52a..fae0b6fcca 100644 --- a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt +++ b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt @@ -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", + ), + ), }, } \ No newline at end of file diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt index 880e90c52a..fae0b6fcca 100644 --- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt +++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt @@ -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", + ), + ), }, } \ No newline at end of file diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt index 7746acd225..566174882d 100644 --- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt +++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt @@ -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", + ), + ), }, } \ No newline at end of file diff --git a/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/crates/project-model/test_data/output/rust_project_cfg_groups.txt index 587d3c1782..9b4be19c41 100644 --- a/crates/project-model/test_data/output/rust_project_cfg_groups.txt +++ b/crates/project-model/test_data/output/rust_project_cfg_groups.txt @@ -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, }, } \ No newline at end of file diff --git a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt index 00805c79bc..4c8e66e8e9 100644 --- a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt +++ b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt @@ -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, }, } \ No newline at end of file diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index ba72ea35df..56dcad0eb1 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -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); } diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index 613f27c795..37dfb87721 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -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, })))