diff --git a/Cargo.lock b/Cargo.lock index 3a6f0cc82a..73e31f9664 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1092,7 +1092,7 @@ dependencies = [ "ra_hir 0.1.0", "ra_ide_api 0.1.0", "ra_project_model 0.1.0", - "ra_vfs 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ra_vfs 0.2.6", "ra_vfs_glob 0.1.0", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1198,7 +1198,7 @@ dependencies = [ "ra_project_model 0.1.0", "ra_syntax 0.1.0", "ra_text_edit 0.1.0", - "ra_vfs 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ra_vfs 0.2.6", "ra_vfs_glob 0.1.0", "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1308,7 +1308,6 @@ dependencies = [ [[package]] name = "ra_vfs" version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1324,7 +1323,7 @@ name = "ra_vfs_glob" version = "0.1.0" dependencies = [ "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ra_vfs 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ra_vfs 0.2.6", ] [[package]] @@ -2135,7 +2134,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum ra_rustc_lexer 0.1.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6baccda91574dfadd7f8a0bc8f9f110f874b6b484289b2536d3dbf4f0d5d97bb" -"checksum ra_vfs 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "865bb9e0f71916f7c7527af4843a2a67d1b0789f7c91c512a6b4ded69af98249" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" diff --git a/Cargo.toml b/Cargo.toml index e44c9570fd..849a6b90cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ incremental = true debug = 1 # only line info [patch.'crates-io'] +ra_vfs = { path = "../ra_vfs" } diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index bbe140b7ab..bd1ffd8f51 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::{ }; use ra_syntax::{SyntaxKind, TextRange, TextUnit}; use ra_text_edit::{AtomTextEdit, TextEdit}; +use ra_vfs::LineEndings; use crate::{req, world::WorldSnapshot, Result}; @@ -88,10 +89,10 @@ impl Conv for Severity { } } -impl ConvWith<&'_ LineIndex> for CompletionItem { +impl ConvWith<(&'_ LineIndex, LineEndings)> for CompletionItem { type Output = ::lsp_types::CompletionItem; - fn conv_with(self, ctx: &LineIndex) -> ::lsp_types::CompletionItem { + fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> ::lsp_types::CompletionItem { let mut additional_text_edits = Vec::new(); let mut text_edit = None; // 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 { } } -impl ConvWith<&'_ LineIndex> for TextEdit { +impl ConvWith<(&'_ LineIndex, LineEndings)> for TextEdit { type Output = Vec; - fn conv_with(self, line_index: &LineIndex) -> Vec { - self.as_atoms().iter().map_conv_with(line_index).collect() + fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> Vec { + self.as_atoms().iter().map_conv_with(ctx).collect() } } -impl ConvWith<&'_ LineIndex> for &'_ AtomTextEdit { +impl ConvWith<(&'_ LineIndex, LineEndings)> for &'_ AtomTextEdit { type Output = lsp_types::TextEdit; - fn conv_with(self, line_index: &LineIndex) -> lsp_types::TextEdit { - lsp_types::TextEdit { - range: self.delete.conv_with(line_index), - new_text: self.insert.clone(), + fn conv_with( + self, + (line_index, line_endings): (&LineIndex, LineEndings), + ) -> lsp_types::TextEdit { + eprintln!("line_endings = {:?}", line_endings); + let mut new_text = self.insert.clone(); + if line_endings == LineEndings::Dos { + new_text = new_text.replace('\n', "\r\n"); } + lsp_types::TextEdit { range: self.delete.conv_with(line_index), new_text } } } @@ -352,7 +358,9 @@ impl TryConvWith for SourceFileEdit { version: None, }; let line_index = world.analysis().file_line_index(self.file_id)?; - let edits = self.edit.as_atoms().iter().map_conv_with(&line_index).collect(); + let line_endings = world.file_line_endings(self.file_id); + let edits = + self.edit.as_atoms().iter().map_conv_with((&line_index, line_endings)).collect(); Ok(TextDocumentEdit { text_document, edits }) } } diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index b465707f8c..3a559e845d 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( let _p = profile("handle_on_type_formatting"); let mut position = params.text_document_position.try_conv_with(&world)?; let line_index = world.analysis().file_line_index(position.file_id)?; + let line_endings = world.file_line_endings(position.file_id); // in `ra_ide_api`, the `on_type` invariant is that // `text.char_at(position) == typed_char`. @@ -156,7 +157,7 @@ pub fn handle_on_type_formatting( // This should be a single-file edit let edit = edit.source_file_edits.pop().unwrap(); - let change: Vec = edit.edit.conv_with(&line_index); + let change: Vec = edit.edit.conv_with((&line_index, line_endings)); Ok(Some(change)) } @@ -370,8 +371,9 @@ pub fn handle_completion( Some(items) => items, }; let line_index = world.analysis().file_line_index(position.file_id)?; + let line_endings = world.file_line_endings(position.file_id); let items: Vec = - items.into_iter().map(|item| item.conv_with(&line_index)).collect(); + items.into_iter().map(|item| item.conv_with((&line_index, line_endings))).collect(); Ok(Some(items.into())) } diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 9990ef62e1..10f96812fb 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; use ra_ide_api::{ Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, }; -use ra_vfs::{RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; +use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; use relative_path::RelativePathBuf; @@ -210,6 +210,10 @@ impl WorldSnapshot { Ok(url) } + pub fn file_line_endings(&self, id: FileId) -> LineEndings { + self.vfs.read().file_line_endings(VfsFile(id.0)) + } + pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result { let base = self.vfs.read().root2path(VfsRoot(root.0)); 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 ec075a2fd8..152681062e 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; "range": { "end": { "character": 0, - "line": 6 + "line": 7 }, "start": { "character": 0, @@ -418,15 +418,15 @@ fn main() {{}} #[test] fn preserves_dos_line_endings() { let server = Project::with_fixture( - &r#" + &" //- Cargo.toml [package] -name = "foo" -version = "0.0.0" +name = \"foo\" +version = \"0.0.0\" //- src/main.rs /// Some Docs\r\nfn main() {} -"#, +", ) .server(); diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index ea99ac0629..816d01f09e 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 { } }; }; + let margin = fixture .lines() .filter(|it| it.trim_start().starts_with("//-")) .map(|it| it.len() - it.trim_start().len()) .next() .expect("empty fixture"); - let lines = fixture.lines().filter_map(|line| { - if line.len() >= margin { - assert!(line[..margin].trim().is_empty()); - Some(&line[margin..]) - } else { - assert!(line.trim().is_empty()); - None - } - }); + + let lines = fixture + .split('\n') // don't use `.lines` to not drop `\r\n` + .filter_map(|line| { + if line.len() >= margin { + assert!(line[..margin].trim().is_empty()); + Some(&line[margin..]) + } else { + assert!(line.trim().is_empty()); + None + } + }); for line in lines { if line.starts_with("//-") {