racer_cargo_metadata/
mapping.rs1use crate::metadata::{Metadata, Package, PackageId, Resolve, ResolveNode, Target};
2use racer_interner::InternedString;
3use std::collections::HashMap;
4use std::path::{Path, PathBuf};
5
6#[derive(Clone, Debug)]
8pub struct PackageMap {
9 manifest_to_idx: HashMap<PathBuf, PackageIdx>,
10 id_to_idx: HashMap<PackageId, PackageIdx>,
11 packages: Vec<PackageInner>,
12}
13
14#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
15pub enum Edition {
16 Ed2015,
17 Ed2018,
18 Ed2021,
19}
20
21impl Edition {
22 pub fn from_str(s: &str) -> Self {
23 match s {
24 "2015" => Edition::Ed2015,
25 "2018" => Edition::Ed2018,
26 "2021" => Edition::Ed2021,
27 _ => unreachable!("got unexpected edition {}", s),
28 }
29 }
30}
31
32#[derive(Clone, Debug)]
33struct PackageInner {
34 edition: Edition,
35 deps: Vec<(InternedString, PathBuf)>,
36 lib: Option<Target>,
37 id: PackageId,
38}
39
40impl PackageInner {
41 fn new(ed: InternedString, id: PackageId, lib: Option<Target>) -> Self {
42 PackageInner {
43 edition: Edition::from_str(ed.as_str()),
44 deps: Vec::new(),
45 id,
46 lib,
47 }
48 }
49}
50
51#[derive(Clone, Copy, Debug, Eq, PartialEq)]
52pub struct PackageIdx(usize);
53
54impl PackageMap {
55 pub fn from_metadata(meta: Metadata) -> Self {
56 let Metadata {
57 packages, resolve, ..
58 } = meta;
59 PackageMap::new(packages, resolve)
60 }
61 pub fn new(packages: Vec<Package>, resolve: Option<Resolve>) -> Self {
62 let mut manifest_to_idx = HashMap::new();
63 let mut id_to_idx = HashMap::new();
64 let mut inner = Vec::new();
65 for (i, package) in packages.into_iter().enumerate() {
66 let Package {
67 id,
68 targets,
69 manifest_path,
70 edition,
71 ..
72 } = package;
73 id_to_idx.insert(id, PackageIdx(i));
74 manifest_to_idx.insert(manifest_path, PackageIdx(i));
75 let lib = targets.into_iter().find(|t| t.is_lib()).to_owned();
76 inner.push(PackageInner::new(edition, id, lib));
77 }
78 if let Some(res) = resolve {
79 construct_deps(res.nodes, &id_to_idx, &mut inner);
80 }
81 PackageMap {
82 manifest_to_idx,
83 id_to_idx,
84 packages: inner,
85 }
86 }
87 pub fn ids<'a>(&'a self) -> impl 'a + Iterator<Item = PackageId> {
88 self.packages.iter().map(|p| p.id)
89 }
90 pub fn id_to_idx(&self, id: PackageId) -> Option<PackageIdx> {
91 self.id_to_idx.get(&id).map(|&x| x)
92 }
93 pub fn get_idx(&self, path: &Path) -> Option<PackageIdx> {
94 self.manifest_to_idx.get(path).map(|&id| id)
95 }
96 pub fn get_id(&self, idx: PackageIdx) -> PackageId {
97 self.packages[idx.0].id
98 }
99 pub fn get_edition(&self, idx: PackageIdx) -> Edition {
100 self.packages[idx.0].edition
101 }
102 pub fn get_lib(&self, idx: PackageIdx) -> Option<&Target> {
103 self.packages[idx.0].lib.as_ref()
104 }
105 pub fn get_lib_src_path(&self, idx: PackageIdx) -> Option<&Path> {
106 self.get_lib(idx).map(|t| t.src_path.as_ref())
107 }
108 pub fn get_dependencies(&self, idx: PackageIdx) -> &[(InternedString, PathBuf)] {
109 self.packages[idx.0].deps.as_ref()
110 }
111 pub fn get_src_path_from_libname(&self, id: PackageIdx, s: &str) -> Option<&Path> {
112 let deps = self.get_dependencies(id);
113 let query_str = InternedString::new_if_exists(s)?;
114 deps.iter().find(|t| t.0 == query_str).map(|t| t.1.as_ref())
115 }
116}
117
118fn construct_deps(
119 nodes: Vec<ResolveNode>,
120 id_to_idx: &HashMap<PackageId, PackageIdx>,
121 res: &mut [PackageInner],
122) -> Option<()> {
123 for node in nodes {
124 let idx = id_to_idx.get(&node.id)?;
125 let deps: Vec<_> = node
126 .dependencies
127 .into_iter()
128 .filter_map(|id| {
129 let idx = id_to_idx.get(&id)?;
130 res[idx.0]
131 .lib
132 .as_ref()
133 .map(|l| (l.name, l.src_path.clone()))
134 })
135 .collect();
136 res[idx.0].deps.extend(deps);
137 }
138 Some(())
139}