Skip to main content

squawk_server/
server.rs

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}