aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs105
-rw-r--r--crates/ra_project_model/src/lib.rs50
-rw-r--r--crates/ra_project_model/src/sysroot.rs32
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs6
4 files changed, 84 insertions, 109 deletions
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 10ecfa951..43dbd096a 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -1,6 +1,9 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::path::{Path, PathBuf}; 3use std::{
4 ops,
5 path::{Path, PathBuf},
6};
4 7
5use anyhow::{Context, Result}; 8use anyhow::{Context, Result};
6use cargo_metadata::{CargoOpt, Message, MetadataCommand, PackageId}; 9use cargo_metadata::{CargoOpt, Message, MetadataCommand, PackageId};
@@ -24,6 +27,20 @@ pub struct CargoWorkspace {
24 workspace_root: PathBuf, 27 workspace_root: PathBuf,
25} 28}
26 29
30impl ops::Index<Package> for CargoWorkspace {
31 type Output = PackageData;
32 fn index(&self, index: Package) -> &PackageData {
33 &self.packages[index]
34 }
35}
36
37impl ops::Index<Target> for CargoWorkspace {
38 type Output = TargetData;
39 fn index(&self, index: Target) -> &TargetData {
40 &self.targets[index]
41 }
42}
43
27#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] 44#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
28#[serde(rename_all = "camelCase", default)] 45#[serde(rename_all = "camelCase", default)]
29pub struct CargoFeatures { 46pub struct CargoFeatures {
@@ -61,15 +78,15 @@ pub struct Target(RawId);
61impl_arena_id!(Target); 78impl_arena_id!(Target);
62 79
63#[derive(Debug, Clone)] 80#[derive(Debug, Clone)]
64struct PackageData { 81pub struct PackageData {
65 name: String, 82 pub name: String,
66 manifest: PathBuf, 83 pub manifest: PathBuf,
67 targets: Vec<Target>, 84 pub targets: Vec<Target>,
68 is_member: bool, 85 pub is_member: bool,
69 dependencies: Vec<PackageDependency>, 86 pub dependencies: Vec<PackageDependency>,
70 edition: Edition, 87 pub edition: Edition,
71 features: Vec<String>, 88 pub features: Vec<String>,
72 out_dir: Option<PathBuf>, 89 pub out_dir: Option<PathBuf>,
73} 90}
74 91
75#[derive(Debug, Clone)] 92#[derive(Debug, Clone)]
@@ -79,12 +96,12 @@ pub struct PackageDependency {
79} 96}
80 97
81#[derive(Debug, Clone)] 98#[derive(Debug, Clone)]
82struct TargetData { 99pub struct TargetData {
83 pkg: Package, 100 pub package: Package,
84 name: String, 101 pub name: String,
85 root: PathBuf, 102 pub root: PathBuf,
86 kind: TargetKind, 103 pub kind: TargetKind,
87 is_proc_macro: bool, 104 pub is_proc_macro: bool,
88} 105}
89 106
90#[derive(Debug, Clone, Copy, PartialEq, Eq)] 107#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -115,52 +132,9 @@ impl TargetKind {
115 } 132 }
116} 133}
117 134
118impl Package { 135impl PackageData {
119 pub fn name(self, ws: &CargoWorkspace) -> &str { 136 pub fn root(&self) -> &Path {
120 ws.packages[self].name.as_str() 137 self.manifest.parent().unwrap()
121 }
122 pub fn root(self, ws: &CargoWorkspace) -> &Path {
123 ws.packages[self].manifest.parent().unwrap()
124 }
125 pub fn edition(self, ws: &CargoWorkspace) -> Edition {
126 ws.packages[self].edition
127 }
128 pub fn features(self, ws: &CargoWorkspace) -> &[String] {
129 &ws.packages[self].features
130 }
131 pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Target> + 'a {
132 ws.packages[self].targets.iter().cloned()
133 }
134 #[allow(unused)]
135 pub fn is_member(self, ws: &CargoWorkspace) -> bool {
136 ws.packages[self].is_member
137 }
138 pub fn dependencies<'a>(
139 self,
140 ws: &'a CargoWorkspace,
141 ) -> impl Iterator<Item = &'a PackageDependency> + 'a {
142 ws.packages[self].dependencies.iter()
143 }
144 pub fn out_dir(self, ws: &CargoWorkspace) -> Option<&Path> {
145 ws.packages[self].out_dir.as_ref().map(PathBuf::as_path)
146 }
147}
148
149impl Target {
150 pub fn package(self, ws: &CargoWorkspace) -> Package {
151 ws.targets[self].pkg
152 }
153 pub fn name(self, ws: &CargoWorkspace) -> &str {
154 ws.targets[self].name.as_str()
155 }
156 pub fn root(self, ws: &CargoWorkspace) -> &Path {
157 ws.targets[self].root.as_path()
158 }
159 pub fn kind(self, ws: &CargoWorkspace) -> TargetKind {
160 ws.targets[self].kind
161 }
162 pub fn is_proc_macro(self, ws: &CargoWorkspace) -> bool {
163 ws.targets[self].is_proc_macro
164 } 138 }
165} 139}
166 140
@@ -219,7 +193,7 @@ impl CargoWorkspace {
219 for meta_tgt in meta_pkg.targets { 193 for meta_tgt in meta_pkg.targets {
220 let is_proc_macro = meta_tgt.kind.as_slice() == ["proc-macro"]; 194 let is_proc_macro = meta_tgt.kind.as_slice() == ["proc-macro"];
221 let tgt = targets.alloc(TargetData { 195 let tgt = targets.alloc(TargetData {
222 pkg, 196 package: pkg,
223 name: meta_tgt.name, 197 name: meta_tgt.name,
224 root: meta_tgt.src_path.clone(), 198 root: meta_tgt.src_path.clone(),
225 kind: TargetKind::new(meta_tgt.kind.as_slice()), 199 kind: TargetKind::new(meta_tgt.kind.as_slice()),
@@ -265,7 +239,10 @@ impl CargoWorkspace {
265 } 239 }
266 240
267 pub fn target_by_root(&self, root: &Path) -> Option<Target> { 241 pub fn target_by_root(&self, root: &Path) -> Option<Target> {
268 self.packages().filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root)).next() 242 self.packages()
243 .filter_map(|pkg| self[pkg].targets.iter().find(|&&it| self[it].root == root))
244 .next()
245 .copied()
269 } 246 }
270 247
271 pub fn workspace_root(&self) -> &Path { 248 pub fn workspace_root(&self) -> &Path {
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 081b1fec2..b500a74fb 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -138,12 +138,12 @@ impl ProjectWorkspace {
138 ProjectWorkspace::Cargo { cargo, sysroot } => { 138 ProjectWorkspace::Cargo { cargo, sysroot } => {
139 let mut roots = Vec::with_capacity(cargo.packages().len() + sysroot.crates().len()); 139 let mut roots = Vec::with_capacity(cargo.packages().len() + sysroot.crates().len());
140 for pkg in cargo.packages() { 140 for pkg in cargo.packages() {
141 let root = pkg.root(&cargo).to_path_buf(); 141 let root = cargo[pkg].root().to_path_buf();
142 let member = pkg.is_member(&cargo); 142 let member = cargo[pkg].is_member;
143 roots.push(PackageRoot::new(root, member)); 143 roots.push(PackageRoot::new(root, member));
144 } 144 }
145 for krate in sysroot.crates() { 145 for krate in sysroot.crates() {
146 roots.push(PackageRoot::new(krate.root_dir(&sysroot).to_path_buf(), false)) 146 roots.push(PackageRoot::new(sysroot[krate].root_dir().to_path_buf(), false))
147 } 147 }
148 roots 148 roots
149 } 149 }
@@ -164,7 +164,7 @@ impl ProjectWorkspace {
164 ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { 164 ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => {
165 let mut out_dirs = Vec::with_capacity(cargo.packages().len()); 165 let mut out_dirs = Vec::with_capacity(cargo.packages().len());
166 for pkg in cargo.packages() { 166 for pkg in cargo.packages() {
167 if let Some(out_dir) = pkg.out_dir(&cargo) { 167 if let Some(out_dir) = &cargo[pkg].out_dir {
168 out_dirs.push(out_dir.to_path_buf()); 168 out_dirs.push(out_dir.to_path_buf());
169 } 169 }
170 } 170 }
@@ -260,7 +260,7 @@ impl ProjectWorkspace {
260 ProjectWorkspace::Cargo { cargo, sysroot } => { 260 ProjectWorkspace::Cargo { cargo, sysroot } => {
261 let mut sysroot_crates = FxHashMap::default(); 261 let mut sysroot_crates = FxHashMap::default();
262 for krate in sysroot.crates() { 262 for krate in sysroot.crates() {
263 if let Some(file_id) = load(krate.root(&sysroot)) { 263 if let Some(file_id) = load(&sysroot[krate].root) {
264 // Crates from sysroot have `cfg(test)` disabled 264 // Crates from sysroot have `cfg(test)` disabled
265 let cfg_options = { 265 let cfg_options = {
266 let mut opts = default_cfg_options.clone(); 266 let mut opts = default_cfg_options.clone();
@@ -274,7 +274,7 @@ impl ProjectWorkspace {
274 file_id, 274 file_id,
275 Edition::Edition2018, 275 Edition::Edition2018,
276 Some( 276 Some(
277 CrateName::new(krate.name(&sysroot)) 277 CrateName::new(&sysroot[krate].name)
278 .expect("Sysroot crate names should not contain dashes"), 278 .expect("Sysroot crate names should not contain dashes"),
279 ), 279 ),
280 cfg_options, 280 cfg_options,
@@ -285,8 +285,8 @@ impl ProjectWorkspace {
285 } 285 }
286 } 286 }
287 for from in sysroot.crates() { 287 for from in sysroot.crates() {
288 for to in from.deps(&sysroot) { 288 for &to in sysroot[from].deps.iter() {
289 let name = to.name(&sysroot); 289 let name = &sysroot[to].name;
290 if let (Some(&from), Some(&to)) = 290 if let (Some(&from), Some(&to)) =
291 (sysroot_crates.get(&from), sysroot_crates.get(&to)) 291 (sysroot_crates.get(&from), sysroot_crates.get(&to))
292 { 292 {
@@ -309,18 +309,18 @@ impl ProjectWorkspace {
309 // Next, create crates for each package, target pair 309 // Next, create crates for each package, target pair
310 for pkg in cargo.packages() { 310 for pkg in cargo.packages() {
311 let mut lib_tgt = None; 311 let mut lib_tgt = None;
312 for tgt in pkg.targets(&cargo) { 312 for &tgt in cargo[pkg].targets.iter() {
313 let root = tgt.root(&cargo); 313 let root = cargo[tgt].root.as_path();
314 if let Some(file_id) = load(root) { 314 if let Some(file_id) = load(root) {
315 let edition = pkg.edition(&cargo); 315 let edition = cargo[pkg].edition;
316 let cfg_options = { 316 let cfg_options = {
317 let mut opts = default_cfg_options.clone(); 317 let mut opts = default_cfg_options.clone();
318 opts.insert_features(pkg.features(&cargo).iter().map(Into::into)); 318 opts.insert_features(cargo[pkg].features.iter().map(Into::into));
319 opts 319 opts
320 }; 320 };
321 let mut env = Env::default(); 321 let mut env = Env::default();
322 let mut extern_source = ExternSource::default(); 322 let mut extern_source = ExternSource::default();
323 if let Some(out_dir) = pkg.out_dir(cargo) { 323 if let Some(out_dir) = &cargo[pkg].out_dir {
324 // FIXME: We probably mangle non UTF-8 paths here, figure out a better solution 324 // FIXME: We probably mangle non UTF-8 paths here, figure out a better solution
325 env.set("OUT_DIR", out_dir.to_string_lossy().to_string()); 325 env.set("OUT_DIR", out_dir.to_string_lossy().to_string());
326 if let Some(&extern_source_id) = extern_source_roots.get(out_dir) { 326 if let Some(&extern_source_id) = extern_source_roots.get(out_dir) {
@@ -330,16 +330,16 @@ impl ProjectWorkspace {
330 let crate_id = crate_graph.add_crate_root( 330 let crate_id = crate_graph.add_crate_root(
331 file_id, 331 file_id,
332 edition, 332 edition,
333 Some(CrateName::normalize_dashes(pkg.name(&cargo))), 333 Some(CrateName::normalize_dashes(&cargo[pkg].name)),
334 cfg_options, 334 cfg_options,
335 env, 335 env,
336 extern_source, 336 extern_source,
337 ); 337 );
338 if tgt.kind(&cargo) == TargetKind::Lib { 338 if cargo[tgt].kind == TargetKind::Lib {
339 lib_tgt = Some(crate_id); 339 lib_tgt = Some(crate_id);
340 pkg_to_lib_crate.insert(pkg, crate_id); 340 pkg_to_lib_crate.insert(pkg, crate_id);
341 } 341 }
342 if tgt.is_proc_macro(&cargo) { 342 if cargo[tgt].is_proc_macro {
343 if let Some(proc_macro) = libproc_macro { 343 if let Some(proc_macro) = libproc_macro {
344 if crate_graph 344 if crate_graph
345 .add_dep( 345 .add_dep(
@@ -351,7 +351,7 @@ impl ProjectWorkspace {
351 { 351 {
352 log::error!( 352 log::error!(
353 "cyclic dependency on proc_macro for {}", 353 "cyclic dependency on proc_macro for {}",
354 pkg.name(&cargo) 354 &cargo[pkg].name
355 ) 355 )
356 } 356 }
357 } 357 }
@@ -371,7 +371,7 @@ impl ProjectWorkspace {
371 // For root projects with dashes in their name, 371 // For root projects with dashes in their name,
372 // cargo metadata does not do any normalization, 372 // cargo metadata does not do any normalization,
373 // so we do it ourselves currently 373 // so we do it ourselves currently
374 CrateName::normalize_dashes(pkg.name(&cargo)), 374 CrateName::normalize_dashes(&cargo[pkg].name),
375 to, 375 to,
376 ) 376 )
377 .is_err() 377 .is_err()
@@ -379,7 +379,7 @@ impl ProjectWorkspace {
379 { 379 {
380 log::error!( 380 log::error!(
381 "cyclic dependency between targets of {}", 381 "cyclic dependency between targets of {}",
382 pkg.name(&cargo) 382 &cargo[pkg].name
383 ) 383 )
384 } 384 }
385 } 385 }
@@ -391,7 +391,7 @@ impl ProjectWorkspace {
391 .add_dep(from, CrateName::new("core").unwrap(), core) 391 .add_dep(from, CrateName::new("core").unwrap(), core)
392 .is_err() 392 .is_err()
393 { 393 {
394 log::error!("cyclic dependency on core for {}", pkg.name(&cargo)) 394 log::error!("cyclic dependency on core for {}", &cargo[pkg].name)
395 } 395 }
396 } 396 }
397 if let Some(alloc) = liballoc { 397 if let Some(alloc) = liballoc {
@@ -399,7 +399,7 @@ impl ProjectWorkspace {
399 .add_dep(from, CrateName::new("alloc").unwrap(), alloc) 399 .add_dep(from, CrateName::new("alloc").unwrap(), alloc)
400 .is_err() 400 .is_err()
401 { 401 {
402 log::error!("cyclic dependency on alloc for {}", pkg.name(&cargo)) 402 log::error!("cyclic dependency on alloc for {}", &cargo[pkg].name)
403 } 403 }
404 } 404 }
405 if let Some(std) = libstd { 405 if let Some(std) = libstd {
@@ -407,7 +407,7 @@ impl ProjectWorkspace {
407 .add_dep(from, CrateName::new("std").unwrap(), std) 407 .add_dep(from, CrateName::new("std").unwrap(), std)
408 .is_err() 408 .is_err()
409 { 409 {
410 log::error!("cyclic dependency on std for {}", pkg.name(&cargo)) 410 log::error!("cyclic dependency on std for {}", &cargo[pkg].name)
411 } 411 }
412 } 412 }
413 } 413 }
@@ -416,7 +416,7 @@ impl ProjectWorkspace {
416 // Now add a dep edge from all targets of upstream to the lib 416 // Now add a dep edge from all targets of upstream to the lib
417 // target of downstream. 417 // target of downstream.
418 for pkg in cargo.packages() { 418 for pkg in cargo.packages() {
419 for dep in pkg.dependencies(&cargo) { 419 for dep in cargo[pkg].dependencies.iter() {
420 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { 420 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
421 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 421 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
422 if crate_graph 422 if crate_graph
@@ -425,8 +425,8 @@ impl ProjectWorkspace {
425 { 425 {
426 log::error!( 426 log::error!(
427 "cyclic dependency {} -> {}", 427 "cyclic dependency {} -> {}",
428 pkg.name(&cargo), 428 &cargo[pkg].name,
429 dep.pkg.name(&cargo) 429 &cargo[dep.pkg].name
430 ) 430 )
431 } 431 }
432 } 432 }
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs
index c51957c1f..4ac4fa14d 100644
--- a/crates/ra_project_model/src/sysroot.rs
+++ b/crates/ra_project_model/src/sysroot.rs
@@ -2,7 +2,7 @@
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{bail, Context, Result};
4use std::{ 4use std::{
5 env, 5 env, ops,
6 path::{Path, PathBuf}, 6 path::{Path, PathBuf},
7 process::{Command, Output}, 7 process::{Command, Output},
8}; 8};
@@ -19,10 +19,17 @@ pub struct SysrootCrate(RawId);
19impl_arena_id!(SysrootCrate); 19impl_arena_id!(SysrootCrate);
20 20
21#[derive(Debug, Clone)] 21#[derive(Debug, Clone)]
22struct SysrootCrateData { 22pub struct SysrootCrateData {
23 name: String, 23 pub name: String,
24 root: PathBuf, 24 pub root: PathBuf,
25 deps: Vec<SysrootCrate>, 25 pub deps: Vec<SysrootCrate>,
26}
27
28impl ops::Index<SysrootCrate> for Sysroot {
29 type Output = SysrootCrateData;
30 fn index(&self, index: SysrootCrate) -> &SysrootCrateData {
31 &self.crates[index]
32 }
26} 33}
27 34
28impl Sysroot { 35impl Sysroot {
@@ -129,18 +136,9 @@ fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
129 Ok(src_path) 136 Ok(src_path)
130} 137}
131 138
132impl SysrootCrate { 139impl SysrootCrateData {
133 pub fn name(self, sysroot: &Sysroot) -> &str { 140 pub fn root_dir(&self) -> &Path {
134 &sysroot.crates[self].name 141 self.root.parent().unwrap()
135 }
136 pub fn root(self, sysroot: &Sysroot) -> &Path {
137 sysroot.crates[self].root.as_path()
138 }
139 pub fn root_dir(self, sysroot: &Sysroot) -> &Path {
140 self.root(sysroot).parent().unwrap()
141 }
142 pub fn deps<'a>(self, sysroot: &'a Sysroot) -> impl Iterator<Item = SysrootCrate> + 'a {
143 sysroot.crates[self].deps.iter().copied()
144 } 142 }
145} 143}
146 144
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 321861b16..f87bdcec5 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -77,9 +77,9 @@ impl CargoTargetSpec {
77 ProjectWorkspace::Cargo { cargo, .. } => { 77 ProjectWorkspace::Cargo { cargo, .. } => {
78 let tgt = cargo.target_by_root(&path)?; 78 let tgt = cargo.target_by_root(&path)?;
79 Some(CargoTargetSpec { 79 Some(CargoTargetSpec {
80 package: tgt.package(&cargo).name(&cargo).to_string(), 80 package: cargo[cargo[tgt].package].name.clone(),
81 target: tgt.name(&cargo).to_string(), 81 target: cargo[tgt].name.clone(),
82 target_kind: tgt.kind(&cargo), 82 target_kind: cargo[tgt].kind,
83 }) 83 })
84 } 84 }
85 ProjectWorkspace::Json { .. } => None, 85 ProjectWorkspace::Json { .. } => None,