diff options
Diffstat (limited to 'crates/ra_lsp_server/src/conv.rs')
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 41 |
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 | ||
219 | fn 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 | |||
210 | impl TryConvWith for SourceFileEdit { | 249 | impl TryConvWith for SourceFileEdit { |
211 | type Ctx = ServerWorld; | 250 | type Ctx = ServerWorld; |
212 | type Output = TextDocumentEdit; | 251 | type Output = TextDocumentEdit; |