Skip to main content

flams_lsp/
annotations.rs

1#![allow(clippy::too_many_lines)]
2
3use std::fmt::Write;
4
5use crate::capabilities::STeXSemanticTokens;
6use crate::documents::LSPDocument;
7use crate::{
8    IsLSPRange, ProgressCallbackClient,
9    state::{DocData, LSPState, UrlOrFile},
10};
11use async_lsp::lsp_types as lsp;
12use flams_math_archives::LocalArchive;
13use flams_math_archives::backend::{GlobalBackend, LocalBackend};
14use flams_stex::quickparse::stex::rules::{IncludeProblemArg, SRefOptsA, SRefOptsB};
15use flams_stex::quickparse::{
16    latex::ParsedKeyValue,
17    stex::{
18        AnnotIter, DiagnosticLevel, STeXAnnot, STeXDiagnostic, STeXParseDataI,
19        rules::{
20            MathStructureArg, NotationArg, ParagraphArg, ProblemArg, SModuleArg, SymdeclArg,
21            SymdefArg, TextSymdeclArg, VardefArg,
22        },
23        structs::{
24            InlineMorphAssKind, InlineMorphAssign, ModuleOrStruct, MorphismKind, SymbolReference,
25        },
26    },
27};
28use flams_utils::sourcerefs::{ByteOffset, StringPosition};
29use flams_utils::{
30    prelude::TreeChildIter,
31    sourcerefs::{LSPLineCol, StringRange},
32};
33use ftml_ontology::narrative::elements::paragraphs::ParagraphKind;
34use ftml_uris::{
35    ArchiveId, ArchiveUri, IsDomainUri, IsNarrativeUri, ModuleUri, SymbolUri, Uri, UriWithArchive,
36    UriWithPath,
37};
38use futures::FutureExt;
39use smallvec::SmallVec;
40
41trait AnnotExt: Sized {
42    fn as_symbol(&self) -> Option<(lsp::DocumentSymbol, &[Self])>;
43    fn links(&self, top_archive: Option<&ArchiveUri>, f: impl FnMut(lsp::DocumentLink));
44    fn goto_definition(
45        &self,
46        in_doc: &UrlOrFile,
47        pos: LSPLineCol,
48    ) -> Option<lsp::GotoDefinitionResponse>;
49    fn semantic_tokens(&self, cont: &mut impl FnMut(StringRange<LSPLineCol>, u32));
50    fn hover(
51        &self,
52        top_archive: Option<&ArchiveUri>,
53        pos: LSPLineCol,
54    ) -> Option<either_of::Either<lsp::Hover, (lsp::Range, SymbolReference<LSPLineCol>)>>;
55    fn inlay_hint(&self) -> Option<lsp::InlayHint>;
56    fn code_action(&self, pos: LSPLineCol, url: &lsp::Url) -> lsp::CodeActionResponse;
57}
58
59pub(crate) fn uri_from_archive_relpath(id: &ArchiveId, relpath: &str) -> Option<lsp::Url> {
60    let path = GlobalBackend.with_local_archive(id, |a| a.map(LocalArchive::source_dir))?;
61    let path = relpath.split('/').fold(path, |p, s| p.join(s));
62    lsp::Url::from_file_path(path).ok()
63}
64
65#[allow(deprecated)]
66impl AnnotExt for STeXAnnot {
67    fn as_symbol(&self) -> Option<(lsp::DocumentSymbol, &[Self])> {
68        match self {
69            Self::Module {
70                uri,
71                full_range,
72                name_range,
73                children,
74                ..
75            } => Some((
76                lsp::DocumentSymbol {
77                    name: uri.to_string(),
78                    detail: None,
79                    kind: lsp::SymbolKind::MODULE,
80                    tags: None,
81                    deprecated: None,
82                    range: full_range.into_range(),
83                    selection_range: name_range.into_range(),
84                    children: None,
85                },
86                children,
87            )),
88            Self::MathStructure {
89                uri,
90                name_range,
91                full_range,
92                children,
93                ..
94            } => Some((
95                lsp::DocumentSymbol {
96                    name: uri.uri.to_string(),
97                    detail: None,
98                    kind: lsp::SymbolKind::STRUCT,
99                    tags: None,
100                    deprecated: None,
101                    range: full_range.into_range(),
102                    selection_range: name_range.into_range(),
103                    children: None,
104                },
105                children,
106            )),
107            Self::ConservativeExt {
108                uri,
109                full_range,
110                extstructure_range,
111                children,
112                ..
113            } => Some((
114                lsp::DocumentSymbol {
115                    name: format!("{}_EXT", uri.uri),
116                    detail: None,
117                    kind: lsp::SymbolKind::STRUCT,
118                    tags: None,
119                    deprecated: None,
120                    range: full_range.into_range(),
121                    selection_range: extstructure_range.into_range(),
122                    children: None,
123                },
124                children,
125            )),
126            Self::MorphismEnv {
127                full_range,
128                env_range,
129                uri,
130                children,
131                ..
132            } => Some((
133                lsp::DocumentSymbol {
134                    name: uri.to_string(),
135                    detail: None,
136                    kind: lsp::SymbolKind::INTERFACE,
137                    tags: None,
138                    deprecated: None,
139                    range: full_range.into_range(),
140                    selection_range: env_range.into_range(),
141                    children: None,
142                },
143                children,
144            )),
145            Self::InlineMorphism {
146                full_range,
147                uri,
148                token_range,
149                ..
150            } => Some((
151                lsp::DocumentSymbol {
152                    name: uri.to_string(),
153                    detail: None,
154                    kind: lsp::SymbolKind::INTERFACE,
155                    tags: None,
156                    deprecated: None,
157                    range: full_range.into_range(),
158                    selection_range: token_range.into_range(),
159                    children: None,
160                },
161                &[],
162            )),
163            Self::Paragraph {
164                kind,
165                full_range,
166                name_range,
167                children,
168                ..
169            }
170            | Self::InlineParagraph {
171                kind,
172                full_range,
173                token_range: name_range,
174                children,
175                ..
176            } => Some((
177                lsp::DocumentSymbol {
178                    name: kind.to_string(),
179                    detail: None,
180                    kind: lsp::SymbolKind::PACKAGE,
181                    tags: None,
182                    deprecated: None,
183                    range: full_range.into_range(),
184                    selection_range: name_range.into_range(),
185                    children: None,
186                },
187                children,
188            )),
189            Self::Problem {
190                full_range,
191                name_range,
192                children,
193                ..
194            } => Some((
195                lsp::DocumentSymbol {
196                    name: "problem".to_string(),
197                    detail: None,
198                    kind: lsp::SymbolKind::PACKAGE,
199                    tags: None,
200                    deprecated: None,
201                    range: full_range.into_range(),
202                    selection_range: name_range.into_range(),
203                    children: None,
204                },
205                children,
206            )),
207            Self::Symdecl {
208                uri,
209                main_name_range,
210                full_range,
211                ..
212            }
213            | Self::TextSymdecl {
214                uri,
215                main_name_range,
216                full_range,
217                ..
218            }
219            | Self::Symdef {
220                uri,
221                main_name_range,
222                full_range,
223                ..
224            } => Some((
225                lsp::DocumentSymbol {
226                    name: uri.uri.to_string(),
227                    detail: None,
228                    kind: lsp::SymbolKind::OBJECT,
229                    tags: None,
230                    deprecated: None,
231                    range: full_range.into_range(),
232                    selection_range: main_name_range.into_range(),
233                    children: None,
234                },
235                &[],
236            )),
237            Self::Vardef {
238                name,
239                main_name_range,
240                full_range,
241                ..
242            }
243            | Self::Varseq {
244                name,
245                main_name_range,
246                full_range,
247                ..
248            } => Some((
249                lsp::DocumentSymbol {
250                    name: name.to_string(),
251                    detail: None,
252                    kind: lsp::SymbolKind::VARIABLE,
253                    tags: None,
254                    deprecated: None,
255                    range: full_range.into_range(),
256                    selection_range: main_name_range.into_range(),
257                    children: None,
258                },
259                &[],
260            )),
261            Self::ImportModule {
262                module, full_range, ..
263            } => Some((
264                lsp::DocumentSymbol {
265                    name: format!("import@{}", module.uri),
266                    detail: Some(module.uri.to_string()),
267                    kind: lsp::SymbolKind::PACKAGE,
268                    tags: None,
269                    deprecated: None,
270                    range: full_range.into_range(),
271                    selection_range: full_range.into_range(),
272                    children: None,
273                },
274                &[],
275            )),
276            Self::UseModule {
277                module, full_range, ..
278            } => Some((
279                lsp::DocumentSymbol {
280                    name: format!("usemodule@{}", module.uri),
281                    detail: Some(module.uri.to_string()),
282                    kind: lsp::SymbolKind::PACKAGE,
283                    tags: None,
284                    deprecated: None,
285                    range: full_range.into_range(),
286                    selection_range: full_range.into_range(),
287                    children: None,
288                },
289                &[],
290            )),
291            Self::UseStructure {
292                structure,
293                full_range,
294                ..
295            } => Some((
296                lsp::DocumentSymbol {
297                    name: format!("usestructure@{}", structure.uri),
298                    detail: None,
299                    kind: lsp::SymbolKind::PACKAGE,
300                    tags: None,
301                    deprecated: None,
302                    range: full_range.into_range(),
303                    selection_range: full_range.into_range(),
304                    children: None,
305                },
306                &[],
307            )),
308            Self::SetMetatheory {
309                module, full_range, ..
310            } => Some((
311                lsp::DocumentSymbol {
312                    name: format!("metatheory@{}", module.uri),
313                    detail: Some(module.uri.to_string()),
314                    kind: lsp::SymbolKind::NAMESPACE,
315                    tags: None,
316                    deprecated: None,
317                    range: full_range.into_range(),
318                    selection_range: full_range.into_range(),
319                    children: None,
320                },
321                &[],
322            )),
323            Self::Inputref {
324                archive,
325                filepath,
326                full_range: range,
327                ..
328            }
329            | Self::IncludeProblem {
330                archive,
331                filepath,
332                full_range: range,
333                ..
334            } => Some((
335                lsp::DocumentSymbol {
336                    name: archive.as_ref().map_or_else(
337                        || format!("inputref@{}", filepath.0),
338                        |(a, _)| format!("inputref@[{a}]{}", filepath.0),
339                    ),
340                    detail: None,
341                    kind: lsp::SymbolKind::PACKAGE,
342                    tags: None,
343                    deprecated: None,
344                    range: range.into_range(),
345                    selection_range: range.into_range(),
346                    children: None,
347                },
348                &[],
349            )),
350            Self::MHInput {
351                archive,
352                filepath,
353                full_range: range,
354                ..
355            } => Some((
356                lsp::DocumentSymbol {
357                    name: archive.as_ref().map_or_else(
358                        || format!("mhinput@{}", filepath.0),
359                        |(a, _)| format!("mhinput@[{a}]{}", filepath.0),
360                    ),
361                    detail: None,
362                    kind: lsp::SymbolKind::PACKAGE,
363                    tags: None,
364                    deprecated: None,
365                    range: range.into_range(),
366                    selection_range: range.into_range(),
367                    children: None,
368                },
369                &[],
370            )),
371            Self::MHGraphics { .. }
372            | Self::SemanticMacro { .. }
373            | Self::VariableMacro { .. }
374            | Self::SymName { .. }
375            | Self::Symref { .. }
376            | Self::Notation { .. }
377            | Self::Svar { .. }
378            | Self::Symuse { .. }
379            | Self::Definiens { .. }
380            | Self::Defnotation { .. }
381            | Self::RenameDecl { .. }
382            | Self::Precondition { .. }
383            | Self::Objective { .. }
384            | Self::Assign { .. }
385            | Self::SRef { .. }
386            | Self::SnifySuggestion { .. } => None,
387        }
388    }
389
390    fn links(&self, top_archive: Option<&ArchiveUri>, mut cont: impl FnMut(lsp::DocumentLink)) {
391        match self {
392            Self::IncludeProblem {
393                archive, filepath, ..
394            } => {
395                let Some(a) = archive
396                    .as_ref()
397                    .map_or_else(|| top_archive.map(ArchiveUri::archive_id), |(a, _)| Some(a))
398                else {
399                    return;
400                };
401                let Some(uri) = uri_from_archive_relpath(a, &filepath.0) else {
402                    return;
403                };
404                cont(lsp::DocumentLink {
405                    range: filepath.1.into_range(),
406                    target: Some(uri),
407                    tooltip: None,
408                    data: None,
409                });
410            }
411            Self::SRef {
412                label_range,
413                opt_args,
414                in_opt_args,
415                target_path,
416                in_doc,
417                ..
418            } => {
419                if let Ok(url) = lsp::Url::from_file_path(target_path) {
420                    for o in opt_args {
421                        if let SRefOptsA::File(f) = o {
422                            cont(lsp::DocumentLink {
423                                range: f.val_range.into_range(),
424                                target: Some(url.clone()),
425                                tooltip: None,
426                                data: None,
427                            });
428                            break;
429                        }
430                    }
431                    cont(lsp::DocumentLink {
432                        range: label_range.into_range(),
433                        target: Some(url),
434                        tooltip: None,
435                        data: None,
436                    });
437                }
438                if let Some((_, id)) = in_doc
439                    && let Ok(url) = lsp::Url::from_file_path(id)
440                    && let Some(rng) = in_opt_args.iter().find_map(|a| {
441                        if let SRefOptsB::File(f) = a {
442                            Some(f.val_range)
443                        } else {
444                            None
445                        }
446                    })
447                {
448                    cont(lsp::DocumentLink {
449                        range: rng.into_range(),
450                        target: Some(url),
451                        tooltip: None,
452                        data: None,
453                    });
454                }
455            }
456            Self::MHGraphics {
457                archive, filepath, ..
458            } => {
459                let Some(a) = archive.as_ref().map_or_else(
460                    || top_archive.map(UriWithArchive::archive_id),
461                    |(a, _)| Some(a),
462                ) else {
463                    return;
464                };
465                let Some(uri) = uri_from_archive_relpath(a, &filepath.0) else {
466                    return;
467                };
468                cont(lsp::DocumentLink {
469                    range: filepath.1.into_range(),
470                    target: Some(uri),
471                    tooltip: None,
472                    data: None,
473                });
474            }
475            Self::Inputref {
476                archive,
477                token_range,
478                filepath,
479                full_range: range,
480                ..
481            }
482            | Self::MHInput {
483                archive,
484                token_range,
485                filepath,
486                full_range: range,
487                ..
488            } => {
489                let Some(a) = archive.as_ref().map_or_else(
490                    || top_archive.map(UriWithArchive::archive_id),
491                    |(a, _)| Some(a),
492                ) else {
493                    return;
494                };
495                let Some(uri) = uri_from_archive_relpath(a, &filepath.0) else {
496                    return;
497                };
498                let mut range = *range;
499                range.start = token_range.end;
500                cont(lsp::DocumentLink {
501                    range: range.into_range(),
502                    target: Some(uri),
503                    tooltip: None,
504                    data: None,
505                });
506            }
507            Self::ImportModule { .. }
508            | Self::UseModule { .. }
509            | Self::SemanticMacro { .. }
510            | Self::VariableMacro { .. }
511            | Self::SetMetatheory { .. }
512            | Self::Module { .. }
513            | Self::MathStructure { .. }
514            | Self::Symdecl { .. }
515            | Self::TextSymdecl { .. }
516            | Self::SymName { .. }
517            | Self::Symref { .. }
518            | Self::Notation { .. }
519            | Self::Symdef { .. }
520            | Self::Vardef { .. }
521            | Self::Paragraph { .. }
522            | Self::Symuse { .. }
523            | Self::Svar { .. }
524            | Self::Varseq { .. }
525            | Self::Definiens { .. }
526            | Self::Defnotation { .. }
527            | Self::ConservativeExt { .. }
528            | Self::UseStructure { .. }
529            | Self::InlineParagraph { .. }
530            | Self::Problem { .. }
531            | Self::MorphismEnv { .. }
532            | Self::RenameDecl { .. }
533            | Self::Precondition { .. }
534            | Self::Objective { .. }
535            | Self::Assign { .. }
536            | Self::InlineMorphism { .. }
537            | Self::SnifySuggestion { .. } => (),
538        }
539    }
540
541    fn semantic_tokens(&self, cont: &mut impl FnMut(StringRange<LSPLineCol>, u32)) {
542        match self {
543            Self::SRef {
544                token_range,
545                opt_args,
546                in_opt_args,
547                ..
548            } => {
549                use SRefOptsA as A;
550                use SRefOptsB as B;
551                cont(*token_range, STeXSemanticTokens::REF_MACRO);
552                for o in opt_args {
553                    match o {
554                        A::Archive(a) | A::File(a) => {
555                            cont(a.key_range, STeXSemanticTokens::KEYWORD);
556                        }
557                        A::Fallback(a) => {
558                            cont(a.key_range, STeXSemanticTokens::KEYWORD);
559                            for e in &a.val {
560                                e.semantic_tokens(cont);
561                            }
562                        }
563                        A::Pre(a) | A::Post(a) => {
564                            cont(a.key_range, STeXSemanticTokens::KEYWORD);
565                        }
566                    }
567                }
568                for o in in_opt_args {
569                    match o {
570                        B::Archive(a) | B::File(a) => {
571                            cont(a.key_range, STeXSemanticTokens::KEYWORD);
572                        }
573                        B::Title(a) => {
574                            cont(a.key_range, STeXSemanticTokens::KEYWORD);
575                            for e in &a.val {
576                                e.semantic_tokens(cont);
577                            }
578                        }
579                    }
580                }
581            }
582            Self::Module {
583                name_range,
584                full_range,
585                smodule_range,
586                opts,
587                children,
588                ..
589            } => {
590                cont(*smodule_range, STeXSemanticTokens::DECLARATION);
591                for o in opts {
592                    match o {
593                        SModuleArg::Title(v) => {
594                            cont(v.key_range, STeXSemanticTokens::KEYWORD);
595                            for e in &v.val {
596                                e.semantic_tokens(cont);
597                            }
598                        }
599                        SModuleArg::Sig(ParsedKeyValue {
600                            key_range,
601                            val_range,
602                            ..
603                        }) => {
604                            cont(*key_range, STeXSemanticTokens::KEYWORD);
605                            cont(*val_range, STeXSemanticTokens::KEYWORD);
606                        }
607                        //SModuleArg::Creators(ParsedKeyValue{key_range,..}) |
608                        //SModuleArg::Contributors(ParsedKeyValue{key_range,..}) |
609                        SModuleArg::Meta(ParsedKeyValue { key_range, .. }) => {
610                            cont(*key_range, STeXSemanticTokens::KEYWORD);
611                        }
612                    }
613                }
614                cont(*name_range, STeXSemanticTokens::NAME);
615                for c in children {
616                    c.semantic_tokens(cont);
617                }
618                let mut end_range = *full_range;
619                end_range.end.col -= 1;
620                end_range.start.line = end_range.end.line;
621                #[allow(clippy::cast_possible_truncation)]
622                {
623                    end_range.start.col = end_range.end.col - const { "smodule".len() as u32 };
624                }
625                cont(end_range, STeXSemanticTokens::DECLARATION);
626            }
627            Self::MathStructure {
628                extends,
629                name_range,
630                opts,
631                full_range,
632                children,
633                mathstructure_range,
634                ..
635            } => {
636                cont(*mathstructure_range, STeXSemanticTokens::DECLARATION);
637                cont(*name_range, STeXSemanticTokens::NAME);
638                for o in opts {
639                    match o {
640                        MathStructureArg::This(ParsedKeyValue { key_range, val, .. }) => {
641                            cont(*key_range, STeXSemanticTokens::KEYWORD);
642                            for e in val {
643                                e.semantic_tokens(cont);
644                            }
645                        }
646                        MathStructureArg::Name(range, _) => {
647                            cont(*range, STeXSemanticTokens::NAME);
648                        }
649                    }
650                }
651                for (_, r) in extends {
652                    cont(*r, STeXSemanticTokens::SYMBOL);
653                }
654                for c in children {
655                    c.semantic_tokens(cont);
656                }
657                let mut end_range = *full_range;
658                end_range.end.col -= 1;
659                end_range.start.line = end_range.end.line;
660                let s = if extends.is_empty() {
661                    "mathstructure"
662                } else {
663                    "extstructure"
664                };
665                end_range.start.col = end_range.end.col - s.len() as u32;
666                cont(end_range, STeXSemanticTokens::DECLARATION);
667            }
668            Self::ConservativeExt {
669                ext_range,
670                full_range,
671                extstructure_range,
672                children,
673                ..
674            } => {
675                cont(*extstructure_range, STeXSemanticTokens::DECLARATION);
676                cont(*ext_range, STeXSemanticTokens::SYMBOL);
677                for c in children {
678                    c.semantic_tokens(cont);
679                }
680                let mut end_range = *full_range;
681                end_range.end.col -= 1;
682                end_range.start.line = end_range.end.line;
683                end_range.start.col = end_range.end.col - "extstructure*".len() as u32;
684                cont(end_range, STeXSemanticTokens::DECLARATION);
685            }
686            Self::MorphismEnv {
687                env_range,
688                star,
689                kind,
690                name_range,
691                domain_range,
692                full_range,
693                domain,
694                children,
695                ..
696            } => {
697                cont(*env_range, STeXSemanticTokens::DECLARATION);
698                cont(*name_range, STeXSemanticTokens::NAME);
699                match domain {
700                    ModuleOrStruct::Struct(_) => cont(*domain_range, STeXSemanticTokens::SYMBOL),
701                    _ => (),
702                }
703                for c in children {
704                    c.semantic_tokens(cont);
705                }
706
707                let mut end_range = *full_range;
708                end_range.end.col -= 1;
709                end_range.start.line = end_range.end.line;
710                let len = match kind {
711                    MorphismKind::CopyModule => "copymodule".len(),
712                    MorphismKind::InterpretModule => "interpretmodule".len(),
713                };
714                let len = if *star { len + 1 } else { len };
715                end_range.start.col = end_range.end.col - len as u32;
716                cont(end_range, STeXSemanticTokens::DECLARATION);
717            }
718            Self::InlineMorphism {
719                token_range,
720                name_range,
721                domain_range,
722                domain,
723                assignments,
724                ..
725            } => {
726                cont(*token_range, STeXSemanticTokens::DECLARATION);
727                cont(*name_range, STeXSemanticTokens::NAME);
728                match domain {
729                    ModuleOrStruct::Struct(_) => cont(*domain_range, STeXSemanticTokens::SYMBOL),
730                    _ => (),
731                }
732                for InlineMorphAssign {
733                    first,
734                    second,
735                    symbol_range,
736                    ..
737                } in assignments
738                {
739                    cont(*symbol_range, STeXSemanticTokens::SYMBOL);
740                    if let Some((e, knd)) = first {
741                        let end = LSPLineCol::new(e.line, e.col + 1);
742                        let range = StringRange { start: *e, end };
743                        cont(range, STeXSemanticTokens::KEYWORD);
744                        match knd {
745                            InlineMorphAssKind::Df(v) => {
746                                for c in v {
747                                    c.semantic_tokens(cont);
748                                }
749                            }
750                            InlineMorphAssKind::Rename(mn, _, n) => {
751                                if let Some((_, mn)) = mn {
752                                    cont(*mn, STeXSemanticTokens::NAME);
753                                }
754                                cont(*n, STeXSemanticTokens::NAME);
755                            }
756                        }
757                    }
758                    if let Some((e, knd)) = second {
759                        let end = LSPLineCol::new(e.line, e.col + 1);
760                        let range = StringRange { start: *e, end };
761                        cont(range, STeXSemanticTokens::KEYWORD);
762                        match knd {
763                            InlineMorphAssKind::Df(v) => {
764                                for c in v {
765                                    c.semantic_tokens(cont);
766                                }
767                            }
768                            InlineMorphAssKind::Rename(mn, _, n) => {
769                                if let Some((_, mn)) = mn {
770                                    cont(*mn, STeXSemanticTokens::NAME);
771                                }
772                                cont(*n, STeXSemanticTokens::NAME);
773                            }
774                        }
775                    }
776                }
777            }
778            Self::UseModule { token_range, .. } => cont(*token_range, STeXSemanticTokens::LOCAL),
779            Self::UseStructure {
780                token_range,
781                structure_range,
782                ..
783            } => {
784                cont(*token_range, STeXSemanticTokens::LOCAL);
785                cont(*structure_range, STeXSemanticTokens::SYMBOL);
786            }
787            Self::IncludeProblem {
788                token_range, args, ..
789            } => {
790                cont(*token_range, STeXSemanticTokens::REF_MACRO);
791                for a in args {
792                    let r = match a {
793                        IncludeProblemArg::Min(m) => m.key_range,
794                        IncludeProblemArg::Pts(m) => m.key_range,
795                        IncludeProblemArg::Archive(m) => m.key_range,
796                    };
797                    cont(r, STeXSemanticTokens::KEYWORD);
798                }
799            }
800            Self::Inputref {
801                token_range: range, ..
802            }
803            | Self::MHInput {
804                token_range: range, ..
805            }
806            | Self::MHGraphics {
807                token_range: range, ..
808            }
809            | Self::Defnotation { full_range: range } => {
810                cont(*range, STeXSemanticTokens::REF_MACRO)
811            }
812            Self::SetMetatheory { token_range, .. } | Self::ImportModule { token_range, .. } => {
813                cont(*token_range, STeXSemanticTokens::DECLARATION)
814            }
815            Self::SemanticMacro { token_range, .. } => {
816                cont(*token_range, STeXSemanticTokens::SYMBOL)
817            }
818            Self::VariableMacro { token_range, .. } => {
819                cont(*token_range, STeXSemanticTokens::VARIABLE)
820            }
821            Self::Problem {
822                full_range,
823                name_range,
824                parsed_args,
825                children,
826                ..
827            } => {
828                cont(*name_range, STeXSemanticTokens::REF_MACRO);
829                for e in parsed_args {
830                    match e {
831                        /*ProblemArg::Name(ParsedKeyValue{key_range,val_range,..}) => {
832                            cont(*key_range,STeXSemanticTokens::KEYWORD);
833                            cont(*val_range,STeXSemanticTokens::NAME);
834                        }*/
835                        ProblemArg::Autogradable(ParsedKeyValue {
836                            key_range,
837                            val_range,
838                            ..
839                        }) => {
840                            cont(*key_range, STeXSemanticTokens::KEYWORD);
841                            cont(*val_range, STeXSemanticTokens::KEYWORD);
842                        }
843                        ProblemArg::Style(ParsedKeyValue { key_range, .. })
844                        | ProblemArg::Pts(ParsedKeyValue { key_range, .. })
845                        | ProblemArg::Min(ParsedKeyValue { key_range, .. })
846                        | ProblemArg::Id(ParsedKeyValue { key_range, .. }) => {
847                            cont(*key_range, STeXSemanticTokens::KEYWORD)
848                        }
849                        ProblemArg::Title(ParsedKeyValue { key_range, val, .. }) => {
850                            cont(*key_range, STeXSemanticTokens::KEYWORD);
851                            for c in val {
852                                c.semantic_tokens(cont);
853                            }
854                        }
855                    }
856                }
857                for c in children {
858                    c.semantic_tokens(cont);
859                }
860                let mut end_range = *full_range;
861                end_range.end.col -= 1;
862                end_range.start.line = end_range.end.line;
863                cont(end_range, STeXSemanticTokens::REF_MACRO);
864            }
865            Self::Paragraph {
866                kind,
867                symbol,
868                name_range,
869                parsed_args,
870                children,
871                full_range,
872                ..
873            } => {
874                if symbol.is_some() {
875                    cont(*name_range, STeXSemanticTokens::DECLARATION);
876                } else {
877                    cont(*name_range, STeXSemanticTokens::REF_MACRO);
878                }
879                for e in parsed_args {
880                    match e {
881                        ParagraphArg::Tp(ParsedKeyValue { key_range, val, .. })
882                        | ParagraphArg::Df(ParsedKeyValue { key_range, val, .. })
883                        | ParagraphArg::Return(ParsedKeyValue { key_range, val, .. })
884                        | ParagraphArg::Argtypes(ParsedKeyValue { key_range, val, .. })
885                        | ParagraphArg::Title(ParsedKeyValue { key_range, val, .. }) => {
886                            cont(*key_range, STeXSemanticTokens::KEYWORD);
887                            for c in val {
888                                c.semantic_tokens(cont);
889                            }
890                        }
891                        ParagraphArg::Args(ParsedKeyValue {
892                            key_range,
893                            val_range,
894                            ..
895                        }) => {
896                            cont(*key_range, STeXSemanticTokens::KEYWORD);
897                            cont(*val_range, STeXSemanticTokens::KEYWORD);
898                        }
899                        ParagraphArg::Name(ParsedKeyValue {
900                            key_range,
901                            val_range,
902                            ..
903                        })
904                        | ParagraphArg::MacroName(ParsedKeyValue {
905                            key_range,
906                            val_range,
907                            ..
908                        }) => {
909                            cont(*key_range, STeXSemanticTokens::KEYWORD);
910                            cont(*val_range, STeXSemanticTokens::NAME);
911                        }
912                        ParagraphArg::Style(ParsedKeyValue { key_range, .. })
913                        | ParagraphArg::Assoc(ParsedKeyValue { key_range, .. })
914                        | ParagraphArg::Role(ParsedKeyValue { key_range, .. })
915                        | ParagraphArg::Reorder(ParsedKeyValue { key_range, .. })
916                        | ParagraphArg::From(ParsedKeyValue { key_range, .. })
917                        | ParagraphArg::To(ParsedKeyValue { key_range, .. })
918                        | ParagraphArg::Judgment(ParsedKeyValue { key_range, .. })
919                        | ParagraphArg::Id(ParsedKeyValue { key_range, .. }) => {
920                            cont(*key_range, STeXSemanticTokens::KEYWORD)
921                        }
922                        ParagraphArg::Fors(ParsedKeyValue { key_range, val, .. }) => {
923                            cont(*key_range, STeXSemanticTokens::KEYWORD);
924                            for (_, f) in val {
925                                cont(*f, STeXSemanticTokens::SYMBOL);
926                            }
927                        }
928                    }
929                }
930                for c in children {
931                    c.semantic_tokens(cont);
932                }
933                let mut end_range = *full_range;
934                end_range.end.col -= 1;
935                end_range.start.line = end_range.end.line;
936                let parname = match kind {
937                    ParagraphKind::Definition => "sdefinition".len(),
938                    ParagraphKind::Paragraph => "sparagraph".len(),
939                    ParagraphKind::Proof => "sproof".len(),
940                    ParagraphKind::Example => "sexample".len(),
941                    ParagraphKind::Assertion => "sassertion".len(),
942                    _ => return,
943                };
944                end_range.start.col = end_range.end.col - parname as u32;
945                if symbol.is_some() {
946                    cont(end_range, STeXSemanticTokens::DECLARATION);
947                } else {
948                    cont(end_range, STeXSemanticTokens::REF_MACRO);
949                }
950            }
951            Self::InlineParagraph {
952                symbol,
953                token_range,
954                parsed_args,
955                children,
956                ..
957            } => {
958                if symbol.is_some() {
959                    cont(*token_range, STeXSemanticTokens::DECLARATION);
960                } else {
961                    cont(*token_range, STeXSemanticTokens::REF_MACRO);
962                }
963                for e in parsed_args {
964                    match e {
965                        ParagraphArg::Tp(ParsedKeyValue { key_range, val, .. })
966                        | ParagraphArg::Df(ParsedKeyValue { key_range, val, .. })
967                        | ParagraphArg::Return(ParsedKeyValue { key_range, val, .. })
968                        | ParagraphArg::Argtypes(ParsedKeyValue { key_range, val, .. })
969                        | ParagraphArg::Title(ParsedKeyValue { key_range, val, .. }) => {
970                            cont(*key_range, STeXSemanticTokens::KEYWORD);
971                            for c in val {
972                                c.semantic_tokens(cont);
973                            }
974                        }
975                        ParagraphArg::Args(ParsedKeyValue {
976                            key_range,
977                            val_range,
978                            ..
979                        }) => {
980                            cont(*key_range, STeXSemanticTokens::KEYWORD);
981                            cont(*val_range, STeXSemanticTokens::KEYWORD);
982                        }
983                        ParagraphArg::Name(ParsedKeyValue {
984                            key_range,
985                            val_range,
986                            ..
987                        })
988                        | ParagraphArg::MacroName(ParsedKeyValue {
989                            key_range,
990                            val_range,
991                            ..
992                        }) => {
993                            cont(*key_range, STeXSemanticTokens::KEYWORD);
994                            cont(*val_range, STeXSemanticTokens::NAME);
995                        }
996                        ParagraphArg::Style(ParsedKeyValue { key_range, .. })
997                        | ParagraphArg::Assoc(ParsedKeyValue { key_range, .. })
998                        | ParagraphArg::Role(ParsedKeyValue { key_range, .. })
999                        | ParagraphArg::Reorder(ParsedKeyValue { key_range, .. })
1000                        | ParagraphArg::Judgment(ParsedKeyValue { key_range, .. })
1001                        | ParagraphArg::From(ParsedKeyValue { key_range, .. })
1002                        | ParagraphArg::To(ParsedKeyValue { key_range, .. })
1003                        | ParagraphArg::Id(ParsedKeyValue { key_range, .. }) => {
1004                            cont(*key_range, STeXSemanticTokens::KEYWORD)
1005                        }
1006                        ParagraphArg::Fors(ParsedKeyValue { key_range, val, .. }) => {
1007                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1008                            for (_, f) in val {
1009                                cont(*f, STeXSemanticTokens::SYMBOL);
1010                            }
1011                        }
1012                    }
1013                }
1014                for c in children {
1015                    c.semantic_tokens(cont);
1016                }
1017            }
1018            Self::Symdecl {
1019                main_name_range,
1020                token_range,
1021                parsed_args,
1022                ..
1023            } => {
1024                cont(*token_range, STeXSemanticTokens::DECLARATION);
1025                cont(*main_name_range, STeXSemanticTokens::NAME);
1026
1027                for e in parsed_args {
1028                    match e {
1029                        SymdeclArg::Tp(ParsedKeyValue { key_range, val, .. })
1030                        | SymdeclArg::Df(ParsedKeyValue { key_range, val, .. })
1031                        | SymdeclArg::Return(ParsedKeyValue { key_range, val, .. })
1032                        | SymdeclArg::Argtypes(ParsedKeyValue { key_range, val, .. }) => {
1033                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1034                            for c in val {
1035                                c.semantic_tokens(cont);
1036                            }
1037                        }
1038                        SymdeclArg::Args(ParsedKeyValue {
1039                            key_range,
1040                            val_range,
1041                            ..
1042                        }) => {
1043                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1044                            cont(*val_range, STeXSemanticTokens::KEYWORD);
1045                        }
1046                        SymdeclArg::Name(ParsedKeyValue {
1047                            key_range,
1048                            val_range,
1049                            ..
1050                        }) => {
1051                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1052                            cont(*val_range, STeXSemanticTokens::NAME);
1053                        }
1054                        SymdeclArg::Style(ParsedKeyValue { key_range, .. })
1055                        | SymdeclArg::Assoc(ParsedKeyValue { key_range, .. })
1056                        | SymdeclArg::Role(ParsedKeyValue { key_range, .. })
1057                        | SymdeclArg::Reorder(ParsedKeyValue { key_range, .. }) => {
1058                            cont(*key_range, STeXSemanticTokens::KEYWORD)
1059                        }
1060                    }
1061                }
1062            }
1063            Self::TextSymdecl {
1064                main_name_range,
1065                token_range,
1066                parsed_args,
1067                ..
1068            } => {
1069                cont(*token_range, STeXSemanticTokens::DECLARATION);
1070                cont(*main_name_range, STeXSemanticTokens::NAME);
1071
1072                for e in parsed_args {
1073                    match e {
1074                        TextSymdeclArg::Tp(ParsedKeyValue { key_range, val, .. })
1075                        | TextSymdeclArg::Df(ParsedKeyValue { key_range, val, .. }) => {
1076                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1077                            for c in val {
1078                                c.semantic_tokens(cont);
1079                            }
1080                        }
1081                        TextSymdeclArg::Name(ParsedKeyValue {
1082                            key_range,
1083                            val_range,
1084                            ..
1085                        }) => {
1086                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1087                            cont(*val_range, STeXSemanticTokens::NAME);
1088                        }
1089                        TextSymdeclArg::Style(ParsedKeyValue { key_range, .. }) => {
1090                            cont(*key_range, STeXSemanticTokens::KEYWORD)
1091                        }
1092                    }
1093                }
1094            }
1095            Self::Symdef {
1096                main_name_range,
1097                token_range,
1098                parsed_args,
1099                ..
1100            } => {
1101                cont(*token_range, STeXSemanticTokens::DECLARATION);
1102                cont(*main_name_range, STeXSemanticTokens::NAME);
1103
1104                for e in parsed_args {
1105                    match e {
1106                        SymdefArg::Tp(ParsedKeyValue { key_range, val, .. })
1107                        | SymdefArg::Df(ParsedKeyValue { key_range, val, .. })
1108                        | SymdefArg::Return(ParsedKeyValue { key_range, val, .. })
1109                        | SymdefArg::Op(ParsedKeyValue { key_range, val, .. })
1110                        | SymdefArg::Argtypes(ParsedKeyValue { key_range, val, .. }) => {
1111                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1112                            for c in val {
1113                                c.semantic_tokens(cont);
1114                            }
1115                        }
1116                        SymdefArg::Args(ParsedKeyValue {
1117                            key_range,
1118                            val_range,
1119                            ..
1120                        }) => {
1121                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1122                            cont(*val_range, STeXSemanticTokens::KEYWORD);
1123                        }
1124                        SymdefArg::Name(ParsedKeyValue {
1125                            key_range,
1126                            val_range,
1127                            ..
1128                        }) => {
1129                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1130                            cont(*val_range, STeXSemanticTokens::NAME);
1131                        }
1132                        SymdefArg::Id(v, _) => cont(*v, STeXSemanticTokens::NAME),
1133                        SymdefArg::Style(ParsedKeyValue { key_range, .. })
1134                        | SymdefArg::Assoc(ParsedKeyValue { key_range, .. })
1135                        | SymdefArg::Role(ParsedKeyValue { key_range, .. })
1136                        | SymdefArg::Prec(ParsedKeyValue { key_range, .. })
1137                        | SymdefArg::Reorder(ParsedKeyValue { key_range, .. }) => {
1138                            cont(*key_range, STeXSemanticTokens::KEYWORD)
1139                        }
1140                    }
1141                }
1142            }
1143            Self::RenameDecl {
1144                token_range,
1145                orig_range,
1146                name_range,
1147                macroname_range,
1148                ..
1149            } => {
1150                cont(*token_range, STeXSemanticTokens::DECLARATION);
1151                cont(*orig_range, STeXSemanticTokens::SYMBOL);
1152                if let Some(n) = name_range {
1153                    cont(*n, STeXSemanticTokens::NAME);
1154                }
1155                cont(*macroname_range, STeXSemanticTokens::NAME);
1156            }
1157            Self::Assign {
1158                token_range,
1159                orig_range,
1160                ..
1161            } => {
1162                cont(*token_range, STeXSemanticTokens::DECLARATION);
1163                cont(*orig_range, STeXSemanticTokens::SYMBOL);
1164            }
1165            Self::Svar { full_range, .. } => cont(*full_range, STeXSemanticTokens::VARIABLE),
1166            Self::Vardef {
1167                main_name_range,
1168                token_range,
1169                parsed_args,
1170                ..
1171            }
1172            | Self::Varseq {
1173                main_name_range,
1174                token_range,
1175                parsed_args,
1176                ..
1177            } => {
1178                cont(*token_range, STeXSemanticTokens::LOCAL);
1179                cont(*main_name_range, STeXSemanticTokens::NAME);
1180
1181                for e in parsed_args {
1182                    match e {
1183                        VardefArg::Tp(ParsedKeyValue { key_range, val, .. })
1184                        | VardefArg::Df(ParsedKeyValue { key_range, val, .. })
1185                        | VardefArg::Return(ParsedKeyValue { key_range, val, .. })
1186                        | VardefArg::Op(ParsedKeyValue { key_range, val, .. })
1187                        | VardefArg::Argtypes(ParsedKeyValue { key_range, val, .. }) => {
1188                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1189                            for c in val {
1190                                c.semantic_tokens(cont);
1191                            }
1192                        }
1193                        VardefArg::Args(ParsedKeyValue {
1194                            key_range,
1195                            val_range,
1196                            ..
1197                        }) => {
1198                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1199                            cont(*val_range, STeXSemanticTokens::KEYWORD);
1200                        }
1201                        VardefArg::Name(ParsedKeyValue {
1202                            key_range,
1203                            val_range,
1204                            ..
1205                        }) => {
1206                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1207                            cont(*val_range, STeXSemanticTokens::NAME);
1208                        }
1209                        VardefArg::Id(v, _) => cont(*v, STeXSemanticTokens::NAME),
1210                        VardefArg::Style(ParsedKeyValue { key_range, .. })
1211                        | VardefArg::Assoc(ParsedKeyValue { key_range, .. })
1212                        | VardefArg::Role(ParsedKeyValue { key_range, .. })
1213                        | VardefArg::Prec(ParsedKeyValue { key_range, .. })
1214                        | VardefArg::Bind(ParsedKeyValue { key_range, .. })
1215                        | VardefArg::Reorder(ParsedKeyValue { key_range, .. }) => {
1216                            cont(*key_range, STeXSemanticTokens::KEYWORD)
1217                        }
1218                    }
1219                }
1220            }
1221            Self::Notation {
1222                token_range,
1223                name_range,
1224                notation_args,
1225                ..
1226            } => {
1227                cont(*token_range, STeXSemanticTokens::DECLARATION);
1228                cont(*name_range, STeXSemanticTokens::SYMBOL);
1229                for e in notation_args {
1230                    match e {
1231                        NotationArg::Op(ParsedKeyValue { key_range, val, .. }) => {
1232                            cont(*key_range, STeXSemanticTokens::KEYWORD);
1233                            for c in val {
1234                                c.semantic_tokens(cont);
1235                            }
1236                        }
1237                        NotationArg::Id(v, _) => cont(*v, STeXSemanticTokens::NAME),
1238                        NotationArg::Prec(ParsedKeyValue { key_range, .. }) => {
1239                            cont(*key_range, STeXSemanticTokens::KEYWORD)
1240                        }
1241                    }
1242                }
1243            }
1244            Self::SymName {
1245                token_range,
1246                name_range,
1247                ..
1248            }
1249            | Self::Symref {
1250                token_range,
1251                name_range,
1252                ..
1253            }
1254            | Self::Symuse {
1255                token_range,
1256                name_range,
1257                ..
1258            } => {
1259                cont(*token_range, STeXSemanticTokens::REF_MACRO);
1260                cont(*name_range, STeXSemanticTokens::SYMBOL);
1261            }
1262            Self::Precondition {
1263                token_range,
1264                dim_range,
1265                symbol_range,
1266                ..
1267            }
1268            | Self::Objective {
1269                token_range,
1270                dim_range,
1271                symbol_range,
1272                ..
1273            } => {
1274                cont(*token_range, STeXSemanticTokens::REF_MACRO);
1275                cont(*dim_range, STeXSemanticTokens::KEYWORD);
1276                cont(*symbol_range, STeXSemanticTokens::SYMBOL);
1277            }
1278            Self::Definiens {
1279                token_range,
1280                name_range,
1281                ..
1282            } => {
1283                cont(*token_range, STeXSemanticTokens::REF_MACRO);
1284                if let Some(r) = name_range {
1285                    cont(*r, STeXSemanticTokens::SYMBOL);
1286                }
1287            }
1288            Self::SnifySuggestion { .. } => (),
1289        }
1290    }
1291
1292    fn hover(
1293        &self,
1294        top_archive: Option<&ArchiveUri>,
1295        pos: LSPLineCol,
1296    ) -> Option<either_of::Either<lsp::Hover, (lsp::Range, SymbolReference<LSPLineCol>)>> {
1297        fn uriname(pre: &str, d: &impl std::fmt::Display) -> String {
1298            format!("{pre}<sup>`{d}`</sup>")
1299        }
1300        //tracing::info!("Here: {self:?}");
1301        match self {
1302            Self::SymName {
1303                uri,
1304                name_range: range,
1305                ..
1306            }
1307            | Self::Symref {
1308                uri,
1309                name_range: range,
1310                ..
1311            }
1312            | Self::Notation {
1313                uri,
1314                name_range: range,
1315                ..
1316            }
1317            | Self::Symuse {
1318                uri,
1319                name_range: range,
1320                ..
1321            }
1322            | Self::Precondition {
1323                uri,
1324                symbol_range: range,
1325                ..
1326            }
1327            | Self::Objective {
1328                uri,
1329                symbol_range: range,
1330                ..
1331            }
1332            | Self::Definiens {
1333                uri,
1334                name_range: Some(range),
1335                ..
1336            } => Some(
1337                either_of::Either::Right((
1338                    StringRange::into_range(*range),
1339                    uri.first().unwrap_or_else(|| unreachable!()).clone(),
1340                )), /*lsp::Hover {
1341                        range: Some(StringRange::into_range(*range)),
1342                        contents: lsp::HoverContents::Markup(lsp::MarkupContent {
1343                            kind: lsp::MarkupKind::Markdown,
1344                            value: uriname("", &uri.first().unwrap_or_else(|| unreachable!()).uri),
1345                        }),
1346                    }*/
1347            ),
1348            Self::SemanticMacro {
1349                uri,
1350                full_range: range,
1351                ..
1352            }
1353            | Self::ConservativeExt {
1354                uri,
1355                ext_range: range,
1356                ..
1357            }
1358            | Self::UseStructure {
1359                structure: uri,
1360                structure_range: range,
1361                ..
1362            }
1363            | Self::MorphismEnv {
1364                domain: ModuleOrStruct::Struct(uri),
1365                domain_range: range,
1366                ..
1367            }
1368            | Self::RenameDecl {
1369                uri,
1370                orig_range: range,
1371                ..
1372            }
1373            | Self::Assign {
1374                uri,
1375                orig_range: range,
1376                ..
1377            } => Some(
1378                either_of::Either::Right((StringRange::into_range(*range), uri.clone())), /*lsp::Hover {
1379                                                                                              range: Some(StringRange::into_range(*range)),
1380                                                                                              contents: lsp::HoverContents::Markup(lsp::MarkupContent {
1381                                                                                                  kind: lsp::MarkupKind::Markdown,
1382                                                                                                  value: uriname("", &uri.uri),
1383                                                                                              }),
1384                                                                                          }*/
1385            ),
1386            Self::InlineMorphism {
1387                domain_range,
1388                domain,
1389                assignments,
1390                ..
1391            } => {
1392                if domain_range.contains(pos) {
1393                    let uri = match domain {
1394                        ModuleOrStruct::Struct(sym) => sym,
1395                        _ => return None,
1396                    };
1397                    return Some(
1398                        either_of::Either::Right((
1399                            StringRange::into_range(*domain_range),
1400                            uri.clone(),
1401                        )), /*lsp::Hover {
1402                                range: Some(StringRange::into_range(*domain_range)),
1403                                contents: lsp::HoverContents::Markup(lsp::MarkupContent {
1404                                    kind: lsp::MarkupKind::Markdown,
1405                                    value: uriname("", uri.uri),
1406                                }),
1407                            }*/
1408                    );
1409                }
1410                for a in assignments {
1411                    if a.symbol_range.contains(pos) {
1412                        return Some(
1413                            either_of::Either::Right((
1414                                StringRange::into_range(a.symbol_range),
1415                                a.symbol.clone(),
1416                            )), /*lsp::Hover {
1417                                    range: Some(StringRange::into_range(a.symbol_range)),
1418                                    contents: lsp::HoverContents::Markup(lsp::MarkupContent {
1419                                        kind: lsp::MarkupKind::Markdown,
1420                                        value: uriname("", &a.symbol.uri),
1421                                    }),
1422                                }*/
1423                        );
1424                    }
1425                }
1426                None
1427            }
1428            Self::Svar {
1429                full_range, name, ..
1430            }
1431            | Self::VariableMacro {
1432                name, full_range, ..
1433            } => Some(either_of::Either::Left(lsp::Hover {
1434                range: Some(StringRange::into_range(*full_range)),
1435                contents: lsp::HoverContents::Markup(lsp::MarkupContent {
1436                    kind: lsp::MarkupKind::Markdown,
1437                    value: uriname("Variable ", name),
1438                }),
1439            })),
1440            Self::MathStructure { extends, .. } => extends.iter().find_map(|(s, r)| {
1441                if r.contains(pos) {
1442                    Some(
1443                        either_of::Either::Right((StringRange::into_range(*r), s.clone())), /*lsp::Hover {
1444                                                                                                range: Some(StringRange::into_range(*r)),
1445                                                                                                contents: lsp::HoverContents::Markup(lsp::MarkupContent {
1446                                                                                                    kind: lsp::MarkupKind::Markdown,
1447                                                                                                    value: uriname("", &s.uri),
1448                                                                                                }),
1449                                                                                            }*/
1450                    )
1451                } else {
1452                    None
1453                }
1454            }),
1455            Self::Paragraph { parsed_args, .. } | Self::InlineParagraph { parsed_args, .. } => {
1456                for p in parsed_args {
1457                    if let ParagraphArg::Fors(ParsedKeyValue { val_range, val, .. }) = p {
1458                        if val_range.contains(pos) {
1459                            for (s, r) in val {
1460                                if r.contains(pos) {
1461                                    return Some(
1462                                        either_of::Either::Right((
1463                                            StringRange::into_range(*r),
1464                                            s.first().unwrap_or_else(|| unreachable!()).clone(),
1465                                        )), /*lsp::Hover {
1466                                                range: Some(StringRange::into_range(*r)),
1467                                                contents: lsp::HoverContents::Markup(lsp::MarkupContent {
1468                                                    kind: lsp::MarkupKind::Markdown,
1469                                                    value: uriname(
1470                                                        "",
1471                                                        &s.first().unwrap_or_else(|| unreachable!()).uri,
1472                                                    ),
1473                                                }),
1474                                            }*/
1475                                    );
1476                                }
1477                            }
1478                        }
1479                        return None;
1480                    }
1481                }
1482                None
1483            }
1484            Self::MHGraphics {
1485                filepath,
1486                archive,
1487                full_range,
1488                ..
1489            } => {
1490                let Some(a) = archive.as_ref().map_or_else(
1491                    || top_archive.map(UriWithArchive::archive_id),
1492                    |(a, _)| Some(a),
1493                ) else {
1494                    return None;
1495                };
1496                let Some(uri) = uri_from_archive_relpath(a, &filepath.0) else {
1497                    return None;
1498                };
1499                Some(either_of::Either::Left(lsp::Hover {
1500                    range: Some(StringRange::into_range(*full_range)),
1501                    contents: lsp::HoverContents::Markup(lsp::MarkupContent {
1502                        kind: lsp::MarkupKind::Markdown,
1503                        value: format!("![img]({uri})"),
1504                    }),
1505                }))
1506            }
1507            Self::Module {
1508                uri,
1509                name_range,
1510                full_range,
1511                ..
1512            } => {
1513                let range = StringRange {
1514                    start: full_range.start,
1515                    end: name_range.end,
1516                };
1517                Some(either_of::Either::Left(lsp::Hover {
1518                    range: Some(StringRange::into_range(range)),
1519                    contents: lsp::HoverContents::Markup(lsp::MarkupContent {
1520                        kind: lsp::MarkupKind::Markdown,
1521                        value: uri.to_string(),
1522                    }),
1523                }))
1524            }
1525            Self::ImportModule { .. }
1526            | Self::UseModule { .. }
1527            | Self::SetMetatheory { .. }
1528            | Self::Inputref { .. }
1529            | Self::IncludeProblem { .. }
1530            | Self::MHInput { .. }
1531            | Self::Symdecl { .. }
1532            | Self::Symdef { .. }
1533            | Self::Vardef { .. }
1534            | Self::Varseq { .. }
1535            | Self::Definiens { .. }
1536            | Self::TextSymdecl { .. }
1537            | Self::Problem { .. }
1538            | Self::Defnotation { .. }
1539            | Self::MorphismEnv { .. }
1540            | Self::SnifySuggestion { .. }
1541            | Self::SRef { .. } => None,
1542        }
1543    }
1544    fn inlay_hint(&self) -> Option<lsp::InlayHint> {
1545        match self {
1546            Self::SymName {
1547                uri,
1548                full_range,
1549                mode: mod_,
1550                ..
1551            } => {
1552                let name = uri
1553                    .first()
1554                    .unwrap_or_else(|| unreachable!())
1555                    .uri
1556                    .name()
1557                    .last();
1558                let name = format!("={}", mod_.apply(name));
1559                Some(lsp::InlayHint {
1560                    position: StringRange::into_range(*full_range).end,
1561                    label: lsp::InlayHintLabel::String(name),
1562                    kind: Some(lsp::InlayHintKind::PARAMETER),
1563                    text_edits: None,
1564                    tooltip: None,
1565                    padding_left: None,
1566                    padding_right: None,
1567                    data: None,
1568                })
1569            }
1570            Self::Definiens {
1571                uri,
1572                name_range: None,
1573                full_range,
1574                ..
1575            } => Some(lsp::InlayHint {
1576                position: StringRange::into_range(*full_range).end,
1577                label: lsp::InlayHintLabel::String(format!(
1578                    "[{}]",
1579                    uri.first().unwrap_or_else(|| unreachable!()).uri.name()
1580                )),
1581                kind: Some(lsp::InlayHintKind::PARAMETER),
1582                text_edits: None,
1583                tooltip: None,
1584                padding_left: None,
1585                padding_right: None,
1586                data: None,
1587            }),
1588            _ => None,
1589        }
1590    }
1591    fn code_action(&self, pos: LSPLineCol, url: &lsp::Url) -> lsp::CodeActionResponse {
1592        fn from_syms(
1593            url: &lsp::Url,
1594            v: &[SymbolReference<LSPLineCol>],
1595            r: StringRange<LSPLineCol>,
1596        ) -> lsp::CodeActionResponse {
1597            use std::fmt::Write;
1598            let all_strs: SmallVec<_, 2> = v
1599                .iter()
1600                .map(|u| {
1601                    let mut ret = u.uri.archive_id().to_string();
1602                    if let Some(p) = u.uri.path() {
1603                        ret.push('/');
1604                        ret.push_str(p.as_ref());
1605                    }
1606                    let _ = write!(ret, "?{}?{}", u.uri.module_name(), u.uri.name());
1607                    ret
1608                })
1609                .collect();
1610            v.iter()
1611                .map(|u| {
1612                    let disam = disamb(&u.uri, &all_strs);
1613                    let mut edits = std::collections::HashMap::default();
1614                    edits.insert(
1615                        url.clone(),
1616                        vec![lsp::TextEdit {
1617                            range: StringRange::into_range(r),
1618                            new_text: disam.clone(),
1619                        }],
1620                    );
1621                    lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction {
1622                        title: disam,
1623                        kind: Some(lsp::CodeActionKind::QUICKFIX),
1624                        diagnostics: None,
1625                        edit: Some(lsp::WorkspaceEdit {
1626                            document_changes: None,
1627                            changes: Some(edits),
1628                            change_annotations: None,
1629                        }),
1630                        command: None,
1631                        is_preferred: None,
1632                        disabled: None,
1633                        data: None,
1634                    })
1635                })
1636                .collect()
1637        }
1638        match self {
1639            Self::Notation {
1640                uri, name_range, ..
1641            }
1642            | Self::SymName {
1643                uri, name_range, ..
1644            }
1645            | Self::Symuse {
1646                uri, name_range, ..
1647            }
1648            | Self::Symref {
1649                uri, name_range, ..
1650            }
1651            | Self::Precondition {
1652                uri,
1653                symbol_range: name_range,
1654                ..
1655            }
1656            | Self::Objective {
1657                uri,
1658                symbol_range: name_range,
1659                ..
1660            }
1661            | Self::Definiens {
1662                uri,
1663                name_range: Some(name_range),
1664                ..
1665            } => {
1666                if !name_range.contains(pos) {
1667                    return Vec::new();
1668                }
1669                if uri.len() > 1 {
1670                    from_syms(url, uri, *name_range)
1671                } else {
1672                    Vec::new()
1673                }
1674            }
1675
1676            Self::Paragraph { parsed_args, .. } | Self::InlineParagraph { parsed_args, .. } => {
1677                let fors = parsed_args.iter().find_map(|a| {
1678                    if let ParagraphArg::Fors(ls) = a {
1679                        Some(ls)
1680                    } else {
1681                        None
1682                    }
1683                });
1684                if let Some(fors) = fors {
1685                    for (s, r) in &fors.val {
1686                        if !r.contains(pos) {
1687                            continue;
1688                        }
1689                        if s.len() > 1 {
1690                            return from_syms(url, s, *r);
1691                        }
1692                        return Vec::new();
1693                    }
1694                }
1695                Vec::new()
1696            }
1697            Self::SnifySuggestion { range, symbols } => {
1698                if range.contains(pos) {
1699                    let mut ret: Vec<lsp::CodeActionOrCommand> = symbols
1700                        .iter()
1701                        .map(|(s, needs_usemodule)| {
1702                            lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction {
1703                                title: s.to_string(),
1704                                kind: Some(lsp::CodeActionKind::QUICKFIX), //::QUICKFIX),
1705                                diagnostics: None,
1706                                edit: None,
1707                                command: Some(lsp::Command {
1708                                    title: "insert".to_string(),
1709                                    command: "snify/annotate".to_string(),
1710                                    arguments: Some(vec![
1711                                        s.to_string().into(),
1712                                        (*needs_usemodule).into(),
1713                                        url.to_string().into(),
1714                                        ::serde_json::to_value(*range).expect("wut"),
1715                                    ]),
1716                                }),
1717                                is_preferred: None,
1718                                disabled: None,
1719                                data: None,
1720                            })
1721                        })
1722                        .collect();
1723                    ret.push(lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction {
1724                        title: "(ignore)".to_string(),
1725                        kind: Some(lsp::CodeActionKind::QUICKFIX), //::QUICKFIX),
1726                        diagnostics: None,
1727                        edit: None,
1728                        command: Some(lsp::Command {
1729                            title: "insert".to_string(),
1730                            command: "snify/annotate".to_string(),
1731                            arguments: Some(vec![
1732                                String::new().into(),
1733                                false.into(),
1734                                url.to_string().into(),
1735                                ::serde_json::to_value(*range).expect("wut"),
1736                            ]),
1737                        }),
1738                        is_preferred: None,
1739                        disabled: None,
1740                        data: None,
1741                    }));
1742                    ret
1743                } else {
1744                    Vec::new()
1745                }
1746            }
1747            Self::Problem { .. }
1748            | Self::Module { .. }
1749            | Self::MathStructure { .. }
1750            | Self::ConservativeExt { .. }
1751            | Self::MorphismEnv { .. }
1752            | Self::InlineMorphism { .. }
1753            | Self::SemanticMacro { .. }
1754            | Self::VariableMacro { .. }
1755            | Self::Svar { .. }
1756            | Self::ImportModule { .. }
1757            | Self::UseModule { .. }
1758            | Self::UseStructure { .. }
1759            | Self::SetMetatheory { .. }
1760            | Self::Inputref { .. }
1761            | Self::IncludeProblem { .. }
1762            | Self::MHGraphics { .. }
1763            | Self::MHInput { .. }
1764            | Self::Symdecl { .. }
1765            | Self::TextSymdecl { .. }
1766            | Self::RenameDecl { .. }
1767            | Self::Symdef { .. }
1768            | Self::Vardef { .. }
1769            | Self::Varseq { .. }
1770            | Self::Defnotation { .. }
1771            | Self::Definiens { .. }
1772            | Self::Assign { .. }
1773            | Self::SRef { .. } => Vec::new(),
1774        }
1775    }
1776
1777    fn goto_definition(
1778        &self,
1779        in_doc: &UrlOrFile,
1780        pos: LSPLineCol,
1781    ) -> Option<lsp::GotoDefinitionResponse> {
1782        macro_rules! here {
1783            ($r:expr) => {
1784                Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
1785                    uri: in_doc.clone().into(),
1786                    range: StringRange::into_range($r),
1787                }))
1788            };
1789        }
1790        match self {
1791            Self::Module { name_range, .. } => {
1792                if !name_range.contains(pos) {
1793                    return None;
1794                };
1795                here!(*name_range)
1796            }
1797            Self::MathStructure {
1798                extends,
1799                name_range,
1800                opts,
1801                ..
1802            } => {
1803                if name_range.contains(pos) {
1804                    return here!(*name_range);
1805                }
1806                for o in opts {
1807                    if let MathStructureArg::Name(range, _) = o {
1808                        if range.contains(pos) {
1809                            return here!(*range);
1810                        }
1811                    }
1812                }
1813                extends.iter().find_map(|(uri, r)| {
1814                    if r.contains(pos) {
1815                        let Some(p) = &uri.filepath else { return None };
1816                        let Ok(url) = lsp::Url::from_file_path(p) else {
1817                            return None;
1818                        };
1819                        //tracing::info!("Going to definition for {}: {}@{:?}",uri.uri,url,range);
1820                        Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
1821                            uri: url,
1822                            range: StringRange::into_range(uri.range),
1823                        }))
1824                    } else {
1825                        None
1826                    }
1827                })
1828            }
1829            Self::MorphismEnv {
1830                domain_range,
1831                name_range,
1832                domain,
1833                ..
1834            } => {
1835                if name_range.contains(pos) {
1836                    return here!(*name_range);
1837                }
1838                if domain_range.contains(pos) {
1839                    let Some((p, range)) = (match domain {
1840                        ModuleOrStruct::Module(uri) => {
1841                            uri.full_path.as_ref().map(|r| (r, StringRange::default()))
1842                        }
1843                        ModuleOrStruct::Struct(uri) => {
1844                            uri.filepath.as_ref().map(|r| (r, uri.range))
1845                        }
1846                    }) else {
1847                        return None;
1848                    };
1849                    let Ok(url) = lsp::Url::from_file_path(p) else {
1850                        return None;
1851                    };
1852                    return Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
1853                        uri: url,
1854                        range: StringRange::into_range(range),
1855                    }));
1856                } else {
1857                    None
1858                }
1859            }
1860            Self::InlineMorphism {
1861                domain_range,
1862                domain,
1863                assignments,
1864                name_range,
1865                ..
1866            } => {
1867                if name_range.contains(pos) {
1868                    return here!(*name_range);
1869                }
1870                if domain_range.contains(pos) {
1871                    let Some((p, range)) = (match domain {
1872                        ModuleOrStruct::Module(uri) => {
1873                            uri.full_path.as_ref().map(|r| (r, StringRange::default()))
1874                        }
1875                        ModuleOrStruct::Struct(uri) => {
1876                            uri.filepath.as_ref().map(|r| (r, uri.range))
1877                        }
1878                    }) else {
1879                        return None;
1880                    };
1881                    let Ok(url) = lsp::Url::from_file_path(p) else {
1882                        return None;
1883                    };
1884                    return Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
1885                        uri: url,
1886                        range: StringRange::into_range(range),
1887                    }));
1888                }
1889                for a in assignments {
1890                    if a.symbol_range.contains(pos) {
1891                        let Some(p) = &a.symbol.filepath else {
1892                            return None;
1893                        };
1894                        let Ok(url) = lsp::Url::from_file_path(p) else {
1895                            return None;
1896                        };
1897                        return Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
1898                            uri: url,
1899                            range: StringRange::into_range(a.symbol_range),
1900                        }));
1901                    }
1902                    if let Some((_, InlineMorphAssKind::Rename(_, _, r))) = &a.first {
1903                        if r.contains(pos) {
1904                            return here!(*r);
1905                        }
1906                    }
1907                    if let Some((_, InlineMorphAssKind::Rename(_, _, r))) = &a.second {
1908                        if r.contains(pos) {
1909                            return here!(*r);
1910                        }
1911                    }
1912                }
1913                None
1914            }
1915            Self::Paragraph { parsed_args, .. } | Self::InlineParagraph { parsed_args, .. } => {
1916                for p in parsed_args {
1917                    match p {
1918                        ParagraphArg::Fors(ParsedKeyValue { val_range, val, .. }) => {
1919                            if val_range.contains(pos) {
1920                                for (s, r) in val {
1921                                    if r.contains(pos) {
1922                                        let Some(p) =
1923                                            &s.first().unwrap_or_else(|| unreachable!()).filepath
1924                                        else {
1925                                            return None;
1926                                        };
1927                                        let Ok(url) = lsp::Url::from_file_path(p) else {
1928                                            return None;
1929                                        };
1930                                        //tracing::info!("Going to definition for {}: {}@{:?}",s.uri,url,range);
1931                                        return Some(lsp::GotoDefinitionResponse::Scalar(
1932                                            lsp::Location {
1933                                                uri: url,
1934                                                range: StringRange::into_range(
1935                                                    s.first()
1936                                                        .unwrap_or_else(|| unreachable!())
1937                                                        .range,
1938                                                ),
1939                                            },
1940                                        ));
1941                                    }
1942                                }
1943                            }
1944                            return None;
1945                        }
1946                        ParagraphArg::Name(ParsedKeyValue { val_range, .. })
1947                        | ParagraphArg::MacroName(ParsedKeyValue { val_range, .. })
1948                            if val_range.contains(pos) =>
1949                        {
1950                            return here!(*val_range);
1951                        }
1952                        _ => (),
1953                    }
1954                }
1955                None
1956            }
1957            Self::Symdecl {
1958                main_name_range,
1959                parsed_args,
1960                ..
1961            } => {
1962                if main_name_range.contains(pos) {
1963                    return here!(*main_name_range);
1964                }
1965                for a in parsed_args {
1966                    if let SymdeclArg::Name(ParsedKeyValue { val_range, .. }) = a {
1967                        if val_range.contains(pos) {
1968                            return here!(*val_range);
1969                        }
1970                    }
1971                }
1972                None
1973            }
1974            Self::TextSymdecl {
1975                main_name_range,
1976                parsed_args,
1977                ..
1978            } => {
1979                if main_name_range.contains(pos) {
1980                    return here!(*main_name_range);
1981                }
1982                for a in parsed_args {
1983                    if let TextSymdeclArg::Name(ParsedKeyValue { val_range, .. }) = a {
1984                        if val_range.contains(pos) {
1985                            return here!(*val_range);
1986                        }
1987                    }
1988                }
1989                None
1990            }
1991            Self::Symdef {
1992                main_name_range,
1993                parsed_args,
1994                ..
1995            } => {
1996                if main_name_range.contains(pos) {
1997                    return here!(*main_name_range);
1998                }
1999                for a in parsed_args {
2000                    if let SymdefArg::Name(ParsedKeyValue { val_range, .. }) = a {
2001                        if val_range.contains(pos) {
2002                            return here!(*val_range);
2003                        }
2004                    }
2005                }
2006                None
2007            }
2008            Self::RenameDecl {
2009                uri,
2010                orig_range,
2011                name_range,
2012                macroname_range,
2013                ..
2014            } => {
2015                if let Some(name_range) = name_range {
2016                    if name_range.contains(pos) {
2017                        return here!(*name_range);
2018                    }
2019                }
2020                if macroname_range.contains(pos) {
2021                    return here!(*macroname_range);
2022                }
2023                if !orig_range.contains(pos) {
2024                    return None;
2025                };
2026                let Some(p) = &uri.filepath else { return None };
2027                let Ok(url) = lsp::Url::from_file_path(p) else {
2028                    return None;
2029                };
2030                //tracing::info!("Going to definition for {}: {}@{:?}",uri.uri,url,range);
2031                Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
2032                    uri: url,
2033                    range: StringRange::into_range(uri.range),
2034                }))
2035            }
2036            Self::Vardef {
2037                main_name_range,
2038                parsed_args,
2039                ..
2040            }
2041            | Self::Varseq {
2042                main_name_range,
2043                parsed_args,
2044                ..
2045            } => {
2046                if main_name_range.contains(pos) {
2047                    return here!(*main_name_range);
2048                }
2049                for a in parsed_args {
2050                    if let VardefArg::Name(ParsedKeyValue { val_range, .. }) = a {
2051                        if val_range.contains(pos) {
2052                            return here!(*val_range);
2053                        }
2054                    }
2055                }
2056                None
2057            }
2058
2059            Self::ImportModule {
2060                module,
2061                archive_range,
2062                path_range,
2063                ..
2064            }
2065            | Self::UseModule {
2066                module,
2067                archive_range,
2068                path_range,
2069                ..
2070            }
2071            | Self::SetMetatheory {
2072                archive_range,
2073                path_range,
2074                module,
2075                ..
2076            } => {
2077                let range = archive_range.map_or(*path_range, |a| StringRange {
2078                    start: a.start,
2079                    end: path_range.end,
2080                });
2081                if !range.contains(pos) {
2082                    return None;
2083                };
2084                let Some(p) = module.full_path.as_ref() else {
2085                    return None;
2086                };
2087                let Ok(uri) = lsp::Url::from_file_path(p) else {
2088                    return None;
2089                };
2090                Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
2091                    uri,
2092                    range: lsp::Range::default(),
2093                }))
2094            }
2095            Self::ConservativeExt { ext_range, uri, .. } => {
2096                if !ext_range.contains(pos) {
2097                    return None;
2098                };
2099                let Some(p) = &uri.filepath else { return None };
2100                let Ok(url) = lsp::Url::from_file_path(p) else {
2101                    return None;
2102                };
2103                //tracing::info!("Going to definition for {}: {}@{:?}",uri.uri,url,range);
2104                Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
2105                    uri: url,
2106                    range: StringRange::into_range(uri.range),
2107                }))
2108            }
2109            Self::SymName {
2110                uri,
2111                name_range: range,
2112                ..
2113            }
2114            | Self::Symref {
2115                uri,
2116                name_range: range,
2117                ..
2118            }
2119            | Self::Notation {
2120                uri,
2121                name_range: range,
2122                ..
2123            }
2124            | Self::Symuse {
2125                uri,
2126                name_range: range,
2127                ..
2128            }
2129            | Self::Precondition {
2130                uri,
2131                symbol_range: range,
2132                ..
2133            }
2134            | Self::Objective {
2135                uri,
2136                symbol_range: range,
2137                ..
2138            }
2139            | Self::Definiens {
2140                uri,
2141                name_range: Some(range),
2142                ..
2143            } => {
2144                if !range.contains(pos) {
2145                    return None;
2146                };
2147                let Some(p) = &uri.first().unwrap_or_else(|| unreachable!()).filepath else {
2148                    return None;
2149                };
2150                let Ok(url) = lsp::Url::from_file_path(p) else {
2151                    return None;
2152                };
2153                //tracing::info!("Going to definition for {}: {}@{:?}",uri.uri,url,range);
2154                Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
2155                    uri: url,
2156                    range: StringRange::into_range(
2157                        uri.first().unwrap_or_else(|| unreachable!()).range,
2158                    ),
2159                }))
2160            }
2161            Self::SemanticMacro {
2162                uri,
2163                token_range: range,
2164                ..
2165            }
2166            | Self::UseStructure {
2167                structure: uri,
2168                structure_range: range,
2169                ..
2170            }
2171            | Self::Assign {
2172                uri,
2173                orig_range: range,
2174                ..
2175            } => {
2176                if !range.contains(pos) {
2177                    return None;
2178                };
2179                let Some(p) = &uri.filepath else { return None };
2180                let Ok(url) = lsp::Url::from_file_path(p) else {
2181                    return None;
2182                };
2183                //tracing::info!("Going to definition for {}: {}@{:?}",uri.uri,url,range);
2184                Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
2185                    uri: url,
2186                    range: StringRange::into_range(uri.range),
2187                }))
2188            }
2189            Self::VariableMacro {
2190                orig, full_range, ..
2191            } => {
2192                if !full_range.contains(pos) {
2193                    return None;
2194                };
2195                Some(lsp::GotoDefinitionResponse::Scalar(lsp::Location {
2196                    uri: in_doc.clone().into(),
2197                    range: StringRange::into_range(*orig),
2198                }))
2199            }
2200            Self::Svar { .. }
2201            | Self::Inputref { .. }
2202            | Self::IncludeProblem { .. }
2203            | Self::MHGraphics { .. }
2204            | Self::MHInput { .. }
2205            | Self::Problem { .. }
2206            | Self::Definiens { .. }
2207            | Self::Defnotation { .. }
2208            | Self::SnifySuggestion { .. }
2209            | Self::SRef { .. } => None,
2210        }
2211    }
2212}
2213
2214impl LSPState {
2215    #[must_use]
2216    pub fn get_diagnostics(
2217        &self,
2218        uri: &UrlOrFile,
2219        progress: Option<ProgressCallbackClient>,
2220    ) -> Option<impl std::future::Future<Output = lsp::DocumentDiagnosticReportResult> + use<>>
2221    {
2222        fn default() -> lsp::DocumentDiagnosticReportResult {
2223            lsp::DocumentDiagnosticReportResult::Report(lsp::DocumentDiagnosticReport::Full(
2224                lsp::RelatedFullDocumentDiagnosticReport::default(),
2225            ))
2226        }
2227        let d = self.get(uri)?;
2228        let slf = self.clone();
2229        Some(async move {
2230            d.with_annots(slf, false, |data| {
2231                let diags = &data.diagnostics;
2232                let r = lsp::DocumentDiagnosticReportResult::Report(
2233                    lsp::DocumentDiagnosticReport::Full(lsp::RelatedFullDocumentDiagnosticReport {
2234                        related_documents: None,
2235                        full_document_diagnostic_report: lsp::FullDocumentDiagnosticReport {
2236                            result_id: None,
2237                            items: diags.iter().map(to_diagnostic).collect(),
2238                        },
2239                    }),
2240                );
2241                tracing::trace!("diagnostics: {:?}", r);
2242                if let Some(p) = progress {
2243                    p.finish()
2244                }
2245                r
2246            })
2247            .await
2248            .unwrap_or_else(default)
2249        })
2250    }
2251
2252    #[must_use]
2253    pub fn get_symbols(
2254        &self,
2255        uri: &UrlOrFile,
2256        progress: Option<ProgressCallbackClient>,
2257    ) -> Option<impl std::future::Future<Output = Option<lsp::DocumentSymbolResponse>> + use<>>
2258    {
2259        #[allow(deprecated)]
2260        fn to_symbols(v: &[STeXAnnot]) -> Vec<lsp::DocumentSymbol> {
2261            let mut curr = v.iter();
2262            let mut ret = Vec::new();
2263            let mut stack = Vec::new();
2264            //tracing::info!("Annotations: {v:?}");
2265            loop {
2266                if let Some(e) = curr.next() {
2267                    if let Some((mut symbol, children)) = e.as_symbol() {
2268                        if children.is_empty() {
2269                            ret.push(symbol)
2270                        } else {
2271                            let old = std::mem::replace(&mut curr, children.iter());
2272                            symbol.children = Some(std::mem::take(&mut ret));
2273                            stack.push((old, symbol));
2274                        }
2275                    }
2276                } else if let Some((i, mut s)) = stack.pop() {
2277                    curr = i;
2278                    std::mem::swap(
2279                        &mut ret,
2280                        s.children.as_mut().unwrap_or_else(|| unreachable!()),
2281                    );
2282                    ret.push(s);
2283                } else {
2284                    break;
2285                }
2286            }
2287            //tracing::info!("Returns: {ret:?}");
2288            ret
2289        }
2290
2291        let d = self.get(uri)?;
2292        let slf = self.clone();
2293        Some(d.with_annots(slf, false, |data| {
2294            let r = lsp::DocumentSymbolResponse::Nested(to_symbols(&data.annotations));
2295            tracing::trace!("document symbols: {:?}", r);
2296            if let Some(p) = progress {
2297                p.finish()
2298            }
2299            r
2300        }))
2301    }
2302
2303    #[must_use]
2304    pub fn get_links(
2305        &self,
2306        uri: &UrlOrFile,
2307        progress: Option<ProgressCallbackClient>,
2308    ) -> Option<impl std::future::Future<Output = Option<Vec<lsp::DocumentLink>>> + use<>> {
2309        let d = self.get(uri)?;
2310        let da = d.archive().cloned();
2311        let slf = self.clone();
2312        Some(d.with_annots(slf, false, move |data| {
2313            let mut ret = Vec::new();
2314            let iter: AnnotIter = data.annotations.iter().into();
2315            for e in <AnnotIter as TreeChildIter<STeXAnnot>>::dfs(iter) {
2316                e.links(da.as_ref(), |l| ret.push(l));
2317            }
2318            //tracing::info!("document links: {:?}",ret);
2319            if let Some(p) = progress {
2320                p.finish()
2321            }
2322            ret
2323        }))
2324    }
2325
2326    pub fn prepare_module_hierarchy(
2327        &self,
2328        uri: UrlOrFile,
2329        _: Option<ProgressCallbackClient>,
2330    ) -> Option<impl std::future::Future<Output = Option<Vec<lsp::CallHierarchyItem>>> + use<>>
2331    {
2332        let d = self.get(&uri)?;
2333        let url: lsp::Url = uri.into();
2334        d.document_uri().map(|doc| {
2335            std::future::ready(Some(vec![lsp::CallHierarchyItem {
2336                name: format!("{}.{}", doc.document_name(), doc.language()),
2337                kind: lsp::SymbolKind::FILE,
2338                tags: None,
2339                detail: None,
2340                uri: url.clone(),
2341                range: lsp::Range::default(), //{start:lsp::Position{line:0,character:0},end:lsp::Position{line:u32::MAX,character:u32::MAX}},
2342                selection_range: lsp::Range::default(),
2343                data: Some(doc.to_string().into()),
2344            }]))
2345        })
2346    }
2347
2348    pub fn module_hierarchy_imports(
2349        &self,
2350        url: lsp::Url,
2351        kind: lsp::SymbolKind,
2352        uri: Uri,
2353        _: Option<ProgressCallbackClient>,
2354    ) -> Option<
2355        impl std::future::Future<Output = Option<Vec<lsp::CallHierarchyIncomingCall>>> + use<>,
2356    > {
2357        Some(std::future::ready({
2358            let url = url.into();
2359            let d = self.documents.read().get(&url).cloned()?;
2360            let annots = match d {
2361                DocData::Doc(d) => d.annotations,
2362                DocData::Data(d, _) => d,
2363            };
2364            let data = annots.lock();
2365            let mut rets = Vec::new();
2366            let (chs, usemods) = if kind == lsp::SymbolKind::FILE {
2367                (&*data.annotations, true)
2368            } else {
2369                let mut iter: AnnotIter = data.annotations.iter().into();
2370                (
2371                    iter.find_map(|e| match e {
2372                        STeXAnnot::Module {
2373                            uri: muri,
2374                            children,
2375                            ..
2376                        } if matches!(&uri,Uri::Module(u) if u == muri) => Some(&**children),
2377                        STeXAnnot::MathStructure {
2378                            uri: suri,
2379                            children,
2380                            extends,
2381                            ..
2382                        } if matches!(&uri,Uri::Symbol(u) if u == &suri.uri) => {
2383                            for (sym, range) in extends {
2384                                if let Some(p) = sym.filepath.as_ref() {
2385                                    let Ok(url) = lsp::Url::from_file_path(p) else {
2386                                        continue;
2387                                    };
2388                                    rets.push(lsp::CallHierarchyIncomingCall {
2389                                        from_ranges: vec![IsLSPRange::into_range(*range)],
2390                                        from: lsp::CallHierarchyItem {
2391                                            name: sym.uri.name().to_string(),
2392                                            detail: Some(
2393                                                sym.uri
2394                                                    .to_string()
2395                                                    .split_once("a=")
2396                                                    .unwrap_or_else(|| unreachable!())
2397                                                    .1
2398                                                    .to_string(),
2399                                            ),
2400                                            kind: lsp::SymbolKind::STRUCT,
2401                                            tags: None,
2402                                            uri: url,
2403                                            range: lsp::Range::default(),
2404                                            selection_range: lsp::Range::default(),
2405                                            data: Some(sym.uri.to_string().into()),
2406                                        },
2407                                    });
2408                                }
2409                            }
2410                            Some(&**children)
2411                        }
2412                        _ => None,
2413                    })?,
2414                    false,
2415                )
2416            };
2417            let iter: AnnotIter = chs.iter().into();
2418            for e in <AnnotIter as TreeChildIter<STeXAnnot>>::dfs(iter) {
2419                match e {
2420                    STeXAnnot::ImportModule {
2421                        module, full_range, ..
2422                    } if !usemods => {
2423                        let Some(p) = module.full_path.as_ref() else {
2424                            continue;
2425                        };
2426                        let Ok(url) = lsp::Url::from_file_path(p) else {
2427                            continue;
2428                        };
2429                        rets.push(lsp::CallHierarchyIncomingCall {
2430                            from_ranges: vec![lsp::Range::default()],
2431                            from: lsp::CallHierarchyItem {
2432                                detail: Some(
2433                                    module
2434                                        .uri
2435                                        .to_string()
2436                                        .split_once("a=")
2437                                        .unwrap_or_else(|| unreachable!())
2438                                        .1
2439                                        .to_string(),
2440                                ),
2441                                name: module.uri.module_name().to_string(),
2442                                kind: lsp::SymbolKind::CLASS,
2443                                tags: None,
2444                                uri: url,
2445                                range: IsLSPRange::into_range(*full_range),
2446                                selection_range: IsLSPRange::into_range(*full_range),
2447                                data: Some(module.uri.to_string().into()),
2448                            },
2449                        })
2450                    }
2451                    STeXAnnot::Module {
2452                        uri,
2453                        name_range,
2454                        full_range,
2455                        ..
2456                    } if usemods => rets.push(lsp::CallHierarchyIncomingCall {
2457                        from_ranges: vec![IsLSPRange::into_range(*full_range)],
2458                        from: lsp::CallHierarchyItem {
2459                            detail: Some(
2460                                uri.to_string()
2461                                    .split_once("a=")
2462                                    .unwrap_or_else(|| unreachable!())
2463                                    .1
2464                                    .to_string(),
2465                            ),
2466                            name: uri.module_name().to_string(),
2467                            kind: lsp::SymbolKind::MODULE,
2468                            tags: None,
2469                            uri: url.clone().into(),
2470                            range: IsLSPRange::into_range(*full_range),
2471                            selection_range: IsLSPRange::into_range(*name_range),
2472                            data: Some(uri.to_string().into()),
2473                        },
2474                    }),
2475                    STeXAnnot::UseModule {
2476                        module, full_range, ..
2477                    } if usemods => {
2478                        let Some(p) = module.full_path.as_ref() else {
2479                            continue;
2480                        };
2481                        let Ok(url) = lsp::Url::from_file_path(p) else {
2482                            continue;
2483                        };
2484                        rets.push(lsp::CallHierarchyIncomingCall {
2485                            from_ranges: vec![lsp::Range::default()],
2486                            from: lsp::CallHierarchyItem {
2487                                detail: Some(
2488                                    module
2489                                        .uri
2490                                        .to_string()
2491                                        .split_once("a=")
2492                                        .unwrap_or_else(|| unreachable!())
2493                                        .1
2494                                        .to_string(),
2495                                ),
2496                                name: module.uri.module_name().to_string(),
2497                                kind: lsp::SymbolKind::METHOD,
2498                                tags: None,
2499                                uri: url,
2500                                range: IsLSPRange::into_range(*full_range),
2501                                selection_range: IsLSPRange::into_range(*full_range),
2502                                data: Some(module.uri.to_string().into()),
2503                            },
2504                        })
2505                    }
2506                    _ => (),
2507                }
2508            }
2509            Some(rets)
2510        }))
2511    }
2512
2513    #[must_use]
2514    pub fn get_references(
2515        &self,
2516        uri: UrlOrFile,
2517        position: lsp::Position,
2518        _: Option<ProgressCallbackClient>,
2519    ) -> Option<impl std::future::Future<Output = Option<Vec<lsp::Location>>> + use<>> {
2520        let d = self.get(&uri)?;
2521        let pos = LSPLineCol::new(position.line, position.character);
2522        let slf = self.clone();
2523        enum Target {
2524            Module(ModuleUri),
2525            Structure(SymbolUri),
2526            Symbol(SymbolUri),
2527            Morphism(SymbolUri),
2528        }
2529        Some(async move {
2530            let e = d
2531                .with_annots(slf.clone(), false, move |data| {
2532                    match at_position(data, pos)? {
2533                        STeXAnnot::Module { uri, .. } => Some(Target::Module(uri.clone())),
2534                        STeXAnnot::MathStructure { uri, .. } => {
2535                            Some(Target::Structure(uri.uri.clone()))
2536                        }
2537                        STeXAnnot::MorphismEnv { uri, .. }
2538                        | STeXAnnot::InlineMorphism { uri, .. } => {
2539                            Some(Target::Morphism(uri.clone()))
2540                        }
2541                        STeXAnnot::Symdecl { uri, .. }
2542                        | STeXAnnot::TextSymdecl { uri, .. }
2543                        | STeXAnnot::Paragraph {
2544                            symbol: Some(uri), ..
2545                        }
2546                        | STeXAnnot::InlineParagraph {
2547                            symbol: Some(uri), ..
2548                        }
2549                        | STeXAnnot::Symdef { uri, .. } => Some(Target::Symbol(uri.uri.clone())),
2550                        STeXAnnot::RenameDecl { .. } => None, // TODO
2551                        STeXAnnot::Vardef { .. } | STeXAnnot::Varseq { .. } => {
2552                            // TODO
2553                            None
2554                        }
2555                        _ => None,
2556                    }
2557                })
2558                .await??;
2559            tokio::task::spawn_blocking(move || {
2560                let all = slf.documents.read();
2561                macro_rules! iter {
2562                    ($annot:ident => $then:expr) => {
2563                        for (k,v) in all.iter() {
2564                            let data = match v {
2565                                DocData::Data(d,_ ) => d,
2566                                DocData::Doc(d) => &d.annotations
2567                            };
2568                            let data = data.lock();
2569                            let iter : AnnotIter = data.annotations.iter().into();
2570                            macro_rules! here {
2571                                ($e:expr) => {
2572                                    lsp::Location {
2573                                        uri:k.clone().into(),
2574                                        range: StringRange::into_range($e)
2575                                    }
2576                                }
2577                            }
2578                            for $annot in <AnnotIter as TreeChildIter<STeXAnnot>>::dfs(iter) { $then }
2579                            drop(data);
2580                        }
2581                    }
2582                }
2583                let mut ret = Vec::new();
2584                match e {
2585                    Target::Module(muri) => {
2586                        iter!(a => match a {
2587                            STeXAnnot::ImportModule{module,full_range,..} | STeXAnnot::UseModule{module,full_range,..} if module.uri == muri => {
2588                                ret.push(here!(*full_range))
2589                            }
2590                            STeXAnnot::MorphismEnv{domain:ModuleOrStruct::Module(rf),domain_range,..} |
2591                            STeXAnnot::InlineMorphism{domain:ModuleOrStruct::Module(rf),domain_range,..}
2592                                if rf.uri == muri => ret.push(here!(*domain_range)),
2593                            _ => ()
2594                        })
2595                    }
2596                    Target::Structure(suri) | Target::Morphism(suri) | Target::Symbol(suri) => {
2597                        iter!(a => match a {
2598                            STeXAnnot::MathStructure{extends,..} => for (s,r) in extends {
2599                                if s.uri == suri { ret.push(here!(*r)); }
2600                            }
2601                            STeXAnnot::ConservativeExt{uri,extstructure_range:range,..} |
2602                            STeXAnnot::MorphismEnv{domain:ModuleOrStruct::Struct(uri),domain_range:range,..} |
2603                            STeXAnnot::InlineMorphism{domain:ModuleOrStruct::Struct(uri),domain_range:range,..} |
2604                            STeXAnnot::SemanticMacro{uri,token_range:range,..} |
2605                            STeXAnnot::UseStructure{structure:uri,structure_range:range,..} |
2606                            STeXAnnot::RenameDecl{uri,orig_range:range,..} |
2607                            STeXAnnot::Assign{uri,orig_range:range,..}
2608                                if uri.uri == suri => ret.push(here!(*range)),
2609                            STeXAnnot::Notation{uri,name_range:range,..} |
2610                            STeXAnnot::SymName{uri,name_range:range,..} |
2611                            STeXAnnot::Symuse{uri,name_range:range,..} |
2612                            STeXAnnot::Symref{uri,name_range:range,..} |
2613                            STeXAnnot::Precondition{uri,symbol_range:range,.. } |
2614                            STeXAnnot::Objective{uri,symbol_range:range,.. } |
2615                            STeXAnnot::Definiens{uri,full_range:range,..} => {
2616                                for u in uri {
2617                                    if u.uri == suri { ret.push(here!(*range)) }
2618                                }
2619                            }
2620                            STeXAnnot::Paragraph{parsed_args,..} | STeXAnnot::InlineParagraph{parsed_args,..} => {
2621                                for a in parsed_args {
2622                                    if let ParagraphArg::Fors(ParsedKeyValue{val,..}) = a {
2623                                        for (uri,range) in val {
2624                                            for u in uri {
2625                                                if u.uri == suri { ret.push(here!(*range)) }
2626                                            }
2627                                        }
2628                                    }
2629                                }
2630                            }
2631                            _ => ()
2632                        })
2633                    }
2634                }
2635                ret
2636            }).await.ok()
2637        })
2638    }
2639
2640    #[must_use]
2641    pub fn get_hover(
2642        &self,
2643        uri: &UrlOrFile,
2644        position: lsp::Position,
2645        _: Option<ProgressCallbackClient>,
2646    ) -> Option<impl std::future::Future<Output = Option<lsp::Hover>> + use<>> {
2647        fn get_comment(txt: &str, pos: LSPLineCol, out: &mut String) {
2648            let off = pos.into_other::<ByteOffset>(txt).0;
2649            let mut lines = txt[..off].trim_end().lines();
2650            let mut ret = Vec::new();
2651            while let Some(l) = lines.next_back()
2652                && let l = l.trim_start()
2653                && l.starts_with("%%")
2654            {
2655                let l = l[2..].trim();
2656                ret.push(l);
2657            }
2658            if !ret.is_empty() {
2659                out.push_str("\n_____\n");
2660                for s in ret.into_iter().rev() {
2661                    out.push_str(s);
2662                    out.push('\n');
2663                }
2664            }
2665        }
2666        let d = self.get(uri)?;
2667        let da = d.archive().cloned();
2668        let pos = LSPLineCol::new(position.line, position.character);
2669        let slf = self.clone();
2670        let fut = d.with_annots(self.clone(), false, move |data| {
2671            at_position(data, pos).and_then(|e| e.hover(da.as_ref(), pos))
2672        });
2673        Some(async move {
2674            let o = fut.await.flatten()?;
2675            let (range, s) = match o {
2676                either_of::Either::Left(a) => return Some(a),
2677                either_of::Either::Right((range, s)) => (range, s),
2678            };
2679            let mut ret = format!("<sup>`{}`</sup>", s.uri);
2680            if let Some(fp) = s.filepath.as_ref()
2681                && let Ok(url) = lsp::Url::from_file_path(fp)
2682            {
2683                let url = url.into();
2684                let src = if let Some(src) = slf.get(&url) {
2685                    Some(src)
2686                } else if let Ok(txt) = tokio::fs::read_to_string(fp).await {
2687                    slf.insert(url.clone(), txt);
2688                    slf.get(&url)
2689                } else {
2690                    None
2691                };
2692
2693                if let Some(src) = src.as_ref()
2694                    && !src.with_text(|txt| {
2695                        if txt.is_empty() {
2696                            false
2697                        } else {
2698                            get_comment(txt, s.range.start, &mut ret);
2699                            true
2700                        }
2701                    })
2702                    && let Some(p) = src.path()
2703                    && let Ok(txt) = tokio::fs::read_to_string(p).await
2704                {
2705                    get_comment(&txt, s.range.start, &mut ret);
2706                    src.set_text(txt);
2707                }
2708
2709                if let Some(src) = src {
2710                    slf.hover_metadata(src, s, &mut ret).await;
2711                }
2712            }
2713
2714            Some(lsp::Hover {
2715                range: Some(range),
2716                contents: lsp::HoverContents::Markup(lsp::MarkupContent {
2717                    kind: lsp::MarkupKind::Markdown,
2718                    value: ret,
2719                }),
2720            })
2721        })
2722    }
2723
2724    #[must_use]
2725    pub fn get_codeaction(
2726        &self,
2727        uri: UrlOrFile,
2728        range: lsp::Range,
2729        _context: lsp::CodeActionContext,
2730        _: Option<ProgressCallbackClient>,
2731    ) -> Option<impl std::future::Future<Output = Option<lsp::CodeActionResponse>> + use<>> {
2732        let d = self.get(&uri)?;
2733        let pos = LSPLineCol::new(range.start.line, range.start.character);
2734        let url = uri.into();
2735        Some(
2736            d.with_annots(self.clone(), false, move |data| {
2737                at_position(data, pos).map(|e| e.code_action(pos, &url))
2738            })
2739            .map(|o| o.flatten()),
2740        )
2741    }
2742
2743    #[must_use]
2744    pub fn get_goto_definition(
2745        &self,
2746        uri: UrlOrFile,
2747        position: lsp::Position,
2748        _: Option<ProgressCallbackClient>,
2749    ) -> Option<impl std::future::Future<Output = Option<lsp::GotoDefinitionResponse>> + use<>>
2750    {
2751        let d = self.get(&uri)?;
2752        let pos = LSPLineCol::new(position.line, position.character);
2753        Some(
2754            d.with_annots(self.clone(), false, move |data| {
2755                at_position(data, pos).and_then(|e| e.goto_definition(&uri, pos))
2756            })
2757            .map(|o| o.flatten()),
2758        )
2759    }
2760
2761    #[must_use]
2762    pub fn get_inlay_hints(
2763        &self,
2764        uri: &UrlOrFile,
2765        _: Option<ProgressCallbackClient>,
2766    ) -> Option<impl std::future::Future<Output = Option<Vec<lsp::InlayHint>>> + use<>> {
2767        let d = self.get(uri)?;
2768        Some(d.with_annots(self.clone(), false, move |data| {
2769            let iter: AnnotIter = data.annotations.iter().into();
2770            <AnnotIter as TreeChildIter<STeXAnnot>>::dfs(iter)
2771                .filter_map(|e| e.inlay_hint())
2772                .collect()
2773        }))
2774    }
2775
2776    pub fn get_semantic_tokens(
2777        &self,
2778        uri: &UrlOrFile,
2779        progress: Option<ProgressCallbackClient>,
2780        _range: Option<lsp::Range>,
2781    ) -> Option<impl std::future::Future<Output = Option<lsp::SemanticTokens>> + use<>> {
2782        //let range = range.map(SourceRange::from_range);
2783        let d = self.get(uri)?;
2784        Some(d.with_annots(self.clone(), false, |data| {
2785            let mut ret = Vec::new();
2786            let mut curr = (0u32, 0u32);
2787            for e in data.annotations.iter() {
2788                e.semantic_tokens(&mut |range, tp| {
2789                    if range.start.line < curr.0 {
2790                        return;
2791                    }
2792                    let delta_line = range.start.line - curr.0;
2793                    let delta_start = if delta_line == 0 {
2794                        if range.start.col > curr.1 {
2795                            range.start.col - curr.1
2796                        } else {
2797                            return;
2798                        }
2799                    } else {
2800                        range.start.col
2801                    };
2802                    curr = (range.start.line, range.start.col);
2803                    if range.start.line == range.end.line {
2804                        let length = if range.end.col < range.start.col {
2805                            999
2806                        } else {
2807                            range.end.col - range.start.col
2808                        };
2809                        ret.push(lsp::SemanticToken {
2810                            delta_line,
2811                            delta_start,
2812                            length,
2813                            token_type: tp,
2814                            token_modifiers_bitset: 0,
2815                        });
2816                    } else {
2817                        ret.push(lsp::SemanticToken {
2818                            delta_line,
2819                            delta_start,
2820                            length: 999,
2821                            token_type: tp,
2822                            token_modifiers_bitset: 0,
2823                        });
2824                        // TODO
2825                    }
2826                });
2827            }
2828
2829            if let Some(p) = progress {
2830                p.finish()
2831            }
2832            lsp::SemanticTokens {
2833                result_id: None,
2834                data: ret,
2835            }
2836        }))
2837    }
2838
2839    async fn hover_metadata(
2840        self,
2841        src: LSPDocument,
2842        s: SymbolReference<LSPLineCol>,
2843        out: &mut String,
2844    ) {
2845        #[derive(Clone, Copy, Default)]
2846        struct SymbolData {
2847            macro_name: Option<StringRange<LSPLineCol>>,
2848            args: Option<StringRange<LSPLineCol>>,
2849            tp: Option<StringRange<LSPLineCol>>,
2850            df: Option<StringRange<LSPLineCol>>,
2851            returns: Option<StringRange<LSPLineCol>>,
2852        }
2853        impl SymbolData {
2854            const fn is_empty(self) -> bool {
2855                self.macro_name.is_none()
2856                    && self.args.is_none()
2857                    && self.tp.is_none()
2858                    && self.df.is_none()
2859                    && self.returns.is_none()
2860            }
2861            fn write(self, sym_text: &str, start: LSPLineCol, out: &mut String) {
2862                out.push_str("| | |\n| --- | --- |\n");
2863                if let Some(m) = self.macro_name {
2864                    let m = &sym_text[m - start];
2865                    let _ = writeln!(out, "| *macro* | `\\{m}`|");
2866                }
2867                if let Some(a) = self.args {
2868                    //tracing::warn!("Arguments: {sym_text:?} @ {}", a - start);
2869                    let a = &sym_text[a - start];
2870                    let _ = writeln!(out, "| *arguments* | {a} |");
2871                }
2872                if let Some(r) = self.returns {
2873                    //tracing::warn!("Returns: {sym_text:?} @ {}", r - start);
2874                    let r = &sym_text[r - start];
2875                    let _ = writeln!(out, "| *returns* | `{}` |", r.replace('\n', ""));
2876                }
2877                if let Some(t) = self.tp {
2878                    //tracing::warn!("Type: {sym_text:?} @ {}", t - start);
2879                    let t = &sym_text[t - start];
2880                    let _ = writeln!(out, "| *type* | `{}` |", t.replace('\n', ""));
2881                }
2882                if let Some(d) = self.df {
2883                    //tracing::warn!("Definiens: {sym_text:?} @ {}", d - start);
2884                    let d = &sym_text[d - start];
2885                    let _ = writeln!(out, "| *definiens* | `{}` |", d.replace('\n', ""));
2886                }
2887            }
2888        }
2889        struct Assignment {}
2890        enum Data {
2891            Symbol(SymbolData),
2892            Structure {
2893                extensions: Vec<SymbolReference<LSPLineCol>>,
2894                fields: Vec<SymbolData>,
2895            },
2896            Morphism(Vec<Assignment>),
2897        }
2898
2899        match src
2900            .clone()
2901            .with_annots(self, false, move |data| {
2902                let iter: AnnotIter = data.annotations.iter().into();
2903                for a in <AnnotIter as TreeChildIter<STeXAnnot>>::dfs(iter) {
2904                    match a {
2905                        STeXAnnot::MathStructure {
2906                            uri,
2907                            extends,
2908                            opts,
2909                            children,
2910                            ..
2911                        } if uri.uri == s.uri => {
2912                            // TODO
2913                            ()
2914                        }
2915                        STeXAnnot::MorphismEnv {
2916                            uri,
2917                            star,
2918                            domain,
2919                            kind,
2920                            children,
2921                            ..
2922                        } if *uri == s.uri => {
2923                            // TODO
2924                            ()
2925                        }
2926                        STeXAnnot::InlineMorphism {
2927                            uri,
2928                            domain,
2929                            domain_range,
2930                            kind,
2931                            assignments,
2932                            ..
2933                        } if *uri == s.uri => {
2934                            // TODO
2935                            ()
2936                        }
2937                        STeXAnnot::Paragraph {
2938                            symbol: Some(uri),
2939                            parsed_args,
2940                            children,
2941                            full_range,
2942                            ..
2943                        }
2944                        | STeXAnnot::InlineParagraph {
2945                            symbol: Some(uri),
2946                            parsed_args,
2947                            children,
2948                            full_range,
2949                            ..
2950                        } if uri.uri == s.uri => {
2951                            let mut data = SymbolData::default();
2952                            for l in parsed_args {
2953                                match l {
2954                                    ParagraphArg::Args(v) => data.args = Some(v.val_range),
2955                                    ParagraphArg::Tp(t) => data.tp = Some(t.val_range),
2956                                    ParagraphArg::Df(d) => data.df = Some(d.val_range),
2957                                    ParagraphArg::Return(r) => data.returns = Some(r.val_range),
2958                                    ParagraphArg::MacroName(r) => {
2959                                        data.macro_name = Some(r.val_range);
2960                                    }
2961                                    _ => (),
2962                                }
2963                            }
2964                            return Some((*full_range, Data::Symbol(data)));
2965                        }
2966                        STeXAnnot::Symdecl {
2967                            uri,
2968                            parsed_args,
2969                            starred,
2970                            main_name_range,
2971                            full_range,
2972                            ..
2973                        } if uri.uri == s.uri => {
2974                            let mut data = SymbolData::default();
2975                            if !starred {
2976                                data.macro_name = Some(*main_name_range);
2977                            }
2978                            for l in parsed_args {
2979                                match l {
2980                                    SymdeclArg::Args(v) => data.args = Some(v.val_range),
2981                                    SymdeclArg::Tp(t) => data.tp = Some(t.val_range),
2982                                    SymdeclArg::Df(d) => data.df = Some(d.val_range),
2983                                    SymdeclArg::Return(r) => data.returns = Some(r.val_range),
2984                                    _ => (),
2985                                }
2986                            }
2987                            return Some((*full_range, Data::Symbol(data)));
2988                        }
2989                        STeXAnnot::TextSymdecl {
2990                            uri,
2991                            parsed_args,
2992                            main_name_range,
2993                            full_range,
2994                            ..
2995                        } if uri.uri == s.uri => {
2996                            let mut data = SymbolData::default();
2997                            data.macro_name = Some(*main_name_range);
2998                            for l in parsed_args {
2999                                match l {
3000                                    TextSymdeclArg::Tp(t) => data.tp = Some(t.val_range),
3001                                    TextSymdeclArg::Df(d) => data.df = Some(d.val_range),
3002                                    _ => (),
3003                                }
3004                            }
3005                            return Some((*full_range, Data::Symbol(data)));
3006                        }
3007                        STeXAnnot::Symdef {
3008                            uri,
3009                            parsed_args,
3010                            main_name_range,
3011                            full_range,
3012                            ..
3013                        } if uri.uri == s.uri => {
3014                            let mut data = SymbolData::default();
3015                            data.macro_name = Some(*main_name_range);
3016                            for l in parsed_args {
3017                                match l {
3018                                    SymdefArg::Args(v) => data.args = Some(v.val_range),
3019                                    SymdefArg::Tp(t) => data.tp = Some(t.val_range),
3020                                    SymdefArg::Df(d) => data.df = Some(d.val_range),
3021                                    SymdefArg::Return(r) => data.returns = Some(r.val_range),
3022                                    _ => (),
3023                                }
3024                            }
3025                            return Some((*full_range, Data::Symbol(data)));
3026                        }
3027                        _ => (),
3028                    }
3029                }
3030                None
3031            })
3032            .await
3033            .flatten()
3034        {
3035            Some((r, Data::Symbol(s))) if !s.is_empty() => src.with_text(|txt| {
3036                out.push_str("\n______\n");
3037                let start = r.start.into_other::<ByteOffset>(txt);
3038                let txt = &txt[start.0..];
3039                s.write(txt, r.start, out);
3040            }),
3041            Some((r, Data::Structure { extensions, fields })) => (),
3042            Some((r, Data::Morphism(_))) => (),
3043            _ => (),
3044        }
3045    }
3046}
3047
3048fn at_position(data: &STeXParseDataI, position: LSPLineCol) -> Option<&STeXAnnot> {
3049    let mut ret = None;
3050    let iter: AnnotIter = data.annotations.iter().into();
3051    for e in <AnnotIter as TreeChildIter<STeXAnnot>>::dfs(iter) {
3052        let range = e.range();
3053        if range.contains(position) {
3054            ret = Some(e);
3055        } else if range.start > position {
3056            if ret.is_some() {
3057                break;
3058            }
3059        }
3060    }
3061    ret
3062}
3063
3064#[must_use]
3065pub fn to_diagnostic(diag: &STeXDiagnostic) -> lsp::Diagnostic {
3066    lsp::Diagnostic {
3067        range: diag.range.into_range(),
3068        severity: Some(match diag.level {
3069            DiagnosticLevel::Error => lsp::DiagnosticSeverity::ERROR,
3070            DiagnosticLevel::Info => lsp::DiagnosticSeverity::INFORMATION,
3071            DiagnosticLevel::Warning => lsp::DiagnosticSeverity::WARNING,
3072            DiagnosticLevel::Hint => lsp::DiagnosticSeverity::HINT,
3073        }),
3074        code: None,
3075        code_description: None,
3076        source: None,
3077        message: diag.message.clone(),
3078        related_information: None,
3079        tags: None,
3080        data: None,
3081    }
3082}
3083#[must_use]
3084pub fn into_diagnostic(diag: STeXDiagnostic) -> lsp::Diagnostic {
3085    lsp::Diagnostic {
3086        range: diag.range.into_range(),
3087        severity: Some(match diag.level {
3088            DiagnosticLevel::Error => lsp::DiagnosticSeverity::ERROR,
3089            DiagnosticLevel::Info => lsp::DiagnosticSeverity::INFORMATION,
3090            DiagnosticLevel::Warning => lsp::DiagnosticSeverity::WARNING,
3091            DiagnosticLevel::Hint => lsp::DiagnosticSeverity::HINT,
3092        }),
3093        code: None,
3094        code_description: None,
3095        source: None,
3096        message: diag.message,
3097        related_information: None,
3098        tags: None,
3099        data: None,
3100    }
3101}
3102
3103fn disamb(uri: &SymbolUri, all: &[String]) -> String {
3104    let mut ret = format!("?{}", uri.name());
3105    if all.iter().filter(|s| s.ends_with(&ret)).count() == 1 {
3106        return ret;
3107    }
3108    ret = format!("?{}{ret}", uri.module_name());
3109    if all.iter().filter(|s| s.ends_with(&ret)).count() == 1 {
3110        return ret;
3111    }
3112    if let Some(path) = uri.path() {
3113        let mut had_path = false;
3114        for s in path.steps().rev() {
3115            if had_path {
3116                ret = format!("{s}/{ret}");
3117            } else {
3118                had_path = true;
3119                ret = format!("{s}{ret}");
3120            }
3121            if all.iter().filter(|s| s.ends_with(&ret)).count() == 1 {
3122                return ret;
3123            }
3124        }
3125    }
3126    for i in uri.archive_id().steps().rev() {
3127        ret = format!("{i}/{ret}");
3128        if all.iter().filter(|s| s.ends_with(&ret)).count() == 1 {
3129            return ret;
3130        }
3131    }
3132    ret
3133}