mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 23:04:49 +00:00
Support basic diagnostic reporting
This commit is contained in:
parent
c50925240d
commit
9d365a8a57
11 changed files with 572 additions and 3 deletions
112
crates/lang_srv/src/server.rs
Normal file
112
crates/lang_srv/src/server.rs
Normal file
|
@ -0,0 +1,112 @@
|
|||
use parking_lot::{Mutex, MutexGuard};
|
||||
use registry::{DocumentChange, Registry};
|
||||
use tower_lsp::jsonrpc::Result;
|
||||
use tower_lsp::lsp_types::*;
|
||||
use tower_lsp::{Client, LanguageServer, LspService, Server};
|
||||
|
||||
mod convert;
|
||||
mod registry;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RocLs {
|
||||
client: Client,
|
||||
registry: Mutex<Registry>,
|
||||
}
|
||||
|
||||
impl RocLs {
|
||||
pub fn new(client: Client) -> Self {
|
||||
Self {
|
||||
client,
|
||||
registry: Mutex::new(Registry::default()),
|
||||
}
|
||||
}
|
||||
|
||||
fn registry(&self) -> MutexGuard<Registry> {
|
||||
self.registry.lock()
|
||||
}
|
||||
|
||||
pub fn capabilities() -> ServerCapabilities {
|
||||
let text_document_sync = Some(TextDocumentSyncCapability::Options(
|
||||
// TODO: later on make this incremental
|
||||
TextDocumentSyncOptions {
|
||||
open_close: Some(true),
|
||||
change: Some(TextDocumentSyncKind::FULL),
|
||||
..TextDocumentSyncOptions::default()
|
||||
},
|
||||
));
|
||||
let hover_provider = Some(HoverProviderCapability::Simple(true));
|
||||
|
||||
ServerCapabilities {
|
||||
text_document_sync,
|
||||
hover_provider,
|
||||
..ServerCapabilities::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Records a document content change.
|
||||
async fn change(&self, fi: Url, text: String, version: i32) {
|
||||
self.registry()
|
||||
.apply_change(DocumentChange::Modified(fi.clone(), text));
|
||||
|
||||
let diagnostics = self.registry().diagnostics(&fi);
|
||||
self.client
|
||||
.publish_diagnostics(fi, diagnostics, Some(version))
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn close(&self, fi: Url) {
|
||||
self.registry().apply_change(DocumentChange::Closed(fi));
|
||||
}
|
||||
}
|
||||
|
||||
#[tower_lsp::async_trait]
|
||||
impl LanguageServer for RocLs {
|
||||
async fn initialize(&self, _: InitializeParams) -> Result<InitializeResult> {
|
||||
Ok(InitializeResult {
|
||||
capabilities: Self::capabilities(),
|
||||
..InitializeResult::default()
|
||||
})
|
||||
}
|
||||
|
||||
async fn initialized(&self, _: InitializedParams) {
|
||||
self.client
|
||||
.log_message(MessageType::INFO, "Roc language server initialized.")
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn did_open(&self, params: DidOpenTextDocumentParams) {
|
||||
let TextDocumentItem {
|
||||
uri, text, version, ..
|
||||
} = params.text_document;
|
||||
self.change(uri, text, version).await;
|
||||
}
|
||||
|
||||
async fn did_change(&self, params: DidChangeTextDocumentParams) {
|
||||
let VersionedTextDocumentIdentifier { uri, version, .. } = params.text_document;
|
||||
|
||||
// NOTE: We specify that we expect full-content syncs in the server capabilities,
|
||||
// so here we assume the only change passed is a change of the entire document's content.
|
||||
let TextDocumentContentChangeEvent { text, .. } =
|
||||
params.content_changes.into_iter().next().unwrap();
|
||||
|
||||
self.change(uri, text, version).await;
|
||||
}
|
||||
|
||||
async fn did_close(&self, params: DidCloseTextDocumentParams) {
|
||||
let TextDocumentIdentifier { uri } = params.text_document;
|
||||
self.close(uri).await;
|
||||
}
|
||||
|
||||
async fn shutdown(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let stdin = tokio::io::stdin();
|
||||
let stdout = tokio::io::stdout();
|
||||
|
||||
let (service, socket) = LspService::new(RocLs::new);
|
||||
Server::new(stdin, stdout, socket).serve(service).await;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue