1#![allow(clippy::cognitive_complexity)]
2
3use std::ops::ControlFlow;
4
5use crate::{
6 annotations::to_diagnostic,
7 documents::LSPDocument,
8 state::{LSPState, UrlOrFile},
9 BuildParams, ClientExt, HtmlRequestParams, NewArchiveParams, ProgressCallbackServer,
10 QuizRequestParams, StandaloneExportParams,
11};
12
13use super::{FLAMSLSPServer, ServerWrapper};
14use async_lsp::{
15 lsp_types::{self as lsp},
16 LanguageClient, LanguageServer, ResponseError,
17};
18use flams_ontology::uris::ArchiveURITrait;
19use flams_stex::quickparse::stex::{AnnotIter, STeXAnnot};
20use flams_system::{
21 backend::{archives::LocalArchive, Backend, GlobalBackend},
22 formats::FormatOrTargets,
23};
24use flams_utils::{prelude::TreeChildIter, unwrap};
25use futures::{future::BoxFuture, FutureExt, TryFutureExt};
26
27macro_rules! impl_request {
28 ($name:ident = $struct:ident) => {
29 fn $name(
30 &mut self,
31 params: <lsp::request::$struct as lsp::request::Request>::Params,
32 ) -> Res<<lsp::request::$struct as lsp::request::Request>::Result> {
33 tracing::info!("LSP: {params:?}");
34 Box::pin(std::future::ready(Err(ResponseError::new(
35 async_lsp::ErrorCode::METHOD_NOT_FOUND,
36 format!(
37 "No such method: {}",
38 <lsp::request::$struct as lsp::request::Request>::METHOD
39 ),
40 ))))
41 }
42 };
43 (? $name:ident = $struct:ident => ($default:expr)) => {
44 fn $name(
45 &mut self,
46 params: <lsp::request::$struct as lsp::request::Request>::Params,
47 ) -> Res<<lsp::request::$struct as lsp::request::Request>::Result> {
48 tracing::info!("LSP: {params:?}");
49 Box::pin(std::future::ready(Ok($default)))
50 }
51 };
52 (! $name:ident = $struct:ident => ($default:expr)) => {
53 fn $name(
54 &mut self,
55 params: <lsp::request::$struct as lsp::request::Request>::Params,
56 ) -> Res<<lsp::request::$struct as lsp::request::Request>::Result> {
57 tracing::debug!("LSP: {params:?}");
58 Box::pin(std::future::ready(Ok($default)))
59 }
60 };
61}
62
63macro_rules! impl_notification {
64 (! $name:ident = $struct:ident) => {
65 fn $name(
66 &mut self,
67 params: <lsp::notification::$struct as lsp::notification::Notification>::Params,
68 ) -> Self::NotifyResult {
69 tracing::debug!("LSP: {params:?}");
70 ControlFlow::Continue(())
71 }
72 };
73 ($name:ident = $struct:ident) => {
74 fn $name(
75 &mut self,
76 params: <lsp::notification::$struct as lsp::notification::Notification>::Params,
77 ) -> Self::NotifyResult {
78 tracing::info!("LSP: {params:?}");
79 ControlFlow::Break(Err(async_lsp::Error::Routing(format!(
80 "Unhandled notification: {}",
81 <lsp::notification::$struct as lsp::notification::Notification>::METHOD,
82 ))))
83 }
84 };
85}
86
87#[inline]
88fn fut<T: Send + 'static>(f: impl FnOnce() -> Result<T, String> + Send + 'static) -> Res<T> {
89 Box::pin(tokio::task::spawn_blocking(f).map_ok_or_else(
90 |e| {
91 Err(ResponseError::new(
92 async_lsp::ErrorCode::REQUEST_FAILED,
93 e.to_string(),
94 ))
95 },
96 |r| r.map_err(|e| ResponseError::new(async_lsp::ErrorCode::REQUEST_FAILED, e)),
97 ))
98}
99fn block<T: Send + 'static>(
100 f: impl FnOnce() -> Result<T, String> + Send + 'static,
101) -> impl std::future::Future<Output = Result<T, String>> {
102 tokio::task::spawn_blocking(f).map_ok_or_else(|e| Err(e.to_string()), |r| r)
103}
104fn wrap_fut<T: Send + 'static>(
105 f: impl std::future::Future<Output = Result<T, String>> + Send + 'static,
106) -> Res<T> {
107 Box::pin(f.map_err(|e| ResponseError::new(async_lsp::ErrorCode::REQUEST_FAILED, e)))
108}
109
110impl<T: FLAMSLSPServer> ServerWrapper<T> {
111 pub(crate) fn html_request(&mut self, params: HtmlRequestParams) -> Res<Option<String>> {
112 let mut client = self.inner.client().clone();
113 let state = self.inner.state().clone();
114 Box::pin(
115 tokio::task::spawn_blocking(move || {
116 state
117 .build_html(¶ms.uri.into(), &mut client)
118 .map(|d| d.to_string())
119 })
120 .map_err(|e| ResponseError::new(async_lsp::ErrorCode::REQUEST_FAILED, e.to_string())),
121 )
122 }
123
124 pub(crate) fn new_archive(
125 &mut self,
126 NewArchiveParams { archive, urlbase }: NewArchiveParams,
127 ) -> <Self as LanguageServer>::NotifyResult {
128 let mut client = self.inner.client().clone();
129 tokio::task::spawn_blocking(move || {
130 match flams_system::backend::GlobalBackend::get().new_archive(
131 &archive,
132 &urlbase,
133 "stex",
134 "helloworld.tex",
135 include_str!("stex_default.txt"),
136 ) {
137 Ok(path) => {
138 let _ = client.show_message(lsp::ShowMessageParams {
139 typ: lsp::MessageType::INFO,
140 message: format!("Created new archive {archive}"),
141 });
142 client.open_file(&path);
143 }
144 Err(e) => {
145 let _ = client.show_message(lsp::ShowMessageParams {
146 typ: lsp::MessageType::ERROR,
147 message: format!("Error creating new archive {archive}: {e:#}"),
148 });
149 }
150 }
151 });
152 ControlFlow::Continue(())
153 }
154
155 pub(crate) fn export_standalone(
156 &mut self,
157 params: StandaloneExportParams,
158 ) -> <Self as LanguageServer>::NotifyResult {
159 let StandaloneExportParams { uri, target } = params;
160 let uri: UrlOrFile = uri.into();
161 let state = self.inner.state().clone();
162 let mut client = self.inner.client().clone();
163 tokio::task::spawn_blocking(move || {
164 let Some(doc) = state.get(&uri) else {
165 let _ = client.show_message(lsp::ShowMessageParams {
166 typ: lsp::MessageType::ERROR,
167 message: format!("Not a valid file path: {uri}"),
168 });
169 return;
170 };
171 let Some(doc_uri) = doc.document_uri() else {
172 let _ = client.show_message(lsp::ShowMessageParams {
173 typ: lsp::MessageType::ERROR,
174 message: format!("Document for {uri} not found"),
175 });
176 return;
177 };
178 let Some(file) = doc.path() else {
179 let _ = client.show_message(lsp::ShowMessageParams {
180 typ: lsp::MessageType::ERROR,
181 message: format!("File for {uri} not found"),
182 });
183 return;
184 };
185 let progress = ProgressCallbackServer::new(
186 client.clone(),
187 format!("Exporting {}", doc_uri.name()),
188 None,
189 );
190 if let Err(e) = flams_stex::export_standalone(doc_uri, file, &target) {
191 let _ = client.show_message(lsp::ShowMessageParams {
192 typ: lsp::MessageType::ERROR,
193 message: format!(
194 "Error exporting {} to {}: {e:#}",
195 file.display(),
196 target.display()
197 ),
198 });
199 } else {
200 let _ = client.show_message(lsp::ShowMessageParams {
201 typ: lsp::MessageType::INFO,
202 message: format!(
203 "Finished exporting {} to {}\n\nYou may want to verify the exported file actually compiles",
204 file.display(),
205 target.display()
206 ),
207 });
208 }
209 drop(progress);
210 });
211 ControlFlow::Continue(())
212 }
213
214 pub(crate) fn quiz_request(&mut self, params: QuizRequestParams) -> Res<String> {
215 use flams_system::backend::docfile::QuizExtension;
216 fn get_res(url: UrlOrFile, state: LSPState) -> Result<String, String> {
217 let doc = state
218 .get(&url)
219 .ok_or_else(|| "Document not found".to_string())?;
220 let uri = doc
221 .document_uri()
222 .ok_or_else(|| "Document URI not found".to_string())?;
223 let doc = state
224 .backend()
225 .get_document(uri)
226 .ok_or_else(|| "Document not found".to_string())?;
227 let quiz = doc.as_quiz(state.backend()).map_err(|e| format!("{e:#}"))?;
228 serde_json::to_string(&quiz).map_err(|e| format!("{e:#}"))
229 }
230 let state = self.inner.state().clone();
231 let mut client = self.inner.client().clone();
232 Box::pin(async move {
233 let url: UrlOrFile = params.uri.into();
234 tokio::task::spawn_blocking(move || match get_res(url, state) {
235 Err(e) => {
236 let _ = client.show_message(lsp::ShowMessageParams {
237 typ: lsp::MessageType::ERROR,
238 message: e.clone(),
239 });
240 Err(ResponseError::new(async_lsp::ErrorCode::REQUEST_FAILED, e))
241 }
242 Ok(r) => Ok(r),
243 })
244 .map_err(|e| ResponseError::new(async_lsp::ErrorCode::REQUEST_FAILED, e.to_string()))
245 .await?
246 })
247 }
248
249 fn build(
250 doc: &LSPDocument,
251 uri: &impl std::fmt::Display,
252 stale_only: bool,
253 ) -> Result<(), String> {
254 let Some(id) = doc.archive().map(|a| a.archive_id()) else {
255 return Err(format!("Containing archive for {uri} not found"));
256 };
257 let Some(rel_path) = doc.relative_path() else {
258 return Err(format!("relative path for {uri} not found"));
259 };
260 flams_system::building::queue_manager::QueueManager::get().with_global(move |queue| {
262 queue.enqueue_archive(
263 id,
264 FormatOrTargets::Format(flams_stex::STEX),
265 stale_only,
266 Some(rel_path),
267 false,
268 )
269 });
270 Ok(())
271 }
272
273 pub(crate) fn build_one(&mut self, params: BuildParams) -> Res<()> {
274 let state = self.inner.state().clone();
275 fut(move || {
276 let url: UrlOrFile = params.uri.into();
277 let Some(doc) = state.get(&url) else {
278 return Err(format!("Document not found: {url}"));
279 };
280 Self::build(&doc, &url, false)
281 })
282 }
283 pub(crate) fn build_all(&mut self, params: BuildParams) -> Res<()> {
284 let state = self.inner.state().clone();
285 let client = self.inner.client().clone();
286 wrap_fut(async move {
287 let istate = state.clone();
288 let url = block(move || {
289 let url: UrlOrFile = params.uri.into();
290 let Some(doc) = istate.get(&url) else {
291 return Err(format!("Document not found: {url}"));
292 };
293 Self::build(&doc, &url, false)?;
294 Ok(url)
295 })
296 .await?;
297 let deps = triomphe::Arc::new(parking_lot::Mutex::new(vec![url]));
298 let mut curr = 0;
299 loop {
300 let url = {
301 let dps = deps.lock();
302 if curr == dps.len() {
303 break;
304 }
305 let d = dps[curr].clone();
306 drop(dps);
307 d
308 };
309 curr += 1;
310 let Some(d) = state.get(&url) else {
311 continue;
313 };
314 let iclient = client.clone();
317 let d_archive = d.archive().cloned();
318 let Some(vec) = d
319 .with_annots_block(state.clone(), move |annots| {
320 let mut client = iclient;
321 <AnnotIter as TreeChildIter<STeXAnnot>>::dfs(AnnotIter::from(
322 annots.annotations.iter(),
323 ))
324 .filter_map(|a| match a {
325 STeXAnnot::Inputref {
326 archive, filepath, ..
327 }
328 | STeXAnnot::MHInput {
329 archive, filepath, ..
330 }
331 | STeXAnnot::IncludeProblem {
332 archive, filepath, ..
333 } => {
334 let archive = archive
335 .as_ref()
336 .map(|a| &a.0)
337 .unwrap_or_else(|| unwrap!(d_archive.as_ref()).archive_id());
338 let Some(uri) = crate::annotations::uri_from_archive_relpath(
339 &archive,
340 &filepath.0,
341 ) else {
342 let _ = client.show_message(lsp::ShowMessageParams {
343 typ: lsp::MessageType::ERROR,
344 message: format!(
345 "Could not find file [{archive}]{{{}}}",
346 &filepath.0
347 ),
348 });
349 return None;
350 };
351 let url: UrlOrFile = uri.into();
352 Some(url)
353 }
354 STeXAnnot::ImportModule { module, .. }
355 | STeXAnnot::UseModule { module, .. } => {
356 let Some(uri) = module
357 .full_path
358 .as_ref()
359 .and_then(|e| lsp::Url::from_file_path(e).ok())
360 else {
361 let _ = client.show_message(lsp::ShowMessageParams {
362 typ: lsp::MessageType::ERROR,
363 message: format!(
364 "Could not find module file {}",
365 &module.uri
366 ),
367 });
368 return None;
369 };
370 let url: UrlOrFile = uri.into();
371 Some(url)
372 }
373 _ => None,
374 })
375 .collect::<Vec<_>>()
376 })
377 .await
378 else {
379 continue;
380 };
381 for url in vec {
382 {
383 let mut dep_lock = deps.lock();
384 if dep_lock.contains(&url) {
385 continue;
386 }
387 dep_lock.push(url.clone());
388 }
389 let state = state.clone();
390 let mut client = client.clone();
391 block(move || {
392 let Some(doc) = state.force_get(&url) else {
393 let _ = client.show_message(lsp::ShowMessageParams {
394 typ: lsp::MessageType::ERROR,
395 message: format!("Could not find document {url}"),
396 });
397 return Ok(());
398 };
399 if let Err(e) = Self::build(&doc, &url, true) {
400 let _ = client.show_message(lsp::ShowMessageParams {
401 typ: lsp::MessageType::ERROR,
402 message: format!("Could not queue document {url}: {e}"),
403 });
404 }
405 Ok(())
406 })
407 .await?
408 }
409 }
410 Ok(())
411 })
412 }
413
414 pub(crate) fn reload(
415 &mut self,
416 _: crate::ReloadParams,
417 ) -> <Self as LanguageServer>::NotifyResult {
418 let state = self.inner.state().clone();
419 let client = self.inner.client().clone();
420 let _ = tokio::task::spawn_blocking(move || {
421 tracing::info!("LSP: reload");
422 state.backend().reset();
423 state.load_mathhubs(client.clone());
424 client.update_mathhub();
425 });
426 ControlFlow::Continue(())
427 }
428
429 pub(crate) fn install(
430 &mut self,
431 params: crate::InstallParams,
432 ) -> <Self as LanguageServer>::NotifyResult {
433 let state = self.inner.state().clone();
434 let client = self.inner.client().clone();
435 let mut progress = ProgressCallbackServer::new(client, "Installing".to_string(), None);
436 let _ = tokio::task::spawn(async move {
437 let crate::InstallParams {
438 archives,
439 remote_url,
440 } = params;
441 let mut rescan = false;
442 let archives = {
443 let mut ret = Vec::new();
444 let exis = GlobalBackend::get().all_archives();
445 for a in archives {
446 if exis.iter().any(|e| *e.id() == a) || ret.contains(&a) {
447 continue;
448 }
449 ret.push(a);
450 }
451 ret
452 };
453 let len = archives.len();
454 for (i, a) in archives.into_iter().enumerate() {
455 let url = format!("{remote_url}/api/backend/download?id={a}");
456 let prefix = format!("{}/{len}: {a}", i + 1);
457 progress.update(prefix.clone(), None);
458 if LocalArchive::unzip_from_remote(a.clone(), &url, |p| {
459 progress.update(format!("{prefix}: {}", p.display()), None)
460 })
461 .await
462 .is_err()
463 {
464 let _ = progress.client_mut().show_message(lsp::ShowMessageParams {
465 message: format!("Failed to install archive {a}"),
466 typ: lsp::MessageType::ERROR,
467 });
468 } else {
469 rescan = true;
470 }
471 }
472 let client = progress.client().clone();
473 drop(progress);
474 if rescan {
475 let _ = tokio::task::spawn_blocking(move || {
476 state.backend().reset();
478 state.load_mathhubs(client.clone());
479 client.update_mathhub();
480 });
481 } else {
482 client.update_mathhub();
483 }
484 });
485 ControlFlow::Continue(())
486 }
487}
488
489type Res<T> = BoxFuture<'static, Result<T, ResponseError>>;
490
491impl<T: FLAMSLSPServer> LanguageServer for ServerWrapper<T> {
492 type Error = ResponseError;
493 type NotifyResult = ControlFlow<async_lsp::Result<()>>;
494
495 fn initialize(&mut self, params: lsp::InitializeParams) -> Res<lsp::InitializeResult> {
496 tracing::info!("LSP: initialize");
497 self.inner.initialize(
498 params
499 .workspace_folders
500 .unwrap_or_default()
501 .into_iter()
502 .map(|f| (f.name, f.uri)),
503 );
504 Box::pin(std::future::ready({
505 Ok(lsp::InitializeResult {
506 capabilities: super::capabilities::capabilities(),
507 server_info: None,
508 })
509 }))
510 }
511
512 fn shutdown(&mut self, (): ()) -> Res<()> {
513 tracing::info!("LSP: shutdown");
514 Box::pin(std::future::ready(Ok(())))
515 }
516
517 fn initialized(&mut self, _params: lsp::InitializedParams) -> Self::NotifyResult {
521 tracing::info!("LSP: initialized");
522 self.inner.initialized();
523 ControlFlow::Continue(())
526 }
527
528 impl_notification!(!exit = Exit);
529
530 impl_notification!(!did_change_workspace_folders = DidChangeWorkspaceFolders);
532 impl_notification!(!did_change_configuration = DidChangeConfiguration);
533 impl_notification!(!did_change_watched_files = DidChangeWatchedFiles);
534 impl_notification!(!did_create_files = DidCreateFiles);
535 impl_notification!(!did_rename_files = DidRenameFiles);
536 impl_notification!(!did_delete_files = DidDeleteFiles);
537
538 fn did_open(&mut self, params: lsp::DidOpenTextDocumentParams) -> Self::NotifyResult {
541 let document = params.text_document;
542 tracing::trace!(
543 "URI: {}, language: {}, version: {}, text: \n{}",
544 document.uri,
545 document.language_id,
546 document.version,
547 document.text
548 );
549 self.inner
550 .state()
551 .insert(document.uri.into(), document.text);
552 ControlFlow::Continue(())
553 }
554
555 #[allow(clippy::let_underscore_future)]
556 fn did_change(&mut self, params: lsp::DidChangeTextDocumentParams) -> Self::NotifyResult {
558 let document = params.text_document;
559 let uri = document.uri.clone().into();
560 if let Some(d) = self.inner.state().get(&uri) {
561 for change in params.content_changes {
562 tracing::trace!(
563 "URI: {},version: {}, text: \"{}\", range: {:?}",
564 document.uri,
565 document.version,
566 change.text,
567 change.range
568 );
569 d.delta(change.text, change.range);
570 }
571 let mut client = self.inner.client().clone();
572 let _ = tokio::spawn(d.with_annots(self.inner.state().clone(), move |a| {
573 let r = lsp::PublishDiagnosticsParams {
574 uri: document.uri,
575 diagnostics: a.diagnostics.iter().map(to_diagnostic).collect(),
576 version: None,
577 };
578 let _ = client.publish_diagnostics(r);
579 }));
580 } else {
581 tracing::warn!("document not found: {}", document.uri);
582 }
583 ControlFlow::Continue(())
584 }
585
586 #[allow(clippy::let_underscore_future)]
587 fn did_save(&mut self, params: lsp::DidSaveTextDocumentParams) -> Self::NotifyResult {
589 tracing::trace!("did_save: {}", params.text_document.uri);
590 let state = self.inner.state().clone();
591 let client = self.inner.client().clone();
592 let uri = params.text_document.uri.into();
593 let _ = tokio::task::spawn_blocking(move || {
594 state.build_html_and_notify(&uri, client);
595 });
596 ControlFlow::Continue(())
597 }
598
599 impl_notification!(!will_save = WillSaveTextDocument);
600
601 fn did_close(&mut self, params: lsp::DidCloseTextDocumentParams) -> Self::NotifyResult {
603 tracing::trace!("did_close: {}", params.text_document.uri);
604 ControlFlow::Continue(())
605 }
606
607 impl_notification!(work_done_progress_cancel = WorkDoneProgressCancel);
610
611 impl_notification!(!set_trace = SetTrace);
613 impl_notification!(!cancel_request = Cancel);
614 impl_notification!(!progress = Progress);
615
616 fn document_symbol(
622 &mut self,
623 params: lsp::DocumentSymbolParams,
624 ) -> Res<Option<lsp::DocumentSymbolResponse>> {
625 tracing::trace_span!("document_symbol").in_scope(move || {
626 tracing::trace!(
627 "uri: {},work_done_progress_params: {:?}, partial_results: {:?}",
628 params.text_document.uri,
629 params.work_done_progress_params,
630 params.partial_result_params
631 );
632 let p = params
633 .work_done_progress_params
634 .work_done_token
635 .map(|tk| self.get_progress(tk));
636 self.inner
637 .state()
638 .get_symbols(¶ms.text_document.uri.into(), p)
639 .map_or_else(
640 || Box::pin(std::future::ready(Ok(None))) as _,
641 |f| Box::pin(f.map(Result::Ok)) as _,
642 )
643 })
644 }
645
646 fn document_diagnostic(
648 &mut self,
649 params: lsp::DocumentDiagnosticParams,
650 ) -> Res<lsp::DocumentDiagnosticReportResult> {
651 fn default() -> lsp::DocumentDiagnosticReportResult {
652 lsp::DocumentDiagnosticReportResult::Report(lsp::DocumentDiagnosticReport::Full(
653 lsp::RelatedFullDocumentDiagnosticReport::default(),
654 ))
655 }
656 tracing::trace_span!("document_diagnostics").in_scope(move || {
657 tracing::trace!("work_done_progress_params: {:?}, partial_results: {:?}, position: {:?}, context: {:?}",
658 params.work_done_progress_params,
659 params.partial_result_params,
660 params.text_document,
661 params.identifier
662 );
663
664 let p = params.work_done_progress_params.work_done_token.map(
665 |tk| self.get_progress(tk)
666 );
667 self.inner.state().get_diagnostics(¶ms.text_document.uri.into(),p)
668 .map_or_else(|| Box::pin(std::future::ready(Ok(default()))) as _,
669 |f| Box::pin(f.map(Result::Ok)) as _
670 )
671 })
672 }
673
674 fn references(&mut self, params: lsp::ReferenceParams) -> Res<Option<Vec<lsp::Location>>> {
676 tracing::trace_span!("references").in_scope(move || {
677 tracing::trace!("work_done_progress_params: {:?}, partial_results: {:?}, position: {:?}, context: {:?}",
678 params.work_done_progress_params,
679 params.partial_result_params,
680 params.text_document_position,
681 params.context
682 );
683 let p = params.work_done_progress_params.work_done_token.map(
684 |tk| self.get_progress(tk)
685 );
686 self.inner.state().get_references(
687 params.text_document_position.text_document.uri.into(),
688 params.text_document_position.position,p
689 ).map_or_else(|| Box::pin(std::future::ready(Ok(None))) as _,
690 |f| Box::pin(f.map(Result::Ok)) as _
691 )
692 })
693 }
694
695 fn document_link(
697 &mut self,
698 params: lsp::DocumentLinkParams,
699 ) -> Res<Option<Vec<lsp::DocumentLink>>> {
700 tracing::trace_span!("document_link").in_scope(move || {
701 tracing::trace!(
702 "uri: {},work_done_progress_params: {:?}, partial_results: {:?}",
703 params.text_document.uri,
704 params.work_done_progress_params,
705 params.partial_result_params
706 );
707 let p = params
708 .work_done_progress_params
709 .work_done_token
710 .map(|tk| self.get_progress(tk));
711 self.inner
712 .state()
713 .get_links(¶ms.text_document.uri.into(), p)
714 .map_or_else(
715 || Box::pin(std::future::ready(Ok(None))) as _,
716 |f| Box::pin(f.map(Result::Ok)) as _,
717 )
718 })
719 }
720
721 fn hover(&mut self, params: lsp::HoverParams) -> Res<Option<lsp::Hover>> {
723 tracing::trace_span!("hover").in_scope(move || {
724 tracing::trace!(
725 "uri: {},work_done_progress_params: {:?}, position: {:?}",
726 params.text_document_position_params.text_document.uri,
727 params.work_done_progress_params,
728 params.text_document_position_params.position
729 );
730 let p = params
731 .work_done_progress_params
732 .work_done_token
733 .map(|tk| self.get_progress(tk));
734 self.inner
735 .state()
736 .get_hover(
737 ¶ms
738 .text_document_position_params
739 .text_document
740 .uri
741 .into(),
742 params.text_document_position_params.position,
743 p,
744 )
745 .map_or_else(
746 || Box::pin(std::future::ready(Ok(None))) as _,
747 |f| Box::pin(f.map(Result::Ok)) as _,
748 )
749 })
750 }
751
752 fn definition(
754 &mut self,
755 params: lsp::GotoDefinitionParams,
756 ) -> Res<Option<lsp::GotoDefinitionResponse>> {
757 tracing::trace_span!("definition").in_scope(move || {
758 tracing::trace!(
759 "uri: {},work_done_progress_params: {:?}, position: {:?}",
760 params.text_document_position_params.text_document.uri,
761 params.work_done_progress_params,
762 params.text_document_position_params.position
763 );
764 let p = params
765 .work_done_progress_params
766 .work_done_token
767 .map(|tk| self.get_progress(tk));
768 self.inner
769 .state()
770 .get_goto_definition(
771 params
772 .text_document_position_params
773 .text_document
774 .uri
775 .into(),
776 params.text_document_position_params.position,
777 p,
778 )
779 .map_or_else(
780 || Box::pin(std::future::ready(Ok(None))) as _,
781 |f| Box::pin(f.map(Result::Ok)) as _,
782 )
783 })
784 }
785
786 impl_request!(! code_lens = CodeLensRequest => (None));
787
788 impl_request!(! declaration = GotoDefinition => (None));
789
790 impl_request!(! workspace_diagnostic = WorkspaceDiagnosticRequest => (lsp::WorkspaceDiagnosticReportResult::Report(lsp::WorkspaceDiagnosticReport {items:Vec::new()})));
791 fn inlay_hint(&mut self, params: lsp::InlayHintParams) -> Res<Option<Vec<lsp::InlayHint>>> {
838 tracing::trace_span!("inlay hint").in_scope(move || {
839 tracing::trace!(
840 "uri: {},work_done_progress_params: {:?}",
841 params.text_document.uri,
842 params.work_done_progress_params,
843 );
844 let p = params
845 .work_done_progress_params
846 .work_done_token
847 .map(|tk| self.get_progress(tk));
848 self.inner
849 .state()
850 .get_inlay_hints(¶ms.text_document.uri.into(), p)
851 .map_or_else(
852 || Box::pin(std::future::ready(Ok(None))) as _,
853 |f| Box::pin(f.map(Result::Ok)) as _,
854 )
855 })
856 }
857 impl_request!(inlay_hint_resolve = InlayHintResolveRequest);
859
860 fn code_action(
862 &mut self,
863 params: lsp::CodeActionParams,
864 ) -> Res<Option<lsp::CodeActionResponse>> {
865 tracing::trace_span!("code_action").in_scope(move || {
866 tracing::trace!(
867 "uri: {},work_done_progress_params: {:?}; range: {:?}; context:{:?}",
868 params.text_document.uri, params.work_done_progress_params,
870 params.range,
871 params.context
872 );
873 let p = params
874 .work_done_progress_params
875 .work_done_token
876 .map(|tk| self.get_progress(tk));
877 self.inner
878 .state()
879 .get_codeaction(
880 params.text_document.uri.into(),
881 params.range,
882 params.context,
883 p,
884 )
885 .map_or_else(
886 || Box::pin(std::future::ready(Ok(None))) as _,
887 |f| Box::pin(f.map(Result::Ok)) as _,
888 )
889 })
890 }
891
892 fn prepare_call_hierarchy(
894 &mut self,
895 params: lsp::CallHierarchyPrepareParams,
896 ) -> Res<Option<Vec<lsp::CallHierarchyItem>>> {
897 tracing::trace_span!("prepare_call_hierarchy").in_scope(move || {
898 tracing::trace!(
899 "uri: {},work_done_progress_params: {:?}; position: {:?}",
900 params.text_document_position_params.text_document.uri,
901 params.work_done_progress_params,
902 params.text_document_position_params.position
903 );
904 let p = params
905 .work_done_progress_params
906 .work_done_token
907 .map(|tk| self.get_progress(tk));
908 self.inner
909 .state()
910 .prepare_module_hierarchy(
911 params
912 .text_document_position_params
913 .text_document
914 .uri
915 .into(),
916 p,
917 )
918 .map_or_else(
919 || Box::pin(std::future::ready(Ok(None))) as _,
920 |f| Box::pin(f.map(Result::Ok)) as _,
921 )
922 })
923 }
924
925 fn incoming_calls(
928 &mut self,
929 params: lsp::CallHierarchyIncomingCallsParams,
930 ) -> Res<Option<Vec<lsp::CallHierarchyIncomingCall>>> {
931 tracing::trace_span!("incoming_call_hierarchy").in_scope(move || {
932 tracing::trace!(
933 "uri: {},work_done_progress_params: {:?};",
934 params.item.uri,
935 params.work_done_progress_params,
936 );
937 let p = params
938 .work_done_progress_params
939 .work_done_token
940 .map(|tk| self.get_progress(tk));
941 if let Some(d) = params
942 .item
943 .data
944 .and_then(|d| d.as_str().and_then(|d| d.parse().ok()))
945 {
946 self.inner
947 .state()
948 .module_hierarchy_imports(params.item.uri, params.item.kind, d, p)
949 .map_or_else(
950 || Box::pin(std::future::ready(Ok(None))) as _,
951 |f| Box::pin(f.map(Result::Ok)) as _,
952 )
953 } else {
954 Box::pin(std::future::ready(Ok(None))) as _
955 }
956 })
957 }
958 impl_request!(outgoing_calls = CallHierarchyOutgoingCalls);
959
960 impl_request!(! document_highlight = DocumentHighlightRequest => (None));
961 impl_request!(! folding_range = FoldingRangeRequest => (None));
962
963 impl_request!(implementation = GotoImplementation);
964 impl_request!(type_definition = GotoTypeDefinition);
965 impl_request!(document_color = DocumentColor);
966 impl_request!(color_presentation = ColorPresentationRequest);
967 impl_request!(selection_range = SelectionRangeRequest);
968 impl_request!(moniker = MonikerRequest);
969 impl_request!(inline_value = InlineValueRequest);
970 impl_request!(on_type_formatting = OnTypeFormatting);
971 impl_request!(range_formatting = RangeFormatting);
972 impl_request!(formatting = Formatting);
973 impl_request!(prepare_rename = PrepareRenameRequest);
974 impl_request!(rename = Rename);
975 impl_request!(prepare_type_hierarchy = TypeHierarchyPrepare);
976 impl_request!(will_save_wait_until = WillSaveWaitUntil);
977
978 impl_request!(!completion = Completion => (None));
979
980 impl_request!(signature_help = SignatureHelpRequest);
981 impl_request!(linked_editing_range = LinkedEditingRange);
982
983 fn semantic_tokens_full(
986 &mut self,
987 params: lsp::SemanticTokensParams,
988 ) -> Res<Option<lsp::SemanticTokensResult>> {
989 tracing::trace_span!("semantic_tokens_full").in_scope(|| {
990 tracing::trace!(
991 "work_done_progress_params: {:?}, partial_results: {:?}, uri: {}",
992 params.work_done_progress_params,
993 params.partial_result_params,
994 params.text_document.uri
995 );
996 let p = params
997 .work_done_progress_params
998 .work_done_token
999 .map(|tk| self.get_progress(tk));
1000 self.inner
1001 .state()
1002 .get_semantic_tokens(¶ms.text_document.uri.into(), p, None)
1003 .map_or_else(
1004 || Box::pin(std::future::ready(Ok(None))) as _,
1005 |f| Box::pin(f.map(|r| Ok(r.map(lsp::SemanticTokensResult::Tokens)))) as _,
1006 )
1007 })
1008 }
1009
1010 fn semantic_tokens_range(
1012 &mut self,
1013 params: lsp::SemanticTokensRangeParams,
1014 ) -> Res<Option<lsp::SemanticTokensRangeResult>> {
1015 tracing::trace_span!("semantic_tokens_range").in_scope(|| {
1016 tracing::trace!(
1017 "work_done_progress_params: {:?}, partial_results: {:?}, range: {:?}, uri:{}",
1018 params.work_done_progress_params,
1019 params.partial_result_params,
1020 params.range,
1021 params.text_document.uri
1022 );
1023 let p = params
1024 .work_done_progress_params
1025 .work_done_token
1026 .map(|tk| self.get_progress(tk));
1027 self.inner
1028 .state()
1029 .get_semantic_tokens(¶ms.text_document.uri.into(), p, Some(params.range))
1030 .map_or_else(
1031 || Box::pin(std::future::ready(Ok(None))) as _,
1032 |f| Box::pin(f.map(|r| Ok(r.map(lsp::SemanticTokensRangeResult::Tokens)))) as _,
1033 )
1034 })
1035 }
1036
1037 fn semantic_tokens_full_delta(
1039 &mut self,
1040 params: lsp::SemanticTokensDeltaParams,
1041 ) -> Res<Option<lsp::SemanticTokensFullDeltaResult>> {
1042 tracing::info_span!("semantic_tokens_full_delta").in_scope(|| {
1043 tracing::info!("work_done_progress_params: {:?}, partial_results: {:?}, previous_result_id: {:?}, uri:{}",
1044 params.work_done_progress_params,
1045 params.partial_result_params,
1046 params.previous_result_id,
1047 params.text_document.uri
1048 );
1049 Box::pin(std::future::ready(Ok(None)))
1050 })
1051 }
1052
1053 impl_request!(will_create_files = WillCreateFiles);
1055 impl_request!(will_rename_files = WillRenameFiles);
1056 impl_request!(will_delete_files = WillDeleteFiles);
1057 impl_request!(symbol = WorkspaceSymbolRequest);
1058 impl_request!(execute_command = ExecuteCommand);
1059
1060 impl_request!(supertypes = TypeHierarchySupertypes);
1062 impl_request!(subtypes = TypeHierarchySubtypes);
1063
1064 impl_request!(completion_item_resolve = ResolveCompletionItem);
1066
1067 impl_request!(code_action_resolve = CodeActionResolveRequest);
1069
1070 impl_request!(workspace_symbol_resolve = WorkspaceSymbolResolve);
1072
1073 impl_request!(code_lens_resolve = CodeLensResolve);
1075
1076 impl_request!(document_link_resolve = DocumentLinkResolve);
1078}