aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/conv.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-16 10:54:24 +0100
committerAleksey Kladov <[email protected]>2018-09-16 11:07:39 +0100
commitb5021411a84822cb3f1e3aeffad9550dd15bdeb6 (patch)
tree9dca564f8e51b298dced01c4ce669c756dce3142 /crates/ra_lsp_server/src/conv.rs
parentba0bfeee12e19da40b5eabc8d0408639af10e96f (diff)
rename all things
Diffstat (limited to 'crates/ra_lsp_server/src/conv.rs')
-rw-r--r--crates/ra_lsp_server/src/conv.rs296
1 files changed, 296 insertions, 0 deletions
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
new file mode 100644
index 000000000..759e5e914
--- /dev/null
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -0,0 +1,296 @@
1use languageserver_types::{
2 Range, SymbolKind, Position, TextEdit, Location, Url,
3 TextDocumentIdentifier, VersionedTextDocumentIdentifier, TextDocumentItem,
4 TextDocumentPositionParams, TextDocumentEdit,
5};
6use ra_editor::{LineIndex, LineCol, Edit, AtomEdit};
7use ra_syntax::{SyntaxKind, TextUnit, TextRange};
8use ra_analysis::{FileId, SourceChange, SourceFileEdit, FileSystemEdit};
9
10use {
11 Result,
12 server_world::ServerWorld,
13 req,
14};
15
16pub trait Conv {
17 type Output;
18 fn conv(self) -> Self::Output;
19}
20
21pub trait ConvWith {
22 type Ctx;
23 type Output;
24 fn conv_with(self, ctx: &Self::Ctx) -> Self::Output;
25}
26
27pub trait TryConvWith {
28 type Ctx;
29 type Output;
30 fn try_conv_with(self, ctx: &Self::Ctx) -> Result<Self::Output>;
31}
32
33impl Conv for SyntaxKind {
34 type Output = SymbolKind;
35
36 fn conv(self) -> <Self as Conv>::Output {
37 match self {
38 SyntaxKind::FN_DEF => SymbolKind::Function,
39 SyntaxKind::STRUCT_DEF => SymbolKind::Struct,
40 SyntaxKind::ENUM_DEF => SymbolKind::Enum,
41 SyntaxKind::TRAIT_DEF => SymbolKind::Interface,
42 SyntaxKind::MODULE => SymbolKind::Module,
43 SyntaxKind::TYPE_DEF => SymbolKind::TypeParameter,
44 SyntaxKind::STATIC_DEF => SymbolKind::Constant,
45 SyntaxKind::CONST_DEF => SymbolKind::Constant,
46 SyntaxKind::IMPL_ITEM => SymbolKind::Object,
47 _ => SymbolKind::Variable,
48 }
49 }
50}
51
52impl ConvWith for Position {
53 type Ctx = LineIndex;
54 type Output = TextUnit;
55
56 fn conv_with(self, line_index: &LineIndex) -> TextUnit {
57 // TODO: UTF-16
58 let line_col = LineCol {
59 line: self.line as u32,
60 col: (self.character as u32).into(),
61 };
62 line_index.offset(line_col)
63 }
64}
65
66impl ConvWith for TextUnit {
67 type Ctx = LineIndex;
68 type Output = Position;
69
70 fn conv_with(self, line_index: &LineIndex) -> Position {
71 let line_col = line_index.line_col(self);
72 // TODO: UTF-16
73 Position::new(line_col.line as u64, u32::from(line_col.col) as u64)
74 }
75}
76
77impl ConvWith for TextRange {
78 type Ctx = LineIndex;
79 type Output = Range;
80
81 fn conv_with(self, line_index: &LineIndex) -> Range {
82 Range::new(
83 self.start().conv_with(line_index),
84 self.end().conv_with(line_index),
85 )
86 }
87}
88
89impl ConvWith for Range {
90 type Ctx = LineIndex;
91 type Output = TextRange;
92
93 fn conv_with(self, line_index: &LineIndex) -> TextRange {
94 TextRange::from_to(
95 self.start.conv_with(line_index),
96 self.end.conv_with(line_index),
97 )
98 }
99}
100
101impl ConvWith for Edit {
102 type Ctx = LineIndex;
103 type Output = Vec<TextEdit>;
104
105 fn conv_with(self, line_index: &LineIndex) -> Vec<TextEdit> {
106 self.into_atoms()
107 .into_iter()
108 .map_conv_with(line_index)
109 .collect()
110 }
111}
112
113impl ConvWith for AtomEdit {
114 type Ctx = LineIndex;
115 type Output = TextEdit;
116
117 fn conv_with(self, line_index: &LineIndex) -> TextEdit {
118 TextEdit {
119 range: self.delete.conv_with(line_index),
120 new_text: self.insert,
121 }
122 }
123}
124
125impl<T: ConvWith> ConvWith for Option<T> {
126 type Ctx = <T as ConvWith>::Ctx;
127 type Output = Option<<T as ConvWith>::Output>;
128 fn conv_with(self, ctx: &Self::Ctx) -> Self::Output {
129 self.map(|x| ConvWith::conv_with(x, ctx))
130 }
131}
132
133impl<'a> TryConvWith for &'a Url {
134 type Ctx = ServerWorld;
135 type Output = FileId;
136 fn try_conv_with(self, world: &ServerWorld) -> Result<FileId> {
137 world.uri_to_file_id(self)
138 }
139}
140
141impl TryConvWith for FileId {
142 type Ctx = ServerWorld;
143 type Output = Url;
144 fn try_conv_with(self, world: &ServerWorld) -> Result<Url> {
145 world.file_id_to_uri(self)
146 }
147}
148
149impl<'a> TryConvWith for &'a TextDocumentItem {
150 type Ctx = ServerWorld;
151 type Output = FileId;
152 fn try_conv_with(self, world: &ServerWorld) -> Result<FileId> {
153 self.uri.try_conv_with(world)
154 }
155}
156
157impl<'a> TryConvWith for &'a VersionedTextDocumentIdentifier {
158 type Ctx = ServerWorld;
159 type Output = FileId;
160 fn try_conv_with(self, world: &ServerWorld) -> Result<FileId> {
161 self.uri.try_conv_with(world)
162 }
163}
164
165impl<'a> TryConvWith for &'a TextDocumentIdentifier {
166 type Ctx = ServerWorld;
167 type Output = FileId;
168 fn try_conv_with(self, world: &ServerWorld) -> Result<FileId> {
169 world.uri_to_file_id(&self.uri)
170 }
171}
172
173impl<T: TryConvWith> TryConvWith for Vec<T> {
174 type Ctx = <T as TryConvWith>::Ctx;
175 type Output = Vec<<T as TryConvWith>::Output>;
176 fn try_conv_with(self, ctx: &Self::Ctx) -> Result<Self::Output> {
177 let mut res = Vec::with_capacity(self.len());
178 for item in self {
179 res.push(item.try_conv_with(ctx)?);
180 }
181 Ok(res)
182 }
183}
184
185impl TryConvWith for SourceChange {
186 type Ctx = ServerWorld;
187 type Output = req::SourceChange;
188 fn try_conv_with(self, world: &ServerWorld) -> Result<req::SourceChange> {
189 let cursor_position = match self.cursor_position {
190 None => None,
191 Some(pos) => {
192 let line_index = world.analysis().file_line_index(pos.file_id);
193 Some(TextDocumentPositionParams {
194 text_document: TextDocumentIdentifier::new(pos.file_id.try_conv_with(world)?),
195 position: pos.offset.conv_with(&line_index),
196 })
197 }
198 };
199 let source_file_edits = self.source_file_edits.try_conv_with(world)?;
200 let file_system_edits = self.file_system_edits.try_conv_with(world)?;
201 Ok(req::SourceChange {
202 label: self.label,
203 source_file_edits,
204 file_system_edits,
205 cursor_position,
206 })
207 }
208}
209
210impl TryConvWith for SourceFileEdit {
211 type Ctx = ServerWorld;
212 type Output = TextDocumentEdit;
213 fn try_conv_with(self, world: &ServerWorld) -> Result<TextDocumentEdit> {
214 let text_document = VersionedTextDocumentIdentifier {
215 uri: self.file_id.try_conv_with(world)?,
216 version: None,
217 };
218 let line_index = world.analysis().file_line_index(self.file_id);
219 let edits = self.edits
220 .into_iter()
221 .map_conv_with(&line_index)
222 .collect();
223 Ok(TextDocumentEdit { text_document, edits })
224 }
225}
226
227impl TryConvWith for FileSystemEdit {
228 type Ctx = ServerWorld;
229 type Output = req::FileSystemEdit;
230 fn try_conv_with(self, world: &ServerWorld) -> Result<req::FileSystemEdit> {
231 let res = match self {
232 FileSystemEdit::CreateFile { anchor, path } => {
233 let uri = world.file_id_to_uri(anchor)?;
234 let path = &path.as_str()[3..]; // strip `../` b/c url is weird
235 let uri = uri.join(path)?;
236 req::FileSystemEdit::CreateFile { uri }
237 },
238 FileSystemEdit::MoveFile { file, path } => {
239 let src = world.file_id_to_uri(file)?;
240 let path = &path.as_str()[3..]; // strip `../` b/c url is weird
241 let dst = src.join(path)?;
242 req::FileSystemEdit::MoveFile { src, dst }
243 },
244 };
245 Ok(res)
246 }
247}
248
249pub fn to_location(
250 file_id: FileId,
251 range: TextRange,
252 world: &ServerWorld,
253 line_index: &LineIndex,
254) -> Result<Location> {
255 let url = file_id.try_conv_with(world)?;
256 let loc = Location::new(
257 url,
258 range.conv_with(line_index),
259 );
260 Ok(loc)
261}
262
263pub trait MapConvWith<'a>: Sized {
264 type Ctx;
265 type Output;
266
267 fn map_conv_with(self, ctx: &'a Self::Ctx) -> ConvWithIter<'a, Self, Self::Ctx> {
268 ConvWithIter { iter: self, ctx }
269 }
270}
271
272impl<'a, I> MapConvWith<'a> for I
273 where I: Iterator,
274 I::Item: ConvWith
275{
276 type Ctx = <I::Item as ConvWith>::Ctx;
277 type Output = <I::Item as ConvWith>::Output;
278}
279
280pub struct ConvWithIter<'a, I, Ctx: 'a> {
281 iter: I,
282 ctx: &'a Ctx,
283}
284
285impl<'a, I, Ctx> Iterator for ConvWithIter<'a, I, Ctx>
286 where
287 I: Iterator,
288 I::Item: ConvWith<Ctx=Ctx>,
289{
290 type Item = <I::Item as ConvWith>::Output;
291
292 fn next(&mut self) -> Option<Self::Item> {
293 self.iter.next().map(|item| item.conv_with(self.ctx))
294 }
295}
296