glyph_lsp/
lib.rs

1//! Language Server Protocol implementation for Glyph
2//!
3//! This crate provides LSP support for Glyph, enabling IDE features like:
4//! - Syntax highlighting
5//! - Error diagnostics
6//! - Code completion
7//! - Go to definition
8//! - Hover information
9
10use dashmap::DashMap;
11use tower_lsp::lsp_types::*;
12use tower_lsp::{Client, LanguageServer, LspService, Server};
13
14pub struct GlyphLanguageServer {
15    client: Client,
16    documents: DashMap<Url, String>,
17}
18
19#[tower_lsp::async_trait]
20impl LanguageServer for GlyphLanguageServer {
21    async fn initialize(
22        &self,
23        _: InitializeParams,
24    ) -> tower_lsp::jsonrpc::Result<InitializeResult> {
25        Ok(InitializeResult {
26            server_info: Some(ServerInfo {
27                name: "glyph-lsp".to_string(),
28                version: Some(env!("CARGO_PKG_VERSION").to_string()),
29            }),
30            capabilities: ServerCapabilities {
31                text_document_sync: Some(TextDocumentSyncCapability::Kind(
32                    TextDocumentSyncKind::FULL,
33                )),
34                completion_provider: Some(CompletionOptions {
35                    resolve_provider: Some(false),
36                    trigger_characters: Some(vec![".".to_string()]),
37                    ..Default::default()
38                }),
39                hover_provider: Some(HoverProviderCapability::Simple(true)),
40                ..Default::default()
41            }
42        })
43    }
44
45    async fn initialized(&self, _: InitializedParams) {
46        self.client
47            .log_message(MessageType::INFO, "Glyph language server initialized")
48            .await;
49    }
50
51    async fn shutdown(&self) -> tower_lsp::jsonrpc::Result<()> {
52        Ok(())
53    }
54
55    async fn did_open(&self, params: DidOpenTextDocumentParams) {
56        self.documents
57            .insert(params.text_document.uri.clone(), params.text_document.text);
58    }
59
60    async fn did_change(&self, params: DidChangeTextDocumentParams) {
61        if let Some(mut doc) = self.documents.get_mut(&params.text_document.uri) {
62            *doc = params.content_changes[0].text.clone();
63        }
64    }
65
66    async fn did_close(&self, params: DidCloseTextDocumentParams) {
67        self.documents.remove(&params.text_document.uri);
68    }
69}
70
71impl GlyphLanguageServer {
72    pub fn new(client: Client) -> Self {
73        Self {
74            client,
75            documents: DashMap::new(),
76        }
77    }
78}
79
80pub async fn run_lsp_server() -> anyhow::Result<()> {
81    let stdin = tokio::io::stdin();
82    let stdout = tokio::io::stdout();
83
84    let (service, socket) = LspService::new(GlyphLanguageServer::new);
85    Server::new(stdin, stdout, socket).serve(service).await;
86
87    Ok(())
88}