use std::sync::Arc;
use super::update_configuration;
use crate::config::InitializationOptions;
use crate::world::{WorkspaceState, DEFAULT_WORKSPACE_URI};
use crate::World;
use jsona_util::environment::Environment;
use lsp_async_stub::{rpc::Error, Context, Params, RequestWriter};
use lsp_types::notification::{DidChangeConfiguration, Notification};
use lsp_types::request::RegisterCapability;
use lsp_types::{
CompletionOptions, FoldingRangeProviderCapability, HoverProviderCapability, InitializedParams,
OneOf, Registration, RegistrationParams, SelectionRangeProviderCapability, ServerCapabilities,
ServerInfo, TextDocumentSyncCapability, TextDocumentSyncKind,
WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities,
};
use lsp_types::{InitializeParams, InitializeResult};
#[tracing::instrument(skip_all)]
pub async fn initialize<E: Environment>(
context: Context<World<E>>,
params: Params<InitializeParams>,
) -> Result<InitializeResult, Error> {
let p = params.required()?;
if let Some(init_opts) = p.initialization_options {
match serde_json::from_value::<InitializationOptions>(init_opts) {
Ok(c) => context.initialization_options.store(Arc::new(c)),
Err(error) => {
tracing::error!(%error, "invalid initialization options");
}
}
}
let mut wss = context.workspaces.write().await;
if let Some(workspaces) = p.workspace_folders {
for workspace in workspaces {
wss.entry(workspace.uri.clone())
.or_insert(WorkspaceState::new(context.env.clone(), workspace.uri));
}
} else {
wss.entry(DEFAULT_WORKSPACE_URI.clone())
.or_insert(WorkspaceState::new(
context.env.clone(),
DEFAULT_WORKSPACE_URI.clone(),
));
}
Ok(InitializeResult {
capabilities: ServerCapabilities {
workspace: Some(WorkspaceServerCapabilities {
workspace_folders: Some(WorkspaceFoldersServerCapabilities {
supported: Some(true),
change_notifications: Some(OneOf::Left(true)),
}),
..Default::default()
}),
text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)),
folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
document_symbol_provider: Some(OneOf::Left(true)),
document_formatting_provider: Some(OneOf::Left(true)),
hover_provider: Some(HoverProviderCapability::Simple(true)),
completion_provider: Some(CompletionOptions {
resolve_provider: Some(false),
trigger_characters: Some(vec![":".into(), "(".into(), "@".into()]),
..Default::default()
}),
..Default::default()
},
server_info: Some(ServerInfo {
name: "JSONA".into(),
version: Some(env!("CARGO_PKG_VERSION").into()),
}),
offset_encoding: None,
})
}
#[tracing::instrument(skip_all)]
pub async fn initialized<E: Environment>(
context: Context<World<E>>,
_params: Params<InitializedParams>,
) {
if let Err(error) = context
.clone()
.write_request::<RegisterCapability, _>(Some(RegistrationParams {
registrations: vec![Registration {
id: context.id.clone(),
method: DidChangeConfiguration::METHOD.into(),
register_options: None,
}],
}))
.await
{
tracing::error!(?error, "failed to send registration");
}
context
.env
.spawn_local(update_configuration(context.clone()));
}