diff options
-rw-r--r-- | crates/ra_db/src/input.rs | 3 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/project_model.rs | 15 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/server_world.rs | 39 |
3 files changed, 43 insertions, 14 deletions
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 7d9faa43c..a48d05b98 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -48,6 +48,9 @@ impl CrateGraph { | |||
48 | assert!(prev.is_none()); | 48 | assert!(prev.is_none()); |
49 | crate_id | 49 | crate_id |
50 | } | 50 | } |
51 | //FIXME: check that we don't have cycles here. | ||
52 | // Just a simple depth first search from `to` should work, | ||
53 | // the graph is small. | ||
51 | pub fn add_dep(&mut self, from: CrateId, to: CrateId) { | 54 | pub fn add_dep(&mut self, from: CrateId, to: CrateId) { |
52 | self.arena.get_mut(&from).unwrap().add_dep(to) | 55 | self.arena.get_mut(&from).unwrap().add_dep(to) |
53 | } | 56 | } |
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs index 22495f49c..5da71b9f5 100644 --- a/crates/ra_lsp_server/src/project_model.rs +++ b/crates/ra_lsp_server/src/project_model.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | use std::path::{Path, PathBuf}; | 1 | use std::path::{Path, PathBuf}; |
2 | 2 | ||
3 | use serde_derive::Serialize; | ||
4 | use cargo_metadata::{metadata_run, CargoOpt}; | 3 | use cargo_metadata::{metadata_run, CargoOpt}; |
5 | use ra_syntax::SmolStr; | 4 | use ra_syntax::SmolStr; |
6 | use rustc_hash::{FxHashMap, FxHashSet}; | 5 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -11,15 +10,22 @@ use crate::{ | |||
11 | thread_watcher::{ThreadWatcher, Worker}, | 10 | thread_watcher::{ThreadWatcher, Worker}, |
12 | }; | 11 | }; |
13 | 12 | ||
13 | /// `CargoWorksapce` represents the logical structure of, well, a Cargo | ||
14 | /// workspace. It pretty closely mirrors `cargo metadata` output. | ||
15 | /// | ||
16 | /// Note that internally, rust analyzer uses a differnet structure: | ||
17 | /// `CrateGraph`. `CrateGraph` is lower-level: it knows only about the crates, | ||
18 | /// while this knows about `Pacakges` & `Targets`: purely cargo-related | ||
19 | /// concepts. | ||
14 | #[derive(Debug, Clone)] | 20 | #[derive(Debug, Clone)] |
15 | pub struct CargoWorkspace { | 21 | pub struct CargoWorkspace { |
16 | packages: Vec<PackageData>, | 22 | packages: Vec<PackageData>, |
17 | targets: Vec<TargetData>, | 23 | targets: Vec<TargetData>, |
18 | } | 24 | } |
19 | 25 | ||
20 | #[derive(Clone, Copy, Debug, Serialize)] | 26 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
21 | pub struct Package(usize); | 27 | pub struct Package(usize); |
22 | #[derive(Clone, Copy, Debug, Serialize)] | 28 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
23 | pub struct Target(usize); | 29 | pub struct Target(usize); |
24 | 30 | ||
25 | #[derive(Debug, Clone)] | 31 | #[derive(Debug, Clone)] |
@@ -62,6 +68,9 @@ impl Package { | |||
62 | pub fn is_member(self, ws: &CargoWorkspace) -> bool { | 68 | pub fn is_member(self, ws: &CargoWorkspace) -> bool { |
63 | ws.pkg(self).is_member | 69 | ws.pkg(self).is_member |
64 | } | 70 | } |
71 | pub fn dependencies<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Package> + 'a { | ||
72 | ws.pkg(self).dependencies.iter().cloned() | ||
73 | } | ||
65 | } | 74 | } |
66 | 75 | ||
67 | impl Target { | 76 | impl Target { |
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index c3f89ad5f..f2d602dc7 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -13,7 +13,7 @@ use failure::{bail, format_err}; | |||
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | path_map::{PathMap, Root}, | 15 | path_map::{PathMap, Root}, |
16 | project_model::CargoWorkspace, | 16 | project_model::{CargoWorkspace, TargetKind}, |
17 | vfs::{FileEvent, FileEventKind}, | 17 | vfs::{FileEvent, FileEventKind}, |
18 | Result, | 18 | Result, |
19 | }; | 19 | }; |
@@ -142,17 +142,34 @@ impl ServerWorldState { | |||
142 | } | 142 | } |
143 | pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { | 143 | pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { |
144 | let mut crate_graph = CrateGraph::default(); | 144 | let mut crate_graph = CrateGraph::default(); |
145 | ws.iter() | 145 | let mut pkg_to_lib_crate = FxHashMap::default(); |
146 | .flat_map(|ws| { | 146 | let mut pkg_crates = FxHashMap::default(); |
147 | ws.packages() | 147 | for ws in ws.iter() { |
148 | .flat_map(move |pkg| pkg.targets(ws)) | 148 | for pkg in ws.packages() { |
149 | .map(move |tgt| tgt.root(ws)) | 149 | for tgt in pkg.targets(ws) { |
150 | }) | 150 | let root = tgt.root(ws); |
151 | .for_each(|root| { | 151 | if let Some(file_id) = self.path_map.get_id(root) { |
152 | if let Some(file_id) = self.path_map.get_id(root) { | 152 | let crate_id = crate_graph.add_crate_root(file_id); |
153 | crate_graph.add_crate_root(file_id); | 153 | if tgt.kind(ws) == TargetKind::Lib { |
154 | pkg_to_lib_crate.insert(pkg, crate_id); | ||
155 | } | ||
156 | pkg_crates | ||
157 | .entry(pkg) | ||
158 | .or_insert_with(Vec::new) | ||
159 | .push(crate_id); | ||
160 | } | ||
161 | } | ||
162 | } | ||
163 | for pkg in ws.packages() { | ||
164 | for dep in pkg.dependencies(ws) { | ||
165 | if let Some(&to) = pkg_to_lib_crate.get(&dep) { | ||
166 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | ||
167 | crate_graph.add_dep(from, to); | ||
168 | } | ||
169 | } | ||
154 | } | 170 | } |
155 | }); | 171 | } |
172 | } | ||
156 | self.workspaces = Arc::new(ws); | 173 | self.workspaces = Arc::new(ws); |
157 | let mut change = AnalysisChange::new(); | 174 | let mut change = AnalysisChange::new(); |
158 | change.set_crate_graph(crate_graph); | 175 | change.set_crate_graph(crate_graph); |