summaryrefslogtreecommitdiff
path: root/support/texlab/src/features/symbol/types.rs
blob: 96b26be1539b9abbe4bc4c85255caeb61185c527 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use lsp_types::{DocumentSymbol, Location, Range, SymbolInformation, SymbolKind, Url};

use crate::{
    db::Word,
    util::{self, lang_data::BibtexEntryTypeCategory, lsp_enums::Structure},
    Db, SymbolConfig,
};

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum InternalSymbolKind {
    Section,
    Figure,
    Algorithm,
    Table,
    Listing,
    Enumeration,
    EnumerationItem,
    Theorem,
    Equation,
    Entry(BibtexEntryTypeCategory),
    Field,
    String,
}

impl InternalSymbolKind {
    pub fn into_symbol_kind(self) -> SymbolKind {
        match self {
            Self::Section => Structure::Section.symbol_kind(),
            Self::Figure | Self::Algorithm | Self::Table | Self::Listing => {
                Structure::Float.symbol_kind()
            }
            Self::Enumeration => Structure::Environment.symbol_kind(),
            Self::EnumerationItem => Structure::Item.symbol_kind(),
            Self::Theorem => Structure::Theorem.symbol_kind(),
            Self::Equation => Structure::Equation.symbol_kind(),
            Self::Entry(category) => Structure::Entry(category).symbol_kind(),
            Self::Field => Structure::Field.symbol_kind(),
            Self::String => Structure::Entry(BibtexEntryTypeCategory::String).symbol_kind(),
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct InternalSymbol {
    pub name: String,
    pub label: Option<Word>,
    pub kind: InternalSymbolKind,
    pub deprecated: bool,
    pub full_range: Range,
    pub selection_range: Range,
    pub children: Vec<InternalSymbol>,
}

impl InternalSymbol {
    pub fn search_text(&self) -> String {
        let kind = match self.kind {
            InternalSymbolKind::Section => "latex section",
            InternalSymbolKind::Figure => "latex float figure",
            InternalSymbolKind::Algorithm => "latex float algorithm",
            InternalSymbolKind::Table => "latex float table",
            InternalSymbolKind::Listing => "latex float listing",
            InternalSymbolKind::Enumeration => "latex enumeration",
            InternalSymbolKind::EnumerationItem => "latex enumeration item",
            InternalSymbolKind::Theorem => "latex math",
            InternalSymbolKind::Equation => "latex math equation",
            InternalSymbolKind::Entry(_) => "bibtex entry",
            InternalSymbolKind::Field => "bibtex field",
            InternalSymbolKind::String => "bibtex string",
        };
        format!("{} {}", kind, self.name).to_lowercase()
    }

    pub fn flatten(mut self, buffer: &mut Vec<Self>) {
        if self.kind == InternalSymbolKind::Field {
            return;
        }
        for symbol in self.children.drain(..) {
            symbol.flatten(buffer);
        }
        buffer.push(self);
    }

    pub fn filter(container: &mut Vec<InternalSymbol>, config: &SymbolConfig) {
        let mut i = 0;
        while i < container.len() {
            let symbol = &mut container[i];

            if util::regex_filter::filter(
                &symbol.name,
                &config.allowed_patterns,
                &config.ignored_patterns,
            ) {
                Self::filter(&mut symbol.children, config);
                i += 1;
            } else {
                drop(symbol);
                let mut symbol = container.remove(i);
                container.append(&mut symbol.children);
            }
        }
    }

    pub fn into_document_symbol(self, db: &dyn Db) -> DocumentSymbol {
        let children = self
            .children
            .into_iter()
            .map(|child| child.into_document_symbol(db))
            .collect();

        #[allow(deprecated)]
        DocumentSymbol {
            name: self.name,
            detail: self.label.map(|word| word.text(db).clone()),
            kind: self.kind.into_symbol_kind(),
            deprecated: Some(self.deprecated),
            range: self.full_range,
            selection_range: self.selection_range,
            children: Some(children),
            tags: None,
        }
    }

    pub fn into_symbol_info(self, uri: Url) -> SymbolInformation {
        #[allow(deprecated)]
        SymbolInformation {
            name: self.name,
            kind: self.kind.into_symbol_kind(),
            deprecated: Some(self.deprecated),
            location: Location::new(uri, self.full_range),
            container_name: None,
            tags: None,
        }
    }
}