use crate::{
config::DEFAULT_CONFIGURATION_SECTION,
world::{World, DEFAULT_WORKSPACE_URI},
};
use anyhow::Context as AnyhowContext;
use jsona_util::environment::Environment;
use lsp_async_stub::{Context, Params, RequestWriter};
use lsp_types::{
request::WorkspaceConfiguration, ConfigurationItem, ConfigurationParams,
DidChangeConfigurationParams,
};
use serde_json::Value;
use url::Url;
#[tracing::instrument(skip_all)]
pub async fn configuration_change<E: Environment>(
context: Context<World<E>>,
_params: Params<DidChangeConfigurationParams>,
) {
update_configuration(context).await;
}
#[tracing::instrument(skip_all)]
pub async fn update_configuration<E: Environment>(context: Context<World<E>>) {
let workspaces = context.workspaces.read().await;
let urls: Vec<&Url> = workspaces.keys().collect();
let items: Vec<_> = urls
.clone()
.into_iter()
.map(|uri| {
let scope_uri = if *uri == *DEFAULT_WORKSPACE_URI {
Some(DEFAULT_WORKSPACE_URI.clone())
} else {
Some(uri.clone())
};
ConfigurationItem {
scope_uri,
section: Some(DEFAULT_CONFIGURATION_SECTION.to_string()),
}
})
.collect();
let res = context
.clone()
.write_request::<WorkspaceConfiguration, _>(Some(ConfigurationParams { items }))
.await
.context("failed to fetch configuration")
.and_then(|res| res.into_result().context("invalid configuration response"));
match res {
Ok(configs) => {
for (config, uri) in configs.into_iter().zip(urls) {
if config.is_object() {
context.env.spawn_local(initialize_workspace(
context.clone(),
uri.clone(),
config.clone(),
));
}
}
}
Err(error) => {
tracing::error!(?error, "failed to fetch configuration");
}
}
}
pub async fn initialize_workspace<E: Environment>(
context: Context<World<E>>,
uri: Url,
config: Value,
) {
let mut workspaces = context.workspaces.write().await;
if let Some(ws) = workspaces.get_mut(&uri) {
if let Err(error) = ws.initialize(context.clone(), &config).await {
tracing::error!(%error, %uri, "failed to update workspace");
}
}
}