aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--crates/ra_lsp_server/Cargo.toml1
-rw-r--r--crates/ra_lsp_server/src/project_model.rs56
3 files changed, 28 insertions, 30 deletions
diff --git a/Cargo.lock b/Cargo.lock
index dba94aa6b..45f1feb7e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -733,6 +733,7 @@ dependencies = [
733 "languageserver-types 0.53.1 (registry+https://github.com/rust-lang/crates.io-index)", 733 "languageserver-types 0.53.1 (registry+https://github.com/rust-lang/crates.io-index)",
734 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 734 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
735 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 735 "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
736 "ra_arena 0.1.0",
736 "ra_ide_api 0.1.0", 737 "ra_ide_api 0.1.0",
737 "ra_syntax 0.1.0", 738 "ra_syntax 0.1.0",
738 "ra_text_edit 0.1.0", 739 "ra_text_edit 0.1.0",
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 296fae34f..b4a7b3388 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -30,6 +30,7 @@ thread_worker = { path = "../thread_worker" }
30ra_syntax = { path = "../ra_syntax" } 30ra_syntax = { path = "../ra_syntax" }
31ra_text_edit = { path = "../ra_text_edit" } 31ra_text_edit = { path = "../ra_text_edit" }
32ra_ide_api = { path = "../ra_ide_api" } 32ra_ide_api = { path = "../ra_ide_api" }
33ra_arena = { path = "../ra_arena" }
33gen_lsp_server = { path = "../gen_lsp_server" } 34gen_lsp_server = { path = "../gen_lsp_server" }
34ra_vfs = { path = "../ra_vfs" } 35ra_vfs = { path = "../ra_vfs" }
35 36
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs
index ff9befe46..9f429c9a1 100644
--- a/crates/ra_lsp_server/src/project_model.rs
+++ b/crates/ra_lsp_server/src/project_model.rs
@@ -2,6 +2,7 @@ use std::path::{Path, PathBuf};
2 2
3use cargo_metadata::{metadata_run, CargoOpt}; 3use cargo_metadata::{metadata_run, CargoOpt};
4use ra_syntax::SmolStr; 4use ra_syntax::SmolStr;
5use ra_arena::{Arena, RawId, impl_arena_id};
5use rustc_hash::FxHashMap; 6use rustc_hash::FxHashMap;
6use failure::{format_err, bail}; 7use failure::{format_err, bail};
7use thread_worker::{WorkerHandle, Worker}; 8use thread_worker::{WorkerHandle, Worker};
@@ -17,14 +18,17 @@ use crate::Result;
17/// concepts. 18/// concepts.
18#[derive(Debug, Clone)] 19#[derive(Debug, Clone)]
19pub struct CargoWorkspace { 20pub struct CargoWorkspace {
20 packages: Vec<PackageData>, 21 packages: Arena<Package, PackageData>,
21 targets: Vec<TargetData>, 22 targets: Arena<Target, TargetData>,
22} 23}
23 24
24#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 25#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
25pub struct Package(usize); 26pub struct Package(RawId);
27impl_arena_id!(Package);
28
26#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 29#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
27pub struct Target(usize); 30pub struct Target(RawId);
31impl_arena_id!(Target);
28 32
29#[derive(Debug, Clone)] 33#[derive(Debug, Clone)]
30struct PackageData { 34struct PackageData {
@@ -61,38 +65,38 @@ pub enum TargetKind {
61 65
62impl Package { 66impl Package {
63 pub fn name(self, ws: &CargoWorkspace) -> &str { 67 pub fn name(self, ws: &CargoWorkspace) -> &str {
64 ws.pkg(self).name.as_str() 68 ws.packages[self].name.as_str()
65 } 69 }
66 pub fn root(self, ws: &CargoWorkspace) -> &Path { 70 pub fn root(self, ws: &CargoWorkspace) -> &Path {
67 ws.pkg(self).manifest.parent().unwrap() 71 ws.packages[self].manifest.parent().unwrap()
68 } 72 }
69 pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Target> + 'a { 73 pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Target> + 'a {
70 ws.pkg(self).targets.iter().cloned() 74 ws.packages[self].targets.iter().cloned()
71 } 75 }
72 #[allow(unused)] 76 #[allow(unused)]
73 pub fn is_member(self, ws: &CargoWorkspace) -> bool { 77 pub fn is_member(self, ws: &CargoWorkspace) -> bool {
74 ws.pkg(self).is_member 78 ws.packages[self].is_member
75 } 79 }
76 pub fn dependencies<'a>( 80 pub fn dependencies<'a>(
77 self, 81 self,
78 ws: &'a CargoWorkspace, 82 ws: &'a CargoWorkspace,
79 ) -> impl Iterator<Item = &'a PackageDependency> + 'a { 83 ) -> impl Iterator<Item = &'a PackageDependency> + 'a {
80 ws.pkg(self).dependencies.iter() 84 ws.packages[self].dependencies.iter()
81 } 85 }
82} 86}
83 87
84impl Target { 88impl Target {
85 pub fn package(self, ws: &CargoWorkspace) -> Package { 89 pub fn package(self, ws: &CargoWorkspace) -> Package {
86 ws.tgt(self).pkg 90 ws.targets[self].pkg
87 } 91 }
88 pub fn name(self, ws: &CargoWorkspace) -> &str { 92 pub fn name(self, ws: &CargoWorkspace) -> &str {
89 ws.tgt(self).name.as_str() 93 ws.targets[self].name.as_str()
90 } 94 }
91 pub fn root(self, ws: &CargoWorkspace) -> &Path { 95 pub fn root(self, ws: &CargoWorkspace) -> &Path {
92 ws.tgt(self).root.as_path() 96 ws.targets[self].root.as_path()
93 } 97 }
94 pub fn kind(self, ws: &CargoWorkspace) -> TargetKind { 98 pub fn kind(self, ws: &CargoWorkspace) -> TargetKind {
95 ws.tgt(self).kind 99 ws.targets[self].kind
96 } 100 }
97} 101}
98 102
@@ -106,25 +110,24 @@ impl CargoWorkspace {
106 ) 110 )
107 .map_err(|e| format_err!("cargo metadata failed: {}", e))?; 111 .map_err(|e| format_err!("cargo metadata failed: {}", e))?;
108 let mut pkg_by_id = FxHashMap::default(); 112 let mut pkg_by_id = FxHashMap::default();
109 let mut packages = Vec::new(); 113 let mut packages = Arena::default();
110 let mut targets = Vec::new(); 114 let mut targets = Arena::default();
111 115
112 let ws_members = &meta.workspace_members; 116 let ws_members = &meta.workspace_members;
113 117
114 for meta_pkg in meta.packages { 118 for meta_pkg in meta.packages {
115 let pkg = Package(packages.len());
116 let is_member = ws_members.contains(&meta_pkg.id); 119 let is_member = ws_members.contains(&meta_pkg.id);
117 pkg_by_id.insert(meta_pkg.id.clone(), pkg); 120 let pkg = packages.alloc(PackageData {
118 let mut pkg_data = PackageData {
119 name: meta_pkg.name.into(), 121 name: meta_pkg.name.into(),
120 manifest: meta_pkg.manifest_path.clone(), 122 manifest: meta_pkg.manifest_path.clone(),
121 targets: Vec::new(), 123 targets: Vec::new(),
122 is_member, 124 is_member,
123 dependencies: Vec::new(), 125 dependencies: Vec::new(),
124 }; 126 });
127 let pkg_data = &mut packages[pkg];
128 pkg_by_id.insert(meta_pkg.id.clone(), pkg);
125 for meta_tgt in meta_pkg.targets { 129 for meta_tgt in meta_pkg.targets {
126 let tgt = Target(targets.len()); 130 let tgt = targets.alloc(TargetData {
127 targets.push(TargetData {
128 pkg, 131 pkg,
129 name: meta_tgt.name.into(), 132 name: meta_tgt.name.into(),
130 root: meta_tgt.src_path.clone(), 133 root: meta_tgt.src_path.clone(),
@@ -132,7 +135,6 @@ impl CargoWorkspace {
132 }); 135 });
133 pkg_data.targets.push(tgt); 136 pkg_data.targets.push(tgt);
134 } 137 }
135 packages.push(pkg_data)
136 } 138 }
137 let resolve = meta.resolve.expect("metadata executed with deps"); 139 let resolve = meta.resolve.expect("metadata executed with deps");
138 for node in resolve.nodes { 140 for node in resolve.nodes {
@@ -142,26 +144,20 @@ impl CargoWorkspace {
142 name: dep_node.name.into(), 144 name: dep_node.name.into(),
143 pkg: pkg_by_id[&dep_node.pkg], 145 pkg: pkg_by_id[&dep_node.pkg],
144 }; 146 };
145 packages[source.0].dependencies.push(dep); 147 packages[source].dependencies.push(dep);
146 } 148 }
147 } 149 }
148 150
149 Ok(CargoWorkspace { packages, targets }) 151 Ok(CargoWorkspace { packages, targets })
150 } 152 }
151 pub fn packages<'a>(&'a self) -> impl Iterator<Item = Package> + 'a { 153 pub fn packages<'a>(&'a self) -> impl Iterator<Item = Package> + 'a {
152 (0..self.packages.len()).map(Package) 154 self.packages.iter().map(|(id, _pkg)| id)
153 } 155 }
154 pub fn target_by_root(&self, root: &Path) -> Option<Target> { 156 pub fn target_by_root(&self, root: &Path) -> Option<Target> {
155 self.packages() 157 self.packages()
156 .filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root)) 158 .filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root))
157 .next() 159 .next()
158 } 160 }
159 fn pkg(&self, pkg: Package) -> &PackageData {
160 &self.packages[pkg.0]
161 }
162 fn tgt(&self, tgt: Target) -> &TargetData {
163 &self.targets[tgt.0]
164 }
165} 161}
166 162
167fn find_cargo_toml(path: &Path) -> Result<PathBuf> { 163fn find_cargo_toml(path: &Path) -> Result<PathBuf> {