Skip to main content

only_semantic/
folding.rs

1use text_size::TextRange;
2
3use crate::SemanticSnapshot;
4
5/// Kind of folding range produced for editor consumers.
6///
7/// Args:
8/// None.
9///
10/// Returns:
11/// Stable folding categories for namespace and task blocks.
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum FoldingRangeKind {
14    Namespace,
15    Task,
16}
17
18/// Foldable source span for editor consumers.
19///
20/// Args:
21/// None.
22///
23/// Returns:
24/// One semantic folding range and its category.
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct FoldingRange {
27    pub range: TextRange,
28    pub kind: FoldingRangeKind,
29}
30
31/// Builds folding ranges from one semantic snapshot.
32///
33/// Args:
34/// snapshot: Immutable semantic snapshot for one document version.
35///
36/// Returns:
37/// Foldable ranges for namespace blocks and task blocks.
38pub fn folding_ranges(snapshot: &SemanticSnapshot) -> Vec<FoldingRange> {
39    let mut ranges = snapshot
40        .document
41        .tasks
42        .iter()
43        .map(|task| FoldingRange {
44            range: task.range,
45            kind: FoldingRangeKind::Task,
46        })
47        .collect::<Vec<_>>();
48
49    for namespace in &snapshot.document.namespaces {
50        let namespace_range = snapshot
51            .document
52            .tasks
53            .iter()
54            .filter(|task| task.namespace.as_deref() == Some(namespace.name.as_str()))
55            .fold(namespace.range, |range, task| {
56                TextRange::new(range.start(), range.end().max(task.range.end()))
57            });
58
59        ranges.push(FoldingRange {
60            range: namespace_range,
61            kind: FoldingRangeKind::Namespace,
62        });
63    }
64
65    ranges
66}