aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_cli/src/load_cargo.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-02-17 16:33:37 +0000
committerGitHub <[email protected]>2020-02-17 16:33:37 +0000
commit0abb7c27acfe3d8491736e09f5e48c6f755c772a (patch)
treebbbf059cd41cb48859710155c30d5dac4a657440 /crates/ra_cli/src/load_cargo.rs
parentf7b0135c64da13d64fb0add0c96e84289beb07b4 (diff)
parentd7be1da8df45027ce18b8af9da68ed98b9a454cc (diff)
Merge #3196
3196: Cleanup imports r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_cli/src/load_cargo.rs')
-rw-r--r--crates/ra_cli/src/load_cargo.rs153
1 files changed, 153 insertions, 0 deletions
diff --git a/crates/ra_cli/src/load_cargo.rs b/crates/ra_cli/src/load_cargo.rs
new file mode 100644
index 000000000..2d6433f18
--- /dev/null
+++ b/crates/ra_cli/src/load_cargo.rs
@@ -0,0 +1,153 @@
1//! FIXME: write short doc here
2
3use std::{collections::HashSet, error::Error, path::Path};
4
5use rustc_hash::FxHashMap;
6
7use crossbeam_channel::{unbounded, Receiver};
8use ra_db::{CrateGraph, FileId, SourceRootId};
9use ra_ide::{AnalysisChange, AnalysisHost, FeatureFlags};
10use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace};
11use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch};
12use ra_vfs_glob::RustPackageFilterBuilder;
13
14type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
15
16fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId {
17 FileId(f.0)
18}
19fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
20 SourceRootId(r.0)
21}
22
23pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> {
24 let root = std::env::current_dir()?.join(root);
25 let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?;
26 let project_roots = ws.to_roots();
27 let (sender, receiver) = unbounded();
28 let sender = Box::new(move |t| sender.send(t).unwrap());
29 let (mut vfs, roots) = Vfs::new(
30 project_roots
31 .iter()
32 .map(|pkg_root| {
33 RootEntry::new(
34 pkg_root.path().clone(),
35 RustPackageFilterBuilder::default()
36 .set_member(pkg_root.is_member())
37 .into_vfs_filter(),
38 )
39 })
40 .collect(),
41 sender,
42 Watch(false),
43 );
44
45 // FIXME: cfg options?
46 let default_cfg_options = {
47 let mut opts = get_rustc_cfg_options();
48 opts.insert_atom("test".into());
49 opts.insert_atom("debug_assertion".into());
50 opts
51 };
52
53 let (crate_graph, _crate_names) =
54 ws.to_crate_graph(&default_cfg_options, &mut |path: &Path| {
55 let vfs_file = vfs.load(path);
56 log::debug!("vfs file {:?} -> {:?}", path, vfs_file);
57 vfs_file.map(vfs_file_to_id)
58 });
59 log::debug!("crate graph: {:?}", crate_graph);
60
61 let source_roots = roots
62 .iter()
63 .map(|&vfs_root| {
64 let source_root_id = vfs_root_to_id(vfs_root);
65 let project_root = project_roots
66 .iter()
67 .find(|it| it.path() == &vfs.root2path(vfs_root))
68 .unwrap()
69 .clone();
70 (source_root_id, project_root)
71 })
72 .collect::<FxHashMap<_, _>>();
73 let host = load(&source_roots, crate_graph, &mut vfs, receiver);
74 Ok((host, source_roots))
75}
76
77pub fn load(
78 source_roots: &FxHashMap<SourceRootId, PackageRoot>,
79 crate_graph: CrateGraph,
80 vfs: &mut Vfs,
81 receiver: Receiver<VfsTask>,
82) -> AnalysisHost {
83 let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
84 let mut host = AnalysisHost::new(lru_cap, FeatureFlags::default());
85 let mut analysis_change = AnalysisChange::new();
86 analysis_change.set_crate_graph(crate_graph);
87
88 // wait until Vfs has loaded all roots
89 let mut roots_loaded = HashSet::new();
90 for task in receiver {
91 vfs.handle_task(task);
92 let mut done = false;
93 for change in vfs.commit_changes() {
94 match change {
95 VfsChange::AddRoot { root, files } => {
96 let source_root_id = vfs_root_to_id(root);
97 let is_local = source_roots[&source_root_id].is_member();
98 log::debug!(
99 "loaded source root {:?} with path {:?}",
100 source_root_id,
101 vfs.root2path(root)
102 );
103 analysis_change.add_root(source_root_id, is_local);
104 analysis_change.set_debug_root_path(
105 source_root_id,
106 source_roots[&source_root_id].path().display().to_string(),
107 );
108
109 let mut file_map = FxHashMap::default();
110 for (vfs_file, path, text) in files {
111 let file_id = vfs_file_to_id(vfs_file);
112 analysis_change.add_file(source_root_id, file_id, path.clone(), text);
113 file_map.insert(path, file_id);
114 }
115 roots_loaded.insert(source_root_id);
116 if roots_loaded.len() == vfs.n_roots() {
117 done = true;
118 }
119 }
120 VfsChange::AddFile { root, file, path, text } => {
121 let source_root_id = vfs_root_to_id(root);
122 let file_id = vfs_file_to_id(file);
123 analysis_change.add_file(source_root_id, file_id, path, text);
124 }
125 VfsChange::RemoveFile { .. } | VfsChange::ChangeFile { .. } => {
126 // We just need the first scan, so just ignore these
127 }
128 }
129 }
130 if done {
131 break;
132 }
133 }
134
135 host.apply_change(analysis_change);
136 host
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 use hir::Crate;
144
145 #[test]
146 fn test_loading_rust_analyzer() {
147 let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
148 let (host, _roots) = load_cargo(path).unwrap();
149 let n_crates = Crate::all(host.raw_database()).len();
150 // RA has quite a few crates, but the exact count doesn't matter
151 assert!(n_crates > 20);
152 }
153}