aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_project_model/src/lib.rs129
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs11
-rw-r--r--crates/rust-analyzer/src/main_loop.rs5
-rw-r--r--crates/rust-analyzer/src/main_loop/subscriptions.rs2
-rw-r--r--crates/rust-analyzer/src/vfs_glob.rs10
-rw-r--r--crates/rust-analyzer/src/world.rs57
6 files changed, 94 insertions, 120 deletions
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index dd9c80691..0ab64a1e0 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -62,16 +62,16 @@ pub struct PackageRoot {
62 /// Is a member of the current workspace 62 /// Is a member of the current workspace
63 is_member: bool, 63 is_member: bool,
64} 64}
65
66impl PackageRoot { 65impl PackageRoot {
67 pub fn new(path: PathBuf, is_member: bool) -> PackageRoot { 66 pub fn new_member(path: PathBuf) -> PackageRoot {
68 PackageRoot { path, is_member } 67 Self { path, is_member: true }
69 } 68 }
70 69 pub fn new_non_member(path: PathBuf) -> PackageRoot {
71 pub fn path(&self) -> &PathBuf { 70 Self { path, is_member: false }
71 }
72 pub fn path(&self) -> &Path {
72 &self.path 73 &self.path
73 } 74 }
74
75 pub fn is_member(&self) -> bool { 75 pub fn is_member(&self) -> bool {
76 self.is_member 76 self.is_member
77 } 77 }
@@ -130,70 +130,45 @@ impl ProjectWorkspace {
130 pub fn to_roots(&self) -> Vec<PackageRoot> { 130 pub fn to_roots(&self) -> Vec<PackageRoot> {
131 match self { 131 match self {
132 ProjectWorkspace::Json { project } => { 132 ProjectWorkspace::Json { project } => {
133 let mut roots = Vec::with_capacity(project.roots.len()); 133 project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect()
134 for root in &project.roots {
135 roots.push(PackageRoot::new(root.path.clone(), true));
136 }
137 roots
138 }
139 ProjectWorkspace::Cargo { cargo, sysroot } => {
140 let mut roots = Vec::with_capacity(cargo.packages().len() + sysroot.crates().len());
141 for pkg in cargo.packages() {
142 let root = cargo[pkg].root().to_path_buf();
143 let member = cargo[pkg].is_member;
144 roots.push(PackageRoot::new(root, member));
145 }
146 for krate in sysroot.crates() {
147 roots.push(PackageRoot::new(sysroot[krate].root_dir().to_path_buf(), false))
148 }
149 roots
150 } 134 }
135 ProjectWorkspace::Cargo { cargo, sysroot } => cargo
136 .packages()
137 .map(|pkg| PackageRoot {
138 path: cargo[pkg].root().to_path_buf(),
139 is_member: cargo[pkg].is_member,
140 })
141 .chain(sysroot.crates().map(|krate| {
142 PackageRoot::new_non_member(sysroot[krate].root_dir().to_path_buf())
143 }))
144 .collect(),
151 } 145 }
152 } 146 }
153 147
154 pub fn out_dirs(&self) -> Vec<PathBuf> { 148 pub fn out_dirs(&self) -> Vec<PathBuf> {
155 match self { 149 match self {
156 ProjectWorkspace::Json { project } => { 150 ProjectWorkspace::Json { project } => {
157 let mut out_dirs = Vec::with_capacity(project.crates.len()); 151 project.crates.iter().filter_map(|krate| krate.out_dir.as_ref()).cloned().collect()
158 for krate in &project.crates {
159 if let Some(out_dir) = &krate.out_dir {
160 out_dirs.push(out_dir.to_path_buf());
161 }
162 }
163 out_dirs
164 } 152 }
165 ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { 153 ProjectWorkspace::Cargo { cargo, sysroot: _ } => {
166 let mut out_dirs = Vec::with_capacity(cargo.packages().len()); 154 cargo.packages().filter_map(|pkg| cargo[pkg].out_dir.as_ref()).cloned().collect()
167 for pkg in cargo.packages() {
168 if let Some(out_dir) = &cargo[pkg].out_dir {
169 out_dirs.push(out_dir.to_path_buf());
170 }
171 }
172 out_dirs
173 } 155 }
174 } 156 }
175 } 157 }
176 158
177 pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { 159 pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> {
178 match self { 160 match self {
179 ProjectWorkspace::Json { project } => { 161 ProjectWorkspace::Json { project } => project
180 let mut proc_macro_dylib_paths = Vec::with_capacity(project.crates.len()); 162 .crates
181 for krate in &project.crates { 163 .iter()
182 if let Some(out_dir) = &krate.proc_macro_dylib_path { 164 .filter_map(|krate| krate.proc_macro_dylib_path.as_ref())
183 proc_macro_dylib_paths.push(out_dir.to_path_buf()); 165 .cloned()
184 } 166 .collect(),
185 } 167 ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo
186 proc_macro_dylib_paths 168 .packages()
187 } 169 .filter_map(|pkg| cargo[pkg].proc_macro_dylib_path.as_ref())
188 ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { 170 .cloned()
189 let mut proc_macro_dylib_paths = Vec::with_capacity(cargo.packages().len()); 171 .collect(),
190 for pkg in cargo.packages() {
191 if let Some(dylib_path) = &cargo[pkg].proc_macro_dylib_path {
192 proc_macro_dylib_paths.push(dylib_path.to_path_buf());
193 }
194 }
195 proc_macro_dylib_paths
196 }
197 } 172 }
198 } 173 }
199 174
@@ -216,10 +191,12 @@ impl ProjectWorkspace {
216 let mut crate_graph = CrateGraph::default(); 191 let mut crate_graph = CrateGraph::default();
217 match self { 192 match self {
218 ProjectWorkspace::Json { project } => { 193 ProjectWorkspace::Json { project } => {
219 let mut crates = FxHashMap::default(); 194 let crates: FxHashMap<_, _> = project
220 for (id, krate) in project.crates.iter().enumerate() { 195 .crates
221 let crate_id = json_project::CrateId(id); 196 .iter()
222 if let Some(file_id) = load(&krate.root_module) { 197 .enumerate()
198 .filter_map(|(seq_index, krate)| {
199 let file_id = load(&krate.root_module)?;
223 let edition = match krate.edition { 200 let edition = match krate.edition {
224 json_project::Edition::Edition2015 => Edition::Edition2015, 201 json_project::Edition::Edition2015 => Edition::Edition2015,
225 json_project::Edition::Edition2018 => Edition::Edition2018, 202 json_project::Edition::Edition2018 => Edition::Edition2018,
@@ -249,8 +226,8 @@ impl ProjectWorkspace {
249 .clone() 226 .clone()
250 .map(|it| proc_macro_client.by_dylib_path(&it)); 227 .map(|it| proc_macro_client.by_dylib_path(&it));
251 // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env 228 // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env
252 crates.insert( 229 Some((
253 crate_id, 230 json_project::CrateId(seq_index),
254 crate_graph.add_crate_root( 231 crate_graph.add_crate_root(
255 file_id, 232 file_id,
256 edition, 233 edition,
@@ -261,9 +238,9 @@ impl ProjectWorkspace {
261 extern_source, 238 extern_source,
262 proc_macro.unwrap_or_default(), 239 proc_macro.unwrap_or_default(),
263 ), 240 ),
264 ); 241 ))
265 } 242 })
266 } 243 .collect();
267 244
268 for (id, krate) in project.crates.iter().enumerate() { 245 for (id, krate) in project.crates.iter().enumerate() {
269 for dep in &krate.deps { 246 for dep in &krate.deps {
@@ -287,9 +264,11 @@ impl ProjectWorkspace {
287 } 264 }
288 } 265 }
289 ProjectWorkspace::Cargo { cargo, sysroot } => { 266 ProjectWorkspace::Cargo { cargo, sysroot } => {
290 let mut sysroot_crates = FxHashMap::default(); 267 let sysroot_crates: FxHashMap<_, _> = sysroot
291 for krate in sysroot.crates() { 268 .crates()
292 if let Some(file_id) = load(&sysroot[krate].root) { 269 .filter_map(|krate| {
270 let file_id = load(&sysroot[krate].root)?;
271
293 // Crates from sysroot have `cfg(test)` disabled 272 // Crates from sysroot have `cfg(test)` disabled
294 let cfg_options = { 273 let cfg_options = {
295 let mut opts = default_cfg_options.clone(); 274 let mut opts = default_cfg_options.clone();
@@ -300,22 +279,22 @@ impl ProjectWorkspace {
300 let env = Env::default(); 279 let env = Env::default();
301 let extern_source = ExternSource::default(); 280 let extern_source = ExternSource::default();
302 let proc_macro = vec![]; 281 let proc_macro = vec![];
282 let crate_name = CrateName::new(&sysroot[krate].name)
283 .expect("Sysroot crate names should not contain dashes");
303 284
304 let crate_id = crate_graph.add_crate_root( 285 let crate_id = crate_graph.add_crate_root(
305 file_id, 286 file_id,
306 Edition::Edition2018, 287 Edition::Edition2018,
307 Some( 288 Some(crate_name),
308 CrateName::new(&sysroot[krate].name)
309 .expect("Sysroot crate names should not contain dashes"),
310 ),
311 cfg_options, 289 cfg_options,
312 env, 290 env,
313 extern_source, 291 extern_source,
314 proc_macro, 292 proc_macro,
315 ); 293 );
316 sysroot_crates.insert(krate, crate_id); 294 Some((krate, crate_id))
317 } 295 })
318 } 296 .collect();
297
319 for from in sysroot.crates() { 298 for from in sysroot.crates() {
320 for &to in sysroot[from].deps.iter() { 299 for &to in sysroot[from].deps.iter() {
321 let name = &sysroot[to].name; 300 let name = &sysroot[to].name;
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 2c0bde920..69133e4e4 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -36,8 +36,7 @@ pub(crate) fn load_cargo(
36 extern_dirs.extend(ws.out_dirs()); 36 extern_dirs.extend(ws.out_dirs());
37 37
38 let mut project_roots = ws.to_roots(); 38 let mut project_roots = ws.to_roots();
39 project_roots 39 project_roots.extend(extern_dirs.iter().cloned().map(PackageRoot::new_non_member));
40 .extend(extern_dirs.iter().map(|path| PackageRoot::new(path.to_path_buf(), false)));
41 40
42 let (sender, receiver) = unbounded(); 41 let (sender, receiver) = unbounded();
43 let sender = Box::new(move |t| sender.send(t).unwrap()); 42 let sender = Box::new(move |t| sender.send(t).unwrap());
@@ -46,7 +45,7 @@ pub(crate) fn load_cargo(
46 .iter() 45 .iter()
47 .map(|pkg_root| { 46 .map(|pkg_root| {
48 RootEntry::new( 47 RootEntry::new(
49 pkg_root.path().clone(), 48 pkg_root.path().to_owned(),
50 RustPackageFilterBuilder::default() 49 RustPackageFilterBuilder::default()
51 .set_member(pkg_root.is_member()) 50 .set_member(pkg_root.is_member())
52 .into_vfs_filter(), 51 .into_vfs_filter(),
@@ -58,12 +57,12 @@ pub(crate) fn load_cargo(
58 ); 57 );
59 58
60 let source_roots = roots 59 let source_roots = roots
61 .iter() 60 .into_iter()
62 .map(|&vfs_root| { 61 .map(|vfs_root| {
63 let source_root_id = vfs_root_to_id(vfs_root); 62 let source_root_id = vfs_root_to_id(vfs_root);
64 let project_root = project_roots 63 let project_root = project_roots
65 .iter() 64 .iter()
66 .find(|it| it.path() == &vfs.root2path(vfs_root)) 65 .find(|it| it.path() == vfs.root2path(vfs_root))
67 .unwrap() 66 .unwrap()
68 .clone(); 67 .clone();
69 (source_root_id, project_root) 68 (source_root_id, project_root)
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 95e676e0f..8d1429196 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -23,6 +23,7 @@ use lsp_types::{
23use ra_flycheck::{url_from_path_with_drive_lowercasing, CheckTask}; 23use ra_flycheck::{url_from_path_with_drive_lowercasing, CheckTask};
24use ra_ide::{Canceled, FileId, LibraryData, SourceRootId}; 24use ra_ide::{Canceled, FileId, LibraryData, SourceRootId};
25use ra_prof::profile; 25use ra_prof::profile;
26use ra_project_model::{PackageRoot, ProjectWorkspace};
26use ra_vfs::{VfsFile, VfsTask, Watch}; 27use ra_vfs::{VfsFile, VfsTask, Watch};
27use relative_path::RelativePathBuf; 28use relative_path::RelativePathBuf;
28use rustc_hash::FxHashSet; 29use rustc_hash::FxHashSet;
@@ -131,8 +132,8 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
131 let registration_options = req::DidChangeWatchedFilesRegistrationOptions { 132 let registration_options = req::DidChangeWatchedFilesRegistrationOptions {
132 watchers: workspaces 133 watchers: workspaces
133 .iter() 134 .iter()
134 .flat_map(|ws| ws.to_roots()) 135 .flat_map(ProjectWorkspace::to_roots)
135 .filter(|root| root.is_member()) 136 .filter(PackageRoot::is_member)
136 .map(|root| format!("{}/**/*.rs", root.path().display())) 137 .map(|root| format!("{}/**/*.rs", root.path().display()))
137 .map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None }) 138 .map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None })
138 .collect(), 139 .collect(),
diff --git a/crates/rust-analyzer/src/main_loop/subscriptions.rs b/crates/rust-analyzer/src/main_loop/subscriptions.rs
index bee6437cf..2c76418be 100644
--- a/crates/rust-analyzer/src/main_loop/subscriptions.rs
+++ b/crates/rust-analyzer/src/main_loop/subscriptions.rs
@@ -17,6 +17,6 @@ impl Subscriptions {
17 self.subs.remove(&file_id); 17 self.subs.remove(&file_id);
18 } 18 }
19 pub(crate) fn subscriptions(&self) -> Vec<FileId> { 19 pub(crate) fn subscriptions(&self) -> Vec<FileId> {
20 self.subs.iter().cloned().collect() 20 self.subs.iter().copied().collect()
21 } 21 }
22} 22}
diff --git a/crates/rust-analyzer/src/vfs_glob.rs b/crates/rust-analyzer/src/vfs_glob.rs
index 91b33f94e..ff37a7008 100644
--- a/crates/rust-analyzer/src/vfs_glob.rs
+++ b/crates/rust-analyzer/src/vfs_glob.rs
@@ -29,10 +29,14 @@ impl RustPackageFilterBuilder {
29 self.is_member = is_member; 29 self.is_member = is_member;
30 self 30 self
31 } 31 }
32 pub fn exclude(mut self, glob: Glob) -> RustPackageFilterBuilder { 32
33 self.exclude.add(glob); 33 pub fn exclude(mut self, globs: impl IntoIterator<Item = Glob>) -> RustPackageFilterBuilder {
34 for glob in globs.into_iter() {
35 self.exclude.add(glob);
36 }
34 self 37 self
35 } 38 }
39
36 pub fn into_vfs_filter(self) -> Box<dyn Filter> { 40 pub fn into_vfs_filter(self) -> Box<dyn Filter> {
37 let RustPackageFilterBuilder { is_member, mut exclude } = self; 41 let RustPackageFilterBuilder { is_member, mut exclude } = self;
38 for &glob in ALWAYS_IGNORED { 42 for &glob in ALWAYS_IGNORED {
@@ -87,7 +91,7 @@ fn test_globs() {
87 91
88 let filter = RustPackageFilterBuilder::default() 92 let filter = RustPackageFilterBuilder::default()
89 .set_member(true) 93 .set_member(true)
90 .exclude(Glob::new("src/llvm-project/**").unwrap()) 94 .exclude(std::iter::once(Glob::new("src/llvm-project/**").unwrap()))
91 .into_vfs_filter(); 95 .into_vfs_filter();
92 96
93 assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang"))); 97 assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang")));
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs
index 5674f42ef..365f57d8c 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/world.rs
@@ -87,44 +87,35 @@ impl WorldState {
87 ) -> WorldState { 87 ) -> WorldState {
88 let mut change = AnalysisChange::new(); 88 let mut change = AnalysisChange::new();
89 89
90 let mut roots = Vec::new(); 90 let extern_dirs: FxHashSet<_> =
91 roots.extend(folder_roots.iter().map(|path| { 91 workspaces.iter().flat_map(ProjectWorkspace::out_dirs).collect();
92 let mut filter = RustPackageFilterBuilder::default().set_member(true); 92
93 for glob in exclude_globs.iter() { 93 let roots: Vec<_> = {
94 filter = filter.exclude(glob.clone()); 94 let create_filter = |is_member| {
95 } 95 RustPackageFilterBuilder::default()
96 RootEntry::new(path.clone(), filter.into_vfs_filter()) 96 .set_member(is_member)
97 })); 97 .exclude(exclude_globs.iter().cloned())
98 for ws in workspaces.iter() { 98 .into_vfs_filter()
99 roots.extend(ws.to_roots().into_iter().map(|pkg_root| { 99 };
100 let mut filter = 100 folder_roots
101 RustPackageFilterBuilder::default().set_member(pkg_root.is_member()); 101 .iter()
102 for glob in exclude_globs.iter() { 102 .map(|path| RootEntry::new(path.clone(), create_filter(true)))
103 filter = filter.exclude(glob.clone()); 103 .chain(workspaces.iter().flat_map(ProjectWorkspace::to_roots).map(|pkg_root| {
104 } 104 RootEntry::new(pkg_root.path().to_owned(), create_filter(pkg_root.is_member()))
105 RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter()) 105 }))
106 })); 106 .chain(
107 } 107 extern_dirs
108 108 .iter()
109 let mut extern_dirs = FxHashSet::default(); 109 .map(|path| RootEntry::new(path.to_owned(), create_filter(false))),
110 for ws in workspaces.iter() { 110 )
111 extern_dirs.extend(ws.out_dirs()); 111 .collect()
112 } 112 };
113
114 let mut extern_source_roots = FxHashMap::default();
115
116 roots.extend(extern_dirs.iter().map(|path| {
117 let mut filter = RustPackageFilterBuilder::default().set_member(false);
118 for glob in exclude_globs.iter() {
119 filter = filter.exclude(glob.clone());
120 }
121 RootEntry::new(PathBuf::from(&path), filter.into_vfs_filter())
122 }));
123 113
124 let (task_sender, task_receiver) = unbounded(); 114 let (task_sender, task_receiver) = unbounded();
125 let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); 115 let task_sender = Box::new(move |t| task_sender.send(t).unwrap());
126 let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); 116 let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch);
127 117
118 let mut extern_source_roots = FxHashMap::default();
128 for r in vfs_roots { 119 for r in vfs_roots {
129 let vfs_root_path = vfs.root2path(r); 120 let vfs_root_path = vfs.root2path(r);
130 let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); 121 let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it));