lsp_core/util/
mod.rs

1use std::{
2    borrow::Borrow,
3    ops::{Deref, DerefMut},
4};
5
6use lsp_types::{Location, Position, Range};
7use ropey::Rope;
8
9use crate::Label;
10
11// pub mod cache;
12pub mod fs;
13/// Commonly used RDF prefixes
14pub mod ns;
15pub mod token;
16pub mod triple;
17
18// /// Maps http:// and https:// urls to virtual:// urls
19// /// This enables the editor to show them
20// pub fn make_virtual_url(url: &str, prefix: &str) -> Option<Url> {
21//     if !url.starts_with("http") {
22//         return None;
23//     }
24//
25//     let url = format!("virtual://prefix/{}.ttl", prefix);
26//
27//     lsp_types::Url::parse(&url).ok()
28// }
29
30pub fn range_to_range(range: &std::ops::Range<usize>, rope: &Rope) -> Option<Range> {
31    let start = offset_to_position(range.start, rope)?;
32    let end = offset_to_position(range.end, rope)?;
33    Range::new(start, end).into()
34}
35
36pub fn lsp_range_to_range(range: &lsp_types::Range, rope: &Rope) -> Option<std::ops::Range<usize>> {
37    if range.start.line as usize >= rope.len_lines() || range.end.line as usize >= rope.len_lines()
38    {
39        return None;
40    }
41
42    let start = rope.line_to_byte(range.start.line as usize) + range.start.character as usize;
43    let end = rope.line_to_byte(range.end.line as usize) + range.end.character as usize;
44
45    Some(start..end)
46}
47
48pub fn offset_to_position(offset: usize, rope: &Rope) -> Option<Position> {
49    let line = rope.try_char_to_line(offset).ok()?;
50    let first_char = rope.try_line_to_char(line).ok()?;
51    let column = offset - first_char;
52    Some(Position::new(line as u32, column as u32))
53}
54pub fn position_to_offset(position: Position, rope: &Rope) -> Option<usize> {
55    let line_offset = rope.try_line_to_char(position.line as usize).ok()?;
56    let line_length = rope.get_line(position.line as usize)?.len_chars();
57
58    if (position.character as usize) < line_length {
59        Some(line_offset + position.character as usize)
60    } else {
61        None
62    }
63}
64pub fn offsets_to_range(start: usize, end: usize, rope: &Rope) -> Option<Range> {
65    let start = offset_to_position(start, rope)?;
66    let end = offset_to_position(end, rope)?;
67    Some(Range { start, end })
68}
69
70#[derive(Debug, Clone)]
71pub struct Spanned<T>(pub T, pub std::ops::Range<usize>);
72impl<T> Default for Spanned<T>
73where
74    T: Default,
75{
76    fn default() -> Self {
77        Self(T::default(), 0..1)
78    }
79}
80
81impl<T> Spanned<T> {
82    pub fn map<O>(self, f: impl Fn(T) -> O) -> Spanned<O> {
83        let v = f(self.0);
84        Spanned(v, self.1)
85    }
86    pub fn map_ref<'a, O: 'a>(&'a self, f: impl Fn(&'a T) -> O) -> Spanned<O> {
87        let v = f(&self.0);
88        Spanned(v, self.1.clone())
89    }
90    pub fn as_ref<'a>(&'a self) -> Spanned<&'a T> {
91        Spanned(&self.0, self.1.clone())
92    }
93
94    pub fn try_map_ref<'a, O>(&'a self, f: impl FnOnce(&'a T) -> Option<O>) -> Option<Spanned<O>> {
95        if let Some(v) = f(&self.0) {
96            Some(Spanned(v, self.1.clone()))
97        } else {
98            None
99        }
100    }
101    pub fn try_map<O>(self, f: impl FnOnce(T) -> Option<O>) -> Option<Spanned<O>> {
102        if let Some(v) = f(self.0) {
103            Some(Spanned(v, self.1))
104        } else {
105            None
106        }
107    }
108}
109impl<T> Spanned<Option<T>> {
110    pub fn transpose(self) -> Option<Spanned<T>> {
111        self.0.map(|inner| Spanned(inner, self.1))
112    }
113}
114
115impl<T: PartialEq> PartialEq for Spanned<T> {
116    fn eq(&self, other: &Self) -> bool {
117        self.0.eq(&other.0)
118    }
119}
120impl<T: std::hash::Hash> std::hash::Hash for Spanned<T> {
121    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
122        self.0.hash(state)
123    }
124}
125impl<T: PartialEq> Eq for Spanned<T> {}
126
127pub fn spanned<T>(t: T, span: std::ops::Range<usize>) -> Spanned<T> {
128    Spanned(t, span)
129}
130
131impl Borrow<str> for Spanned<String> {
132    #[inline]
133    fn borrow(&self) -> &str {
134        &self[..]
135    }
136}
137
138impl<T> Deref for Spanned<T> {
139    type Target = T;
140
141    fn deref(&self) -> &Self::Target {
142        &self.0
143    }
144}
145
146impl<T> DerefMut for Spanned<T> {
147    fn deref_mut(&mut self) -> &mut Self::Target {
148        &mut self.0
149    }
150}
151
152impl<T> Spanned<T> {
153    pub fn into_value(self) -> T {
154        self.0
155    }
156    pub fn into_span(self) -> std::ops::Range<usize> {
157        self.1
158    }
159    pub fn value(&self) -> &T {
160        &self.0
161    }
162    pub fn value_mut(&mut self) -> &mut T {
163        &mut self.0
164    }
165    pub fn span(&self) -> &std::ops::Range<usize> {
166        &self.1
167    }
168}
169
170pub fn token_to_location(
171    token: &std::ops::Range<usize>,
172    label: &Label,
173    rope: &Rope,
174) -> Option<Location> {
175    let range = range_to_range(token, rope)?;
176    Some(Location {
177        range,
178        uri: label.0.clone(),
179    })
180}