1use anyhow::Result;
2use log::info;
3use lsp_server::Connection;
4use lsp_types::{
5 CodeActionKind, CodeActionOptions, CodeActionProviderCapability, CompletionOptions,
6 DiagnosticOptions, DiagnosticServerCapabilities, FoldingRangeProviderCapability,
7 HoverProviderCapability, InitializeParams, OneOf, SelectionRangeProviderCapability,
8 ServerCapabilities, TextDocumentSyncCapability, TextDocumentSyncKind, WorkDoneProgressOptions,
9};
10
11use crate::global_state::GlobalState;
12
13pub fn run() -> Result<()> {
14 info!("Starting Squawk LSP server");
15
16 let (connection, io_threads) = Connection::stdio();
17
18 let server_capabilities = serde_json::to_value(&ServerCapabilities {
19 text_document_sync: Some(TextDocumentSyncCapability::Kind(
20 TextDocumentSyncKind::INCREMENTAL,
21 )),
22 code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions {
23 code_action_kinds: Some(vec![
24 CodeActionKind::QUICKFIX,
25 CodeActionKind::REFACTOR_REWRITE,
26 ]),
27 work_done_progress_options: WorkDoneProgressOptions {
28 work_done_progress: None,
29 },
30 resolve_provider: None,
31 })),
32 selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)),
33 references_provider: Some(OneOf::Left(true)),
34 definition_provider: Some(OneOf::Left(true)),
35 hover_provider: Some(HoverProviderCapability::Simple(true)),
36 inlay_hint_provider: Some(OneOf::Left(true)),
37 diagnostic_provider: Some(DiagnosticServerCapabilities::Options(DiagnosticOptions {
38 identifier: None,
39 inter_file_dependencies: false,
40 workspace_diagnostics: false,
41 work_done_progress_options: WorkDoneProgressOptions {
42 work_done_progress: None,
43 },
44 })),
45 document_symbol_provider: Some(OneOf::Left(true)),
46 folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)),
47 completion_provider: Some(CompletionOptions {
48 resolve_provider: Some(false),
49 trigger_characters: Some(vec![".".to_owned()]),
50 all_commit_characters: None,
51 work_done_progress_options: WorkDoneProgressOptions {
52 work_done_progress: None,
53 },
54 completion_item: None,
55 }),
56 ..Default::default()
57 })
58 .unwrap();
59
60 info!("LSP server initializing connection...");
61 let initialization_params = connection.initialize(server_capabilities)?;
62 info!("LSP server initialized, entering main loop");
63
64 main_loop(connection, initialization_params)?;
65
66 info!("LSP server shutting down");
67
68 io_threads.join()?;
69 Ok(())
70}
71
72fn main_loop(connection: Connection, params: serde_json::Value) -> Result<()> {
73 info!("Server main loop");
74
75 let init_params: InitializeParams = serde_json::from_value(params).unwrap_or_default();
76 info!("Client process ID: {:?}", init_params.process_id);
77 let client_name = init_params.client_info.map(|x| x.name);
78 info!("Client name: {client_name:?}");
79
80 GlobalState::new(connection.sender).run(connection.receiver)
81}