aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_db/src/input.rs3
-rw-r--r--crates/ra_lsp_server/src/project_model.rs15
-rw-r--r--crates/ra_lsp_server/src/server_world.rs39
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 @@
1use std::path::{Path, PathBuf}; 1use std::path::{Path, PathBuf};
2 2
3use serde_derive::Serialize;
4use cargo_metadata::{metadata_run, CargoOpt}; 3use cargo_metadata::{metadata_run, CargoOpt};
5use ra_syntax::SmolStr; 4use ra_syntax::SmolStr;
6use rustc_hash::{FxHashMap, FxHashSet}; 5use 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)]
15pub struct CargoWorkspace { 21pub 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)]
21pub struct Package(usize); 27pub struct Package(usize);
22#[derive(Clone, Copy, Debug, Serialize)] 28#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
23pub struct Target(usize); 29pub 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
67impl Target { 76impl 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
14use crate::{ 14use 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);