aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/conv.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src/conv.rs')
-rw-r--r--crates/ra_lsp_server/src/conv.rs41
1 files changed, 40 insertions, 1 deletions
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 759e5e914..08a656569 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -190,9 +190,13 @@ impl TryConvWith for SourceChange {
190 None => None, 190 None => None,
191 Some(pos) => { 191 Some(pos) => {
192 let line_index = world.analysis().file_line_index(pos.file_id); 192 let line_index = world.analysis().file_line_index(pos.file_id);
193 let edits = self.source_file_edits.iter().find(|it| it.file_id == pos.file_id)
194 .map(|it| it.edits.as_slice()).unwrap_or(&[]);
195 let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits);
196 let position = Position::new(line_col.line as u64, u32::from(line_col.col) as u64);
193 Some(TextDocumentPositionParams { 197 Some(TextDocumentPositionParams {
194 text_document: TextDocumentIdentifier::new(pos.file_id.try_conv_with(world)?), 198 text_document: TextDocumentIdentifier::new(pos.file_id.try_conv_with(world)?),
195 position: pos.offset.conv_with(&line_index), 199 position,
196 }) 200 })
197 } 201 }
198 }; 202 };
@@ -207,6 +211,41 @@ impl TryConvWith for SourceChange {
207 } 211 }
208} 212}
209 213
214// HACK: we should translate offset to line/column using linde_index *with edits applied*.
215// A naive version of this function would be to apply `edits` to the original text,
216// construct a new line index and use that, but it would be slow.
217//
218// Writing fast & correct version is issue #105, let's use a quick hack in the meantime
219fn translate_offset_with_edit(
220 pre_edit_index: &LineIndex,
221 offset: TextUnit,
222 edits: &[AtomEdit],
223) -> LineCol {
224 let fallback = pre_edit_index.line_col(offset);
225 let edit = match edits.first() {
226 None => return fallback,
227 Some(edit) => edit
228 };
229 let end_offset = edit.delete.start() + TextUnit::of_str(&edit.insert);
230 if !(edit.delete.start() <= offset && offset <= end_offset) {
231 return fallback
232 }
233 let rel_offset = offset - edit.delete.start();
234 let in_edit_line_col = LineIndex::new(&edit.insert).line_col(rel_offset);
235 let edit_line_col = pre_edit_index.line_col(edit.delete.start());
236 if in_edit_line_col.line == 0 {
237 LineCol {
238 line: edit_line_col.line,
239 col: edit_line_col.col + in_edit_line_col.col,
240 }
241 } else {
242 LineCol {
243 line: edit_line_col.line + in_edit_line_col.line,
244 col: in_edit_line_col.col,
245 }
246 }
247}
248
210impl TryConvWith for SourceFileEdit { 249impl TryConvWith for SourceFileEdit {
211 type Ctx = ServerWorld; 250 type Ctx = ServerWorld;
212 type Output = TextDocumentEdit; 251 type Output = TextDocumentEdit;