Move cargo metadata off the main loop

This commit is contained in:
Aleksey Kladov 2020-07-02 16:47:42 +02:00
parent 83f3cdca4f
commit 6c7578bd7a
4 changed files with 56 additions and 43 deletions

View file

@ -150,7 +150,7 @@ impl ProjectManifest {
impl ProjectWorkspace {
pub fn load(
manifest: ProjectManifest,
cargo_features: &CargoConfig,
cargo_config: &CargoConfig,
with_sysroot: bool,
) -> Result<ProjectWorkspace> {
let res = match manifest {
@ -166,7 +166,7 @@ impl ProjectWorkspace {
ProjectWorkspace::Json { project }
}
ProjectManifest::CargoToml(cargo_toml) => {
let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)
let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_config)
.with_context(|| {
format!(
"Failed to read Cargo metadata from Cargo.toml file {}",

View file

@ -21,6 +21,7 @@ use crate::{
lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress},
Result,
};
use ra_project_model::ProjectWorkspace;
pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
log::info!("initial config: {:#?}", config);
@ -58,6 +59,7 @@ enum Event {
pub(crate) enum Task {
Response(Response),
Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
Workspaces(Vec<anyhow::Result<ProjectWorkspace>>),
Unit,
}
@ -111,6 +113,14 @@ impl GlobalState {
}
fn run(mut self, inbox: Receiver<lsp_server::Message>) -> Result<()> {
if self.config.linked_projects.is_empty() && self.config.notifications.cargo_toml_not_found
{
self.show_message(
lsp_types::MessageType::Error,
"rust-analyzer failed to discover workspace".to_string(),
);
};
let registration_options = lsp_types::TextDocumentRegistrationOptions {
document_selector: Some(vec![
lsp_types::DocumentFilter {
@ -140,7 +150,7 @@ impl GlobalState {
|_, _| (),
);
self.reload();
self.fetch_workspaces();
while let Some(event) = self.next_event(&inbox) {
if let Event::Lsp(lsp_server::Message::Notification(not)) = &event {
@ -182,6 +192,7 @@ impl GlobalState {
self.diagnostics.set_native_diagnostics(file_id, diagnostics)
}
}
Task::Workspaces(workspaces) => self.switch_workspaces(workspaces),
Task::Unit => (),
}
self.analysis_host.maybe_collect_garbage();
@ -320,7 +331,7 @@ impl GlobalState {
self.register_request(&req, request_received);
RequestDispatcher { req: Some(req), global_state: self }
.on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.reload()))?
.on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces()))?
.on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))?
.on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))?
.on_sync::<lsp_types::request::Shutdown>(|_, ()| Ok(()))?

View file

@ -11,6 +11,7 @@ use vfs::{file_set::FileSetConfig, AbsPath};
use crate::{
config::{Config, FilesWatcher, LinkedProject},
global_state::{GlobalState, Handle},
main_loop::Task,
};
impl GlobalState {
@ -20,51 +21,51 @@ impl GlobalState {
self.analysis_host.update_lru_capacity(old_config.lru_capacity);
}
if self.config.linked_projects != old_config.linked_projects {
self.reload()
self.fetch_workspaces()
} else if self.config.flycheck != old_config.flycheck {
self.reload_flycheck();
}
}
pub(crate) fn reload(&mut self) {
log::info!("reloading projects: {:?}", self.config.linked_projects);
if self.config.linked_projects.is_empty() && self.config.notifications.cargo_toml_not_found
{
self.show_message(
lsp_types::MessageType::Error,
"rust-analyzer failed to discover workspace".to_string(),
);
};
let workspaces = {
self.config
.linked_projects
.iter()
.map(|project| match project {
LinkedProject::ProjectManifest(manifest) => {
ra_project_model::ProjectWorkspace::load(
manifest.clone(),
&self.config.cargo,
self.config.with_sysroot,
)
}
LinkedProject::InlineJsonProject(it) => {
Ok(ra_project_model::ProjectWorkspace::Json { project: it.clone() })
}
})
.collect::<Vec<_>>()
.into_iter()
.filter_map(|res| {
res.map_err(|err| {
log::error!("failed to load workspace: {:#}", err);
self.show_message(
lsp_types::MessageType::Error,
format!("rust-analyzer failed to load workspace: {:#}", err),
);
pub(crate) fn fetch_workspaces(&mut self) {
self.task_pool.handle.spawn({
let linked_projects = self.config.linked_projects.clone();
let cargo_config = self.config.cargo.clone();
let with_sysroot = self.config.with_sysroot.clone();
move || {
let workspaces = linked_projects
.iter()
.map(|project| match project {
LinkedProject::ProjectManifest(manifest) => {
ra_project_model::ProjectWorkspace::load(
manifest.clone(),
&cargo_config,
with_sysroot,
)
}
LinkedProject::InlineJsonProject(it) => {
Ok(ra_project_model::ProjectWorkspace::Json { project: it.clone() })
}
})
.ok()
.collect::<Vec<_>>();
Task::Workspaces(workspaces)
}
});
}
pub(crate) fn switch_workspaces(&mut self, workspaces: Vec<anyhow::Result<ProjectWorkspace>>) {
log::info!("reloading projects: {:?}", self.config.linked_projects);
let workspaces = workspaces
.into_iter()
.filter_map(|res| {
res.map_err(|err| {
log::error!("failed to load workspace: {:#}", err);
self.show_message(
lsp_types::MessageType::Error,
format!("rust-analyzer failed to load workspace: {:#}", err),
);
})
.collect::<Vec<_>>()
};
.ok()
})
.collect::<Vec<_>>();
if let FilesWatcher::Client = self.config.files.watcher {
let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {

View file

@ -447,6 +447,7 @@ version = \"0.0.0\"
",
)
.server();
server.wait_until_workspace_is_loaded();
server.request::<OnEnter>(
TextDocumentPositionParams {