From 18486a02fae5966e61f16ea7bc5c33c6c7c69487 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 13 Aug 2018 13:46:05 +0300 Subject: indexing infra --- crates/server/src/main_loop/mod.rs | 61 ++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 9 deletions(-) (limited to 'crates/server/src/main_loop') diff --git a/crates/server/src/main_loop/mod.rs b/crates/server/src/main_loop/mod.rs index 5b7093ad7..f954e632c 100644 --- a/crates/server/src/main_loop/mod.rs +++ b/crates/server/src/main_loop/mod.rs @@ -1,6 +1,9 @@ mod handlers; -use std::collections::HashSet; +use std::{ + path::PathBuf, + collections::{HashSet, HashMap}, +}; use threadpool::ThreadPool; use crossbeam_channel::{Sender, Receiver}; @@ -13,6 +16,7 @@ use { Task, Result, io::{Io, RawMsg, RawRequest, RawNotification}, util::FilePath, + vfs::{FileEvent, FileEventKind}, main_loop::handlers::{ handle_syntax_tree, handle_extend_selection, @@ -28,24 +32,33 @@ pub(super) fn main_loop( io: &mut Io, world: &mut WorldState, pool: &mut ThreadPool, - sender: Sender, - receiver: Receiver, + task_sender: Sender, + task_receiver: Receiver, + fs_events_receiver: Receiver>, ) -> Result<()> { info!("server initialized, serving requests"); let mut next_request_id = 0; let mut pending_requests: HashSet = HashSet::new(); + let mut mem_map: HashMap> = HashMap::new(); + let mut fs_events_receiver = Some(&fs_events_receiver); loop { enum Event { Msg(RawMsg), Task(Task), + Fs(Vec), ReceiverDead, + FsWatcherDead, } let event = select! { recv(io.receiver(), msg) => match msg { Some(msg) => Event::Msg(msg), None => Event::ReceiverDead, }, - recv(receiver, task) => Event::Task(task.unwrap()), + recv(task_receiver, task) => Event::Task(task.unwrap()), + recv(fs_events_receiver, events) => match events { + Some(events) => Event::Fs(events), + None => Event::FsWatcherDead, + } }; match event { @@ -53,6 +66,9 @@ pub(super) fn main_loop( io.cleanup_receiver()?; unreachable!(); } + Event::FsWatcherDead => { + fs_events_receiver = None; + } Event::Task(task) => { match task { Task::Request(mut request) => { @@ -70,15 +86,36 @@ pub(super) fn main_loop( } continue; } + Event::Fs(events) => { + trace!("fs change, {} events", events.len()); + let changes = events.into_iter() + .map(|event| { + let text = match event.kind { + FileEventKind::Add(text) => Some(text), + FileEventKind::Remove => None, + }; + (event.path, text) + }) + .filter_map(|(path, text)| { + if mem_map.contains_key(path.as_path()) { + mem_map.insert(path, text); + None + } else { + Some((path, text)) + } + }); + + world.change_files(changes); + } Event::Msg(msg) => { match msg { RawMsg::Request(req) => { - if !on_request(io, world, pool, &sender, req)? { + if !on_request(io, world, pool, &task_sender, req)? { return Ok(()); } } RawMsg::Notification(not) => { - on_notification(io, world, pool, &sender, not)? + on_notification(io, world, pool, &task_sender, not, &mut mem_map)? } RawMsg::Response(resp) => { if !pending_requests.remove(&resp.id) { @@ -160,11 +197,13 @@ fn on_notification( pool: &ThreadPool, sender: &Sender, not: RawNotification, + mem_map: &mut HashMap>, ) -> Result<()> { let mut not = Some(not); dispatch::handle_notification::(&mut not, |params| { let path = params.text_document.file_path()?; - world.change_overlay(path, Some(params.text_document.text)); + mem_map.insert(path.clone(), None); + world.change_file(path, Some(params.text_document.text)); update_file_notifications_on_threadpool( pool, world.snapshot(), sender.clone(), params.text_document.uri, ); @@ -175,7 +214,7 @@ fn on_notification( let text = params.content_changes.pop() .ok_or_else(|| format_err!("empty changes"))? .text; - world.change_overlay(path, Some(text)); + world.change_file(path, Some(text)); update_file_notifications_on_threadpool( pool, world.snapshot(), sender.clone(), params.text_document.uri, ); @@ -183,7 +222,11 @@ fn on_notification( })?; dispatch::handle_notification::(&mut not, |params| { let path = params.text_document.file_path()?; - world.change_overlay(path, None); + let text = match mem_map.remove(&path) { + Some(text) => text, + None => bail!("unmatched close notification"), + }; + world.change_file(path, text); let not = req::PublishDiagnosticsParams { uri: params.text_document.uri, diagnostics: Vec::new(), -- cgit v1.2.3