racer_cargo_metadata/
mapping.rs

1use crate::metadata::{Metadata, Package, PackageId, Resolve, ResolveNode, Target};
2use racer_interner::InternedString;
3use std::collections::HashMap;
4use std::path::{Path, PathBuf};
5
6/// Cached dependencies for racer
7#[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}