Skip to main content

merman_editor_core/
workspace.rs

1use crate::snapshot::{DocumentSnapshot, FenceSnapshot};
2use crate::types::{DocumentKind, DocumentUri};
3use merman_analysis::{
4    AnalyzedDiagram, Analyzer, SourceDescriptor, SourceKind, analyze_document_result_shared,
5};
6use std::collections::HashMap;
7use std::sync::Arc;
8
9#[derive(Debug)]
10pub struct DocumentWorkspace {
11    documents: HashMap<DocumentUri, DocumentSnapshot>,
12    analyzer: Analyzer,
13}
14
15impl Default for DocumentWorkspace {
16    fn default() -> Self {
17        Self::new()
18    }
19}
20
21impl DocumentWorkspace {
22    pub fn new() -> Self {
23        Self::with_analyzer(Analyzer::new())
24    }
25
26    pub fn with_analyzer(analyzer: Analyzer) -> Self {
27        Self {
28            documents: HashMap::new(),
29            analyzer,
30        }
31    }
32
33    pub fn replace_analyzer(&mut self, analyzer: Analyzer) {
34        self.analyzer = analyzer;
35        self.documents.clear();
36    }
37
38    pub fn upsert(
39        &mut self,
40        uri: impl Into<DocumentUri>,
41        version: i32,
42        text: String,
43        kind: DocumentKind,
44    ) -> DocumentSnapshot {
45        let uri = uri.into();
46        let snapshot = self.build_snapshot(uri.clone(), version, text, kind);
47        self.documents.insert(uri, snapshot.clone());
48        snapshot
49    }
50
51    pub fn build_snapshot(
52        &self,
53        uri: impl Into<DocumentUri>,
54        version: i32,
55        text: String,
56        kind: DocumentKind,
57    ) -> DocumentSnapshot {
58        Self::build_snapshot_with_analyzer(&self.analyzer, uri, version, text, kind)
59    }
60
61    pub fn build_snapshot_with_analyzer(
62        analyzer: &Analyzer,
63        uri: impl Into<DocumentUri>,
64        version: i32,
65        text: String,
66        kind: DocumentKind,
67    ) -> DocumentSnapshot {
68        Self::build_snapshot_with_shared_text(analyzer, uri, version, Arc::from(text), kind)
69    }
70
71    pub fn build_snapshot_with_shared_text(
72        analyzer: &Analyzer,
73        uri: impl Into<DocumentUri>,
74        version: i32,
75        text: Arc<str>,
76        kind: DocumentKind,
77    ) -> DocumentSnapshot {
78        let uri = uri.into();
79        let source = source_descriptor_for_document(&uri, kind);
80        let analysis = analyze_document_result_shared(Arc::clone(&text), analyzer, source.clone());
81        let fences = analysis
82            .diagrams()
83            .iter()
84            .map(Self::fence_snapshot)
85            .collect::<Vec<_>>();
86        let source_map = analysis.source_map().clone();
87        DocumentSnapshot {
88            uri,
89            version,
90            kind,
91            source,
92            text,
93            source_map,
94            fences,
95        }
96    }
97
98    pub fn get(&self, uri: &DocumentUri) -> Option<&DocumentSnapshot> {
99        self.documents.get(uri)
100    }
101
102    pub fn remove(&mut self, uri: &DocumentUri) {
103        self.documents.remove(uri);
104    }
105
106    pub fn snapshots(&self) -> Vec<DocumentSnapshot> {
107        self.documents.values().cloned().collect()
108    }
109
110    fn fence_snapshot(diagram: &AnalyzedDiagram) -> FenceSnapshot {
111        FenceSnapshot {
112            source_id: diagram.source_id.clone(),
113            index: diagram.index,
114            source: diagram.source.clone(),
115            start: diagram.start,
116            body_start: diagram.body_start,
117            body_end: diagram.body_end,
118            end: diagram.end,
119            text: diagram.text.clone(),
120            fence_delimiter: diagram.fence_delimiter,
121            diagram_type: diagram.syntax.diagram_type.clone(),
122            text_index: diagram.syntax.text_index.clone(),
123        }
124    }
125}
126
127fn source_descriptor_for_document(uri: &DocumentUri, kind: DocumentKind) -> SourceDescriptor {
128    let source_kind = match kind {
129        DocumentKind::Diagram => SourceKind::Diagram,
130        DocumentKind::Markdown => SourceKind::Markdown,
131        DocumentKind::Mdx => SourceKind::Mdx,
132    };
133    merman_analysis::source_descriptor_for_kind(Some(uri.as_str()), source_kind)
134}