aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock8
-rw-r--r--Cargo.toml1
-rw-r--r--crates/ra_lsp_server/src/conv.rs30
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs6
-rw-r--r--crates/ra_lsp_server/src/world.rs6
-rw-r--r--crates/ra_lsp_server/tests/heavy_tests/main.rs10
-rw-r--r--crates/test_utils/src/lib.rs22
7 files changed, 50 insertions, 33 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3a6f0cc82..73e31f966 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1092,7 +1092,7 @@ dependencies = [
1092 "ra_hir 0.1.0", 1092 "ra_hir 0.1.0",
1093 "ra_ide_api 0.1.0", 1093 "ra_ide_api 0.1.0",
1094 "ra_project_model 0.1.0", 1094 "ra_project_model 0.1.0",
1095 "ra_vfs 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 1095 "ra_vfs 0.2.6",
1096 "ra_vfs_glob 0.1.0", 1096 "ra_vfs_glob 0.1.0",
1097 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1097 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1098] 1098]
@@ -1198,7 +1198,7 @@ dependencies = [
1198 "ra_project_model 0.1.0", 1198 "ra_project_model 0.1.0",
1199 "ra_syntax 0.1.0", 1199 "ra_syntax 0.1.0",
1200 "ra_text_edit 0.1.0", 1200 "ra_text_edit 0.1.0",
1201 "ra_vfs 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 1201 "ra_vfs 0.2.6",
1202 "ra_vfs_glob 0.1.0", 1202 "ra_vfs_glob 0.1.0",
1203 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1203 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1204 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1204 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1308,7 +1308,6 @@ dependencies = [
1308[[package]] 1308[[package]]
1309name = "ra_vfs" 1309name = "ra_vfs"
1310version = "0.2.6" 1310version = "0.2.6"
1311source = "registry+https://github.com/rust-lang/crates.io-index"
1312dependencies = [ 1311dependencies = [
1313 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 1312 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1314 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1313 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1324,7 +1323,7 @@ name = "ra_vfs_glob"
1324version = "0.1.0" 1323version = "0.1.0"
1325dependencies = [ 1324dependencies = [
1326 "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 1325 "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
1327 "ra_vfs 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 1326 "ra_vfs 0.2.6",
1328] 1327]
1329 1328
1330[[package]] 1329[[package]]
@@ -2135,7 +2134,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2135"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" 2134"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
2136"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 2135"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
2137"checksum ra_rustc_lexer 0.1.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6baccda91574dfadd7f8a0bc8f9f110f874b6b484289b2536d3dbf4f0d5d97bb" 2136"checksum ra_rustc_lexer 0.1.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6baccda91574dfadd7f8a0bc8f9f110f874b6b484289b2536d3dbf4f0d5d97bb"
2138"checksum ra_vfs 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "865bb9e0f71916f7c7527af4843a2a67d1b0789f7c91c512a6b4ded69af98249"
2139"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 2137"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
2140"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" 2138"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c"
2141"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 2139"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 e44c9570f..849a6b90c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,3 +6,4 @@ incremental = true
6debug = 1 # only line info 6debug = 1 # only line info
7 7
8[patch.'crates-io'] 8[patch.'crates-io']
9ra_vfs = { path = "../ra_vfs" }
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};
12use ra_syntax::{SyntaxKind, TextRange, TextUnit}; 12use ra_syntax::{SyntaxKind, TextRange, TextUnit};
13use ra_text_edit::{AtomTextEdit, TextEdit}; 13use ra_text_edit::{AtomTextEdit, TextEdit};
14use ra_vfs::LineEndings;
14 15
15use crate::{req, world::WorldSnapshot, Result}; 16use crate::{req, world::WorldSnapshot, Result};
16 17
@@ -88,10 +89,10 @@ impl Conv for Severity {
88 } 89 }
89} 90}
90 91
91impl ConvWith<&'_ LineIndex> for CompletionItem { 92impl 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
205impl ConvWith<&'_ LineIndex> for TextEdit { 206impl 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
213impl ConvWith<&'_ LineIndex> for &'_ AtomTextEdit { 214impl 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;
9use ra_ide_api::{ 9use ra_ide_api::{
10 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, 10 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
11}; 11};
12use ra_vfs::{RootEntry, Vfs, VfsChange, VfsFile, VfsRoot}; 12use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot};
13use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; 13use ra_vfs_glob::{Glob, RustPackageFilterBuilder};
14use relative_path::RelativePathBuf; 14use 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]
419fn preserves_dos_line_endings() { 419fn 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]
424name = "foo" 424name = \"foo\"
425version = "0.0.0" 425version = \"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("//-") {