taplo-lsp 0.6.1

Language server for Taplo
Documentation
use crate::world::{World, DEFAULT_WORKSPACE_URL};
use anyhow::Context as AnyhowContext;
use lsp_async_stub::{Context, Params, RequestWriter};
use lsp_types::{
    request::WorkspaceConfiguration, ConfigurationItem, ConfigurationParams,
    DidChangeConfigurationParams,
};
use std::iter::once;
use taplo_common::environment::Environment;

#[tracing::instrument(skip_all)]
pub async fn configuration_change<E: Environment>(
    context: Context<World<E>>,
    params: Params<DidChangeConfigurationParams>,
) {
    let p = match params.optional() {
        None => return,
        Some(p) => p,
    };

    let mut workspaces = context.workspaces.write().await;

    for (_, ws) in workspaces.iter_mut() {
        if let Err(error) = ws.config.update_from_json(&p.settings) {
            tracing::error!(?error, "invalid configuration");
        }

        if let Err(error) = ws.initialize(context.clone(), &context.env).await {
            tracing::error!(%error, "failed to update workspace");
        }
    }
}

#[tracing::instrument(skip_all)]
pub async fn update_configuration<E: Environment>(context: Context<World<E>>) {
    let init_config = context.init_config.load();

    let mut workspaces = context.workspaces.write().await;

    let config_items: Vec<_> = workspaces
        .iter()
        .filter_map(|(url, _)| {
            if *url == *DEFAULT_WORKSPACE_URL {
                None
            } else {
                Some(ConfigurationItem {
                    scope_uri: Some(url.clone()),
                    section: Some(init_config.configuration_section.clone()),
                })
            }
        })
        .collect();

    for (url, _) in workspaces.iter() {
        if *url == *DEFAULT_WORKSPACE_URL {}
    }

    let res = context
        .clone()
        .write_request::<WorkspaceConfiguration, _>(Some(ConfigurationParams {
            items: once(ConfigurationItem {
                scope_uri: None,
                section: Some(init_config.configuration_section.clone()),
            })
            .chain(config_items.iter().cloned())
            .collect::<Vec<_>>(),
        }))
        .await
        .context("failed to fetch configuration")
        .and_then(|res| res.into_result().context("invalid configuration response"));

    match res {
        Ok(configs) => {
            for (i, config) in configs.into_iter().enumerate() {
                if i == 0 && config.is_object() {
                    for (_, ws) in workspaces.iter_mut() {
                        if let Err(error) = ws.config.update_from_json(&config) {
                            tracing::error!(?error, "invalid configuration");
                        }

                        if let Err(error) = ws.initialize(context.clone(), &context.env).await {
                            tracing::error!(%error, "failed to update workspace");
                        }
                    }
                } else if config.is_object() {
                    let ws_url = config_items.get(i - 1).unwrap().scope_uri.as_ref().unwrap();
                    let ws = workspaces.get_mut(ws_url).unwrap();
                    if let Err(error) = ws.config.update_from_json(&config) {
                        tracing::error!(?error, "invalid configuration");
                    }

                    if let Err(error) = ws.initialize(context.clone(), &context.env).await {
                        tracing::error!(%error, "failed to update workspace");
                    }
                }
            }
        }
        Err(error) => {
            tracing::error!(?error, "failed to fetch configuration");
        }
    }
}