flams_lsp/
implementation.rs

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(&params.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        //tracing::info!("Queueing [{id}]{{{rel_path}}}");
261        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                    // should be unreachable ?
312                    continue;
313                };
314                //let deps = deps.clone();
315                //let state = state.clone();
316                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                    // <- necessary, but I don't quite understand why
477                    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    // Notifications -------------------------------------------
518
519    //impl_notification!(! initialized = Initialized);
520    fn initialized(&mut self, _params: lsp::InitializedParams) -> Self::NotifyResult {
521        tracing::info!("LSP: initialized");
522        self.inner.initialized();
523        /*
524         */
525        ControlFlow::Continue(())
526    }
527
528    impl_notification!(!exit = Exit);
529
530    // workspace/
531    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    // textDocument/
539    //impl_notification!(! did_open = DidOpenTextDocument);
540    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    //impl_notification!(! did_change = DidChangeTextDocument);
557    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    //impl_notification!(! did_save = DidSaveTextDocument);
588    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    //impl_notification!(! did_close = DidCloseTextDocument);
602    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    // window/
608    // workDoneProgress/
609    impl_notification!(work_done_progress_cancel = WorkDoneProgressCancel);
610
611    // $/
612    impl_notification!(!set_trace = SetTrace);
613    impl_notification!(!cancel_request = Cancel);
614    impl_notification!(!progress = Progress);
615
616    // Requests -----------------------------------------------
617
618    // textDocument/
619
620    // impl_request!(document_symbol = DocumentSymbolRequest);
621    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(&params.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    // impl_request!(! document_diagnostic = DocumentDiagnosticRequest => (lsp::DocumentDiagnosticReportResult::Report(lsp::DocumentDiagnosticReport::Full(lsp::RelatedFullDocumentDiagnosticReport::default()))));
647    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(&params.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    //impl_request!(? references = References => (None));
675    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    //impl_request!(! document_link = DocumentLinkRequest => (None));
696    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(&params.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    // impl_request!(! hover = HoverRequest => (None));
722    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                    &params
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    // impl_request!(! definition = GotoDefinition => (None));
753    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    /*
792        #[must_use]
793        fn workspace_diagnostic(&mut self, params: lsp::WorkspaceDiagnosticParams) -> Res<lsp::WorkspaceDiagnosticReportResult> {
794            tracing::info_span!("workspace_diagnostics").in_scope(move || {
795                tracing::info!("work_done_progress_params: {:?}, partial_results: {:?}, identifier: {:?}, previous_results_id: {:?}",
796                    params.work_done_progress_params,
797                    params.partial_result_params,
798                    params.identifier,
799                    params.previous_result_ids
800                );
801                if let Some(_token) = params.partial_result_params.partial_result_token {
802                    if self.ws_diagnostics.load(Ordering::Relaxed) {
803                        self.ws_diagnostics.store(false, Ordering::Relaxed);
804                        return Box::pin(std::future::ready(Ok(
805                            lsp::WorkspaceDiagnosticReportResult::Partial(lsp::WorkspaceDiagnosticReportPartialResult {
806                                items:Vec::new()
807                            })
808                        )))
809                    }
810
811                    self.ws_diagnostics.store(true, Ordering::Relaxed);
812                    return Box::pin(std::future::ready(Ok(
813                        lsp::WorkspaceDiagnosticReportResult::Report(lsp::WorkspaceDiagnosticReport {
814                            items:Vec::new()
815                        })
816                    )))
817                }
818
819                /*
820                if let Some(p) = params.work_done_progress_params.work_done_token {
821                    self.get_progress(p).finish_delay();
822                }
823                if let Some(p) = params.partial_result_params.partial_result_token {
824                    self.get_progress(p).finish_delay();
825                }
826                */
827                Box::pin(std::future::ready(Ok(
828                    lsp::WorkspaceDiagnosticReportResult::Report(lsp::WorkspaceDiagnosticReport {
829                        items:Vec::new()
830                    })
831                )))
832            })
833        }
834    */
835
836    //impl_request!(! inlay_hint = InlayHintRequest => (None));
837    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(&params.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    // inlayHint/
858    impl_request!(inlay_hint_resolve = InlayHintResolveRequest);
859
860    //impl_request!(! code_action = CodeActionRequest => (None));
861    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, //.text_document_position_params.text_document.uri,
869                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    //impl_request!(prepare_call_hierarchy = CallHierarchyPrepare);
893    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    // callHierarchy/
926    //impl_request!(incoming_calls = CallHierarchyIncomingCalls);
927    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    // semanticTokens/
984    // impl_request!(semantic_tokens_full = SemanticTokensFullRequest);
985    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(&params.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    // impl_request!(semantic_tokens_range = SemanticTokensRangeRequest);
1011    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(&params.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    // impl_request!(semantic_tokens_full_delta = SemanticTokensFullDeltaRequest);
1038    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    // workspace/
1054    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    // typeHierarchy/
1061    impl_request!(supertypes = TypeHierarchySupertypes);
1062    impl_request!(subtypes = TypeHierarchySubtypes);
1063
1064    // completionItem/
1065    impl_request!(completion_item_resolve = ResolveCompletionItem);
1066
1067    // codeAction/
1068    impl_request!(code_action_resolve = CodeActionResolveRequest);
1069
1070    // workspaceSymbol/
1071    impl_request!(workspace_symbol_resolve = WorkspaceSymbolResolve);
1072
1073    // codeLens/
1074    impl_request!(code_lens_resolve = CodeLensResolve);
1075
1076    // documentLink/
1077    impl_request!(document_link_resolve = DocumentLinkResolve);
1078}