Skip to main content

swls_core/
lang.rs

1use std::{borrow::Cow, ops::Range};
2
3use crate::{lsp_types::SemanticTokenType, prelude::TripleTarget, util::offset_to_position};
4
5pub fn head() -> crate::lsp_types::Range {
6    let start = crate::lsp_types::Position {
7        line: 0,
8        character: 0,
9    };
10    crate::lsp_types::Range {
11        end: start.clone(),
12        start,
13    }
14}
15
16pub trait Lang: 'static {
17    /// Type of the parsed element.
18    type Element: Send + Sync;
19    type ElementError: Into<crate::feature::diagnostics::SimpleDiagnostic>
20        + Send
21        + Sync
22        + std::fmt::Debug;
23
24    const CODE_ACTION: bool;
25    const HOVER: bool;
26    const LANG: &'static str;
27    const TRIGGERS: &'static [&'static str];
28    const LEGEND_TYPES: &'static [SemanticTokenType];
29    const PATTERN: Option<&'static str>;
30
31    /// Map a CST syntax kind to a semantic token type for highlighting.
32    fn semantic_token_type(_kind: rowan::SyntaxKind) -> Option<SemanticTokenType> {
33        None
34    }
35
36    /// Map a CST syntax kind + byte span to semantic token spans for highlighting.
37    fn semantic_token_spans(
38        kind: rowan::SyntaxKind,
39        span: std::ops::Range<usize>,
40        _text: &str,
41    ) -> Vec<(SemanticTokenType, std::ops::Range<usize>)> {
42        Self::semantic_token_type(kind)
43            .map(|t| vec![(t, span)])
44            .unwrap_or_default()
45    }
46}
47
48pub trait LangHelper: std::fmt::Debug {
49    fn keyword(&self) -> &[&'static str];
50    fn default_position(&self) -> TripleTarget {
51        TripleTarget::Subject
52    }
53    fn unquote<'a>(&self, inp: &'a str) -> &'a str {
54        inp
55    }
56    fn quote(&self, inp: &str) -> String {
57        format!("{}", inp)
58    }
59    /// Return `true` if this language provides its own prefix completion and
60    /// the generic [`defined_prefix_completion`] system should be skipped.
61    fn handles_prefix_completion(&self) -> bool {
62        false
63    }
64    fn supports_shape_validation(&self) -> bool {
65        true
66    }
67
68    fn inlay_types_hint(
69        &self,
70        subject: &Range<usize>,
71        rope: &ropey::Rope,
72        last_type: Option<&Range<usize>>,
73        types: Vec<Cow<'_, str>>,
74    ) -> Option<crate::lsp_types::InlayHint> {
75        let (label, position) = if let Some(lt) = last_type {
76            if let Some(pos) = offset_to_position(lt.end, &rope) {
77                let label = format!(", {}", types.join(", "));
78                (label, pos)
79            } else {
80                return None;
81            }
82        } else {
83            let offset = if rope.get_char(subject.start) == Some('[') {
84                subject.start + 1
85            } else {
86                subject.end
87            };
88
89            if let Some(pos) = offset_to_position(offset, &rope) {
90                let label = format!(" a {};", types.join(", "));
91                (label, pos)
92            } else {
93                return None;
94            }
95        };
96
97        return Some(crate::lsp_types::InlayHint {
98            position,
99            label: crate::lsp_types::InlayHintLabel::String(label),
100            kind: None,
101            text_edits: None,
102            tooltip: None,
103            padding_left: None,
104            padding_right: None,
105            data: None,
106        });
107    }
108}