use jsona_util::environment::Environment;
use lsp_async_stub::{util::Mapper, Context, Params, RequestWriter};
use lsp_types::{
notification, Diagnostic, DiagnosticSeverity, DidChangeTextDocumentParams,
DidCloseTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams,
PublishDiagnosticsParams,
};
use url::Url;
use crate::{
diagnostics,
world::{DocumentState, World},
NAME,
};
#[tracing::instrument(skip_all)]
pub(crate) async fn document_open<E: Environment>(
context: Context<World<E>>,
params: Params<DidOpenTextDocumentParams>,
) {
let p = match params.optional() {
None => return,
Some(p) => p,
};
let parse = jsona::parser::parse(&p.text_document.text);
let mapper = Mapper::new_utf16(&p.text_document.text, false);
let mut workspaces = context.workspaces.write().await;
let document_uri = &p.text_document.uri;
let ws = workspaces.by_document_mut(document_uri);
let dom = parse.clone().into_dom();
if ws.lsp_config.schema.enabled {
ws.schemas
.associations()
.add_from_document(document_uri, &dom);
}
ws.documents
.insert(document_uri.clone(), DocumentState { parse, dom, mapper });
let ws_root = ws.root.clone();
drop(workspaces);
diagnostics::publish_diagnostics(context.clone(), ws_root, document_uri.clone()).await;
}
#[tracing::instrument(skip_all)]
pub(crate) async fn document_change<E: Environment>(
context: Context<World<E>>,
params: Params<DidChangeTextDocumentParams>,
) {
let mut p = match params.optional() {
None => return,
Some(p) => p,
};
let change = match p.content_changes.pop() {
None => return,
Some(c) => c,
};
let parse = jsona::parser::parse(&change.text);
let mapper = Mapper::new_utf16(&change.text, false);
let mut workspaces = context.workspaces.write().await;
let document_uri = &p.text_document.uri;
let ws = workspaces.by_document_mut(document_uri);
let dom = parse.clone().into_dom();
ws.documents
.insert(document_uri.clone(), DocumentState { parse, dom, mapper });
let ws_root = ws.root.clone();
drop(workspaces);
diagnostics::publish_diagnostics(context.clone(), ws_root, document_uri.clone()).await;
}
#[tracing::instrument(skip_all)]
pub(crate) async fn document_save<E: Environment>(
_context: Context<World<E>>,
_params: Params<DidSaveTextDocumentParams>,
) {
}
#[tracing::instrument(skip_all)]
pub(crate) async fn document_close<E: Environment>(
context: Context<World<E>>,
params: Params<DidCloseTextDocumentParams>,
) {
let p = match params.optional() {
None => return,
Some(p) => p,
};
let mut workspaces = context.workspaces.write().await;
let document_uri = &p.text_document.uri;
let ws = workspaces.by_document_mut(document_uri);
ws.documents.remove(document_uri);
drop(workspaces);
context.env.spawn_local(diagnostics::clear_diagnostics(
context.clone(),
document_uri.clone(),
));
}
#[tracing::instrument(skip_all, fields(%file))]
async fn hint_excluded<E: Environment>(mut context: Context<World<E>>, file: &Url) {
context
.write_notification::<notification::PublishDiagnostics, _>(Some(PublishDiagnosticsParams {
uri: file.clone(),
diagnostics: vec![Diagnostic {
range: Default::default(),
severity: Some(DiagnosticSeverity::HINT),
code: None,
code_description: None,
source: Some(NAME.into()),
message: "this document has been excluded".into(),
related_information: None,
tags: None,
data: None,
}],
version: None,
}))
.await
.unwrap_or_else(|err| tracing::error!("{err}"));
}