This commit is contained in:
Aleksey Kladov 2020-06-26 00:27:39 +02:00
parent 72fb712dff
commit e70f7dc10c
4 changed files with 38 additions and 32 deletions

View file

@ -59,7 +59,7 @@ impl<'a> RequestDispatcher<'a> {
} }
}; };
self.global_state.task_pool.0.spawn({ self.global_state.task_pool.handle.spawn({
let world = self.global_state.snapshot(); let world = self.global_state.snapshot();
move || { move || {
let result = f(world, params); let result = f(world, params);

View file

@ -13,7 +13,7 @@ use ra_db::{CrateId, VfsPath};
use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FileId}; use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FileId};
use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target};
use stdx::format_to; use stdx::format_to;
use vfs::loader::Handle; use vfs::loader::Handle as _;
use crate::{ use crate::{
config::Config, config::Config,
@ -42,19 +42,26 @@ impl Default for Status {
} }
} }
// Enforces drop order
pub(crate) struct Handle<H, C> {
pub(crate) handle: H,
pub(crate) receiver: C,
}
/// `GlobalState` is the primary mutable state of the language server /// `GlobalState` is the primary mutable state of the language server
/// ///
/// The most interesting components are `vfs`, which stores a consistent /// The most interesting components are `vfs`, which stores a consistent
/// snapshot of the file systems, and `analysis_host`, which stores our /// snapshot of the file systems, and `analysis_host`, which stores our
/// incremental salsa database. /// incremental salsa database.
///
/// Note that this struct has more than on impl in various modules!
pub(crate) struct GlobalState { pub(crate) struct GlobalState {
sender: Sender<lsp_server::Message>, sender: Sender<lsp_server::Message>,
pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>,
pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
pub(crate) flycheck: Option<Handle<FlycheckHandle, Receiver<flycheck::Message>>>,
pub(crate) config: Config, pub(crate) config: Config,
pub(crate) task_pool: (TaskPool<Task>, Receiver<Task>),
pub(crate) analysis_host: AnalysisHost, pub(crate) analysis_host: AnalysisHost,
pub(crate) loader: Box<dyn vfs::loader::Handle>,
pub(crate) task_receiver: Receiver<vfs::loader::Message>,
pub(crate) flycheck: Option<(FlycheckHandle, Receiver<flycheck::Message>)>,
pub(crate) diagnostics: DiagnosticCollection, pub(crate) diagnostics: DiagnosticCollection,
pub(crate) mem_docs: FxHashSet<VfsPath>, pub(crate) mem_docs: FxHashSet<VfsPath>,
pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
@ -82,37 +89,36 @@ impl GlobalState {
lru_capacity: Option<usize>, lru_capacity: Option<usize>,
config: Config, config: Config,
) -> GlobalState { ) -> GlobalState {
let (task_sender, task_receiver) = unbounded::<vfs::loader::Message>();
let loader = { let loader = {
let loader = vfs_notify::NotifyHandle::spawn(Box::new(move |msg| { let (sender, receiver) = unbounded::<vfs::loader::Message>();
task_sender.send(msg).unwrap() let handle =
})); vfs_notify::NotifyHandle::spawn(Box::new(move |msg| sender.send(msg).unwrap()));
Box::new(loader) let handle = Box::new(handle) as Box<dyn vfs::loader::Handle>;
Handle { handle, receiver }
}; };
let task_pool = { let task_pool = {
let (sender, receiver) = unbounded(); let (sender, receiver) = unbounded();
(TaskPool::new(sender), receiver) let handle = TaskPool::new(sender);
Handle { handle, receiver }
}; };
GlobalState { GlobalState {
sender, sender,
config,
task_pool, task_pool,
analysis_host: AnalysisHost::new(lru_capacity),
loader, loader,
task_receiver, config,
analysis_host: AnalysisHost::new(lru_capacity),
flycheck: None, flycheck: None,
diagnostics: Default::default(), diagnostics: Default::default(),
mem_docs: FxHashSet::default(), mem_docs: FxHashSet::default(),
vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))), vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))),
status: Status::default(), status: Status::default(),
req_queue: ReqQueue::default(), req_queue: ReqQueue::default(),
latest_requests: Default::default(),
source_root_config: SourceRootConfig::default(), source_root_config: SourceRootConfig::default(),
proc_macro_client: ProcMacroClient::dummy(), proc_macro_client: ProcMacroClient::dummy(),
workspaces: Arc::new(Vec::new()), workspaces: Arc::new(Vec::new()),
latest_requests: Default::default(),
} }
} }

View file

