jsona_lsp/handlers/
initialize.rs

1use std::sync::Arc;
2
3use super::update_configuration;
4use crate::config::InitializationOptions;
5use crate::world::{WorkspaceState, DEFAULT_WORKSPACE_URI};
6use crate::World;
7use jsona_util::environment::Environment;
8use lsp_async_stub::{rpc::Error, Context, Params, RequestWriter};
9use lsp_types::notification::{DidChangeConfiguration, Notification};
10use lsp_types::request::RegisterCapability;
11use lsp_types::{
12    CompletionOptions, FoldingRangeProviderCapability, HoverProviderCapability, InitializedParams,
13    OneOf, Registration, RegistrationParams, SelectionRangeProviderCapability, ServerCapabilities,
14    ServerInfo, TextDocumentSyncCapability, TextDocumentSyncKind,
15    WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities,
16};
17use lsp_types::{InitializeParams, InitializeResult};
18
19#[tracing::instrument(skip_all)]
20pub async fn initialize<E: Environment>(
21    context: Context<World<E>>,
22    params: Params<InitializeParams>,
23) -> Result<InitializeResult, Error> {
24    let p = params.required()?;
25
26    if let Some(init_opts) = p.initialization_options {
27        match serde_json::from_value::<InitializationOptions>(init_opts) {
28            Ok(c) => context.initialization_options.store(Arc::new(c)),
29            Err(error) => {
30                tracing::error!(%error, "invalid initialization options");
31            }
32        }
33    }
34
35    let mut wss = context.workspaces.write().await;
36    if let Some(workspaces) = p.workspace_folders {
37        for workspace in workspaces {
38            wss.entry(workspace.uri.clone())
39                .or_insert(WorkspaceState::new(context.env.clone(), workspace.uri));
40        }
41    } else {
42        wss.entry(DEFAULT_WORKSPACE_URI.clone())
43            .or_insert(WorkspaceState::new(
44                context.env.clone(),
45                DEFAULT_WORKSPACE_URI.clone(),
46            ));
47    }
48
49    Ok(InitializeResult {
50        capabilities: ServerCapabilities {
51            workspace: Some(WorkspaceServerCapabilities {
52                workspace_folders: Some(WorkspaceFoldersServerCapabilities {
53                    supported: Some(true),
54                    change_notifications: Some(OneOf::Left(true)),
55                }),
56                ..Default::default()
57            }),
58            text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)),
59            folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
60            selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
61            document_symbol_provider: Some(OneOf::Left(true)),
62            document_formatting_provider: Some(OneOf::Left(true)),
63            hover_provider: Some(HoverProviderCapability::Simple(true)),
64            completion_provider: Some(CompletionOptions {
65                resolve_provider: Some(false),
66                trigger_characters: Some(vec![":".into(), "(".into(), "@".into()]),
67                ..Default::default()
68            }),
69            ..Default::default()
70        },
71        server_info: Some(ServerInfo {
72            name: "JSONA".into(),
73            version: Some(env!("CARGO_PKG_VERSION").into()),
74        }),
75        offset_encoding: None,
76    })
77}
78
79#[tracing::instrument(skip_all)]
80pub async fn initialized<E: Environment>(
81    context: Context<World<E>>,
82    _params: Params<InitializedParams>,
83) {
84    if let Err(error) = context
85        .clone()
86        .write_request::<RegisterCapability, _>(Some(RegistrationParams {
87            registrations: vec![Registration {
88                id: context.id.clone(),
89                method: DidChangeConfiguration::METHOD.into(),
90                register_options: None,
91            }],
92        }))
93        .await
94    {
95        tracing::error!(?error, "failed to send registration");
96    }
97    context
98        .env
99        .spawn_local(update_configuration(context.clone()));
100}