jsona_lsp/handlers/
initialize.rs1use 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}