aboutsummaryrefslogtreecommitdiff
path: root/crates/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/server/src')
-rw-r--r--crates/server/src/main_loop/handlers.rs6
-rw-r--r--crates/server/src/main_loop/mod.rs62
-rw-r--r--crates/server/src/project_model.rs29
-rw-r--r--crates/server/src/server_world.rs13
-rw-r--r--crates/server/src/vfs.rs76
5 files changed, 115 insertions, 71 deletions
diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs
index 898195f6d..323d4e95e 100644
--- a/crates/server/src/main_loop/handlers.rs
+++ b/crates/server/src/main_loop/handlers.rs
@@ -141,14 +141,18 @@ pub fn handle_workspace_symbol(
141 token: JobToken, 141 token: JobToken,
142) -> Result<Option<Vec<SymbolInformation>>> { 142) -> Result<Option<Vec<SymbolInformation>>> {
143 let all_symbols = params.query.contains("#"); 143 let all_symbols = params.query.contains("#");
144 let libs = params.query.contains("*");
144 let query = { 145 let query = {
145 let query: String = params.query.chars() 146 let query: String = params.query.chars()
146 .filter(|&c| c != '#') 147 .filter(|&c| c != '#' && c != '*')
147 .collect(); 148 .collect();
148 let mut q = Query::new(query); 149 let mut q = Query::new(query);
149 if !all_symbols { 150 if !all_symbols {
150 q.only_types(); 151 q.only_types();
151 } 152 }
153 if libs {
154 q.libs();
155 }
152 q.limit(128); 156 q.limit(128);
153 q 157 q
154 }; 158 };
diff --git a/crates/server/src/main_loop/mod.rs b/crates/server/src/main_loop/mod.rs
index bb1d638e0..ce61265a2 100644
--- a/crates/server/src/main_loop/mod.rs
+++ b/crates/server/src/main_loop/mod.rs
@@ -38,9 +38,8 @@ pub fn main_loop(
38) -> Result<()> { 38) -> Result<()> {
39 let pool = ThreadPool::new(4); 39 let pool = ThreadPool::new(4);
40 let (task_sender, task_receiver) = bounded::<Task>(16); 40 let (task_sender, task_receiver) = bounded::<Task>(16);
41 let (fs_events_receiver, watcher) = vfs::watch(vec![root.clone()]); 41 let (fs_sender, fs_receiver, fs_watcher) = vfs::roots_loader();
42 let (ws_root_sender, ws_receiver, ws_watcher) = workspace_loader(); 42 let (ws_sender, ws_receiver, ws_watcher) = workspace_loader();
43 ws_root_sender.send(root);
44 43
45 info!("server initialized, serving requests"); 44 info!("server initialized, serving requests");
46 let mut state = ServerWorldState::new(); 45 let mut state = ServerWorldState::new();
@@ -48,13 +47,15 @@ pub fn main_loop(
48 let mut pending_requests = HashMap::new(); 47 let mut pending_requests = HashMap::new();
49 let mut subs = Subscriptions::new(); 48 let mut subs = Subscriptions::new();
50 let main_res = main_loop_inner( 49 let main_res = main_loop_inner(
50 root,
51 &pool, 51 &pool,
52 msg_receriver,
53 msg_sender, 52 msg_sender,
54 task_receiver.clone(), 53 msg_receriver,
55 task_sender, 54 task_sender,
56 fs_events_receiver, 55 task_receiver.clone(),
57 ws_root_sender, 56 fs_sender,
57 fs_receiver,
58 ws_sender,
58 ws_receiver, 59 ws_receiver,
59 &mut state, 60 &mut state,
60 &mut pending_requests, 61 &mut pending_requests,
@@ -68,38 +69,40 @@ pub fn main_loop(
68 pool.join(); 69 pool.join();
69 info!("...threadpool has finished"); 70 info!("...threadpool has finished");
70 71
71 let vfs_res = watcher.stop(); 72 let fs_res = fs_watcher.stop();
72 let ws_res = ws_watcher.stop(); 73 let ws_res = ws_watcher.stop();
73 74
74 main_res?; 75 main_res?;
75 vfs_res?; 76 fs_res?;
76 ws_res?; 77 ws_res?;
77 78
78 Ok(()) 79 Ok(())
79} 80}
80 81
81fn main_loop_inner( 82fn main_loop_inner(
83 ws_root: PathBuf,
82 pool: &ThreadPool, 84 pool: &ThreadPool,
83 msg_receiver: &mut Receiver<RawMessage>,
84 msg_sender: &mut Sender<RawMessage>, 85 msg_sender: &mut Sender<RawMessage>,
85 task_receiver: Receiver<Task>, 86 msg_receiver: &mut Receiver<RawMessage>,
86 task_sender: Sender<Task>, 87 task_sender: Sender<Task>,
87 fs_receiver: Receiver<Vec<FileEvent>>, 88 task_receiver: Receiver<Task>,
88 _ws_roots_sender: Sender<PathBuf>, 89 fs_sender: Sender<PathBuf>,
90 fs_receiver: Receiver<(PathBuf, Vec<FileEvent>)>,
91 ws_sender: Sender<PathBuf>,
89 ws_receiver: Receiver<Result<CargoWorkspace>>, 92 ws_receiver: Receiver<Result<CargoWorkspace>>,
90 state: &mut ServerWorldState, 93 state: &mut ServerWorldState,
91 pending_requests: &mut HashMap<u64, JobHandle>, 94 pending_requests: &mut HashMap<u64, JobHandle>,
92 subs: &mut Subscriptions, 95 subs: &mut Subscriptions,
93) -> Result<()> { 96) -> Result<()> {
94 let mut fs_receiver = Some(fs_receiver); 97 ws_sender.send(ws_root.clone());
98 fs_sender.send(ws_root.clone());
95 loop { 99 loop {
96 #[derive(Debug)] 100 #[derive(Debug)]
97 enum Event { 101 enum Event {
98 Msg(RawMessage), 102 Msg(RawMessage),
99 Task(Task), 103 Task(Task),
100 Fs(Vec<FileEvent>), 104 Fs(PathBuf, Vec<FileEvent>),
101 Ws(Result<CargoWorkspace>), 105 Ws(Result<CargoWorkspace>),
102 FsWatcherDead,
103 } 106 }
104 trace!("selecting"); 107 trace!("selecting");
105 let event = select! { 108 let event = select! {
@@ -109,8 +112,8 @@ fn main_loop_inner(
109 }, 112 },
110 recv(task_receiver, task) => Event::Task(task.unwrap()), 113 recv(task_receiver, task) => Event::Task(task.unwrap()),
111 recv(fs_receiver, events) => match events { 114 recv(fs_receiver, events) => match events {
112 Some(events) => Event::Fs(events), 115 None => bail!("roots watcher died"),
113 None => Event::FsWatcherDead, 116 Some((pb, events)) => Event::Fs(pb, events),
114 } 117 }
115 recv(ws_receiver, ws) => match ws { 118 recv(ws_receiver, ws) => match ws {
116 None => bail!("workspace watcher died"), 119 None => bail!("workspace watcher died"),
@@ -120,19 +123,30 @@ fn main_loop_inner(
120 trace!("selected {:?}", event); 123 trace!("selected {:?}", event);
121 let mut state_changed = false; 124 let mut state_changed = false;
122 match event { 125 match event {
123 Event::FsWatcherDead => fs_receiver = None,
124 Event::Task(task) => on_task(task, msg_sender, pending_requests), 126 Event::Task(task) => on_task(task, msg_sender, pending_requests),
125 Event::Fs(events) => { 127 Event::Fs(root, events) => {
126 trace!("fs change, {} events", events.len()); 128 info!("fs change, {}, {} events", root.display(), events.len());
127 state.apply_fs_changes(events); 129 if root == ws_root {
130 state.apply_fs_changes(events);
131 } else {
132 state.add_library(events);
133 }
128 state_changed = true; 134 state_changed = true;
129 } 135 }
130 Event::Ws(ws) => { 136 Event::Ws(ws) => {
131 match ws { 137 match ws {
132 Ok(ws) => { 138 Ok(ws) => {
133 let not = RawNotification::new::<req::DidReloadWorkspace>(&vec![ws.clone()]); 139 let workspaces = vec![ws];
140 let not = RawNotification::new::<req::DidReloadWorkspace>(&workspaces);
134 msg_sender.send(RawMessage::Notification(not)); 141 msg_sender.send(RawMessage::Notification(not));
135 state.set_workspaces(vec![ws]); 142 for ws in workspaces.iter() {
143 for pkg in ws.packages().filter(|pkg| !pkg.is_member(ws)) {
144 debug!("sending root, {}", pkg.root(ws).to_path_buf().display());
145 // deadlocky :-(
146 fs_sender.send(pkg.root(ws).to_path_buf());
147 }
148 }
149 state.set_workspaces(workspaces);
136 state_changed = true; 150 state_changed = true;
137 } 151 }
138 Err(e) => warn!("loading workspace failed: {}", e), 152 Err(e) => warn!("loading workspace failed: {}", e),
diff --git a/crates/server/src/project_model.rs b/crates/server/src/project_model.rs
index 12233f258..517836e62 100644
--- a/crates/server/src/project_model.rs
+++ b/crates/server/src/project_model.rs
@@ -1,5 +1,5 @@
1use std::{ 1use std::{
2 collections::HashMap, 2 collections::{HashMap, HashSet},
3 path::{Path, PathBuf}, 3 path::{Path, PathBuf},
4}; 4};
5use cargo_metadata::{metadata_run, CargoOpt}; 5use cargo_metadata::{metadata_run, CargoOpt};
@@ -13,7 +13,6 @@ use {
13 13
14#[derive(Debug, Serialize, Clone)] 14#[derive(Debug, Serialize, Clone)]
15pub struct CargoWorkspace { 15pub struct CargoWorkspace {
16 ws_members: Vec<Package>,
17 packages: Vec<PackageData>, 16 packages: Vec<PackageData>,
18 targets: Vec<TargetData>, 17 targets: Vec<TargetData>,
19} 18}
@@ -27,7 +26,8 @@ pub struct Target(usize);
27struct PackageData { 26struct PackageData {
28 name: SmolStr, 27 name: SmolStr,
29 manifest: PathBuf, 28 manifest: PathBuf,
30 targets: Vec<Target> 29 targets: Vec<Target>,
30 is_member: bool,
31} 31}
32 32
33#[derive(Debug, Serialize, Clone)] 33#[derive(Debug, Serialize, Clone)]
@@ -50,9 +50,15 @@ impl Package {
50 pub fn manifest(self, ws: &CargoWorkspace) -> &Path { 50 pub fn manifest(self, ws: &CargoWorkspace) -> &Path {
51 ws.pkg(self).manifest.as_path() 51 ws.pkg(self).manifest.as_path()
52 } 52 }
53 pub fn root(self, ws: &CargoWorkspace) -> &Path {
54 ws.pkg(self).manifest.parent().unwrap()
55 }
53 pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item=Target> + 'a { 56 pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item=Target> + 'a {
54 ws.pkg(self).targets.iter().cloned() 57 ws.pkg(self).targets.iter().cloned()
55 } 58 }
59 pub fn is_member(self, ws: &CargoWorkspace) -> bool {
60 ws.pkg(self).is_member
61 }
56} 62}
57 63
58impl Target { 64impl Target {
@@ -81,13 +87,21 @@ impl CargoWorkspace {
81 let mut pkg_by_id = HashMap::new(); 87 let mut pkg_by_id = HashMap::new();
82 let mut packages = Vec::new(); 88 let mut packages = Vec::new();
83 let mut targets = Vec::new(); 89 let mut targets = Vec::new();
90
91 let ws_members: HashSet<String> = meta.workspace_members
92 .into_iter()
93 .map(|it| it.raw)
94 .collect();
95
84 for meta_pkg in meta.packages { 96 for meta_pkg in meta.packages {
85 let pkg = Package(packages.len()); 97 let pkg = Package(packages.len());
98 let is_member = ws_members.contains(&meta_pkg.id);
86 pkg_by_id.insert(meta_pkg.id.clone(), pkg); 99 pkg_by_id.insert(meta_pkg.id.clone(), pkg);
87 let mut pkg_data = PackageData { 100 let mut pkg_data = PackageData {
88 name: meta_pkg.name.into(), 101 name: meta_pkg.name.into(),
89 manifest: PathBuf::from(meta_pkg.manifest_path), 102 manifest: PathBuf::from(meta_pkg.manifest_path),
90 targets: Vec::new(), 103 targets: Vec::new(),
104 is_member,
91 }; 105 };
92 for meta_tgt in meta_pkg.targets { 106 for meta_tgt in meta_pkg.targets {
93 let tgt = Target(targets.len()); 107 let tgt = Target(targets.len());
@@ -101,19 +115,12 @@ impl CargoWorkspace {
101 } 115 }
102 packages.push(pkg_data) 116 packages.push(pkg_data)
103 } 117 }
104 let ws_members = meta.workspace_members
105 .iter()
106 .map(|it| pkg_by_id[&it.raw])
107 .collect();
108 118
109 Ok(CargoWorkspace { packages, targets, ws_members }) 119 Ok(CargoWorkspace { packages, targets })
110 } 120 }
111 pub fn packages<'a>(&'a self) -> impl Iterator<Item=Package> + 'a { 121 pub fn packages<'a>(&'a self) -> impl Iterator<Item=Package> + 'a {
112 (0..self.packages.len()).map(Package) 122 (0..self.packages.len()).map(Package)
113 } 123 }
114 pub fn ws_members<'a>(&'a self) -> impl Iterator<Item=Package> + 'a {
115 self.ws_members.iter().cloned()
116 }
117 pub fn target_by_root(&self, root: &Path) -> Option<Target> { 124 pub fn target_by_root(&self, root: &Path) -> Option<Target> {
118 self.packages() 125 self.packages()
119 .filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root)) 126 .filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root))
diff --git a/crates/server/src/server_world.rs b/crates/server/src/server_world.rs
index f78b56cf8..95c109e10 100644
--- a/crates/server/src/server_world.rs
+++ b/crates/server/src/server_world.rs
@@ -47,7 +47,6 @@ impl ServerWorldState {
47 .map(|event| { 47 .map(|event| {
48 let text = match event.kind { 48 let text = match event.kind {
49 FileEventKind::Add(text) => Some(text), 49 FileEventKind::Add(text) => Some(text),
50 FileEventKind::Remove => None,
51 }; 50 };
52 (event.path, text) 51 (event.path, text)
53 }) 52 })
@@ -65,6 +64,18 @@ impl ServerWorldState {
65 64
66 self.analysis_host.change_files(changes); 65 self.analysis_host.change_files(changes);
67 } 66 }
67 pub fn add_library(&mut self, events: Vec<FileEvent>) {
68 let pm = &mut self.path_map;
69 let files = events.into_iter()
70 .map(|event| {
71 let text = match event.kind {
72 FileEventKind::Add(text) => text,
73 };
74 (event.path, text)
75 })
76 .map(|(path, text)| (pm.get_or_insert(path), text));
77 self.analysis_host.add_library(files);
78 }
68 79
69 pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId { 80 pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId {
70 let file_id = self.path_map.get_or_insert(path); 81 let file_id = self.path_map.get_or_insert(path);
diff --git a/crates/server/src/vfs.rs b/crates/server/src/vfs.rs
index 2acc3f55f..69a7654af 100644
--- a/crates/server/src/vfs.rs
+++ b/crates/server/src/vfs.rs
@@ -1,5 +1,5 @@
1use std::{ 1use std::{
2 path::PathBuf, 2 path::{PathBuf, Path},
3 fs, 3 fs,
4}; 4};
5 5
@@ -20,46 +20,54 @@ pub struct FileEvent {
20#[derive(Debug)] 20#[derive(Debug)]
21pub enum FileEventKind { 21pub enum FileEventKind {
22 Add(String), 22 Add(String),
23 #[allow(unused)]
24 Remove,
25} 23}
26 24
27pub fn watch(roots: Vec<PathBuf>) -> (Receiver<Vec<FileEvent>>, ThreadWatcher) { 25pub fn roots_loader() -> (Sender<PathBuf>, Receiver<(PathBuf, Vec<FileEvent>)>, ThreadWatcher) {
28 let (sender, receiver) = bounded(16); 26 let (path_sender, path_receiver) = bounded::<PathBuf>(2048);
29 let watcher = ThreadWatcher::spawn("vfs", move || run(roots, sender)); 27 let (event_sender, event_receiver) = bounded::<(PathBuf, Vec<FileEvent>)>(1);
30 (receiver, watcher) 28 let thread = ThreadWatcher::spawn("roots loader", move || {
29 path_receiver
30 .into_iter()
31 .map(|path| {
32 debug!("loading {} ...", path.as_path().display());
33 let events = load_root(path.as_path());
34 debug!("... loaded {}", path.as_path().display());
35 (path, events)
36 })
37 .for_each(|it| event_sender.send(it))
38 });
39
40 (path_sender, event_receiver, thread)
31} 41}
32 42
33fn run(roots: Vec<PathBuf>, sender: Sender<Vec<FileEvent>>) { 43fn load_root(path: &Path) -> Vec<FileEvent> {
34 for root in roots { 44 let mut res = Vec::new();
35 let mut events = Vec::new(); 45 for entry in WalkDir::new(path) {
36 for entry in WalkDir::new(root.as_path()) { 46 let entry = match entry {
37 let entry = match entry { 47 Ok(entry) => entry,
38 Ok(entry) => entry, 48 Err(e) => {
39 Err(e) => { 49 warn!("watcher error: {}", e);
40 warn!("watcher error: {}", e);
41 continue;
42 }
43 };
44 if !entry.file_type().is_file() {
45 continue; 50 continue;
46 } 51 }
47 let path = entry.path(); 52 };
48 if path.extension().and_then(|os| os.to_str()) != Some("rs") { 53 if !entry.file_type().is_file() {
54 continue;
55 }
56 let path = entry.path();
57 if path.extension().and_then(|os| os.to_str()) != Some("rs") {
58 continue;
59 }
60 let text = match fs::read_to_string(path) {
61 Ok(text) => text,
62 Err(e) => {
63 warn!("watcher error: {}", e);
49 continue; 64 continue;
50 } 65 }
51 let text = match fs::read_to_string(path) { 66 };
52 Ok(text) => text, 67 res.push(FileEvent {
53 Err(e) => { 68 path: path.to_owned(),
54 warn!("watcher error: {}", e); 69 kind: FileEventKind::Add(text),
55 continue; 70 })
56 }
57 };
58 events.push(FileEvent {
59 path: path.to_owned(),
60 kind: FileEventKind::Add(text),
61 })
62 }
63 sender.send(events)
64 } 71 }
72 res
65} 73}