Skip to main content

only_semantic/
document_symbols.rs

1use smol_str::SmolStr;
2use text_size::TextRange;
3
4use crate::SemanticSnapshot;
5
6/// Kind of document symbol produced for editor consumers.
7///
8/// Args:
9/// None.
10///
11/// Returns:
12/// Stable symbol categories for namespace and task items.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum DocumentSymbolKind {
15    Namespace,
16    Task,
17}
18
19/// Flat document symbol entry for editor consumers.
20///
21/// Args:
22/// None.
23///
24/// Returns:
25/// Symbol name, container and text range for one source item.
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct DocumentSymbol {
28    pub name: SmolStr,
29    pub detail: Option<SmolStr>,
30    pub kind: DocumentSymbolKind,
31    pub range: TextRange,
32    pub container_name: Option<SmolStr>,
33}
34
35/// Builds flat document symbols from one semantic snapshot.
36///
37/// Args:
38/// snapshot: Immutable semantic snapshot for one document version.
39///
40/// Returns:
41/// Flat symbol list for namespaces and tasks in source order.
42pub fn document_symbols(snapshot: &SemanticSnapshot) -> Vec<DocumentSymbol> {
43    let namespaces = snapshot
44        .document
45        .namespaces
46        .iter()
47        .map(|namespace| DocumentSymbol {
48            name: namespace.name.clone(),
49            detail: namespace.doc.clone(),
50            kind: DocumentSymbolKind::Namespace,
51            range: namespace.range,
52            container_name: None,
53        });
54
55    let tasks = snapshot.document.tasks.iter().map(|task| DocumentSymbol {
56        name: task.name.clone(),
57        detail: Some(task.signature()),
58        kind: DocumentSymbolKind::Task,
59        range: task.range,
60        container_name: task.namespace.clone(),
61    });
62
63    namespaces.chain(tasks).collect()
64}