diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 30 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 6 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/world.rs | 6 | ||||
-rw-r--r-- | crates/ra_lsp_server/tests/heavy_tests/main.rs | 10 | ||||
-rw-r--r-- | crates/test_utils/src/lib.rs | 22 |
5 files changed, 46 insertions, 28 deletions
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index bbe140b7a..bd1ffd8f5 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -11,6 +11,7 @@ use ra_ide_api::{ | |||
11 | }; | 11 | }; |
12 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; | 12 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; |
13 | use ra_text_edit::{AtomTextEdit, TextEdit}; | 13 | use ra_text_edit::{AtomTextEdit, TextEdit}; |
14 | use ra_vfs::LineEndings; | ||
14 | 15 | ||
15 | use crate::{req, world::WorldSnapshot, Result}; | 16 | use crate::{req, world::WorldSnapshot, Result}; |
16 | 17 | ||
@@ -88,10 +89,10 @@ impl Conv for Severity { | |||
88 | } | 89 | } |
89 | } | 90 | } |
90 | 91 | ||
91 | impl ConvWith<&'_ LineIndex> for CompletionItem { | 92 | impl ConvWith<(&'_ LineIndex, LineEndings)> for CompletionItem { |
92 | type Output = ::lsp_types::CompletionItem; | 93 | type Output = ::lsp_types::CompletionItem; |
93 | 94 | ||
94 | fn conv_with(self, ctx: &LineIndex) -> ::lsp_types::CompletionItem { | 95 | fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> ::lsp_types::CompletionItem { |
95 | let mut additional_text_edits = Vec::new(); | 96 | let mut additional_text_edits = Vec::new(); |
96 | let mut text_edit = None; | 97 | let mut text_edit = None; |
97 | // LSP does not allow arbitrary edits in completion, so we have to do a | 98 | // LSP does not allow arbitrary edits in completion, so we have to do a |
@@ -202,22 +203,27 @@ impl Conv for ra_ide_api::FunctionSignature { | |||
202 | } | 203 | } |
203 | } | 204 | } |
204 | 205 | ||
205 | impl ConvWith<&'_ LineIndex> for TextEdit { | 206 | impl ConvWith<(&'_ LineIndex, LineEndings)> for TextEdit { |
206 | type Output = Vec<lsp_types::TextEdit>; | 207 | type Output = Vec<lsp_types::TextEdit>; |
207 | 208 | ||
208 | fn conv_with(self, line_index: &LineIndex) -> Vec<lsp_types::TextEdit> { | 209 | fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> Vec<lsp_types::TextEdit> { |
209 | self.as_atoms().iter().map_conv_with(line_index).collect() | 210 | self.as_atoms().iter().map_conv_with(ctx).collect() |
210 | } | 211 | } |
211 | } | 212 | } |
212 | 213 | ||
213 | impl ConvWith<&'_ LineIndex> for &'_ AtomTextEdit { | 214 | impl ConvWith<(&'_ LineIndex, LineEndings)> for &'_ AtomTextEdit { |
214 | type Output = lsp_types::TextEdit; | 215 | type Output = lsp_types::TextEdit; |
215 | 216 | ||
216 | fn conv_with(self, line_index: &LineIndex) -> lsp_types::TextEdit { | 217 | fn conv_with( |
217 | lsp_types::TextEdit { | 218 | self, |
218 | range: self.delete.conv_with(line_index), | 219 | (line_index, line_endings): (&LineIndex, LineEndings), |
219 | new_text: self.insert.clone(), | 220 | ) -> lsp_types::TextEdit { |
221 | eprintln!("line_endings = {:?}", line_endings); | ||
222 | let mut new_text = self.insert.clone(); | ||
223 | if line_endings == LineEndings::Dos { | ||
224 | new_text = new_text.replace('\n', "\r\n"); | ||
220 | } | 225 | } |
226 | lsp_types::TextEdit { range: self.delete.conv_with(line_index), new_text } | ||
221 | } | 227 | } |
222 | } | 228 | } |
223 | 229 | ||
@@ -352,7 +358,9 @@ impl TryConvWith for SourceFileEdit { | |||
352 | version: None, | 358 | version: None, |
353 | }; | 359 | }; |
354 | let line_index = world.analysis().file_line_index(self.file_id)?; | 360 | let line_index = world.analysis().file_line_index(self.file_id)?; |
355 | let edits = self.edit.as_atoms().iter().map_conv_with(&line_index).collect(); | 361 | let line_endings = world.file_line_endings(self.file_id); |
362 | let edits = | ||
363 | self.edit.as_atoms().iter().map_conv_with((&line_index, line_endings)).collect(); | ||
356 | Ok(TextDocumentEdit { text_document, edits }) | 364 | Ok(TextDocumentEdit { text_document, edits }) |
357 | } | 365 | } |
358 | } | 366 | } |
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index b465707f8..3a559e845 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -138,6 +138,7 @@ pub fn handle_on_type_formatting( | |||
138 | let _p = profile("handle_on_type_formatting"); | 138 | let _p = profile("handle_on_type_formatting"); |
139 | let mut position = params.text_document_position.try_conv_with(&world)?; | 139 | let mut position = params.text_document_position.try_conv_with(&world)?; |
140 | let line_index = world.analysis().file_line_index(position.file_id)?; | 140 | let line_index = world.analysis().file_line_index(position.file_id)?; |
141 | let line_endings = world.file_line_endings(position.file_id); | ||
141 | 142 | ||
142 | // in `ra_ide_api`, the `on_type` invariant is that | 143 | // in `ra_ide_api`, the `on_type` invariant is that |
143 | // `text.char_at(position) == typed_char`. | 144 | // `text.char_at(position) == typed_char`. |
@@ -156,7 +157,7 @@ pub fn handle_on_type_formatting( | |||
156 | // This should be a single-file edit | 157 | // This should be a single-file edit |
157 | let edit = edit.source_file_edits.pop().unwrap(); | 158 | let edit = edit.source_file_edits.pop().unwrap(); |
158 | 159 | ||
159 | let change: Vec<TextEdit> = edit.edit.conv_with(&line_index); | 160 | let change: Vec<TextEdit> = edit.edit.conv_with((&line_index, line_endings)); |
160 | Ok(Some(change)) | 161 | Ok(Some(change)) |
161 | } | 162 | } |
162 | 163 | ||
@@ -370,8 +371,9 @@ pub fn handle_completion( | |||
370 | Some(items) => items, | 371 | Some(items) => items, |
371 | }; | 372 | }; |
372 | let line_index = world.analysis().file_line_index(position.file_id)?; | 373 | let line_index = world.analysis().file_line_index(position.file_id)?; |
374 | let line_endings = world.file_line_endings(position.file_id); | ||
373 | let items: Vec<CompletionItem> = | 375 | let items: Vec<CompletionItem> = |
374 | items.into_iter().map(|item| item.conv_with(&line_index)).collect(); | 376 | items.into_iter().map(|item| item.conv_with((&line_index, line_endings))).collect(); |
375 | 377 | ||
376 | Ok(Some(items.into())) | 378 | Ok(Some(items.into())) |
377 | } | 379 | } |
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 9990ef62e..10f96812f 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs | |||
@@ -9,7 +9,7 @@ use parking_lot::RwLock; | |||
9 | use ra_ide_api::{ | 9 | use ra_ide_api::{ |
10 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, | 10 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, |
11 | }; | 11 | }; |
12 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; | 12 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; |
13 | use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; | 13 | use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; |
14 | use relative_path::RelativePathBuf; | 14 | use relative_path::RelativePathBuf; |
15 | 15 | ||
@@ -210,6 +210,10 @@ impl WorldSnapshot { | |||
210 | Ok(url) | 210 | Ok(url) |
211 | } | 211 | } |
212 | 212 | ||
213 | pub fn file_line_endings(&self, id: FileId) -> LineEndings { | ||
214 | self.vfs.read().file_line_endings(VfsFile(id.0)) | ||
215 | } | ||
216 | |||
213 | pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> { | 217 | pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> { |
214 | let base = self.vfs.read().root2path(VfsRoot(root.0)); | 218 | let base = self.vfs.read().root2path(VfsRoot(root.0)); |
215 | let path = path.to_path(base); | 219 | let path = path.to_path(base); |
diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index ec075a2fd..152681062 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs | |||
@@ -208,7 +208,7 @@ pub use std::collections::HashMap; | |||
208 | "range": { | 208 | "range": { |
209 | "end": { | 209 | "end": { |
210 | "character": 0, | 210 | "character": 0, |
211 | "line": 6 | 211 | "line": 7 |
212 | }, | 212 | }, |
213 | "start": { | 213 | "start": { |
214 | "character": 0, | 214 | "character": 0, |
@@ -418,15 +418,15 @@ fn main() {{}} | |||
418 | #[test] | 418 | #[test] |
419 | fn preserves_dos_line_endings() { | 419 | fn preserves_dos_line_endings() { |
420 | let server = Project::with_fixture( | 420 | let server = Project::with_fixture( |
421 | &r#" | 421 | &" |
422 | //- Cargo.toml | 422 | //- Cargo.toml |
423 | [package] | 423 | [package] |
424 | name = "foo" | 424 | name = \"foo\" |
425 | version = "0.0.0" | 425 | version = \"0.0.0\" |
426 | 426 | ||
427 | //- src/main.rs | 427 | //- src/main.rs |
428 | /// Some Docs\r\nfn main() {} | 428 | /// Some Docs\r\nfn main() {} |
429 | "#, | 429 | ", |
430 | ) | 430 | ) |
431 | .server(); | 431 | .server(); |
432 | 432 | ||
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index ea99ac062..816d01f09 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -134,21 +134,25 @@ pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> { | |||
134 | } | 134 | } |
135 | }; | 135 | }; |
136 | }; | 136 | }; |
137 | |||
137 | let margin = fixture | 138 | let margin = fixture |
138 | .lines() | 139 | .lines() |
139 | .filter(|it| it.trim_start().starts_with("//-")) | 140 | .filter(|it| it.trim_start().starts_with("//-")) |
140 | .map(|it| it.len() - it.trim_start().len()) | 141 | .map(|it| it.len() - it.trim_start().len()) |
141 | .next() | 142 | .next() |
142 | .expect("empty fixture"); | 143 | .expect("empty fixture"); |
143 | let lines = fixture.lines().filter_map(|line| { | 144 | |
144 | if line.len() >= margin { | 145 | let lines = fixture |
145 | assert!(line[..margin].trim().is_empty()); | 146 | .split('\n') // don't use `.lines` to not drop `\r\n` |
146 | Some(&line[margin..]) | 147 | .filter_map(|line| { |
147 | } else { | 148 | if line.len() >= margin { |
148 | assert!(line.trim().is_empty()); | 149 | assert!(line[..margin].trim().is_empty()); |
149 | None | 150 | Some(&line[margin..]) |
150 | } | 151 | } else { |
151 | }); | 152 | assert!(line.trim().is_empty()); |
153 | None | ||
154 | } | ||
155 | }); | ||
152 | 156 | ||
153 | for line in lines { | 157 | for line in lines { |
154 | if line.starts_with("//-") { | 158 | if line.starts_with("//-") { |