aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/project_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src/project_model.rs')
-rw-r--r--crates/ra_lsp_server/src/project_model.rs36
1 files changed, 33 insertions, 3 deletions
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs
index 3305d468a..cb91ada90 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)]
@@ -28,6 +34,13 @@ struct PackageData {
28 manifest: PathBuf, 34 manifest: PathBuf,
29 targets: Vec<Target>, 35 targets: Vec<Target>,
30 is_member: bool, 36 is_member: bool,
37 dependencies: Vec<PackageDependency>,
38}
39
40#[derive(Debug, Clone)]
41pub struct PackageDependency {
42 pub pkg: Package,
43 pub name: SmolStr,
31} 44}
32 45
33#[derive(Debug, Clone)] 46#[derive(Debug, Clone)]
@@ -61,6 +74,12 @@ impl Package {
61 pub fn is_member(self, ws: &CargoWorkspace) -> bool { 74 pub fn is_member(self, ws: &CargoWorkspace) -> bool {
62 ws.pkg(self).is_member 75 ws.pkg(self).is_member
63 } 76 }
77 pub fn dependencies<'a>(
78 self,
79 ws: &'a CargoWorkspace,
80 ) -> impl Iterator<Item = &'a PackageDependency> + 'a {
81 ws.pkg(self).dependencies.iter()
82 }
64} 83}
65 84
66impl Target { 85impl Target {
@@ -106,6 +125,7 @@ impl CargoWorkspace {
106 manifest: PathBuf::from(meta_pkg.manifest_path), 125 manifest: PathBuf::from(meta_pkg.manifest_path),
107 targets: Vec::new(), 126 targets: Vec::new(),
108 is_member, 127 is_member,
128 dependencies: Vec::new(),
109 }; 129 };
110 for meta_tgt in meta_pkg.targets { 130 for meta_tgt in meta_pkg.targets {
111 let tgt = Target(targets.len()); 131 let tgt = Target(targets.len());
@@ -119,6 +139,16 @@ impl CargoWorkspace {
119 } 139 }
120 packages.push(pkg_data) 140 packages.push(pkg_data)
121 } 141 }
142 let resolve = meta.resolve.expect("metadata executed with deps");
143 for node in resolve.nodes {
144 let source = pkg_by_id[&node.id];
145 for id in node.dependencies {
146 let target = pkg_by_id[&id];
147 let name: SmolStr = packages[target.0].name.replace('-', "_").into();
148 let dep = PackageDependency { name, pkg: target };
149 packages[source.0].dependencies.push(dep);
150 }
151 }
122 152
123 Ok(CargoWorkspace { packages, targets }) 153 Ok(CargoWorkspace { packages, targets })
124 } 154 }