1use crate::tokens::Span;
6
7#[allow(dead_code)]
9#[allow(missing_docs)]
10pub struct SourceMapCache {
11 pub cache: std::collections::HashMap<(usize, usize), (usize, usize)>,
13}
14impl SourceMapCache {
15 #[allow(dead_code)]
17 pub fn new() -> Self {
18 SourceMapCache {
19 cache: std::collections::HashMap::new(),
20 }
21 }
22 #[allow(dead_code)]
24 pub fn insert(&mut self, gen_line: usize, gen_col: usize, orig_line: usize, orig_col: usize) {
25 self.cache
26 .insert((gen_line, gen_col), (orig_line, orig_col));
27 }
28 #[allow(dead_code)]
30 pub fn lookup(&self, gen_line: usize, gen_col: usize) -> Option<(usize, usize)> {
31 self.cache.get(&(gen_line, gen_col)).copied()
32 }
33 #[allow(dead_code)]
35 pub fn len(&self) -> usize {
36 self.cache.len()
37 }
38 #[allow(dead_code)]
40 pub fn is_empty(&self) -> bool {
41 self.cache.is_empty()
42 }
43}
44#[allow(dead_code)]
46#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
47pub struct SourcePosition {
48 pub offset: usize,
50 pub line: usize,
52 pub column: usize,
54}
55#[allow(dead_code)]
56impl SourcePosition {
57 pub fn new(offset: usize, line: usize, column: usize) -> Self {
59 Self {
60 offset,
61 line,
62 column,
63 }
64 }
65 pub fn origin() -> Self {
67 Self {
68 offset: 0,
69 line: 1,
70 column: 1,
71 }
72 }
73 pub fn advance_col(self, bytes: usize) -> Self {
75 Self {
76 offset: self.offset + bytes,
77 column: self.column + 1,
78 ..self
79 }
80 }
81 pub fn advance_line(self, bytes: usize) -> Self {
83 Self {
84 offset: self.offset + bytes,
85 line: self.line + 1,
86 column: 1,
87 }
88 }
89 pub fn is_before(&self, other: &SourcePosition) -> bool {
91 self.offset < other.offset
92 }
93 pub fn is_after(&self, other: &SourcePosition) -> bool {
95 self.offset > other.offset
96 }
97}
98#[allow(dead_code)]
100#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
101pub enum DiagnosticSeverity {
102 Hint,
104 Information,
106 Warning,
108 Error,
110}
111#[derive(Clone, Debug, PartialEq)]
113pub struct SemanticToken {
114 pub span: Span,
116 pub token_type: SemanticTokenType,
118 pub modifiers: Vec<SemanticModifier>,
120}
121impl SemanticToken {
122 #[allow(dead_code)]
124 pub fn new(span: Span, token_type: SemanticTokenType) -> Self {
125 Self {
126 span,
127 token_type,
128 modifiers: Vec::new(),
129 }
130 }
131 #[allow(dead_code)]
133 pub fn with_modifiers(
134 span: Span,
135 token_type: SemanticTokenType,
136 modifiers: Vec<SemanticModifier>,
137 ) -> Self {
138 Self {
139 span,
140 token_type,
141 modifiers,
142 }
143 }
144}
145#[allow(dead_code)]
147#[allow(missing_docs)]
148#[derive(Debug, Default)]
149pub struct SourceMapBatch {
150 pub entries: Vec<RangeTransform>,
152}
153impl SourceMapBatch {
154 #[allow(dead_code)]
156 pub fn new() -> Self {
157 SourceMapBatch {
158 entries: Vec::new(),
159 }
160 }
161 #[allow(dead_code)]
163 pub fn add(&mut self, e: RangeTransform) {
164 self.entries.push(e);
165 }
166 #[allow(dead_code)]
168 pub fn total_coverage(&self) -> usize {
169 self.entries.iter().map(|e| e.orig_len()).sum()
170 }
171 #[allow(dead_code)]
173 pub fn length_preserving_count(&self) -> usize {
174 self.entries
175 .iter()
176 .filter(|e| e.is_length_preserving())
177 .count()
178 }
179}
180#[allow(dead_code)]
182#[derive(Debug, Clone, PartialEq)]
183pub struct DocumentSymbol {
184 pub name: String,
186 pub kind: SymbolKind,
188 pub full_span: Span,
190 pub name_span: Span,
192 pub children: Vec<DocumentSymbol>,
194}
195#[allow(dead_code)]
196impl DocumentSymbol {
197 pub fn new(name: String, kind: SymbolKind, full_span: Span, name_span: Span) -> Self {
199 Self {
200 name,
201 kind,
202 full_span,
203 name_span,
204 children: Vec::new(),
205 }
206 }
207 pub fn add_child(&mut self, child: DocumentSymbol) {
209 self.children.push(child);
210 }
211 pub fn has_children(&self) -> bool {
213 !self.children.is_empty()
214 }
215 pub fn find_by_name(&self, name: &str) -> Option<&DocumentSymbol> {
217 if self.name == name {
218 return Some(self);
219 }
220 for child in &self.children {
221 if let Some(found) = child.find_by_name(name) {
222 return Some(found);
223 }
224 }
225 None
226 }
227 pub fn flatten(&self) -> Vec<&DocumentSymbol> {
229 let mut result = vec![self];
230 for child in &self.children {
231 result.extend(child.flatten());
232 }
233 result
234 }
235}
236#[allow(dead_code)]
238#[derive(Debug, Clone, PartialEq)]
239pub struct SourceRegion {
240 pub label: String,
242 pub span: Span,
244 pub meta: Option<String>,
246}
247#[allow(dead_code)]
248impl SourceRegion {
249 pub fn new(label: impl Into<String>, span: Span) -> Self {
251 Self {
252 label: label.into(),
253 span,
254 meta: None,
255 }
256 }
257 pub fn with_meta(label: impl Into<String>, span: Span, meta: impl Into<String>) -> Self {
259 Self {
260 label: label.into(),
261 span,
262 meta: Some(meta.into()),
263 }
264 }
265 pub fn contains_offset(&self, offset: usize) -> bool {
267 offset >= self.span.start && offset < self.span.end
268 }
269 pub fn byte_len(&self) -> usize {
271 self.span.end.saturating_sub(self.span.start)
272 }
273}
274#[derive(Clone, Debug, PartialEq, Eq)]
276pub enum SemanticModifier {
277 Definition,
279 Declaration,
281 Deprecated,
283 Documentation,
285}
286#[derive(Clone, Debug, PartialEq, Eq)]
288pub enum SemanticTokenType {
289 Keyword,
291 Variable,
293 Function,
295 Type,
297 Constructor,
299 Operator,
301 Number,
303 StringLit,
305 Comment,
307 Tactic,
309 Namespace,
311}
312#[derive(Clone, Debug, PartialEq)]
314pub struct SourceEntry {
315 pub span: Span,
317 pub kind: EntryKind,
319 pub name: Option<String>,
321 pub ty_info: Option<String>,
323}
324impl SourceEntry {
325 #[allow(dead_code)]
327 pub fn new(span: Span, kind: EntryKind) -> Self {
328 Self {
329 span,
330 kind,
331 name: None,
332 ty_info: None,
333 }
334 }
335 #[allow(dead_code)]
337 pub fn with_name(span: Span, kind: EntryKind, name: &str) -> Self {
338 Self {
339 span,
340 kind,
341 name: Some(name.to_string()),
342 ty_info: None,
343 }
344 }
345 #[allow(dead_code)]
347 pub fn with_name_and_type(span: Span, kind: EntryKind, name: &str, ty: &str) -> Self {
348 Self {
349 span,
350 kind,
351 name: Some(name.to_string()),
352 ty_info: Some(ty.to_string()),
353 }
354 }
355 #[allow(dead_code)]
357 pub fn contains_offset(&self, offset: usize) -> bool {
358 offset >= self.span.start && offset < self.span.end
359 }
360}
361#[derive(Clone, Debug, PartialEq, Eq)]
363pub enum EntryKind {
364 Definition,
366 Reference,
368 TypeAnnotation,
370 Binder,
372 Constructor,
374 Pattern,
376 Tactic,
378 Keyword,
380 Literal,
382 Comment,
384 DocComment,
386 Operator,
388}
389#[allow(dead_code)]
391#[derive(Debug, Clone, PartialEq)]
392pub struct SourceDiagnostic {
393 pub span: Span,
395 pub severity: DiagnosticSeverity,
397 pub message: String,
399 pub code: Option<String>,
401 pub related: Vec<(Span, String)>,
403}
404#[allow(dead_code)]
405impl SourceDiagnostic {
406 pub fn new(span: Span, severity: DiagnosticSeverity, message: impl Into<String>) -> Self {
408 Self {
409 span,
410 severity,
411 message: message.into(),
412 code: None,
413 related: Vec::new(),
414 }
415 }
416 pub fn error(span: Span, message: impl Into<String>) -> Self {
418 Self::new(span, DiagnosticSeverity::Error, message)
419 }
420 pub fn warning(span: Span, message: impl Into<String>) -> Self {
422 Self::new(span, DiagnosticSeverity::Warning, message)
423 }
424 pub fn info(span: Span, message: impl Into<String>) -> Self {
426 Self::new(span, DiagnosticSeverity::Information, message)
427 }
428 pub fn with_code(mut self, code: impl Into<String>) -> Self {
430 self.code = Some(code.into());
431 self
432 }
433 pub fn with_related(mut self, span: Span, message: impl Into<String>) -> Self {
435 self.related.push((span, message.into()));
436 self
437 }
438 pub fn is_error(&self) -> bool {
440 self.severity == DiagnosticSeverity::Error
441 }
442 pub fn is_warning(&self) -> bool {
444 self.severity == DiagnosticSeverity::Warning
445 }
446}
447#[allow(dead_code)]
449#[derive(Debug, Clone, PartialEq)]
450pub struct GoToDefinitionResult {
451 pub name: String,
453 pub definition_spans: Vec<Span>,
455 pub is_local: bool,
457}
458#[allow(dead_code)]
459impl GoToDefinitionResult {
460 pub fn new(name: String, spans: Vec<Span>, is_local: bool) -> Self {
462 Self {
463 name,
464 definition_spans: spans,
465 is_local,
466 }
467 }
468 pub fn found(&self) -> bool {
470 !self.definition_spans.is_empty()
471 }
472 pub fn primary_span(&self) -> Option<&Span> {
474 self.definition_spans.first()
475 }
476}
477#[allow(dead_code)]
479#[derive(Debug, Clone, Default)]
480pub struct SourceMapStats {
481 pub total_entries: usize,
483 pub definitions: usize,
485 pub references: usize,
487 pub tactics: usize,
489 pub comments: usize,
491 pub operators: usize,
493}
494#[allow(dead_code)]
495impl SourceMapStats {
496 pub fn from_entries(entries: &[SourceEntry]) -> Self {
498 let mut definitions = 0usize;
499 let mut references = 0usize;
500 let mut tactics = 0usize;
501 let mut comments = 0usize;
502 let mut operators = 0usize;
503 for entry in entries {
504 match entry.kind {
505 EntryKind::Definition => definitions += 1,
506 EntryKind::Reference => references += 1,
507 EntryKind::Tactic => tactics += 1,
508 EntryKind::Comment | EntryKind::DocComment => comments += 1,
509 EntryKind::Operator => operators += 1,
510 _ => {}
511 }
512 }
513 Self {
514 total_entries: entries.len(),
515 definitions,
516 references,
517 tactics,
518 comments,
519 operators,
520 }
521 }
522}
523#[allow(dead_code)]
525#[derive(Debug, Clone, Default)]
526pub struct SourceIndex {
527 pub definitions: DefinitionIndex,
529 pub references: ReferenceIndex,
531 pub symbols: Vec<DocumentSymbol>,
533 pub regions: Vec<SourceRegion>,
535}
536#[allow(dead_code)]
537impl SourceIndex {
538 pub fn new() -> Self {
540 Self::default()
541 }
542 pub fn register_definition(&mut self, name: impl Into<String>, span: Span) {
544 self.definitions.register(name, span);
545 }
546 pub fn record_reference(&mut self, name: impl Into<String>, span: Span) {
548 self.references.record(name, span);
549 }
550 pub fn add_symbol(&mut self, symbol: DocumentSymbol) {
552 self.symbols.push(symbol);
553 }
554 pub fn add_region(&mut self, region: SourceRegion) {
556 self.regions.push(region);
557 }
558 pub fn symbol_at_offset(&self, offset: usize) -> Option<&DocumentSymbol> {
560 self.symbols
561 .iter()
562 .find(|&sym| sym.full_span.start <= offset && offset < sym.full_span.end)
563 }
564 pub fn definition_spans(&self, name: &str) -> &[Span] {
566 self.definitions.lookup(name)
567 }
568 pub fn reference_spans(&self, name: &str) -> &[Span] {
570 self.references.uses_of(name)
571 }
572 pub fn top_level_symbols(&self) -> &[DocumentSymbol] {
574 &self.symbols
575 }
576}
577#[allow(dead_code)]
579#[derive(Debug, Clone, Default)]
580pub struct DefinitionIndex {
581 entries: std::collections::HashMap<String, Vec<Span>>,
582}
583#[allow(dead_code)]
584impl DefinitionIndex {
585 pub fn new() -> Self {
587 Self {
588 entries: std::collections::HashMap::new(),
589 }
590 }
591 pub fn register(&mut self, name: impl Into<String>, span: Span) {
593 self.entries.entry(name.into()).or_default().push(span);
594 }
595 pub fn lookup(&self, name: &str) -> &[Span] {
597 self.entries.get(name).map(|v| v.as_slice()).unwrap_or(&[])
598 }
599 pub fn contains(&self, name: &str) -> bool {
601 self.entries.contains_key(name)
602 }
603 pub fn names(&self) -> Vec<&str> {
605 self.entries.keys().map(|s| s.as_str()).collect()
606 }
607 pub fn len(&self) -> usize {
609 self.entries.len()
610 }
611 pub fn is_empty(&self) -> bool {
613 self.entries.is_empty()
614 }
615 pub fn remove(&mut self, name: &str) -> Vec<Span> {
617 self.entries.remove(name).unwrap_or_default()
618 }
619 pub fn merge(&mut self, other: DefinitionIndex) {
621 for (name, spans) in other.entries {
622 self.entries.entry(name).or_default().extend(spans);
623 }
624 }
625}
626#[allow(dead_code)]
628#[allow(missing_docs)]
629pub struct BidiMapper {
630 pub forward: Vec<(usize, usize)>,
632 pub backward: Vec<(usize, usize)>,
634}
635impl BidiMapper {
636 #[allow(dead_code)]
638 pub fn new() -> Self {
639 BidiMapper {
640 forward: Vec::new(),
641 backward: Vec::new(),
642 }
643 }
644 #[allow(dead_code)]
646 pub fn add(&mut self, orig: usize, gen: usize) {
647 self.forward.push((orig, gen));
648 self.backward.push((gen, orig));
649 }
650 #[allow(dead_code)]
652 pub fn to_gen(&self, orig: usize) -> Option<usize> {
653 self.forward
654 .iter()
655 .rev()
656 .find(|(o, _)| *o <= orig)
657 .map(|(_, g)| *g)
658 }
659 #[allow(dead_code)]
661 pub fn to_orig(&self, gen: usize) -> Option<usize> {
662 self.backward
663 .iter()
664 .rev()
665 .find(|(g, _)| *g <= gen)
666 .map(|(_, o)| *o)
667 }
668 #[allow(dead_code)]
670 pub fn len(&self) -> usize {
671 self.forward.len()
672 }
673 #[allow(dead_code)]
675 pub fn is_empty(&self) -> bool {
676 self.forward.is_empty()
677 }
678}
679#[allow(dead_code)]
681#[allow(missing_docs)]
682#[derive(Debug, Clone)]
683pub struct RangeTransform {
684 pub orig_start: usize,
686 pub orig_end: usize,
688 pub gen_start: usize,
690 pub gen_end: usize,
692}
693impl RangeTransform {
694 #[allow(dead_code)]
696 pub fn new(orig_start: usize, orig_end: usize, gen_start: usize, gen_end: usize) -> Self {
697 RangeTransform {
698 orig_start,
699 orig_end,
700 gen_start,
701 gen_end,
702 }
703 }
704 #[allow(dead_code)]
706 pub fn orig_len(&self) -> usize {
707 self.orig_end.saturating_sub(self.orig_start)
708 }
709 #[allow(dead_code)]
711 pub fn gen_len(&self) -> usize {
712 self.gen_end.saturating_sub(self.gen_start)
713 }
714 #[allow(dead_code)]
716 pub fn is_length_preserving(&self) -> bool {
717 self.orig_len() == self.gen_len()
718 }
719}
720#[allow(dead_code)]
722#[allow(missing_docs)]
723pub struct SortedSourceMap {
724 pub pairs: Vec<(usize, usize)>,
726}
727impl SortedSourceMap {
728 #[allow(dead_code)]
730 pub fn new() -> Self {
731 SortedSourceMap { pairs: Vec::new() }
732 }
733 #[allow(dead_code)]
735 pub fn add(&mut self, gen: usize, orig: usize) {
736 self.pairs.push((gen, orig));
737 self.pairs.sort_by_key(|(g, _)| *g);
738 }
739 #[allow(dead_code)]
741 pub fn lookup(&self, gen: usize) -> Option<usize> {
742 let idx = self.pairs.partition_point(|(g, _)| *g <= gen);
743 if idx == 0 {
744 return None;
745 }
746 Some(self.pairs[idx - 1].1)
747 }
748 #[allow(dead_code)]
750 pub fn len(&self) -> usize {
751 self.pairs.len()
752 }
753 #[allow(dead_code)]
755 pub fn is_empty(&self) -> bool {
756 self.pairs.is_empty()
757 }
758}
759#[allow(dead_code)]
761#[allow(missing_docs)]
762#[derive(Debug, Clone)]
763pub struct SourceMapDiff {
764 pub added: usize,
766 pub removed: usize,
768 pub modified: usize,
770}
771pub struct SourceMap {
776 entries: Vec<SourceEntry>,
778 line_offsets: Vec<usize>,
780 source: String,
782 semantic_tokens: Vec<SemanticToken>,
784}
785impl SourceMap {
786 #[allow(dead_code)]
788 pub fn new(source: &str) -> Self {
789 let line_offsets = Self::compute_line_offsets(source);
790 Self {
791 entries: Vec::new(),
792 line_offsets,
793 source: source.to_string(),
794 semantic_tokens: Vec::new(),
795 }
796 }
797 #[allow(dead_code)]
799 pub fn source(&self) -> &str {
800 &self.source
801 }
802 #[allow(dead_code)]
804 pub fn entries(&self) -> &[SourceEntry] {
805 &self.entries
806 }
807 #[allow(dead_code)]
809 pub fn line_count(&self) -> usize {
810 self.line_offsets.len()
811 }
812 #[allow(dead_code)]
816 pub fn offset_to_position(&self, offset: usize) -> (usize, usize) {
817 let line_idx = match self.line_offsets.binary_search(&offset) {
818 Ok(idx) => idx,
819 Err(idx) => {
820 if idx == 0 {
821 0
822 } else {
823 idx - 1
824 }
825 }
826 };
827 let line_start = self.line_offsets[line_idx];
828 let col = offset.saturating_sub(line_start);
829 (line_idx + 1, col + 1)
830 }
831 #[allow(dead_code)]
835 pub fn position_to_offset(&self, line: usize, col: usize) -> usize {
836 if line == 0 || line > self.line_offsets.len() {
837 return self.source.len();
838 }
839 let line_start = self.line_offsets[line - 1];
840 let col_offset = if col > 0 { col - 1 } else { 0 };
841 let max_col = self.line_length(line);
842 line_start + col_offset.min(max_col)
843 }
844 #[allow(dead_code)]
846 pub fn line_content(&self, line: usize) -> &str {
847 if line == 0 || line > self.line_offsets.len() {
848 return "";
849 }
850 let start = self.line_offsets[line - 1];
851 let end = if line < self.line_offsets.len() {
852 self.line_offsets[line]
853 } else {
854 self.source.len()
855 };
856 let text = &self.source[start..end];
857 text.trim_end_matches('\n').trim_end_matches('\r')
858 }
859 #[allow(dead_code)]
861 fn line_length(&self, line: usize) -> usize {
862 self.line_content(line).len()
863 }
864 #[allow(dead_code)]
866 pub fn entry_at(&self, line: usize, col: usize) -> Option<&SourceEntry> {
867 let offset = self.position_to_offset(line, col);
868 let mut best: Option<&SourceEntry> = None;
869 for entry in &self.entries {
870 if entry.contains_offset(offset) {
871 match best {
872 None => best = Some(entry),
873 Some(prev) => {
874 let prev_size = prev.span.end - prev.span.start;
875 let curr_size = entry.span.end - entry.span.start;
876 if curr_size < prev_size {
877 best = Some(entry);
878 }
879 }
880 }
881 }
882 }
883 best
884 }
885 #[allow(dead_code)]
887 pub fn entries_in_range(&self, start: &Span, end: &Span) -> Vec<&SourceEntry> {
888 let range_start = start.start;
889 let range_end = end.end;
890 self.entries
891 .iter()
892 .filter(|e| e.span.start < range_end && e.span.end > range_start)
893 .collect()
894 }
895 #[allow(dead_code)]
897 pub fn definitions(&self) -> Vec<&SourceEntry> {
898 self.entries
899 .iter()
900 .filter(|e| e.kind == EntryKind::Definition)
901 .collect()
902 }
903 #[allow(dead_code)]
905 pub fn references_to(&self, name: &str) -> Vec<&SourceEntry> {
906 self.entries
907 .iter()
908 .filter(|e| e.kind == EntryKind::Reference && e.name.as_deref() == Some(name))
909 .collect()
910 }
911 #[allow(dead_code)]
913 pub fn entries_of_kind(&self, kind: &EntryKind) -> Vec<&SourceEntry> {
914 self.entries.iter().filter(|e| &e.kind == kind).collect()
915 }
916 #[allow(dead_code)]
918 pub fn hover_info(&self, line: usize, col: usize) -> Option<HoverInfo> {
919 let entry = self.entry_at(line, col)?;
920 let name = entry.name.clone()?;
921 let definition_span = if entry.kind == EntryKind::Reference {
922 self.entries
923 .iter()
924 .find(|e| e.kind == EntryKind::Definition && e.name.as_deref() == Some(&name))
925 .map(|e| e.span.clone())
926 } else if entry.kind == EntryKind::Definition {
927 Some(entry.span.clone())
928 } else {
929 None
930 };
931 let doc = definition_span
932 .as_ref()
933 .and_then(|def_span| self.doc_for_definition(def_span.start));
934 Some(HoverInfo {
935 name,
936 kind: entry.kind.clone(),
937 ty: entry.ty_info.clone(),
938 doc,
939 definition_span,
940 })
941 }
942 fn doc_for_definition(&self, def_start: usize) -> Option<String> {
949 let best = self
950 .entries
951 .iter()
952 .filter(|e| e.kind == EntryKind::DocComment && e.span.end <= def_start)
953 .max_by_key(|e| e.span.end)?;
954 let doc_end = best.span.end;
955 let intervening_non_doc = self.entries.iter().any(|e| {
956 e.span.start >= doc_end
957 && e.span.start < def_start
958 && !matches!(
959 e.kind,
960 EntryKind::DocComment | EntryKind::Comment | EntryKind::Keyword
961 )
962 });
963 if intervening_non_doc {
964 None
965 } else {
966 best.name.clone()
967 }
968 }
969 #[allow(dead_code)]
971 pub fn semantic_tokens(&self) -> Vec<SemanticToken> {
972 if !self.semantic_tokens.is_empty() {
973 return self.semantic_tokens.clone();
974 }
975 self.entries
976 .iter()
977 .map(|entry| {
978 let token_type = Self::entry_kind_to_token_type(&entry.kind);
979 let modifiers = Self::entry_kind_to_modifiers(&entry.kind);
980 SemanticToken {
981 span: entry.span.clone(),
982 token_type,
983 modifiers,
984 }
985 })
986 .collect()
987 }
988 #[allow(dead_code)]
990 pub fn span_text(&self, span: &Span) -> &str {
991 let start = span.start.min(self.source.len());
992 let end = span.end.min(self.source.len());
993 &self.source[start..end]
994 }
995 #[allow(dead_code)]
997 pub fn go_to_definition(&self, line: usize, col: usize) -> Option<Span> {
998 let entry = self.entry_at(line, col)?;
999 let name = entry.name.as_deref()?;
1000 if entry.kind == EntryKind::Definition {
1001 return Some(entry.span.clone());
1002 }
1003 self.entries
1004 .iter()
1005 .find(|e| e.kind == EntryKind::Definition && e.name.as_deref() == Some(name))
1006 .map(|e| e.span.clone())
1007 }
1008 #[allow(dead_code)]
1010 pub fn find_all_occurrences(&self, line: usize, col: usize) -> Vec<&SourceEntry> {
1011 let entry = match self.entry_at(line, col) {
1012 Some(e) => e,
1013 None => return Vec::new(),
1014 };
1015 let name = match &entry.name {
1016 Some(n) => n.clone(),
1017 None => return Vec::new(),
1018 };
1019 self.entries
1020 .iter()
1021 .filter(|e| {
1022 e.name.as_deref() == Some(&name)
1023 && matches!(e.kind, EntryKind::Definition | EntryKind::Reference)
1024 })
1025 .collect()
1026 }
1027 fn compute_line_offsets(source: &str) -> Vec<usize> {
1029 let mut offsets = vec![0usize];
1030 for (i, ch) in source.char_indices() {
1031 if ch == '\n' {
1032 offsets.push(i + 1);
1033 }
1034 }
1035 offsets
1036 }
1037 fn entry_kind_to_token_type(kind: &EntryKind) -> SemanticTokenType {
1039 match kind {
1040 EntryKind::Definition => SemanticTokenType::Function,
1041 EntryKind::Reference => SemanticTokenType::Variable,
1042 EntryKind::TypeAnnotation => SemanticTokenType::Type,
1043 EntryKind::Binder => SemanticTokenType::Variable,
1044 EntryKind::Constructor => SemanticTokenType::Constructor,
1045 EntryKind::Pattern => SemanticTokenType::Variable,
1046 EntryKind::Tactic => SemanticTokenType::Tactic,
1047 EntryKind::Keyword => SemanticTokenType::Keyword,
1048 EntryKind::Literal => SemanticTokenType::Number,
1049 EntryKind::Comment => SemanticTokenType::Comment,
1050 EntryKind::DocComment => SemanticTokenType::Comment,
1051 EntryKind::Operator => SemanticTokenType::Operator,
1052 }
1053 }
1054 fn entry_kind_to_modifiers(kind: &EntryKind) -> Vec<SemanticModifier> {
1056 match kind {
1057 EntryKind::Definition => vec![SemanticModifier::Definition],
1058 EntryKind::DocComment => vec![SemanticModifier::Documentation],
1059 _ => Vec::new(),
1060 }
1061 }
1062}
1063#[allow(dead_code)]
1065#[derive(Debug, Clone, Default)]
1066pub struct ReferenceIndex {
1067 entries: std::collections::HashMap<String, Vec<Span>>,
1068}
1069#[allow(dead_code)]
1070impl ReferenceIndex {
1071 pub fn new() -> Self {
1073 Self {
1074 entries: std::collections::HashMap::new(),
1075 }
1076 }
1077 pub fn record(&mut self, name: impl Into<String>, span: Span) {
1079 self.entries.entry(name.into()).or_default().push(span);
1080 }
1081 pub fn uses_of(&self, name: &str) -> &[Span] {
1083 self.entries.get(name).map(|v| v.as_slice()).unwrap_or(&[])
1084 }
1085 pub fn referenced_names(&self) -> Vec<&str> {
1087 self.entries.keys().map(|s| s.as_str()).collect()
1088 }
1089 pub fn total_references(&self) -> usize {
1091 self.entries.values().map(|v| v.len()).sum()
1092 }
1093}
1094pub struct SourceMapBuilder {
1096 entries: Vec<SourceEntry>,
1098 semantic_tokens: Vec<SemanticToken>,
1100 source: String,
1102}
1103impl SourceMapBuilder {
1104 #[allow(dead_code)]
1106 pub fn new(source: &str) -> Self {
1107 Self {
1108 entries: Vec::new(),
1109 semantic_tokens: Vec::new(),
1110 source: source.to_string(),
1111 }
1112 }
1113 #[allow(dead_code)]
1115 pub fn add_entry(&mut self, span: Span, kind: EntryKind, name: Option<String>) {
1116 self.entries.push(SourceEntry {
1117 span,
1118 kind,
1119 name,
1120 ty_info: None,
1121 });
1122 }
1123 #[allow(dead_code)]
1125 pub fn add_entry_with_type(
1126 &mut self,
1127 span: Span,
1128 kind: EntryKind,
1129 name: Option<String>,
1130 ty_info: String,
1131 ) {
1132 self.entries.push(SourceEntry {
1133 span,
1134 kind,
1135 name,
1136 ty_info: Some(ty_info),
1137 });
1138 }
1139 #[allow(dead_code)]
1141 pub fn add_definition(&mut self, span: Span, name: &str) {
1142 self.entries.push(SourceEntry {
1143 span,
1144 kind: EntryKind::Definition,
1145 name: Some(name.to_string()),
1146 ty_info: None,
1147 });
1148 }
1149 #[allow(dead_code)]
1151 pub fn add_definition_with_type(&mut self, span: Span, name: &str, ty_info: &str) {
1152 self.entries.push(SourceEntry {
1153 span,
1154 kind: EntryKind::Definition,
1155 name: Some(name.to_string()),
1156 ty_info: Some(ty_info.to_string()),
1157 });
1158 }
1159 #[allow(dead_code)]
1161 pub fn add_reference(&mut self, span: Span, name: &str) {
1162 self.entries.push(SourceEntry {
1163 span,
1164 kind: EntryKind::Reference,
1165 name: Some(name.to_string()),
1166 ty_info: None,
1167 });
1168 }
1169 #[allow(dead_code)]
1171 pub fn add_binder(&mut self, span: Span, name: &str) {
1172 self.entries.push(SourceEntry {
1173 span,
1174 kind: EntryKind::Binder,
1175 name: Some(name.to_string()),
1176 ty_info: None,
1177 });
1178 }
1179 #[allow(dead_code)]
1181 pub fn add_constructor(&mut self, span: Span, name: &str) {
1182 self.entries.push(SourceEntry {
1183 span,
1184 kind: EntryKind::Constructor,
1185 name: Some(name.to_string()),
1186 ty_info: None,
1187 });
1188 }
1189 #[allow(dead_code)]
1191 pub fn add_keyword(&mut self, span: Span) {
1192 self.entries.push(SourceEntry {
1193 span,
1194 kind: EntryKind::Keyword,
1195 name: None,
1196 ty_info: None,
1197 });
1198 }
1199 #[allow(dead_code)]
1201 pub fn add_literal(&mut self, span: Span) {
1202 self.entries.push(SourceEntry {
1203 span,
1204 kind: EntryKind::Literal,
1205 name: None,
1206 ty_info: None,
1207 });
1208 }
1209 #[allow(dead_code)]
1211 pub fn add_operator(&mut self, span: Span, symbol: &str) {
1212 self.entries.push(SourceEntry {
1213 span,
1214 kind: EntryKind::Operator,
1215 name: Some(symbol.to_string()),
1216 ty_info: None,
1217 });
1218 }
1219 #[allow(dead_code)]
1221 pub fn add_comment(&mut self, span: Span) {
1222 self.entries.push(SourceEntry {
1223 span,
1224 kind: EntryKind::Comment,
1225 name: None,
1226 ty_info: None,
1227 });
1228 }
1229 #[allow(dead_code)]
1231 pub fn add_doc_comment(&mut self, span: Span, text: &str) {
1232 self.entries.push(SourceEntry {
1233 span,
1234 kind: EntryKind::DocComment,
1235 name: Some(text.to_string()),
1236 ty_info: None,
1237 });
1238 }
1239 #[allow(dead_code)]
1241 pub fn add_tactic(&mut self, span: Span, name: &str) {
1242 self.entries.push(SourceEntry {
1243 span,
1244 kind: EntryKind::Tactic,
1245 name: Some(name.to_string()),
1246 ty_info: None,
1247 });
1248 }
1249 #[allow(dead_code)]
1251 pub fn add_pattern(&mut self, span: Span, name: Option<&str>) {
1252 self.entries.push(SourceEntry {
1253 span,
1254 kind: EntryKind::Pattern,
1255 name: name.map(|n| n.to_string()),
1256 ty_info: None,
1257 });
1258 }
1259 #[allow(dead_code)]
1261 pub fn add_type_annotation(&mut self, span: Span) {
1262 self.entries.push(SourceEntry {
1263 span,
1264 kind: EntryKind::TypeAnnotation,
1265 name: None,
1266 ty_info: None,
1267 });
1268 }
1269 #[allow(dead_code)]
1271 pub fn add_semantic_token(&mut self, token: SemanticToken) {
1272 self.semantic_tokens.push(token);
1273 }
1274 #[allow(dead_code)]
1276 pub fn entry_count(&self) -> usize {
1277 self.entries.len()
1278 }
1279 #[allow(dead_code)]
1283 pub fn build(mut self) -> SourceMap {
1284 self.entries.sort_by(|a, b| {
1285 a.span.start.cmp(&b.span.start).then_with(|| {
1286 let a_size = a.span.end - a.span.start;
1287 let b_size = b.span.end - b.span.start;
1288 a_size.cmp(&b_size)
1289 })
1290 });
1291 self.semantic_tokens
1292 .sort_by(|a, b| a.span.start.cmp(&b.span.start));
1293 let line_offsets = SourceMap::compute_line_offsets(&self.source);
1294 SourceMap {
1295 entries: self.entries,
1296 line_offsets,
1297 source: self.source,
1298 semantic_tokens: self.semantic_tokens,
1299 }
1300 }
1301}
1302#[derive(Clone, Debug, PartialEq)]
1304pub struct HoverInfo {
1305 pub name: String,
1307 pub kind: EntryKind,
1309 pub ty: Option<String>,
1311 pub doc: Option<String>,
1313 pub definition_span: Option<Span>,
1315}
1316#[allow(dead_code)]
1318#[allow(missing_docs)]
1319pub struct MapChain {
1320 pub first: BidiMapper,
1322 pub second: BidiMapper,
1324}
1325impl MapChain {
1326 #[allow(dead_code)]
1328 pub fn new(first: BidiMapper, second: BidiMapper) -> Self {
1329 MapChain { first, second }
1330 }
1331 #[allow(dead_code)]
1333 pub fn a_to_c(&self, a: usize) -> Option<usize> {
1334 let b = self.first.to_gen(a)?;
1335 self.second.to_gen(b)
1336 }
1337 #[allow(dead_code)]
1339 pub fn c_to_a(&self, c: usize) -> Option<usize> {
1340 let b = self.second.to_orig(c)?;
1341 self.first.to_orig(b)
1342 }
1343}
1344#[allow(dead_code)]
1346#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1347pub enum SymbolKind {
1348 Theorem,
1350 Definition,
1352 Axiom,
1354 Inductive,
1356 Structure,
1358 Class,
1360 Instance,
1362 Namespace,
1364 Section,
1366 Constructor,
1368 Field,
1370 Variable,
1372}