@ -100,13 +100,13 @@ impl GlobalState {
recv(inbox) -> msg => recv(inbox) -> msg =>
msg.ok().map(Event::Lsp), msg.ok().map(Event::Lsp),
recv(self.task_pool.1) -> task => recv(self.task_pool.receiver) -> task =>
Some(Event::Task(task.unwrap())), Some(Event::Task(task.unwrap())),
recv(self.task_receiver) -> task => recv(self.loader.receiver) -> task =>
Some(Event::Vfs(task.unwrap())), Some(Event::Vfs(task.unwrap())),
recv(self.flycheck.as_ref().map_or(&never(), |it| &it.1)) -> task => recv(self.flycheck.as_ref().map_or(&never(), |it| &it.receiver)) -> task =>
Some(Event::Flycheck(task.unwrap())), Some(Event::Flycheck(task.unwrap())),
} }
} }
@ -132,7 +132,7 @@ impl GlobalState {
let _p = profile("GlobalState::handle_event"); let _p = profile("GlobalState::handle_event");
log::info!("handle_event({:?})", event); log::info!("handle_event({:?})", event);
let queue_count = self.task_pool.0.len(); let queue_count = self.task_pool.handle.len();
if queue_count > 0 { if queue_count > 0 {
log::info!("queued count = {}", queue_count); log::info!("queued count = {}", queue_count);
} }
@ -233,7 +233,7 @@ impl GlobalState {
let state_changed = self.process_changes(); let state_changed = self.process_changes();
if became_ready { if became_ready {
if let Some(flycheck) = &self.flycheck { if let Some(flycheck) = &self.flycheck {
flycheck.0.update(); flycheck.handle.update();
} }
} }
@ -370,7 +370,7 @@ impl GlobalState {
log::error!("orphan DidCloseTextDocument: {}", path) log::error!("orphan DidCloseTextDocument: {}", path)
} }
if let Some(path) = path.as_path() { if let Some(path) = path.as_path() {
this.loader.invalidate(path.to_path_buf()); this.loader.handle.invalidate(path.to_path_buf());
} }
} }
let params = lsp_types::PublishDiagnosticsParams { let params = lsp_types::PublishDiagnosticsParams {
@ -384,7 +384,7 @@ impl GlobalState {
})? })?
.on::<lsp_types::notification::DidSaveTextDocument>(|this, _params| { .on::<lsp_types::notification::DidSaveTextDocument>(|this, _params| {
if let Some(flycheck) = &this.flycheck { if let Some(flycheck) = &this.flycheck {
flycheck.0.update(); flycheck.handle.update();
} }
Ok(()) Ok(())
})? })?
@ -427,7 +427,7 @@ impl GlobalState {
.on::<lsp_types::notification::DidChangeWatchedFiles>(|this, params| { .on::<lsp_types::notification::DidChangeWatchedFiles>(|this, params| {
for change in params.changes { for change in params.changes {
if let Ok(path) = from_proto::abs_path(&change.uri) { if let Ok(path) = from_proto::abs_path(&change.uri) {
this.loader.invalidate(path); this.loader.handle.invalidate(path);
} }
} }
Ok(()) Ok(())
@ -440,7 +440,7 @@ impl GlobalState {
if self.config.publish_diagnostics { if self.config.publish_diagnostics {
let snapshot = self.snapshot(); let snapshot = self.snapshot();
let subscriptions = subscriptions.clone(); let subscriptions = subscriptions.clone();
self.task_pool.0.spawn(move || { self.task_pool.handle.spawn(move || {
let diagnostics = subscriptions let diagnostics = subscriptions
.into_iter() .into_iter()
.filter_map(|file_id| { .filter_map(|file_id| {
@ -458,7 +458,7 @@ impl GlobalState {
Task::Diagnostics(diagnostics) Task::Diagnostics(diagnostics)
}) })
} }
self.task_pool.0.spawn({ self.task_pool.handle.spawn({
let subs = subscriptions; let subs = subscriptions;
let snap = self.snapshot(); let snap = self.snapshot();
move || { move || {

View file

@ -11,7 +11,7 @@ use vfs::{file_set::FileSetConfig, AbsPath};
use crate::{ use crate::{
config::{Config, FilesWatcher, LinkedProject}, config::{Config, FilesWatcher, LinkedProject},
global_state::GlobalState, global_state::{GlobalState, Handle},
}; };
impl GlobalState { impl GlobalState {
@ -105,7 +105,7 @@ impl GlobalState {
FilesWatcher::Client => vec![], FilesWatcher::Client => vec![],
FilesWatcher::Notify => project_folders.watch, FilesWatcher::Notify => project_folders.watch,
}; };
self.loader.set_config(vfs::loader::Config { load: project_folders.load, watch }); self.loader.handle.set_config(vfs::loader::Config { load: project_folders.load, watch });
// Create crate graph from all the workspaces // Create crate graph from all the workspaces
let crate_graph = { let crate_graph = {
@ -113,7 +113,7 @@ impl GlobalState {
let vfs = &mut self.vfs.write().0; let vfs = &mut self.vfs.write().0;
let loader = &mut self.loader; let loader = &mut self.loader;
let mut load = |path: &AbsPath| { let mut load = |path: &AbsPath| {
let contents = loader.load_sync(path); let contents = loader.handle.load_sync(path);
let path = vfs::VfsPath::from(path.to_path_buf()); let path = vfs::VfsPath::from(path.to_path_buf());
vfs.set_file_contents(path.clone(), contents); vfs.set_file_contents(path.clone(), contents);
vfs.file_id(&path) vfs.file_id(&path)
@ -153,9 +153,9 @@ impl GlobalState {
let (sender, receiver) = unbounded(); let (sender, receiver) = unbounded();
let sender = Box::new(move |msg| sender.send(msg).unwrap()); let sender = Box::new(move |msg| sender.send(msg).unwrap());
let cargo_project_root = cargo.workspace_root().to_path_buf(); let cargo_project_root = cargo.workspace_root().to_path_buf();
let flycheck = let handle =
FlycheckHandle::spawn(sender, config.clone(), cargo_project_root.into()); FlycheckHandle::spawn(sender, config.clone(), cargo_project_root.into());
Some((flycheck, receiver)) Some(Handle { handle, receiver })
} }
ProjectWorkspace::Json { .. } => { ProjectWorkspace::Json { .. } => {
log::warn!("Cargo check watching only supported for cargo workspaces, disabling"); log::warn!("Cargo check watching only supported for cargo workspaces, disabling");