Skip to content

Commit 7bada8a

Browse files
bors[bot]matklad
andauthored
Merge #5473
5473: Changes to rust-project.json r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 83f3645 + b68ef12 commit 7bada8a

File tree

8 files changed

+117
-111
lines changed

8 files changed

+117
-111
lines changed

crates/ra_db/src/fixture.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ impl From<Fixture> for FileMeta {
222222
.edition
223223
.as_ref()
224224
.map_or(Edition::Edition2018, |v| Edition::from_str(&v).unwrap()),
225-
env: Env::from(f.env.iter()),
225+
env: f.env.into_iter().collect(),
226226
}
227227
}
228228
}

crates/ra_db/src/input.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how
77
//! actual IO is done and lowered to input.
88
9-
use std::{fmt, ops, str::FromStr, sync::Arc};
9+
use std::{fmt, iter::FromIterator, ops, str::FromStr, sync::Arc};
1010

1111
use ra_cfg::CfgOptions;
1212
use ra_syntax::SmolStr;
@@ -298,18 +298,9 @@ impl fmt::Display for Edition {
298298
}
299299
}
300300

301-
impl<'a, T> From<T> for Env
302-
where
303-
T: Iterator<Item = (&'a String, &'a String)>,
304-
{
305-
fn from(iter: T) -> Self {
306-
let mut result = Self::default();
307-
308-
for (k, v) in iter {
309-
result.entries.insert(k.to_owned(), v.to_owned());
310-
}
311-
312-
result
301+
impl FromIterator<(String, String)> for Env {
302+
fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self {
303+
Env { entries: FromIterator::from_iter(iter) }
313304
}
314305
}
315306

crates/ra_ide/src/mock_analysis.rs

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

44
use ra_cfg::CfgOptions;
5-
use ra_db::{CrateName, Env, FileSet, SourceRoot, VfsPath};
5+
use ra_db::{CrateName, FileSet, SourceRoot, VfsPath};
66
use test_utils::{
77
extract_annotations, extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER,
88
};
@@ -110,7 +110,7 @@ impl MockAnalysis {
110110
data.edition.and_then(|it| it.parse().ok()).unwrap_or(Edition::Edition2018);
111111

112112
let file_id = FileId(i as u32 + 1);
113-
let env = Env::from(data.env.iter());
113+
let env = data.env.into_iter().collect();
114114
if path == "/lib.rs" || path == "/main.rs" {
115115
root_crate = Some(crate_graph.add_crate_root(
116116
file_id,

crates/ra_project_model/src/lib.rs

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ mod sysroot;
77
use std::{
88
fs::{self, read_dir, ReadDir},
99
io,
10-
path::Path,
1110
process::{Command, Output},
1211
};
1312

@@ -35,30 +34,12 @@ pub enum ProjectWorkspace {
3534
/// `PackageRoot` describes a package root folder.
3635
/// Which may be an external dependency, or a member of
3736
/// the current workspace.
38-
#[derive(Debug, Clone)]
37+
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
3938
pub struct PackageRoot {
40-
/// Path to the root folder
41-
path: AbsPathBuf,
4239
/// Is a member of the current workspace
43-
is_member: bool,
44-
out_dir: Option<AbsPathBuf>,
45-
}
46-
impl PackageRoot {
47-
pub fn new_member(path: AbsPathBuf) -> PackageRoot {
48-
Self { path, is_member: true, out_dir: None }
49-
}
50-
pub fn new_non_member(path: AbsPathBuf) -> PackageRoot {
51-
Self { path, is_member: false, out_dir: None }
52-
}
53-
pub fn path(&self) -> &AbsPath {
54-
&self.path
55-
}
56-
pub fn out_dir(&self) -> Option<&AbsPath> {
57-
self.out_dir.as_deref()
58-
}
59-
pub fn is_member(&self) -> bool {
60-
self.is_member
61-
}
40+
pub is_member: bool,
41+
pub include: Vec<AbsPathBuf>,
42+
pub exclude: Vec<AbsPathBuf>,
6243
}
6344

6445
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
@@ -195,18 +176,40 @@ impl ProjectWorkspace {
195176
/// the root is a member of the current workspace
196177
pub fn to_roots(&self) -> Vec<PackageRoot> {
197178
match self {
198-
ProjectWorkspace::Json { project } => {
199-
project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect()
200-
}
179+
ProjectWorkspace::Json { project } => project
180+
.crates
181+
.iter()
182+
.map(|krate| PackageRoot {
183+
is_member: krate.is_workspace_member,
184+
include: krate.include.clone(),
185+
exclude: krate.exclude.clone(),
186+
})
187+
.collect::<FxHashSet<_>>()
188+
.into_iter()
189+
.collect::<Vec<_>>(),
201190
ProjectWorkspace::Cargo { cargo, sysroot } => cargo
202191
.packages()
203-
.map(|pkg| PackageRoot {
204-
path: cargo[pkg].root().to_path_buf(),
205-
is_member: cargo[pkg].is_member,
206-
out_dir: cargo[pkg].out_dir.clone(),
192+
.map(|pkg| {
193+
let is_member = cargo[pkg].is_member;
194+
let pkg_root = cargo[pkg].root().to_path_buf();
195+
196+
let mut include = vec![pkg_root.clone()];
197+
include.extend(cargo[pkg].out_dir.clone());
198+
199+
let mut exclude = vec![pkg_root.join(".git")];
200+
if is_member {
201+
exclude.push(pkg_root.join("target"));
202+
} else {
203+
exclude.push(pkg_root.join("tests"));
204+
exclude.push(pkg_root.join("examples"));
205+
exclude.push(pkg_root.join("benches"));
206+
}
207+
PackageRoot { is_member, include, exclude }
207208
})
208-
.chain(sysroot.crates().map(|krate| {
209-
PackageRoot::new_non_member(sysroot[krate].root_dir().to_path_buf())
209+
.chain(sysroot.crates().map(|krate| PackageRoot {
210+
is_member: false,
211+
include: vec![sysroot[krate].root_dir().to_path_buf()],
212+
exclude: Vec::new(),
210213
}))
211214
.collect(),
212215
}
@@ -255,13 +258,7 @@ impl ProjectWorkspace {
255258
let file_path = &krate.root_module;
256259
let file_id = load(&file_path)?;
257260

258-
let mut env = Env::default();
259-
if let Some(out_dir) = &krate.out_dir {
260-
// NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
261-
if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) {
262-
env.set("OUT_DIR", out_dir);
263-
}
264-
}
261+
let env = krate.env.clone().into_iter().collect();
265262
let proc_macro = krate
266263
.proc_macro_dylib_path
267264
.clone()
@@ -503,18 +500,6 @@ impl ProjectWorkspace {
503500
}
504501
crate_graph
505502
}
506-
507-
pub fn workspace_root_for(&self, path: &Path) -> Option<&AbsPath> {
508-
match self {
509-
ProjectWorkspace::Cargo { cargo, .. } => {
510-
Some(cargo.workspace_root()).filter(|root| path.starts_with(root))
511-
}
512-
ProjectWorkspace::Json { project: ProjectJson { roots, .. }, .. } => roots
513-
.iter()
514-
.find(|root| path.starts_with(&root.path))
515-
.map(|root| root.path.as_path()),
516-
}
517-
}
518503
}
519504

520505
fn get_rustc_cfg_options(target: Option<&str>) -> CfgOptions {

crates/ra_project_model/src/project_json.rs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,16 @@ use std::path::PathBuf;
55
use paths::{AbsPath, AbsPathBuf};
66
use ra_cfg::CfgOptions;
77
use ra_db::{CrateId, CrateName, Dependency, Edition};
8-
use rustc_hash::FxHashSet;
8+
use rustc_hash::{FxHashMap, FxHashSet};
99
use serde::{de, Deserialize};
1010
use stdx::split_delim;
1111

1212
/// Roots and crates that compose this Rust project.
1313
#[derive(Clone, Debug, Eq, PartialEq)]
1414
pub struct ProjectJson {
15-
pub(crate) roots: Vec<Root>,
1615
pub(crate) crates: Vec<Crate>,
1716
}
1817

19-
/// A root points to the directory which contains Rust crates. rust-analyzer watches all files in
20-
/// all roots. Roots might be nested.
21-
#[derive(Clone, Debug, Eq, PartialEq)]
22-
pub struct Root {
23-
pub(crate) path: AbsPathBuf,
24-
}
25-
2618
/// A crate points to the root module of a crate and lists the dependencies of the crate. This is
2719
/// useful in creating the crate graph.
2820
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -32,15 +24,16 @@ pub struct Crate {
3224
pub(crate) deps: Vec<Dependency>,
3325
pub(crate) cfg: CfgOptions,
3426
pub(crate) target: Option<String>,
35-
pub(crate) out_dir: Option<AbsPathBuf>,
27+
pub(crate) env: FxHashMap<String, String>,
3628
pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
3729
pub(crate) is_workspace_member: bool,
30+
pub(crate) include: Vec<AbsPathBuf>,
31+
pub(crate) exclude: Vec<AbsPathBuf>,
3832
}
3933

4034
impl ProjectJson {
4135
pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson {
4236
ProjectJson {
43-
roots: data.roots.into_iter().map(|path| Root { path: base.join(path) }).collect(),
4437
crates: data
4538
.crates
4639
.into_iter()
@@ -50,8 +43,19 @@ impl ProjectJson {
5043
&& !crate_data.root_module.starts_with("..")
5144
|| crate_data.root_module.starts_with(base)
5245
});
46+
let root_module = base.join(crate_data.root_module);
47+
let (include, exclude) = match crate_data.source {
48+
Some(src) => {
49+
let absolutize = |dirs: Vec<PathBuf>| {
50+
dirs.into_iter().map(|it| base.join(it)).collect::<Vec<_>>()
51+
};
52+
(absolutize(src.include_dirs), absolutize(src.exclude_dirs))
53+
}
54+
None => (vec![root_module.parent().unwrap().to_path_buf()], Vec::new()),
55+
};
56+
5357
Crate {
54-
root_module: base.join(crate_data.root_module),
58+
root_module,
5559
edition: crate_data.edition.into(),
5660
deps: crate_data
5761
.deps
@@ -74,11 +78,13 @@ impl ProjectJson {
7478
cfg
7579
},
7680
target: crate_data.target,
77-
out_dir: crate_data.out_dir.map(|it| base.join(it)),
81+
env: crate_data.env,
7882
proc_macro_dylib_path: crate_data
7983
.proc_macro_dylib_path
8084
.map(|it| base.join(it)),
8185
is_workspace_member,
86+
include,
87+
exclude,
8288
}
8389
})
8490
.collect::<Vec<_>>(),
@@ -88,7 +94,6 @@ impl ProjectJson {
8894

8995
#[derive(Deserialize)]
9096
pub struct ProjectJsonData {
91-
roots: Vec<PathBuf>,
9297
crates: Vec<CrateData>,
9398
}
9499

@@ -100,9 +105,11 @@ struct CrateData {
100105
#[serde(default)]
101106
cfg: FxHashSet<String>,
102107
target: Option<String>,
103-
out_dir: Option<PathBuf>,
108+
#[serde(default)]
109+
env: FxHashMap<String, String>,
104110
proc_macro_dylib_path: Option<PathBuf>,
105111
is_workspace_member: Option<bool>,
112+
source: Option<CrateSource>,
106113
}
107114

108115
#[derive(Deserialize)]
@@ -132,6 +139,12 @@ struct DepData {
132139
name: CrateName,
133140
}
134141

142+
#[derive(Deserialize)]
143+
struct CrateSource {
144+
include_dirs: Vec<PathBuf>,
145+
exclude_dirs: Vec<PathBuf>,
146+
}
147+
135148
fn deserialize_crate_name<'de, D>(de: D) -> Result<CrateName, D::Error>
136149
where
137150
D: de::Deserializer<'de>,

crates/rust-analyzer/src/reload.rs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use flycheck::FlycheckHandle;
55
use ra_db::{CrateGraph, SourceRoot, VfsPath};
66
use ra_ide::AnalysisChange;
77
use ra_prof::profile;
8-
use ra_project_model::{PackageRoot, ProcMacroClient, ProjectWorkspace};
8+
use ra_project_model::{ProcMacroClient, ProjectWorkspace};
99
use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind};
1010

1111
use crate::{
@@ -149,8 +149,10 @@ impl GlobalState {
149149
watchers: workspaces
150150
.iter()
151151
.flat_map(ProjectWorkspace::to_roots)
152-
.filter(PackageRoot::is_member)
153-
.map(|root| format!("{}/**/*.rs", root.path().display()))
152+
.filter(|it| it.is_member)
153+
.flat_map(|root| {
154+
root.include.into_iter().map(|it| format!("{}/**/*.rs", it.display()))
155+
})
154156
.map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
155157
.collect(),
156158
};
@@ -261,31 +263,23 @@ impl ProjectFolders {
261263
let mut local_filesets = vec![];
262264

263265
for root in workspaces.iter().flat_map(|it| it.to_roots()) {
264-
let path = root.path().to_owned();
265-
266-
let mut file_set_roots: Vec<VfsPath> = vec![];
266+
let file_set_roots: Vec<VfsPath> =
267+
root.include.iter().cloned().map(VfsPath::from).collect();
267268

268-
let entry = if root.is_member() {
269-
vfs::loader::Entry::local_cargo_package(path.to_path_buf())
270-
} else {
271-
vfs::loader::Entry::cargo_package_dependency(path.to_path_buf())
269+
let entry = {
270+
let mut dirs = vfs::loader::Directories::default();
271+
dirs.extensions.push("rs".into());
272+
dirs.include.extend(root.include);
273+
dirs.exclude.extend(root.exclude);
274+
vfs::loader::Entry::Directories(dirs)
272275
};
273-
res.load.push(entry);
274-
if root.is_member() {
275-
res.watch.push(res.load.len() - 1);
276-
}
277276

278-
if let Some(out_dir) = root.out_dir() {
279-
let out_dir = out_dir.to_path_buf();
280-
res.load.push(vfs::loader::Entry::rs_files_recursively(out_dir.clone()));
281-
if root.is_member() {
282-
res.watch.push(res.load.len() - 1);
283-
}
284-
file_set_roots.push(out_dir.into());
277+
if root.is_member {
278+
res.watch.push(res.load.len());
285279
}
286-
file_set_roots.push(path.to_path_buf().into());
280+
res.load.push(entry);
287281

288-
if root.is_member() {
282+
if root.is_member {
289283
local_filesets.push(fsc.len());
290284
}
291285
fsc.add_file_set(file_set_roots)

crates/vfs/src/loader.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub enum Entry {
1717
/// * it is not under `exclude` path
1818
///
1919
/// If many include/exclude paths match, the longest one wins.
20-
#[derive(Debug, Clone)]
20+
#[derive(Debug, Clone, Default)]
2121
pub struct Directories {
2222
pub extensions: Vec<String>,
2323
pub include: Vec<AbsPathBuf>,

0 commit comments

Comments
 (0)