diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index 4d906c2aeb3b..e4a611346205 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -92,6 +92,8 @@ pub struct CargoConfig { pub sysroot_src: Option, /// rustc private crate source pub rustc_source: Option, + /// Extra includes to add to the VFS. + pub extra_includes: Vec, pub cfg_overrides: CfgOverrides, /// Invoke `cargo check` through the RUSTC_WRAPPER. pub wrap_rustc_in_build_scripts: bool, diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs index 681bce3a5a64..f11138311259 100644 --- a/crates/project-model/src/tests.rs +++ b/crates/project-model/src/tests.rs @@ -49,6 +49,7 @@ fn load_workspace_from_metadata(file: &str) -> ProjectWorkspace { rustc_cfg: Vec::new(), toolchain: None, target_layout: Err("target_data_layout not loaded".into()), + extra_includes: Vec::new(), } } @@ -63,6 +64,7 @@ fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) { toolchain: None, target_layout: Err(Arc::from("test has no data layout")), cfg_overrides: Default::default(), + extra_includes: Vec::new(), }; to_crate_graph(project_workspace, &mut Default::default()) } @@ -284,6 +286,7 @@ fn smoke_test_real_sysroot_cargo() { cfg_overrides: Default::default(), toolchain: None, target_layout: Err("target_data_layout not loaded".into()), + extra_includes: Vec::new(), }; project_workspace.to_crate_graph( &mut { diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index a345c6bcce45..465a1ad0ec50 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -63,6 +63,8 @@ pub struct ProjectWorkspace { pub target_layout: TargetLayoutLoadResult, /// A set of cfg overrides for this workspace. pub cfg_overrides: CfgOverrides, + /// Additional includes to add for the VFS. + pub extra_includes: Vec, } #[derive(Clone)] @@ -104,7 +106,15 @@ pub enum ProjectWorkspaceKind { impl fmt::Debug for ProjectWorkspace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Make sure this isn't too verbose. - let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides } = self; + let Self { + kind, + sysroot, + rustc_cfg, + toolchain, + target_layout, + cfg_overrides, + extra_includes, + } = self; match kind { ProjectWorkspaceKind::Cargo { cargo, error: _, build_scripts, rustc, set_test } => f .debug_struct("Cargo") @@ -117,6 +127,7 @@ impl fmt::Debug for ProjectWorkspace { ) .field("n_rustc_cfg", &rustc_cfg.len()) .field("n_cfg_overrides", &cfg_overrides.len()) + .field("n_extra_includes", &extra_includes.len()) .field("toolchain", &toolchain) .field("data_layout", &target_layout) .field("set_test", set_test) @@ -130,7 +141,8 @@ impl fmt::Debug for ProjectWorkspace { .field("n_rustc_cfg", &rustc_cfg.len()) .field("toolchain", &toolchain) .field("data_layout", &target_layout) - .field("n_cfg_overrides", &cfg_overrides.len()); + .field("n_cfg_overrides", &cfg_overrides.len()) + .field("n_extra_includes", &extra_includes.len()); debug_struct.finish() } @@ -144,6 +156,7 @@ impl fmt::Debug for ProjectWorkspace { .field("toolchain", &toolchain) .field("data_layout", &target_layout) .field("n_cfg_overrides", &cfg_overrides.len()) + .field("n_extra_includes", &extra_includes.len()) .field("set_test", set_test) .finish(), } @@ -320,6 +333,7 @@ impl ProjectWorkspace { cfg_overrides, toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), + extra_includes: config.extra_includes.clone(), }) } @@ -340,6 +354,7 @@ impl ProjectWorkspace { toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: config.cfg_overrides.clone(), + extra_includes: config.extra_includes.clone(), } } @@ -399,6 +414,7 @@ impl ProjectWorkspace { toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: config.cfg_overrides.clone(), + extra_includes: config.extra_includes.clone(), }) } @@ -565,7 +581,13 @@ impl ProjectWorkspace { PackageRoot { is_local: krate.is_workspace_member, - include: krate.include.iter().cloned().chain(build_file).collect(), + include: krate + .include + .iter() + .cloned() + .chain(build_file) + .chain(self.extra_includes.iter().cloned()) + .collect(), exclude: krate.exclude.clone(), } }) @@ -603,6 +625,8 @@ impl ProjectWorkspace { let mut exclude = vec![pkg_root.join(".git")]; if is_local { + include.extend(self.extra_includes.iter().cloned()); + exclude.push(pkg_root.join("target")); } else { exclude.push(pkg_root.join("tests")); @@ -661,6 +685,8 @@ impl ProjectWorkspace { let mut exclude = vec![pkg_root.join(".git")]; if is_local { + include.extend(self.extra_includes.iter().cloned()); + exclude.push(pkg_root.join("target")); } else { exclude.push(pkg_root.join("tests")); diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs index 6b0ce4db7c93..199f61e70f02 100644 --- a/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -93,6 +93,7 @@ impl Tester { toolchain: None, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: Default::default(), + extra_includes: vec![], }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: false, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 30f0031905f1..28afd83e5c95 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -728,6 +728,10 @@ config_data! { /// available on a nightly build. rustfmt_rangeFormatting_enable: bool = false, + /// Additional paths to include in the VFS. Generally for code that is + /// generated or otherwise managed by a build system outside of Cargo, + /// though Cargo might be the eventual consumer. + vfs_extraIncludes: Vec = vec![], /// Workspace symbol search kind. workspace_symbol_search_kind: WorkspaceSymbolSearchKindDef = WorkspaceSymbolSearchKindDef::OnlyTypes, @@ -1926,6 +1930,13 @@ impl Config { }); let sysroot_src = self.cargo_sysrootSrc(source_root).as_ref().map(|sysroot| self.root_path.join(sysroot)); + let extra_includes = self + .vfs_extraIncludes(source_root) + .iter() + .map(String::as_str) + .map(AbsPathBuf::try_from) + .filter_map(Result::ok) + .collect(); CargoConfig { all_targets: *self.cargo_allTargets(source_root), @@ -1940,6 +1951,7 @@ impl Config { sysroot, sysroot_src, rustc_source, + extra_includes, cfg_overrides: project_model::CfgOverrides { global: CfgDiff::new( self.cargo_cfgs(source_root) diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 5b86766aa8ea..b3d3614e22b7 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -1051,6 +1051,13 @@ Show documentation. -- Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`. -- +[[rust-analyzer.vfs.extraIncludes]]rust-analyzer.vfs.extraIncludes (default: `[]`):: ++ +-- +Additional paths to include in the VFS. Generally for code that is +generated or otherwise managed by a build system outside of Cargo, +though Cargo might be the eventual consumer. +-- [[rust-analyzer.workspace.discoverConfig]]rust-analyzer.workspace.discoverConfig (default: `null`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 80246bf3feac..87afc5c281bb 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -2718,6 +2718,19 @@ } } }, + { + "title": "vfs", + "properties": { + "rust-analyzer.vfs.extraIncludes": { + "markdownDescription": "Additional paths to include in the VFS. Generally for code that is\ngenerated or otherwise managed by a build system outside of Cargo,\nthough Cargo might be the eventual consumer.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, { "title": "workspace", "properties": {